Shop OBEX P1 Docs P2 Docs Learn Events
Perl - Device::SerialPort, 2-way communication — Parallax Forums

Perl - Device::SerialPort, 2-way communication

Jason ShortJason Short Posts: 21
edited 2005-10-07 22:33 in BASIC Stamp
I've been using a perl module called Device::SerialPort to glue together Macromedia Flash and my BS2 and It's been working fairly well and I now have two way communications over the web to the stamp. My issue is this: sending data to the stamp via serIn is spotty. I can read perfectly, but I can't write with any reliability. It seems to recognize my input only 50% of the time for any send.

Here is my code (just the important parts):
...
pins VAR WORD
RXData VAR BYTE
main:
SERIN 10, 84, 100, readSenors, [noparse][[/noparse]WAIT ("X"),RXData]
SERIN 10, 84, [noparse][[/noparse]DEC5 pins]
GOTO parseCommand

readSenors:
Do Stuff...
GOTO main

parseCommand:
Do Stuff...
GOTO main

I've adjusted the timeout for the SERIN and it really makes no difference

I tried this with no luck at all: (moving the DEC inline)
SERIN serInPin, 84, 100, readSenors, [noparse][[/noparse]WAIT ("X"),RXData, DEC5 pins]

From the manual's description DEC5 should work if I send this string "XD65535" but it hangs. I have found that RXData get captured, DEC5 is the section that gives me the headaches.

I've also tried this:
SERIN 10, 84, 100, readSenors, [noparse][[/noparse]WAIT ("X"),RXData]
SERIN 10, 84, [noparse][[/noparse]DEC pins]

with sending this string "XD" and then "65535A" but it was very spotty, only working 50% of the time. Again RXData gets captured every time correctly.

I'm guessing there could be two issues. One, I'm just using DEC wrong, or two, I'm sending too quickly in sequence from Perl on the PC side? Or maybe what I think I'm sending is not really the case.

Has anyone used Device::Serial before? is there anything I should know? or an easy way to test my output to the BS2 to see if the fault is on the PC side?

I'll post my Perl server when I get this figured out. It's pretty sweet and uses sockets to connect multiple clients over the internet to the BS2.

Jason

Post Edited (Jason Short) : 10/7/2005 6:21:13 PM GMT

