Shop OBEX P1 Docs P2 Docs Learn Events
BASIC Stamp II and C# — Parallax Forums

BASIC Stamp II and C#

GreenGiant83GreenGiant83 Posts: 43
edited 2006-09-06 02:40 in BASIC Stamp
I connected two servo's together to make a two axis pointer.· I want to be able to control the positions of each of the servo's from a c# program I am writing.· Right now my stamp is basically:
DO
DEBUGIN DEC xpulse,·DEC ypulse
PULSOUT 14, xpulse
PULSOUT 15, ypulse
PAUSE 20
DEBUG 0 'Finish command
LOOP

In my C# program uses the MS Comm control.· I have a timer that sends the x and y pulse widths and then wait for the finish command.· The problem is that there is to much of a delay between the commands, and that makes the movement choppy.· Is there anyway to use c# to write to the chips memory that the stamp could read from with out blocking control while waiting for the debugin command?

Comments

  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2006-09-05 05:44
    Perhaps SERIN would be a better choice in this situation.· The way you're using DEBUGIN would require an ASCII string for the x values followed by a CR, followed by the ASCII y values and another CR.· Using SERIN you could simply accept a binary value without the CR and that would speed things up considerably.· Not to mention, you could use a timeout in your SERIN routine and reduce the PAUSE which would also reduce lag.· Also replace DEBUG with a SEROUT for clarity.· DEBUG and DEBUGIN can be used, but they primarily designed for input/output with the DEBUG terminal where human input is needed.· I hope this helps.· Take care.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • allanlane5allanlane5 Posts: 3,815
    edited 2006-09-05 13:20
    And "SERIN" has a non-blocking 'time-out' mode. So you could do your 20 mSec 'refresh' delay IN the SERIN.
  • BeanBean Posts: 8,129
    edited 2006-09-05 13:20
    Also I believe you can use much faster baud rates with SERIN.
    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com

    There are only two guaranteed ways to become weathy.
    Spend less than you make.
    Make more than you spend.
    ·
  • allanlane5allanlane5 Posts: 3,815
    edited 2006-09-05 13:26
    InVal1 VAR WORD
    InVal2 VAR WORD

    DO
    GOSUB GetPulse ' Include the 'pause' in GetPulse
    PULSOUT 14, xpulse
    PULSOUT 15, ypulse
    LOOP

    GetPulse:
    SEROUT 16, 16468, [noparse][[/noparse]"."] ' Prompt PC to send the data
    SERIN 16, 16468, 20, Timeout, [noparse][[/noparse]DEC InVal1, DEC InVal2]
    IF InVal1 <> 0 THEN xpulse = InVal1
    IF InVal2 <> 0 THEN xpulse = InVal2
    PAUSE 20 ' When here, got data fast, so need a pause
    TIMEOUT: ' When here, timed out, so we've already spent our 20 mSec
    RETURN
  • GreenGiant83GreenGiant83 Posts: 43
    edited 2006-09-05 13:56
    You guys are awesome for getting back to me so quick.· I have a few questions about the SERIN and SEROUT commands.· In the code you provided you use 16468 as the baud rate.· Is there some signifigance to this number?· When I normally think of baud rate i normally thing of 9600.· Also you use pin 16 for the I/O.· This pin 16 is the pin on the serial port, right?· Not one of the normal IO pins that I would use to control the hardware attached to the board?· I want to take as little time as is possible waiting on data from the computer, which may come very quickly or not at all, is it unreasonable to set the timeout on the SERIN to 1ms?· And lastly just a note, the 20ms PAUSE is for the sake of the servo's to ensure a proper duty cycle. Though, if I can guarentee that the will take no less than 1ms than I can turn that down to about 18ms.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2006-09-05 14:49
    Hello,

    ·· If you look in the BASIC Stamp Manual or the Editor Help File under the SERIN/SEROUT command you will see that the baud rates are not specified as numbers like 2400 or 9600.· Instead you would define a constant and use that.· It could be something like N9600, but that value is derived from the parameters listed for these commands.· For 9600 baud true (8, N, 1) you would use 84, however since the programming port is inverted that number becomes 16468.· I hope this helps.· Take care.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • allanlane5allanlane5 Posts: 3,815
    edited 2006-09-05 17:11
    Let's see:

    At 9600 baud, each bit takes 1/9600, or 104 uSec. Now, if you're sending 8N1 (8 data bits, No parity, 1 stop bit) then each byte takes 10 bit periods (start bit, 8 data bits, stop bit) so that's 1.04 mSec per byte sent. So no, if you set the timeout to 1 mSec you'll never get any data. It will ALWAYS time out.

    Now, you realize, that the BS2 will not take any data unless it is 'pending' (waiting) in the SERIN command BEFORE the data starts. This is because the BS2 does no buffering of serial data. So there's a timing issue here.

    You also realize, that in the 'pause' part, the BS2 is doing NOTHING else except pausing. So, if the BS2 is doing 'nothing' anyway, it might as well be doing nothing while 'pended' in the SERIN statement.

    Yes, in the the "SERIN 16" statement, the '16' is a 'pseudo-pin', that tells the BS2 to 'listen' to the programming port. This means P0 through P15 are free for use by your program.

    If you really want it to work efficiently, you'll program the PC side to send its data as quickly after it recieves the "." as possible. This will 'release' the 'pended' SERIN statement as quickly as possible.
  • GreenGiant83GreenGiant83 Posts: 43
    edited 2006-09-05 17:25
    With the command:
    SERIN 16, 16468, 20, Timeout, [noparse][[/noparse]DEC InVal1, DEC InVal2]
    I assume I can·send values of up to 65536 into InVal1 and InVal2, is that true?· From my program in c# what do I need to send out?· Before with the debugin statement I was sending for example "1000\r" a brief pause followed by "500\r".· With this SERIN being one call would I output "1000\r500\r"?· I realize that this a string value which is like char 49 char 48 char 48 char 48 char 13, which makes me wonder if I need to output the data in a different fashion.· I apoligize if this post is somewhat cryptic, I am very new to the hardware scene.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2006-09-05 18:17
    GreenGiant -

    A variable defined as a BYTE can have values from 0-255. A variable defined as a WORD can have values from 0-65535.

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    <!--StartFragment -->
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2006-09-05 19:02
    GreenGiant,

    ·· I still hgihly recommend sending the data in BINARY format.· Using the DEC formatters will still require you to send the ASCII digits of those values, requiring up to 12 bytes instead of the 4 it would take to send any value in BINARY.· You can send the values LOWBYTE/HIGHBYTE and put them directly into the WORD variables on the receiving side.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • GreenGiant83GreenGiant83 Posts: 43
    edited 2006-09-05 21:53
    So from my program I send a total of four bytes? First values low and high bytes followed directly by the second values low and high values?· Then in the BASIC program I would have a call like this?

    SERIN 16, 16468, 20, Timeout, [noparse][[/noparse]InVal1, InVal2]
  • allanlane5allanlane5 Posts: 3,815
    edited 2006-09-05 21:58
    Well, GG83, you've got it. The "DEC" modifier tells the SERIN command to accept what it's recieving as an Ascii string version of the value -- your "1000\r" is exactly what the DEC modifier is looking for. (Maybe "1000\n", not sure).

    Now, since you have TWO "DEC" parameters, the SERIN won't return until the time-out passes, or it gets two parameters. So you don't HAVE to send them in the same string, but you could if you wanted to. I believe if it gets the first value, then times-out, that the first parameter will have a value, while the second parameter will be set to zero.

    Note also, at 9600 baud each character takes about 1 mSec -- so sending "1000\r500\r" would take 9 mSec -- which should work fine. "10000\r10000\r" would be 12 mSec -- still fine, assuming your PC waits for the "." signal before it sends.

    Now, you COULD tell the SERIN to recieve 'raw bytes'.

    SERIN 16, 16864, [noparse][[/noparse]MyVal1.Highbyte, MyVal1.LowByte, MyVal2.HighByte, MyVal2.LowByte]

    This would take less time to be transmitted, but you'd have to 'split' the values on the C# side. It's doable, though. Harder to debug, as you can't read the strings by eye any more.

    Note anything sent to the BS2 WILL be 'echoed' back by the BS2 hardware, so make sure on the C# side you filter that stuff out.
  • GreenGiant83GreenGiant83 Posts: 43
    edited 2006-09-06 01:47
    I know this is basic, but I cant seem find the answer.· I know a word is made up of two bytes.· From playing around with setting a word value and checking its .LOWBYTE and .HIGHBYTE I have deduced the following method to get the low and high byte values.· I wonder if there is not a better method to do this.
    //WordVal == HighByte * 256 + LowByteprivate byte[noparse][[/noparse]] GetBytePair(int val) 
    { 
    byte hByte = (byte)(val / 256); 
    byte lByte = (byte)(val % 256); 
    byte[noparse][[/noparse]] bytes = new byte[noparse][[/noparse]2]; 
    bytes[noparse][[/noparse]0] = lByte; 
    bytes[noparse][[/noparse]1] = hByte; 
    return bytes; 
    }
    

    P.S. There should be a check to ensure that the int value passed does not exceed 65536.
  • allanlane5allanlane5 Posts: 3,815
    edited 2006-09-06 02:40
    Bytes[noparse][[/noparse]0] = (byte) Val & 0xFF
    Bytes[noparse][[/noparse]1] = (byte) (Val / 256) -- assuming "/" is integer division.

    Is there a 'right shift' operator in C#?
Sign In or Register to comment.