Shop OBEX P1 Docs P2 Docs Learn Events
Basic Stamp 2, SERIN, Non-Numeric Characters and C++ — Parallax Forums

Basic Stamp 2, SERIN, Non-Numeric Characters and C++

SB316SB316 Posts: 33
edited 2011-06-21 17:29 in BASIC Stamp
Hi all,

I've been experimenting with serial communication between a Basic Stamp 2 and my PC (running Ubuntu) using C++. I have been using a library (I suppose that's what you would call it) that works with Unix based systems called Termios I've been able to set up a simple test program in which the BS2 waits for a number to be fed to it (via the SERIN command) then blinks an LED that number of times. For example, you send the number 3, it blinks the LED 3 times. My C++ program simply sets some things up using Termios (the baud rate and stuff like that), gets the number to send (simple cin command), then creates an 'ofstream' variable and writes (using the << operator) to the device file '/dev/ttyS0' through the stream. It works fine if the number in question is less than 10. Once you get into double digits the BS2 only works with the first digit, i.e. the number 10 makes the light blink once. I tried using the DEC operator in my SERIN command so that the BS2 would get the actual numeric value of the number sent (before then I was converting from the ASCII value by subtracting 48 from the number I got). I read in the help manual in the Basic Stamp editor software that when you use the DEC operator the SERIN command waits for a non-numeric character to come through, telling it that the sender has finished sending. So, here's the problem: I've tried sending a whole bunch of non-numeric characters from my C++ program. 'a', '\n', '\0', etc. My BS2 just will not blink the light anymore! If I revert back to the original program, the one with the single digit numbers, it works fine. But not when I try to get it to work with double digits.

So, I hope I haven't bored you with my extremely long post. Can anybody help?

P.S. I will be posting another thread about another question I have regarding serial I/O between my BS2 and my computer. I'll post a link to this thread when it's up. Keep your eyes peeled.