Comments

  • Jason ShortJason Short Posts: 21
    edited 2005-10-06 05:22
    Ok, I take back the timeout not being a factor. It seems to be a major one after all. Is 100ms just too short of a wait to read 2 bytes? or are the bytes coming in at some point in the middle of the timeout and occasionally getting cutoff? could be...
    Jason
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2005-10-06 05:35
    Jason -

    Try this first, and see what happens:

    pins VAR WORD
    RXData VAR BYTE

    SERIN serInPin, 84, 100, readSenors, [noparse][[/noparse]WAIT ("X"), RXData, pins]

    If that goes well, then try this:

    pins VAR WORD
    RXData VAR BYTE

    SERIN serInPin, 84, 200, readSenors, [noparse][[/noparse]WAIT ("X"),RXData, DEC 5 pins]

    and if that fails, continue moving the timeout parameter upwards until it becomes reliable.

    If none of that above works, drop the baud rate on both sides until you get reliable communications. Once it becomes reliable, you can consider adding any formatter(s) back in. Any formatter (DEC being one) will take a fair amount of time to execute, and that time occurs during byte fetch time; thus effectively reducing the overall potential throughput. WORD processing (verses BYTE processing) represents the worst case, since more potential digits are involved. More actual digits (in the imput stream) also exacerbates worst case scenario. By worst case here, we're saying longest processing time.

    Regards,

    Bruce Bates
  • allanlane5allanlane5 Posts: 3,815
    edited 2005-10-06 12:47
    Since the BS2 only does single-tasking, it only recieves data while it's 'waiting' in the SERIN command.

    So if you set the time-out to 100 mSecs, what you're doing is hoping that during that magic 100 mSecs you send all of your data. This could work, but if you miss part of the window, what the BS2 gets will be garbled.

    So it sounds like some kind of simple hand-shake might be in order here.

    Also, I think you need a 'space' character between parameters for the BS2 SERIN parsing (dividing things into parameters) to work. If you do that, "X D 65535 " should be correctly recieved by
    "SERIN SerPin, 84, 200, TimeOut, [noparse][[/noparse]WAIT ("X"), RxData, DEC5 MyWord]"

    Note starting a NEW 'SERIN' in the middle of a message is NOT a good idea -- the BS2 will go 'deaf' for 100 uSec or so as the second SERIN statement begins execution.
  • Tom WalkerTom Walker Posts: 509
    edited 2005-10-06 13:31
    allanlane5,
    I thought that the internal SERIN timeout clock resets itself on receipt of any data, so that it won't fall to the timeout label unless there is "silence" for the timeout period. At least previous messages suggesting shorter timeout periods in noisy environments to preven "forever-waits" seem to indicate that this is the case....If that assumption is correct, then one should not have to receive all of their data within the timeout window, would they?

    Seeking understanding...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Truly Understand the Fundamentals and the Path will be so much easier...
  • allanlane5allanlane5 Posts: 3,815
    edited 2005-10-06 14:43
    My understanding was that the time-out would terminate any reception that was occurring. Since some data HAD been read, it would not jump to the 'timeout' label, though.

    So it's very important to send an "end of token" character -- like a space character, or a CHR(13) (aka CR, aka <carriage-return>) at the end of your string, so your last data element will be properly parsed by the SERIN command.

    Some Parallax person can give us the authoritative answer on this, though.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2005-10-06 15:02
    Gents -

    The following comes directly from the PBASIC Help File, and should aid in understanding, but I don't consider it entirely definitive, due to its obvious brevity:

    quote

    result VAR Byte

    Main:
    SERIN 1, 16468, 2000, No_Data, [noparse][[/noparse]DEC result]
    DEBUG CLS, ? result
    STOP

    No_Data:
    DEBUG CLS, "Timed out"
    STOP

    If no data arrives within 2 seconds, the program aborts SERIN and continues at the label No_Data.

    Here's a very important concept: this timeout feature is not picky about the kind of data SERIN receives; if any serial data is received, it prevents the timeout. In the example above, SERIN wants a decimal number. But even if SERIN received letters "ABCD..." at intervals of less than two seconds, it would never abort.

    end quote

    Regards,

    Bruce Bates
  • Jason ShortJason Short Posts: 21
    edited 2005-10-06 16:19
    I'm planning on trying to the handshake today.

    'my front door filter
    SERIN serInPin, 84, 100, readSenors, [noparse][[/noparse]WAIT ("X")];

    'get perl to block until reply for .5 seconds at least

    ' send out an X to perl
    SEROUT serOutPin, 84, [noparse][[/noparse]"X"]

    'when perl gets the X it knows it can send in the clear, and the BS2 blocks
    SERIN serInPin, 84, [noparse][[/noparse]WAIT ("X"), DEC5 pins];

    'once perl sends the data it resumes normal operation
  • Jason ShortJason Short Posts: 21
    edited 2005-10-06 19:31
    I've been playing around and DEC just will not work properly:

    SERIN serInPin, 84, [noparse][[/noparse]RXData, DEC pins]

    I send this string "A 125 A" and it hangs waiting for a number
    I send this string moments later "255 A" and DEC catches the 255 and continues. 125 was lost or ignored in the first place.

    in the manual I see a very complex input style:
    SERIN 1, 16468, [noparse][[/noparse]WAIT("pos: "), DEC yOffset, DEC4 yOffset]

    No matter how I craft the input stream I don't seem to be able to replicate it.

    Is there a preferred character to trigger the DEC formatter?
  • allanlane5allanlane5 Posts: 3,815
    edited 2005-10-06 20:40
    I think DEC likes the '13' character, as in the CR character.

    Again, if you want to get stuff from a SINGLE STRING, don't use two SERIN's to get it.

    You might try sending "A<CR>125<CR>", and see if [noparse][[/noparse]RXData, DEC Pins] gets the data.
    (where "<CR>" is replaced by a single carriage return character, of course. You don't actually send the "<", then "C", etc.)
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2005-10-06 21:47
    Jason -

    It almost seems as if you're testing SERIN to see if you can make it fail. Now that you see it can and will fail when the WRONG data is sent to it; wrong in the sense that it's not how you described it, you might want to send it proper data, and see what it will do. Here is a set of data that should work first time and every time:

    Data based on a SERIN structured like this:
    SERIN serInPin, 84, [noparse][[/noparse]RXData, DEC5 pins]

    Data:

    A1 <CR>
    B12 <CR>
    C123 <CR>
    D1234 <CR>
    E12345 <CR>

    Let us know how you make out with that.

    Regards,

    Bruce Bates
  • Jason ShortJason Short Posts: 21
    edited 2005-10-06 22:08
    ok,
    at least dec now works!

    SERIN serInPin, 84, [noparse][[/noparse]RXData, DEC pins]

    send the string "X\r255\r" ( \r being a Perl escape for a return)

    I couldn't find the preference for certain characters in the manual but CR and LF work really well and they must be before and after.

    I'm still wrestling with the timeout killing my data transfer.
    anything less than 500ms will start garbling my data occasionally. 10ms will garble it every time.
  • Jason ShortJason Short Posts: 21
    edited 2005-10-06 22:23
    Ok now the handshake works...

    main:
    SERIN serInPin, 84, 50, readSenors,[noparse][[/noparse]RXData] ' any data garbled or not will trip this front door 90% of the time
    SEROUT serOutPin, 84, [noparse][[/noparse]"X"] ' send Perl an OK to send the real data
    SERIN serInPin, 84, 5000, main, [noparse][[/noparse]RXData, DEC pins] ' receive the data
    SEROUT serOutPin, 84, [noparse][[/noparse]"Y"] ' let perl know we've read it ok, or have perl try again
    goto parsecommand

    I've not lost any data yet with this method.

    Jason
  • superchumpsuperchump Posts: 10
    edited 2005-10-07 07:01
    Hey Jason,

    Could you post the procedure you're using in perl for the serial port? I may want to try that. My TCL code is getting me nowhere. TCL is not known for playing with serial ports well and I know perl can be used with TK. Thanks.
  • allanlane5allanlane5 Posts: 3,815
    edited 2005-10-07 13:17
    Thanks, Jason, that's a nice solution.

    Note that a 5000 mSec timeout (5 seconds) will terminate almost immediately once the data has been recieved, so you're not really slowing your program down there -- unless of course the data sender has been hosed -- in which case you have a 5 second delay before you detect that, which shouldn't be a problem.

    And yes, it's not obvious that "\r" is a token terminating character that SERIN likes.
  • Jason ShortJason Short Posts: 21
    edited 2005-10-07 18:10
    I'm enclosing the perl source code and the BS2 code

    I've used IO:Select to manage the file handles
    and IO::Socket to manage the networking.

    The Serial port is converted into a file handle and added to a set of file handles within the Select Object
    Select then magically chooses the file handles that have information ready to read and therefor eliminates any blocking.
    Using this method I can get as many clients to connect to the BS2 over the net as I want.

    Run the server by typing "perl serialToFlash.pl" (optionally add a " &" at the end to make it run independently as a process in UNIX.)

    Connect to it with telnet and send commands formatted like this: "code:number". As it is written for my needs, Perl parses the command and formats it for the serial connection to the BS2. You could do any parsing or none if you don't need to. In my example the number represents a Bitmask of output to be set to High or Low. "H:255" will set pins 0-7 to high, "L:24" will set pins 3 and 4 to low. I'm using the XMLSocket object within Flash to connect to the server.

    note: be sure to include the port number with telnet command i.e. telnet 192.168.10.127 7070

    There is a loop that ensures the data sent to the BS2 is received but it is not error checking, only an "OK" that the DEC read the value. Error checking could be added really easily though.

    Also note everything is "event based" meaning only changes are sent over the network. That's why I needed the fast timeout in the command parsing loop. I wanted button presses to be sensed almost immediately but still maintain optimum 2-way communication on a single stamp.

    Jason

    Post Edited (Jason Short) : 10/7/2005 6:22:50 PM GMT
  • superchumpsuperchump Posts: 10
    edited 2005-10-07 22:33
    Thank you much! I'll look more at this this weekend.
Sign In or Register to comment.