View previous topic :: View next topic |
Author |
Message |
Guest
|
Need help to receive string from modem ! |
Posted: Sat Mar 06, 2010 7:05 am |
|
|
Hi, I'm working on an SMS controller project. I want to be able to activate an output if a string from the modem is received.
For example if the modem replies "ok" I want to turn an LED on any time this is received. So far I've tried
strstr
strcmp
and gets
I'm using a PIC 16f876...
ANY IDEAS ? |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Sat Mar 06, 2010 10:14 am |
|
|
you also need to post your compiler version and a small example of your code..
In this case, we'd need to see the code that receives the string and then the code that compares it..
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
Guest
|
|
Posted: Sat Mar 06, 2010 1:33 pm |
|
|
Hi. This is the code I'm trying with. It's not working as I want though.
Code: |
void main() {
char s1[] = ;
char s2[] = "12345";
char ptr;
while(1){
output_low(pin_B6);
output_low(pin_B7);
delay_ms(2000);
gets(s1);
ptr = strstr(s1, s2);
if(ptr)
{
output_high(pin_B7);
break;
}
if(ptr==NULL){
printf("Waiting for string. Press ENT after sending string.");
}
else
{
output_low(pin_B7);
output_high(pin_B6);
}
}
|
The modem returms text messages in PDU format. The last part of the pdu is 12345 for example. Therefore I want to activate output when I recieve 12345.
I'm using CCS C v4.023 |
|
|
Ttelmah Guest
|
|
Posted: Sat Mar 06, 2010 2:08 pm |
|
|
OK.
First problem is s1.
You need to declare this _with enough space to hold the string you are going to receive_. At present, you are declaring it with no size, so when characters are received, these will overwrite the items in memory after this. Something like:
char s1[32];
Allocates 32 characters of storage to s1.
Second problem. ptr. This wants to be declared as a char _pointer_, not as a char. So:
char *ptr;
Third, get rid of the delay. Gets, _waits_ for a line feed to arrive. In your delay, characters _will_ be missed...
Not in what is shown, but make sure that your RS232 declaration, has 'ERRORS' in it.
Then you would normally want to display the 'waiting' message, before calling gets.
Best Wishes |
|
|
Guest
|
|
Posted: Sun Mar 07, 2010 7:29 am |
|
|
Thanks a lot guys. The code works ! ........But I still have a problem
The number of characters to be recieved from the modem is 75 but I am only interested in the last 5. If I set
char s1[75]
char s3[75] my memory (RAM) is overloaded !
How can I ignore the first 60-65 characters ???
Here's my code
void main() {
char s1[12]; // I only want 10-15 here
char s2[] = "12345";
char s3[12]; // I only want 10-15 here
char s4[] = "54321";
char *ptr;
char *ptr2;
puts("AT");
delay_ms(1000);
puts("at+cpms=mt,mt,mt");
delay_ms(1000);
puts("at+csms=1");
delay_ms(1000);
resmsgind:
delay_ms(1000);
puts("at+cnmi=1,2,0,0,1");
goto on;
while(true){
on:
gets(s1); // If more than 12 characters are recieved, output pin 7 goes hi for itself.
ptr = strstr(s1, s2); // It can be turned off with "54321" but it doesn't turn back on.
// gets(s1) buffer is full ?
if(ptr) //
{
output_high(pin_B7);
puts("at+cnmi=1,2,0,0,1");
delay_ms(1000);
goto off;
}
if(ptr==NULL){
printf("Invalid Entry #1"); // s2 did not appear in s1
}
}
while(true){
off:
gets(s3);
ptr2 = strstr(s3, s4);
if(ptr2)
{
output_low(pin_B7);
goto resmsgind;
}
if(ptr2==NULL){
printf("Invalid Entry #2"); // s4 did not appear in s3
}
}
} |
|
|
Sal
Joined: 04 Mar 2010 Posts: 27 Location: Caribbean
|
|
Posted: Tue Mar 09, 2010 4:34 am |
|
|
Can I use a delay like this to limit the characters read from the input stream ?
getch();
delay_ms(25);
gets(string);
Sal |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Tue Mar 09, 2010 6:19 am |
|
|
No you can't use a delay but you can use a loop:-
Code: |
int i;
// Skip the first 60 chars
for (i = 0; i < 60; i++)
{
getc(); // read and ignore char
}
|
|
|
|
Sal
Joined: 04 Mar 2010 Posts: 27 Location: Caribbean
|
|
Posted: Tue Mar 09, 2010 8:05 pm |
|
|
@Wayne_
THANKS A LOT IT WORKS !!! |
|
|
Sal
Joined: 04 Mar 2010 Posts: 27 Location: Caribbean
|
|
Posted: Wed Mar 10, 2010 4:42 am |
|
|
After some testing I now realise I have another issue. What happens if I ignore the 1st 60 characters but too many are entered after.
E.g I want to recieve 12345 after the first 60 characters. But if the string is 12345678, the program freezes or crashes.
I was trying to use fgets() instead of gets() but the program is not compiling.
In the above code I replaced "gets" with
fgets(s1,5,stdin); // I only wanted to read 5 characters...
This is the error
"Stream must be a constant in the valid range"
Any ideas ? or maybe there is another way ?
Thanks again for all your help |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Mar 10, 2010 5:07 am |
|
|
I have just noticed, your code is a bit of a mess in my opinion (before I get slated ), sorry for being so blunt but first of all I like a lot of other C programmers do not like the use of goto's in C. I have never found a reason to use them and they make the code very messy when it doesn't have to be. You may also run in to problems when you come to alter your code later on.
Now some programmers are quite happy to use goto's throughout their code in C and that is upto them but they still would not use them just for the sake of it as you do in your code.
In your code you are jumping into and out of while loops. Whilst this may work in your code (due to the fact that they are infinate while(true) loops) if you changed one of the whiles to have a condition then this would not be checked or initialised before entry into the loop.
If you want to exit a while loop, use the "break" instruction.
I have taken the liberty to re-write the main loop according to my programming style. Just have a look
Code: |
while (true) // main loop
delay_ms(1000);
puts("at+cnmi=1,2,0,0,1");
do {
gets(s1); // If more than 12 characters are recieved, output pin 7 goes hi for itself.
ptr = strstr(s1, s2); // It can be turned off with "54321" but it doesn't turn back on.
// gets(s1) buffer is full ?
if(ptr) //
{
output_high(pin_B7);
puts("at+cnmi=1,2,0,0,1");
delay_ms(1000);
}
else
printf("Invalid Entry #1"); // s2 did not appear in s1
} while (ptr == NULL);
do {
gets(s3);
ptr2 = strstr(s3, s4);
if(ptr2)
output_low(pin_B7);
else
printf("Invalid Entry #2"); // s4 did not appear in s3
} while (ptr2 == NULL);
}
|
I have not tested it so I hope there are no errors.
Sorry if I have come accross a bit high and mighty, and this is a slight diversion from your problem at hand. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Mar 10, 2010 5:20 am |
|
|
Quote: | After some testing I now realise I have another issue. What happens if I ignore the 1st 60 characters but too many are entered after.
E.g I want to recieve 12345 after the first 60 characters. But if the string is 12345678, the program freezes or crashes. | What you are now stumbling upon is the difference between a 'quick and dirty prototype program' and a good program.
Writing a program that handles about 80% of the situations is relative easy. Implementing the last 20%, i.e. handling all the exceptions from the normal situation, is what takes the most time. Sometimes this is called the 80-20 rule: it takes 20% of the time to implement 80% of the functionality, but 80% time is required to implement the last 20% functionality.
Cynical people call it a 90-10 rule, or variations on this.
You have written a program that only reads the last 5 characters out of a stream of 75. Problems arise when the number of received characters is different, and as you have noticed, this will happen.
What you should do is write a routine that examines the received data for a known pattern. On recognition of the pattern you can extract your data.
For more help you'll have to provide more details about your data stream. |
|
|
Sal
Joined: 04 Mar 2010 Posts: 27 Location: Caribbean
|
|
Posted: Wed Mar 10, 2010 7:28 pm |
|
|
@ ckielstra + Wayne_
Constructive criticism is one of the best tools to make a person improve. Thanks for helping...
@ckielstra
As mentioned in the start of the thread I'm doing an SMS project. My data stream is actually a 5 - digit number sent via an SMS message. The modem does not support text mode so what is recieved by the PIC is a long data stream in the form of a PDU message. Although I only want to send "12345" to activate an output, other data is sent in the PDU message such as service number etc. The total length of the string adds up to about 75 characters.
I know the data I'm sending appears as the last part of the PDU stream
e.g If I send "12345"
In PDU this is 0A07xxxxx8xx820xxxxxxxxxxxxxxxxxxxxx0127560690531D98C5603
Thats why I want to ignore all the characters before this string ! |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Mar 11, 2010 4:31 pm |
|
|
If you know the received text is always 5 digits long, then you could read all incoming data and store the data in a 5 byte buffer. On reception of each new byte you shift the data in the buffer 1 position. When you receive a CR character your value is in the buffer.
Instead of shifting the whole buffer you could use a cyclic buffer, this will be faster. |
|
|
|