Shop OBEX P1 Docs P2 Docs Learn Events
Parsing Serial Input String — Parallax Forums

Parsing Serial Input String

maldridgemaldridge Posts: 37
edited 2011-07-02 10:04 in BASIC Stamp
I am retrofitting an old SSR board to use a Basic stamp for my Christmas lights display. Previously I had used a parallel port to drive the board directly, but this year I would like to run the display with my mac mini using fusion. I hit a roadblock when trying to parse the data that is incoming from the serial link.

The program I am using outputs one byte for the intensity of each channel. I need to read this byte and then assign it to the proper channel. I can use a serial header if necessary but I would prefer to avoid it. My link operates at 9600,8,n,1.

At this point, I don't think that the stamp can operate fast enough to do foward phase dimming, but correct me if I'm wrong there.

Below is my code:
' {$STAMP BS2}
' {$PBASIC 2.5}

'--------------------------------------------constants-------------------------------------------
baud CON 84
link CON 16
chan VAR Byte(8)
chanid VAR Byte
'--------------------------------------program initialization------------------------------------

DO
FOR chanid = 1 TO 8
SERIN link, baud, [chan(chanid)]
NEXT

FOR chanid=1 TO 8
IF chan(chanid)>0 THEN HIGH chan(chanid)
NEXT
LOOP

