View previous topic :: View next topic |
Author |
Message |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
Receiving TXT messages - SUPERSEDED / OLD |
Posted: Mon May 10, 2010 3:42 pm |
|
|
++++++++++++++++++++++++++++++++++++++++++++++
EDIT:
Please refer from now on to this code:
http://www.ccsinfo.com/forum/viewtopic.php?t=50390
I WILL NOT BE SUPPORTING THIS CODE ANY MORE
++++++++++++++++++++++++++++++++++++++++++++++
Hello, just wanted to offer my 2 cents, its not exactly an efficient code or a pretty one, or the best solution...
All I offer is a working starting point:
This code will prepare a SE T290A cellphone to receive SMS commands to toggle on/off 4 LEDs using a PIC16F877A.
Hope it helps.
Code: |
#if defined(__PCB__)
#include <16f877a.h>
#include <string.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT
#use delay(clock=20000000) //must be 20 MHz
#elif defined(__PCM__)
#include <16f877a.h>
#include <string.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT
#use delay(clock=20000000) //must be 20 MHz
#use rs 232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // serial
void SerialInt(); // USART INT handler
int TEST_AT(); // Test Modem
int SET_MEM(); // Set used memory
int SET_PDU(); // Set PDU mode
int SET_CNMI(); // basically, set to receive alerts of new sms
int SMSALERT(); // waits for the sms alert.
int READ_SMS(); // cleans text message
void DO_CMD(); // does commands - EDIT:28/01/2013 changed to void
int DEL_SMS(); // deletes SMS
int GET_CMD(); // gets command - EDIT:28/01/2013 changed to int
int GET_OK(int Stop_Search); // Just searches for an OK.
volatile int counter_search=0; //counter to traverse the array
volatile int counter_read=0; //counter to fill the array
Volatile int HitCounter=0; // for string comparison
Volatile int Next_CMD=0;
volatile Char Recieve_String[70]; //buffer for incoming data
void main()
{
SET_TRIS_A( 0x00 ); // to avoid floating pins
SET_TRIS_B( 0x00 );
OUTPUT_B(0X00);
SET_TRIS_C( 0x80 );
SET_TRIS_D( 0x00 );
SET_TRIS_E( 0x00 );
enable_interrupts(INT_RDA); // enable RDA interrupts
enable_interrupts(GLOBAL); // enable global ints
output_high(PIN_D1); // blink for circuit 'ON' confirmation
delay_ms(500);
output_low(PIN_D1);
delay_ms(500);
output_high(PIN_D1);
delay_ms(500);
output_low(PIN_D1);
Delay_ms(1000);
while(1)
{
if(TEST_AT())
{
if(SET_MEM())
{
if(SET_PDU())
{
if(SET_CNMI())
{
if(SMSALERT())
{
if(READ_SMS())
{
if(GET_CMD())
{
if(DEL_SMS())
{
DO_CMD();
}
}
else
DEL_SMS();
}
}
}
}
}
}
}
}
int TEST_AT()
{
counter_read=0;
printf("AT"); //send command
putchar(0x0D); //send return ('enter' in hyperterminal)
output_high(PIN_D1);
While(counter_read<=8) //"A T \R \R \N O K \R \N" characters returned by modem
{
}
output_low(PIN_D1);
counter_read=0;
Delay_ms(500); // ignore all remaining characters received
if(GET_OK(0X0A))
Return(1);
else return(0);
}
int SET_MEM()
{
counter_read=0; //reset all counters.
printf("AT+CPMS=\"ME\",\"ME\",\"ME\""); //text part of the command.
putchar(0x0D); // enter
While(counter_read<25) // stay here, ignore first 25 chars
{
}
counter_read=0; // start filling up the array from cero...from here on, keep the incoming text for parsing
while(counter_read<=28) // acquire all pertinent text, I'm only looking for an "OK" but for now I'm keeping all incoming txt.
{ // maybe for future use...
}
counter_read=0;
Delay_ms(500); // ignore all remaining characters received..if any.
if(GET_OK(0X1C))
Return(1);
else return(0);
}
int SET_PDU()
{
counter_read=0;
printf("AT+CMGF=1"); //send command
putchar(0x0D); //send return
While(counter_read<=15) // get all returned text
{
}
counter_read=0;
Delay_ms(500); // ignore all remaining characters recieved
if(GET_OK(0X0E))
Return(1);
else return(0);
}
int SET_CNMI()
{
counter_read=0; //reset all counters.
printf("AT+CNMI=2,1,2,0,0"); //text part of the command.
putchar(0x0D); //send return
While(counter_read<24) // read all data
{
}
counter_read=0;
Delay_ms(500); // ignore all remaining characters recieved..if any.
if(GET_OK(0X17))
Return(1);
else return(0);
}
int SMSALERT()
{
const char StrCMTI[]={"+CMTI"};
counter_read=0;
While(counter_read<=16) // read all data
{
output_high(PIN_D1); // signal ready to receive sms
}
counter_read=0;
Delay_ms(500); // ignore all remaining characters recieved..if any.
output_low(PIN_D1); // off receive ready light.
counter_search=2;
HitCounter=0;
while((HitCounter!=5)&&(counter_search<8))
{
if(Recieve_String[counter_search]==StrCMTI[counter_search-2])
HitCounter++;
counter_search++;
}
if(HitCounter==0x05)
Return(1);
else return(0);
}
int READ_SMS()
{
counter_read=0;
printf("AT+CMGR=1"); // send command, MEMORY LOCATION OF SMS IS ALWAYS ONE, SINCE I DELETE THEM AFTER PROSCESING
putchar(0x0D);
delay_ms(3000); // long [spam] message... so give time, buffer will loop back one time...
// text will be on second fill.
counter_read=0;
if(GET_OK(0X45))
Return(1);
else return(0);
}
int GET_CMD()
{
const char CMD1[8][7]={"Led1 0","Led1 1","Led2 0","Led2 1","Led3 0","Led3 1","Led4 0","Led4 1"};
int offset=0;
int store_counter=0;
counter_search=0;
while((Recieve_String[counter_search]!='!')&&(counter_search<69)) // wait till command indicator is found '!'
{
counter_search++;
}
counter_search=counter_search+1; // increment one to actual first letter of command
store_Counter=counter_search; // store current position for multiple searches
NEXT_CMD=0; // NEXT_CMD keeps track of the command being read, thus used
while((HitCounter!=6)&&(NEXT_CMD<8)) // compare to all commands in list.
{
counter_search=store_Counter; // initialize counter search with stored counter value.
offset=0; // since value of counter is unknown use a separate counter for the const array
HitCounter=0; // counts number of equal letters found.
while((HitCounter!=6)&&(offset<=6)) // keeps the counters in check...to not overshoot. and compares the strings
{
if(Recieve_String[counter_search]==CMD1[NEXT_CMD][offset]) // if letter is found
HitCounter++;
offset++;
counter_search++;
}
if(HitCounter==6) // if 6 chars found...exit..
{
Return(1);
}
NEXT_CMD++; // if increase to search next command.
}
Return(0);
}
Void DO_CMD()
{
if(NEXT_CMD==0)output_low(PIN_B1);
if(NEXT_CMD==1)output_high(PIN_B1);
if(NEXT_CMD==2)output_low(PIN_B2);
if(NEXT_CMD==3)output_high(PIN_B2);
if(NEXT_CMD==4)output_low(PIN_B3);
if(NEXT_CMD==5)output_high(PIN_B3);
if(NEXT_CMD==6)output_low(PIN_B4);
if(NEXT_CMD==7)output_high(PIN_B4);
}
int DEL_SMS()
{
counter_read=0;
printf("AT+CMGD=1"); //send command
putchar(0x0D); //send return
While(counter_read<=15) // get all returned text
{
}
counter_read=0;
Delay_ms(500); // ignore all remaining characters received
if(GET_OK(0X0E))
Return(1);
else return(0);
}
int GET_OK(Stop_Search)
{
counter_search=0;
while((Recieve_String[counter_search]!='O')&&(counter_search<Stop_Search)) //check buffer until an 'O' is found or 10 chars have been checked.
{
counter_search++; //obvious
}
if((Recieve_String[counter_search]=='O')&&(Recieve_String[counter_search+1]=='K')) //check for a 'K' after the 'O'
{
counter_search=0;
Return(1); //function returns true
}
Return(0);
counter_search=0;
}
#INT_RDA
void SerialInt()
{
Recieve_String[counter_read]=getchar();
counter_read++;
if(counter_read==69)counter_read=0;
}
|
I think I commented enough for it to be readable...
Hope it helps.
Gabriel _________________ CCS PCM 5.078 & CCS PCH 5.093
Last edited by Gabriel on Wed May 01, 2013 9:27 pm; edited 4 times in total |
|
|
drx2k
Joined: 31 Mar 2010 Posts: 10
|
Re: Receiving TXT messages |
Posted: Thu May 26, 2011 9:06 am |
|
|
Hi Gabriel! I just want to ask what I should change in the code if want to use commands without using command indicator like '!'
For example, instead of !Led1 1, I will use Led1 1. |
|
|
chitobuknoy18
Joined: 22 Aug 2011 Posts: 1 Location: Phlippines
|
Re: Receiving TXT messages |
Posted: Mon Aug 22, 2011 10:23 am |
|
|
Hi Gabriel, can I ask what is the compiler being used in this program?Because in my MickroC it has many errors. On other hand can I ask you for the schematic of this project? My email is [email protected] _________________ Im newbiez |
|
|
W4GNS
Joined: 28 Sep 2010 Posts: 14 Location: Virginia, USA
|
|
Posted: Mon Aug 22, 2011 11:33 am |
|
|
I'll go out on a limb here and take a *wild* guess that he used the CCS Compiler, since this is the CCS forum, and not the MikroE forums _________________ PCWH 4.14 |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Sat Oct 08, 2011 7:05 am |
|
|
Schematic?
Pic 16F877A with a Max 232 IC+DB9 connector,LM7805 for power.
4 Resistor+LED on Port B1,2,3,4.
.... thats it.
you need the RS232 serial cable for the phone.... you buy it.
and you need to give it 5V on pin 4 on the DB9 connector...( note this code is specifically for the mentioned phone)
....this code althoug it works... does a lot of usless work.
ive got a revised.... simpler...
Harder..
Better..
Faster..
Stronger....
..........[Dance Break].........
versionthat does away with all the *usless* checks...
.... G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Sat Oct 08, 2011 7:45 am |
|
|
@drx2k:
To eliminate the command indicator, you have to modify the GET_CMD() function....
you need to look for a diferent character....
The problem is that if you do not use a start of command indicator, unless all your commands are the same or start with the same letter you wont be able to find them... unless they always land on the same array index number....not with my current method at least....
by eliminating the use of "!" and simply looking for "Led1 1", "L" becomes your start of command indicator....so its the same...
Code: |
int GET_CMD()
{
const char CMD1[8][7]={"Led1 0","Led1 1","Led2 0","Led2 1","Led3 0","Led3 1","Led4 0","Led4 1"};
int offset=0;
int store_counter=0;
counter_search=0;
while((Recieve_String[counter_search]!='L')&&(counter_search<69)) // wait till command indicator is found '!'
{
counter_search++;
}
// counter_search=counter_search+1; // increment one to actual first letter of command
store_Counter=counter_search; // store current position for multiple searches
NEXT_CMD=0; // NEXT_CMD keeps track of the command being read, thus used
while((HitCounter!=6)&&(NEXT_CMD<8)) // compare to all commands in list.
{
counter_search=store_Counter; // initialize counter search with stored counter value.
offset=0; // since value of counter is unknown use a separate counter for the const array
HitCounter=0; // counts number of equal letters found.
while((HitCounter!=6)&&(offset<=6)) // keeps the counters in check...to not overshoot. and compares the strings
{
if(Recieve_String[counter_search]==CMD1[NEXT_CMD][offset]) // if letter is found
HitCounter++;
offset++;
counter_search++;
}
if(HitCounter==6) // if 6 chars found...exit..
{
Return(1);
}
NEXT_CMD++; // if increase to search next command.
}
Return(0);
}
|
i think the above mod to the code does what you want.... i didnt test it.
but remember that GET_CMD() is called after READ_SMS()....
so if there is another "L" somewhere in the Buffer, GET_CMD will "trigger" on this L and not on your command.
..... G _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
vladtess
Joined: 14 May 2011 Posts: 26
|
|
Posted: Tue Oct 11, 2011 8:13 am |
|
|
W4GNS wrote: | I'll go out on a limb here and take a *wild* guess that he used the CCS Compiler, since this is the CCS forum, and not the MikroE forums |
A totally random guess!! :D |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Mar 13, 2012 3:54 pm |
|
|
I recently started playing with an ENFORA 1218 GSM module I was given.
And nothing much changes from module to module. applying what i learned before... and now ill share my experience...
1) The cable connections must be 100% good.
Bear in mind that the PIC will be the "Master" so if your modem is not responding when you use the same cable you use from the PIC to the PC when you connect it from the PIC to the CELL, you probably need to swap the TX/RX lines. I always forget and waste hours debugging software when what I should be checking is my TX/RX lines. 2 GSM projects, 2 times the same problem... sigh.
2) 75% of the errors can be solved by doing "ATE0"... turning of the echo function of the GSM module.
3) Set up your module to be as least verbose as possible using hyperterminal before even thinking of talking to a PIC.
This means setting your phone to print as least information without you asking for it. and SAVE THE SETTINGS... no point in reseting all parameters with the pic every time. (Like I do on the code I posted in this thread... bad).
4) After point 3 your module should only output the +CMTI string... without you even having to send it any commands... as in you power it... and its ready to give you the CMTI string.
5) Using STRING.H saves you a lot of code and loops and errors.
STRSTR() is particularly useful. Remember to NULL terminate your strings.
6) DELAYS...sigh.... Delays are important. The modules are not as fast as your PIC.
When you do AT+CMGR (read sms) the time it takes for the module to output all the information varies... alot.
When you receive the CMTI string, the sms is not ready to be read. DO NOT read the sms immediately after the module tells you its available. Wait one second and you'll be cool.
300ms sounds like a lot ? Try more like 5 seconds.... when testing... you will be "VERY" surprised.
When expecting a response:
The best solution I've found yet is to poll my input buffer until its received 1 (one) character and then give a 300ms delay. Printing the info at 9600 baud takes very little time. However the module takes forever to start printing.
When sending a command I usually wait a bit (100ms) after I send the return character.
If the above does not solve most of your issues.... its your code.
Edit 26-03-2012: i should point out your USART should use a cicular buffer and be interrupt driven. use the hardware USART.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
farazwan
Joined: 26 Apr 2012 Posts: 13
|
|
Posted: Mon Apr 30, 2012 8:13 am |
|
|
hi Gabriel..
i would like to ask why there is an error when i compile your coding? the error is: A numeric expression must appear here. it occur on Code: | if(READ_SMS())
{
if(GET_CMD())
{
if(DEL_SMS())
{
DO_CMD();
}
else {
DEL_SMS();
}
}
} |
|
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu May 10, 2012 12:54 pm |
|
|
well.... i dont see any error.... which leads me to think... that the error although it shows up in that particular section of code its actually an error in a line ethier before or below the shown code....its a common situation.
you probably changed something prior to the shown code.... and you missed ethier a bracket or a semicolon.
check for that...
G. _________________ CCS PCM 5.078 & CCS PCH 5.093
Last edited by Gabriel on Thu May 10, 2012 1:02 pm; edited 1 time in total |
|
|
ebacson
Joined: 27 May 2012 Posts: 1
|
|
Posted: Sun May 27, 2012 10:35 am |
|
|
farazwan wrote: | hi Gabriel..
i would like to ask why there is an error when i compile your coding? the error is: A numeric expression must appear here. it occur on Code: | if(READ_SMS())
{
if(GET_CMD())
{
if(DEL_SMS())
{
DO_CMD();
}
else {
DEL_SMS();
}
}
} |
|
GET_CMD() is function, do not void() |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Jun 25, 2012 8:24 am |
|
|
Yeah... thats true... i dont know how i missed that...
WTF?
GET_CMD() should be int instead of void...
Thanks for picking that up...
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
dasilvarsa
Joined: 17 May 2007 Posts: 5
|
|
Posted: Tue Jul 10, 2012 1:03 pm |
|
|
What is the exact format of the sms that is sent to the module. ?
I've tried
!LED1 1,!LED2 1,!LED3 0,!LED4 1
!LED1 1!LED2 1!LED3 0!LED4 1
neither of these work for me. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Jul 10, 2012 1:45 pm |
|
|
Hi,
What cell module are you using? what do the indicator lights on D1 say?
are you sure the COM connection is working properly?
see code below:
Code: | const char CMD1[8][7]={"Led1 0","Led1 1","Led2 0","Led2 1","Led3 0","Led3 1","Led4 0","Led4 1"}; |
"!Led1 1" <-- turn ON (without ")
"!Led1 0" <-- turn OFF (without ")
"!Led2 1" <-- turn ON (without ")
.... and so on.
its case sensitive!
be advised that when i coded for this _specific_ phone local echo was enabled on the phone... this must be on or the loops will all fail.
EDIT: just to be clear... you only send one "!LEDx x" command per SMS.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
dasilvarsa
Joined: 17 May 2007 Posts: 5
|
|
Posted: Tue Jul 10, 2012 2:18 pm |
|
|
I'm using sim900 development kit.
Comms is good with Max232 both ends
Other Projects work fine so I don't suspect Comms
Local Echo is on
Must i only send 1 command at a time ?
!Led1 1
or can i send multiple commands in the sms ?
Thanks for your help |
|
|
|