Comments

  • $WMc%$WMc% Posts: 1,884
    edited 2011-06-20 17:37
    Posting your code would help?
  • PJAllenPJAllen Banned Posts: 5,065
    edited 2011-06-20 17:51
    From PBASIC Help --

    SERIN's InputData can be structured as a sophisticated list of actions to perform on the incoming data. This allows you to process incoming data in powerful ways. For example, suppose you have a serial stream that contains "pos: xxxx yyyy" (where xxxx and yyyy are 4-digit numbers) and you want to capture just the decimal y value. The following code would do the trick:

    yCoord VAR Word ' y coordinate
    Main:
    SERIN 1, 16468, [WAIT ("pos: "), SKIP 4, DEC yCoord]
    DEBUG ? yCoord
    END
    The items of the InputData list work together to locate the label "pos: ", skip over the four-byte x data, then convert and capture the decimal y data. This sequence assumes that the x data is always four digits long; if its length varies, the following code would be more appropriate:

    yCoord VAR Word
    Main:
    SERIN 1, 16468, [WAIT ("pos: "), DEC yCoord, DEC yCoord]
    DEBUG ? yOffset
    END

    The unwanted x data is stored in yCoord then replaced by the desired y data. This is a sneaky way to filter out a number of any size without using an extra variable. With a little creativity, you can combine the InputData modifiers to filter and extract almost any data.
  • Mike GMike G Posts: 2,702
    edited 2011-06-20 18:04
    SB316, as you pointed out if you receive the number 1 without the DEC formatter you must subtract 48 to decode the ASCII character to an integer. Therefore the ASCII encoded character sent from you C++ app was 49 (or 0x31h). Lets say you sent the number 11 with the same method. Well, that would be two bytes 49 and 49. Therefore, you would have to subtract 48 from both numbers and multiply one of the number (depends on the format) by 10 then add the numbers together.

    Checkout ASCII encoding.
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-06-20 18:05
    Hi SB316, code would certainly help, in the meantime be aware that if you are using the programming port for your communications every character transmitted to the Stamp is echoed back to the PC, if the echo is not removed then it, or part of it, will be included in the next transmission corrupting your data.

    Using the WAIT instruction as suggested is the way to go when you finally get your protocol figured out, it will make your transmissions much more reliable.

    Jeff T.
  • SB316SB316 Posts: 33
    edited 2011-06-20 18:50
    Ok PJ, so what you're saying is that the "Wait" command overrides the fact that the DEC operator makes the BS2 wait until it receives a non-numeric character. In that case, wouldn't you still need one for the Stamp to distinguish between the two coordinates. But this is my problem. It seems like my Stamp won't stop waiting for the end of my data packet.
  • Mike GMike G Posts: 2,702
    edited 2011-06-20 20:19
    PJ is showing you how to filter input which is great if you understand what you're filtering and why.

    Post your source code.
  • SB316SB316 Posts: 33
    edited 2011-06-21 09:55
    GRRRRRRR! Ok, here's the source code. I tested it out just now and it doesn't work even when I send a single digit number. It did before, every time. It wasn't with that particular .bs2 file, the original was accidentally deleted. But this one should do the same thing, and I know that the .cpp file is the same one that I used when I got it to work before. Anyway, here they are.
  • Mike GMike G Posts: 2,702
    edited 2011-06-21 11:29
    Here's an example in PBASIC using DEBUG and DEBUGIN. DEBUG is like SEROUT and DEBUGIN is like SERIN. I tried to make this a step-by-step process. The first section is using filters the second section is doing the decoding manually. It might be helpful to Google "ASCII Table".
    ' {$STAMP BS2p}
    ' {$PBASIC 2.5}
    
    value   VAR     Byte
    value2  VAR     Byte
    result  VAR     Byte
    counter VAR     Byte
    again   VAR     Byte
    
    
    counter = 1
    
    Main:
    
      value = 0
      value2 = 0
      counter = 1
      result = 0
    
      ' Use a filter to grab 2 digits
      DEBUG "Enter a two digit number: "
      DEBUGIN DEC2 value
      DEBUG CR , "You entered: ", DEC value, CR
    
    
      'Do it manually
      DEBUG CR, "Let's try this again.",CR
      DEBUG "Enter the first digit: "
    
      'Get first number
      DEBUGIN value
      DEBUG CR , "You entered: ", DEC value, CR
    
      'Validation
      IF(value >= 48 AND value <= 57) THEN
        DEBUG "That's ASCII for ", STR value, CR
      ELSE
        DEBUG CR, "I said enter a number!  You get a 1!", CR
        value = 49
      ENDIF
    
      'Get second value
      DEBUG CR, "Enter the second digit: "
      DEBUGIN value2
      DEBUG CR , "You entered: ", DEC value2, CR
      counter = counter * 10
    
      'Validation
      IF(value >= 48 AND value <= 57) THEN
        DEBUG "That's ASCII for ", STR value2, CR
      ELSE
        DEBUG CR, "I said enter a number!  You get a 1!", CR
        value2 = 49
      ENDIF
    
      'Decode two byte ASCII to an integer
      result = ((value-48) * counter) + ((value2-48) * counter/10)
      DEBUG "You entered: ", DEC result, CR
    
      ' Do it again?
      DEBUG "Again (y/n): "
      DEBUGIN again
      IF(again = "y" OR again = "Y") THEN
        DEBUG CLS
        GOTO Main
      ELSE
        END
      ENDIF
    
    GOTO Main
    
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-06-21 17:29
    There should be no need to subtract 48 if you use the DEC formatter. I used a version of the BS2 code that you posted and it works fine, I'll post it here and you know that it is good. The C++ code that you posted has no terminator at the end of the numeric string, I'm not familiar with the methods you are using but I can suggest that you replace outFile << pulseNum; with outFile << pulseNum << '\n';
    pulse VAR Word
    counter VAR Word
    counter2 VAR Word
    main:
    SERIN 16, 3313, [DEC pulse]
    HIGH 2 'Input Recieved
    PAUSE 2000
    LOW 2
    
    FOR counter = 1 TO pulse
    HIGH 1
    PAUSE 1000
    LOW 1
    PAUSE 500
    NEXT
    
    GOTO main
    

    Jeff T.
Sign In or Register to comment.