Phrase serial string from gsm save and use it, propeller Im going crazy
libadman
Posts: 36
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
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
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
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
Using FullDuplexSerial, I simply do stuff like:
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
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
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
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
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:
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.