Shop OBEX P1 Docs P2 Docs Learn Events
Phrase serial string from gsm save and use it, propeller Im going crazy — Parallax Forums

Phrase serial string from gsm save and use it, propeller Im going crazy

libadmanlibadman Posts: 36
edited 2014-01-22 15:22 in General Discussion
I have been going crazy trying to figure out how to phrase data from the serial port. I have a gsm modem that i would like to get info from. I have looked over several code/objects and I understand the general concept but no one FULLY COMMENTS any of the code so I get stuck because I can not understand how to store and use values.


I think this is what i should do
wait on serial data of unknown length maybe ----even look for start character but prefer not
fill buffer until terminator like carriage return but keep reading just get rid of carriage return until no more data
save bytes from buffer to an address
get data address
use data

So far I have tried:

the "case" method (i.e=case "p" do work case "e" do work
the repeat until serial.rx=":"
repeat i from 0 to 20
repeat while byte[ec] <> 13
and so many other code variations......

Can some one help me get on the right track, im using the propeller board, I migrated this project from the basic stamp 2 where i would wait on string "blabla" and then look for a password and then look for a command. im just so aggravated I can not grasp the idea. I have code I have been testing but its all over the place (messy and inoperable) PLEASE HELP ME

Comments

  • homosapienhomosapien Posts: 147
    edited 2014-01-21 10:50
    I have deployed several propeller modules using a SIM900 GSM. The sending and receiivng of serial commands between the GPRS module and Prop is straightforward. I am using the Full Duplex Serial object to drive the serial communications, my procedure is something like this:

    1) Clear the serial buffer
    2) Send a serial command to the GPRS module.
    3) In default mode, the serial Rx will echo my command, as well as showing the response of the GPRS.
    4) I usually parse the serial Rx data by looking for my sent command (using the STRCOMP command from SPIN), and then look for possiple responses, such as 'OK', 'ERROR' or other more specfic data strings (such as a received text message). You will need to build short response strings from the serial Rx buffer with which to do your STRCOMP and simplify the search, and use pointers to determine where you are in the response string and how long the string to match will be.

    You need to do some research to undertand what a string is (a series of ASCII bytes), how it is terminated (usually with a byte $00), and how they are stored in the longs of prop memory, to effectivly use the STRCOMP command.

    If I understand correctly, and oyu are using a propeller to drive a GPRS device, you may want to move this to the propeller forum to get more device specfific responses.

    Nate
  • libadmanlibadman Posts: 36
    edited 2014-01-21 11:13
    Thank you so much for your response! however everything you said I was aware of except the "strcomp", im just having a hard time implementing the code, I have several code examples however do not FULLY understand them. I would like to stick with fullduplexserial and not go to another object. But since we are talking maybe you can help me with this new code im attempting to use.

    It is as follows:


    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000


    obj
    gsm: "Extended_FDSerial" 'I would like to use fullduplexserial


    debug: "TV_Text"
    var


    byte message[16], phonenumber[16], mess1[16], mess2[16], mess3[16], mess5[16], mess6[16], mess7[16]


    dat


    on byte "on", 0
    off byte "off", 0


    pub main

    debug.start (12)
    gsm.start (1, 22, 0, 2400)
    waitcnt (clkfreq * 2 + cnt)


    dira[2] :=1


    readmessage


    pub readmessage




    repeat


    waitcnt (clkfreq * 5 + cnt)
    gsm.rxflush
    gsm.str (string("AT+CMGR=1")) 'Read sms in first memory
    gsm.tx(13) 'CT

    debug.str (string("Get message in memory1..."))


    debug.str(13)
    gsm.RxTime(300,@mess1) 'this is where the issue is--- in full duplex serial im not sure how to write this line, @mess1:=gsm.rxtime(300)
    gsm.RxStrTime(300,@mess2) 'after timeout then what, will it keep trying to read or start over I do not see a "do on timeout" command
    gsm.RxStrTime(300,@mess3)
    gsm.RxStrTime(300,@phonenumber)
    gsm.RxStrTime(300,@mess5)
    gsm.RxStrTime(300,@mess6)
    gsm.RxStrTime(300,@mess7)
    gsm.RxStrTime(300,@message)
    waitcnt (clkfreq * 1 + cnt)
    gsm.str(string("AT+CMGD=1")) 'Delete message in first memory
    gsm.tx(13)
    waitcnt (clkfreq * 1 + cnt)
    debug.newline
    debug.str(@mess1)
    debug.newline
    debug.str(@mess2)
    debug.newline
    debug.str(@mess3)
    debug.newline
    debug.str(@phonenumber)
    debug.newline
    debug.str(@mess5)
    debug.newline
    debug.str(@mess6)
    debug.newline
    debug.str(@mess7)
    debug.newline
    debug.str(@message)


    if strcomp (@message, string("on"))
    on2
    elseif strcomp (@message, string("off"))
    off2




    debug.str(string("no message, repeat"))
    debug.newline



    pub on2


    debug.str(string("Output2 on"))
    outa[2] :=1
    waitcnt (clkfreq * 2 + cnt)
    gsm.str(string("AT+CMGS="))
    'gsm.tx(34) ' send a "
    gsm.str (@phonenumber) 'phonenumber
    'gsm.tx(34)
    gsm.tx(13) ' CR
    waitcnt (clkfreq * 2 + cnt)
    gsm.str (string("Output on"))
    waitcnt (clkfreq * 4 + cnt)
    gsm.tx(26)

    return



    pub off2


    debug.str(string("Output2 off"))
    outa[2] :=0
    waitcnt (clkfreq * 2 + cnt)
    gsm.str(string("AT+CMGS="))
    'gsm.tx(34) ' send a "
    gsm.str (@phonenumber) 'phonenumber
    'gsm.tx(34)
    gsm.tx(13) ' CR
    waitcnt (clkfreq * 2 + cnt)
    gsm.str (string("Ouput off"))
    waitcnt (clkfreq * 4 + cnt)
    gsm.tx(26)
    return


    gsm.RxTime(300,@mess1)
    'this is where the issue is--- in full duplex serial im not sure how to write this line, @mess1:=gsm.rxtime(300)
    gsm.RxStrTime(300,@mess2)
    'after timeout then what, will it keep trying to read or start over I do not see a "do on timeout" command
  • homosapienhomosapien Posts: 147
    edited 2014-01-21 15:00
    I am traveling with a linux computer and no prop IDE or tools, so I have no real reference tools at the moment (or any code of the program I wrote several months ago for this application). I've never used Extended_FDSerial, so I am a little unsure of what the gsm.RxTime(300,@mess1) or gsm.RxStrTime(300,@mess2) etc is supposed to do (but I'm guessing wait 300ms for data and store in array at mess1...)

    Using FullDuplexSerial, I simply do stuff like:
    SERIAL.str(@stringToSend)                                                         'to send a string (usually a command)
    waitcnt(clkfreq/10 + cnt)                                                                    'give GPRS device time to respond and full serial buffer, if there is a response
    if  (char := SERIAL.rxCheck) <> -1                                     'to see if serial data has been received 
            'run buffer-reading and parsing loop here                     (if so, 1st char is in 'char', will need to run loop to bring in addtional chars for parsing)
    else
           'no data received....
    


    I would suggest you start simple as possible and use your chosen serial method to send one command. Use PST to observe the command being sent and response, if any. When you are getting a response that you can see and understand, then grow the program to do what you actually want it to do. You will need to actually observe the commands being sent and responses so you can build an intelligent/efficient parser.


    Nate
  • libadmanlibadman Posts: 36
    edited 2014-01-21 17:24
    Thank you, the code you posted sure help me understand more, im unclear on how to store and use variables. I can already FULLY control the gms shield, send commands and waiting on simple responses like "ok" and "error" and act upon the response. I can make it answer a call and even check for a special character. I am unsure how storing multiple variables from the serial port and then save and use them in plain text, Im also have an issue with timeout, if I could get pass the time out I may be able to do what i need, also I notice if I check a variable like "mess1" for the "@" symbol when the code loops "mess1" is still equal to the "@" symbol which mean the code keep going thinking its a command waiting.

    This code works for what I need, I did not take and reuse it, I wrote it, but I cant seem to advance to password checking and command handling



    pub rf | Identifier
    repeat
    SER.RXFLUSH
    attempt to clear rx before looking

    Identifier:=ser.rx
    get dbyte from serial port
    case Identifier


    ":" : i[0]:=(ser.rx)
    if ":" then read 4 bytes
    i[1]:=(ser.rx)
    i[2]:=(ser.rx)
    i[3]:=(ser.rx)


    if i[2]:="S" and i[3]:="M"
    do not need i[0] or i[1]
    tv.str(string("Sms Found",13))
    if last two byte are "s" and "m" then this is a text start reading it

    de
    go here to start reading the text
    quit

    "R" : tv.str(string("ring",13))
    if the byte is "r" than the phone is ringing go to sub and answer it
    'do something with var_2


    pub de |Identifier
    pub to start reading sms
    tv.str(string("Decoding sms",13))
    tell me an sms is getting ready to be read
    ser.Str(STRING("AT + CMGR=1"))
    as to read the message in location 1
    ser.Tx($0D)
    cr to process command

    if i := ser.Rxtime(500) == "@"
    if "@" is there then start looking for a password followed by a command ----need time out help it often will not find "@"
    rf
    if timeout go back home start over after it starts over bytes are still present and presents false read



    i[0]:=(ser.rx)
    here is where i get stuck, the bytes do not read in correctly, I do not know how many bytes are left but I want to read to the end of stream
    i[1]:=(ser.rx)
    i[2]:=(ser.rx)
    i[3]:=(ser.rx)
    i[4]:=(ser.rx)
    i[5]:=(ser.rx)
    i[6]:=(ser.rx)
    i[7]:=(ser.rx)
    i[8]:=(ser.rx)
    i[9]:=(ser.rx)
    i[10]:=(ser.rx)
    i[11]:=(ser.rx)
    i[12]:=(ser.rx)
    i[13]:=(ser.rx)
    i[14]:=(ser.rx)
    i[15]:=(ser.rx)
    i[16]:=(ser.rx)
    i[17]:=(ser.rx)
    i[18]:=(ser.rx)
    i[19]:=(ser.rx)
    i[0]:=(ser.rx)
    i[1]:=(ser.rx)
    i[2]:=(ser.rx)
    i[3]:=(ser.rx)





    tv.out(i[0])
    tv.out(i[1])
    tv.out(i[2])
    tv.out(i[3])
    rf


    I have also tried this

    waitcnt(cnt + (2 * clkfreq))
    this wait gives time for the rx line to clear



    repeat
    loop this


    SER.RXFLUSH
    attempt to clear rx line

    if (i[0]:=ser.Rx) == ":"
    wait for ever until ":" is received but cant wait on anything else like the phone ringing

    tv.str(string(13,"Trigger Found!",13))
    only happens after the ":" is received

    i[0]:=(ser.rx)
    try and read 4 bytes--I do not want it to sit here but cant get timeout to work
    i[1]:=(ser.rx)
    i[2]:=(ser.rx)
    i[3]:=(ser.rx)


    if i[2]:="S" and i[3]:="M"
    check the 4 bytes and see if its an sms
    tv.str(string("SMS Found",13))
    ser.Str(STRING("AT + CMGR=1"))
    if sms found then ask to read the actual text
    ser.Tx($0D)
    rf
    start over
    quit
    stop this pub
    ELSE
    if not "S" and if not "M" then start over waiting
    CH

    So I have somewhat of an idea of what im doing just not sure on storing and entire message or reading an entire UNKOWN stream from serial then check parts of the info to extract certain things



    ch
  • homosapienhomosapien Posts: 147
    edited 2014-01-22 06:29
    If you could wrap your code with the code tags it would make it much easier for me to read and understand your code.
    As I said earlier, I have no propeller IDE on this computer, so cannot really look up any library objects so I am working from memory on what all objects do...


    Questions for you:
    1) It seems that you are looking for a ":", I am unclear on that, as far as I know, the GPRS never sends a ":"?
    2) Also unclear why you are looking or seeing an "@" symbol. The "@" symbol is simply used in SPIN to denote an address in memory
    3) The timeout issue: I do not see why this is an issue. When using the GPRS, if I send it a command, it either responds in less than 1/10 second or never (which only happens if the unit is disconnected or off). This is why in my code I do a "if SERIAL.rxCheck == -1", this tells me if there is communication.

    As to "storing and entire message or reading an entire UNKOWN stream from serial then check parts of the info to extract certain things":

    The serial object already stores the serial input (up to the buffer size). You may or may not want to 're-store' that buffer - I ONLY do this if I need to quickly get the buffer cleared for more serial communications. I rarely need to do this since the GPRS will mostly only send serial data when I request it to. (Note on the buffer size of the FullDuplexSerial - it is 16 bytes, I have extended mine to 256 bytes since some of the GPRS communications can be long and I don't want a buffer overflow, but this is not critical when just starting out).

    Take a look at the methods you are using in your serial object - some wait for serial data, others don't. Also, check to see what will be returned if there is data and what will be returned if there is no data. I know the rxCheck method from FullDulplexSerial returns -1 if no data, else returns the first byte and moves the buffer pointer to the second byte of the serial data buffer.

    As I said earliuer, I would make your program as simple as possible to start, once it is working in a simple manner, then you can expand it to encompass all the features you want - ie, maybe only start out simply detecting a SMS text and display it. Or even just/only display the complete serial communications.


    Nate
  • libadmanlibadman Posts: 36
    edited 2014-01-22 12:38
    Sorry about the code thing..... I was under the assumption you could maybe spot a mistake by simply looking at the code as many do I apologize.

    1) I am NOT using a GPS I am using a GSM shield, you know as in cell phone not global positioning of any kind even tho I could request such information from the shield that is not my needs so looking for ":" or even "+" this can vary as you see in the code im also looking for a "R"

    2) I am looking for the "@" symbol because this is what would define a text of being a regular text or a command text, If the "@" symbol is there try and read the next 5 bytes to act upon the response (i.e 4 digit password the a single command). its being used literally so im not sure but that should have nothing to do with spin because it is encased in quotes which let the propeller know to take it literally not symbolically, I mean if its a big deal I can change it to "*" or other uncommonly used symbol

    3)Things arent perfect, so just in case for WHATEVER reason the response is not as expected or information is missing or invalid I time out to erase the sms and go back to looking for commands, but when code times out there is often data left in the buffer which throws my program off, when using time-out I often do not get the character im waiting on.... Dont worry about this I will ask someone else

    ok fine the buffer keeps 16 bytes---- HOW DO I READ THE BYTES after communication has stop or compare without storing first- I only want to store it so it can be compared.

    Im not sure if you get when I say I can READ just fine its storing and using the values I have an issue with.

    tv.out(ser.rx)
    will allow me to read everything coming into the serial port-- simple

    as you can see in the code above I can already detect an sms, for me its about doing it properly and in a clean coding manner

    I would like to have a variable ("mess") 16 bytes
    and store data to it
    ser.rx(mess,16)
    as in the serial rx line reading in 16 bytes into the variable and then
    allow me to compare whats stored---- if mess[0]= "Y" then do work.... etc but unsure how to do that
    DO YOU KNOW OFF HAND because it seems were going in circles

    I only want to collect data of variable length store it and be able to compare it. ugh

    BTW I DO NOT have a program this is simply snippets I've made to understand and help with final coding-- so its about as simple as can be the issue is the sms is read and acted upon in stages so it seems like a lot of code but not really, what I want to do overall is not simple AT ALL
  • homosapienhomosapien Posts: 147
    edited 2014-01-22 15:22
    I am quite clear you are using a GSM shield, also known as a GPRS shield.

    If you want to read data from the serial buffer to a byte array named mess[16] using the FullDuplexSerial object, you would simply do something like this:
    repeat x from 0 to 16
      mess[x] := SERIAL.rxCheck    
    

    The 'mess' variable array will have the data from the serial buffer. If there is either no data or not a full 16 bytes of data in the buffer, the 'empty' bytes will be saved as $FF.
Sign In or Register to comment.