Comments

  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-06-19 17:48
    Hi maldridge, I modified your code a little, check out the "STR" formatter in the help file. The timeout is so that the program dooes not hang at that point and I think you will get better results if you did use a header and perhaps a terminator. Your results would be even better if you transmitted a signal from the Stamp requesting the data, a synchronization character. Done right at 9600 your program will run quite fast.
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    '--------------------------------------------constants-------------------------------------------
    baud CON 16468
    link CON 16
    chan VAR Byte(8)
    chanid VAR Byte
    '--------------------------------------program initialization------------------------------------
    
    DO
    
    SERIN link, baud,50,timeout, [STR chan\8]
    timeout:
    FOR chanid=1 TO 8
    IF chan(chanid)>0 THEN HIGH chan(chanid)
    NEXT
    
    LOOP
    

    Jeff T.
  • maldridgemaldridge Posts: 37
    edited 2011-06-19 19:39
    I see the timeout property in the serin command, but doesn't a value have to be set before it can be used? Also, what exactly does the "/" do in the serin command; I can't find any direct reference in the help file.

    Unfortunately the program I am using cannot have the data requested. Instead it is sent at roughly 100ms intervals. I can easily add in the header and terminator to the transmitting plugin, but how should it be added to the pbasic code on the stamp?
  • Mike GMike G Posts: 2,702
    edited 2011-06-19 20:33
    maldridge, can you send two bytes, ID and Value? That would make it a little easier.

    The slash means wait for X\number of bytes. Check out the SERIN command in PBasic help for syntax.
  • maldridgemaldridge Posts: 37
    edited 2011-06-19 21:29
    Unfortunately, no I cannot send id and data. The program that creates these values is not one I can edit/recompile. While I have the option of rewriting the dll that outputs the data, that is beyond my skill level at this time. The data comes in as a linear string of bytes, one byte per channel, from the serial link. I think that I am starting to understand this more.

    I did some googling and then some reading with a fine toothed come of the syntax book and I think that the "/8" is used to capture exactly one channel's worth of data to the variable. Now I just need the program to hold at the start of the loop until the next header arrives. In the BS1, there was a wait command. Is there something similar to this for the BS2?
  • Mike GMike G Posts: 2,702
    edited 2011-06-19 21:49
    there was a wait command. Is there something similar to this for the BS2?
    Yes, also called wait on the BS2, it's in the help file.

    It's not real clear how the protocol works, but I think you get one byte value per channel (or Id) in a 8 byte stream? The index of the byte in memory is the ID or channel. If that's the case, the problem you'll face is syncing up the start of 8 bytes. If you can, send a start byte then you know the next 8 bytes will drop in the right slots.
  • maldridgemaldridge Posts: 37
    edited 2011-06-20 08:29
    This program uses some interesting serial protocols. For any who know DMX512 protocol, it is very similar. I have now configured the program to send a serial header consisting of "~!", this should allow for synchronization easily, but I can't figure out how to add the synchronization without killing the loop speed. Ideally I will use elements of this program to construct one capable of PWM in phase with mains power.

    To clear up any confusion, the data stream is as follows:
    • A header of "~!" is received
    • One byte is transmitted for each channel, in numeric order, even if the channel state has not changed
    • The cycle repeats the next time the state of ANY channel changes (roughly 100ms)

    It should be noted that only the channel intensity is transmitted. It is a value between 0-255, but anything above 00 is being ignored and the relay is just set to 'on.'

    If anyone out there knows C, there is a program which accomplishes a similar function here. It should be noted that there are no spare channels in my design and I do not use a sync/beat channel.
  • Mike GMike G Posts: 2,702
    edited 2011-06-20 08:36
    Use the waitstr to wair for "~!" then grab the nest 8 bytes. This should be very easy.

    See SERIN in the help file and post your source code.
  • maldridgemaldridge Posts: 37
    edited 2011-06-20 13:30
    The SERIN entry in the helpfile is not very clear; I keep getting compiler errors near the WAITSTR argument. Also, in the second SERIN statement, I fail to see how the data for each channel is routed to the appropriat variable, would someone mind explaining that to me?

    The specific help file entry I do not understand is the section 5 entry of the basic stamp command reference pertaining to SERIN. There are two lines at the top listing argument syntax. One specifies for the first generation stamp and the other specifies for the second generation stamp. What I fail to see is how the arguments from the first line are integrated into the second line.


    As requested here is my source code:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    'Program: LightingFirmware
    'Version: 1.0.0
    'Purpose: Interface with Vixen lighting control
    '		software and bridge to SSR grid.
    
    
    '--------------------------------------------resources------------------------------------
    baud CON 16468
    link CON 16
    chan VAR BYTE(8)
    chanid VAR BYTE
    null VAR BYTE
    '--------------------------------------------main loop------------------------------------
    main:
    DO
    SERIN link, baud, 50, timout, WAITSTR "~!", [null]
    SERIN link, baud,50,timeout, [STR chan\8]
    FOR chanid=1 TO 8
    IF chan(chanid)>0 THEN HIGH chan(chanid)
    NEXT
    LOOP
    
    '-------------------------------------------serial timout---------------------------------
    timout: 'in the event of a loss of serial comm, turn off all outputs
    FOR chanid = 1 TO 8
    LOW chanid
    NEXT
    GOTO main
    
  • Mike GMike G Posts: 2,702
    edited 2011-06-20 14:36
    Something like
    SERIN <pin>, <baud>, <timout> [WAIT("~!"), str\8]
    
    http://www.parallax.com/dl/docs/prod/stamps/web-BSM-v2.2.pdf

    The STAMP does not have buffers so you might have to go to 2400 baud.

    Replace your loop(s) with commands like this.
    OUTL= %00000000 
    OUT8 = %0
    
    FOR chanid = 1 TO 8
    LOW chanid
    NEXT
    
  • maldridgemaldridge Posts: 37
    edited 2011-06-21 20:44
    This is what I have now:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    'Program: LightingFirmware
    'Version: 1.0.0
    'Purpose: Interface with Vixen lighting control
    '		software and bridge to SSR grid.
    
    
    '--------------------------------------------resources------------------------------------
    baud CON 16468
    link CON 16
    chan VAR BYTE(8)
    chanid VAR BYTE
    '--------------------------------------------main loop------------------------------------
    main:
    DO
    SERIN link, baud, 50, timeout, [WAIT("~!"), STR chan\8]
    FOR chanid=1 TO 8
    IF chan(chanid)>0 THEN HIGH chan(chanid)
    NEXT
    LOOP
    
    '-------------------------------------------serial timout---------------------------------
    timout: 'in the event of a loss of serial comm, turn off all outputs
    FOR chanid = 1 TO 8
    LOW chanid
    NEXT
    GOTO main
    

    I don't quite understand about the commands you referenced, but at 9600 buad, the stamp should still have almost a tenth of a second left over to act on the data received before needing to process more data.
  • Mike GMike G Posts: 2,702
    edited 2011-06-22 05:34
    I don't quite understand about the commands you referenced, but at 9600 buad, the stamp should still have almost a tenth of a second left over to act on the data received before needing to process more data
    I usually go by the manual. You can grip it and rip it though...
    http://www.parallax.com/dl/docs/prod/stamps/web-BSM-v2.2.pdf

    "Basic wrote:
    *The BS2, BS2e and BS2pe may have trouble synchronizing with the incoming serial stream
    at this rate and higher due to the lack of a hardware input buffer. Use only simple variables
    and no formatters to try to solve this problem.

    Good luck
  • maldridgemaldridge Posts: 37
    edited 2011-07-02 10:04
    Being finally setled in after the move, I have had time to set up my electronics test bench again and test some code. Unfortunatly the following code didn't work:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    'Program: LightingFirmware
    'Version: 1.0.0
    'Purpose: Interface with Vixen lighting control
    '		software and bridge to SSR grid.
    
    
    '--------------------------------------------resources------------------------------------
    'baud CON 16468
    baud CON 84
    link CON 16
    chan VAR BYTE(8)
    chanid VAR BYTE
    '--------------------------------------------main loop------------------------------------
    main:
    DO
    FOR chanid=1 TO 8
    SERIN link, baud, 50,timeout, [WAIT("~!"), DEC` chan(chanid)]
    IF chan(chanid)>0 THEN HIGH chan(chanid)
    NEXT
    LOOP
    
    '-------------------------------------------serial timeout---------------------------------
    timeout: 'in the event of a loss of serial comm, turn off all outputs
    FOR chanid = 1 TO 8
    LOW chanid
    NEXT
    GOTO main
    

    I thought that maybe the data wasn't arriving when I calculated, so then I tried it without the timout:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    'Program: LightingFirmware
    'Version: 1.0.1
    'Purpose: Interface with Vixen lighting control
    '		software and bridge to SSR grid.
    
    
    '--------------------------------------------resources------------------------------------
    'baud CON 16468
    baud CON 84
    link CON 16
    chan VAR BYTE(8)
    chanid VAR BYTE
    '--------------------------------------------main loop------------------------------------
    main:
    DO
    FOR chanid=1 TO 8
    SERIN link, baud, 50,timeout, [WAIT("~!"), DEC` chan(chanid)]
    IF chan(chanid)>0 THEN HIGH chan(chanid)
    NEXT
    LOOP
    
    '-------------------------------------------serial timout---------------------------------
    timeout: 'in the event of a loss of serial comm, turn off all outputs
    'FOR chanid = 1 TO 8
    'LOW chanid
    'NEXT
    GOTO main
    

    But still no luck. I have LEDs connected to P0-P2 for the first three channels, but try as I might, I can't get the program to work. I have also tried sending a string which should definitely work from hyper terminal (it to failed).
Sign In or Register to comment.