|
|
View previous topic :: View next topic |
Author |
Message |
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
SIM800L |
Posted: Wed Aug 22, 2018 12:54 pm |
|
|
Dear all,
please find included the code for SIM800L module. The hardware uses PIC18f4520, but could be any other 18F. I2C LCD, the cheapest Chinese SIM800L quad band module (3,5$ or so). The module's boot is controlled by a logic level 30N06L MOSFET, connected source to system GND and drain to module's ground. Please be aware that this is a part of a bigger project, so there are some things floating around in the code that this example doesn't use at all. The Init_GSM() tries to initialise GSM and it uses timeouts to try and recover if any of the INIT stages doesn't go as planned. So it doesn't just hang if the module refuses to collaborate. I still need to extensively test it, but the first 50 or so messages came through without a glitch. Please be aware how you put the SIM into the module. The slanted part is on the OUTSIDE. I lost a day with that. Some parts of the code are copied from another threads here, and a long time ago. I don't really remember from who, but it helped a ton. Thank you all.
As always, any comments are more than welcome.
main.h
Code: |
#include <18F4520.h>
#device PASS_STRINGS = IN_RAM //copy all the strings to RAM to allow access with pointers
#device ICD=TRUE
//#include <stdlib.h>
#device adc=10 //10 bit AD resolution
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc, high power 16MHz-25MHz
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES DEBUG //No Watch Dog Timer
#use delay(clock=20000000) //20Mhz clock
//#use rs232(baud=115200,parity=N,xmit=PIN_C7,rcv=PIN_C6,bits=8,stream=GSM,errors)
#use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GSM,errors)
//#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GSM,errors)
//#use i2c(Master,slow,sda=PIN_C4,scl=PIN_C3,force_sw)
#use i2c(Master,slow,sda=PIN_C4,scl=PIN_C3, force_hw)
|
main.c
Code: |
#include <main.h>
#include <i2c_Flex_LCD_driver.c>
//#include <defs.h> //definitions of pins and registers
#define BUFFER_SIZE 250 //create 250 byte large buffer
char buffer[BUFFER_SIZE];
int8 next_in = 0; //max. next_in = BUFFER_SIZE -1 !!!!!
// buffer to hold phone number read from EEPROM or SMS message. This is the number SMS is sent to.
#define GSM_NUMBER_SIZE 16 // GSM number buffer size
char GSM_NUMBER[GSM_NUMBER_SIZE]; // GSM number buffer
int8 Next_Number = 0; // pointer to the position in buffer
#define OK_STATUS PIN_E1 // blink LED so you know PIC does something
unsigned int8 SMSCounter = 0; //number of SMS's sent
unsigned int8 Second = 0; //sets a flag GO every second
int1 GO; //starts the execution of the main loop
int1 BLINK; //holds the state for the blinking LEDs
int8 gsm_init= 0;
// Set of AT commands
const char AT[] = "AT\r\n"; // Every AT command starts with "AT"
const char ATE[] = "ATE1\r\n"; // enable command echo
const char CFUN[] = "AT+CFUN=1\r\n"; // full phone functionality
const char IPR[] = "AT+IPR=57600\r\n"; // Set COM speed, not used in this program. Change COM settings if you use it
const char TXT[] = "AT+CMGF=1\r\n"; // set TXT messages
const char GSM_MODE[] = "AT+CSCS=\"GSM\"\r\n"; // Set GSM_MODE
const char STORE_SIM[] = "AT+CPMS=\"SM\",\"SM\",\"SM\"\r"; // Store on SIM Card
const char READ_SMS[] = "AT+CMGR=1\r\n"; // Command for reading message from location 1 from inbox
const char ERASE_SMS[] = "AT+CMGD=1,4\r\n"; // Erasing all messages from inbox
const char CHECK_REGISTERED[] = "AT+CREG?\r\n"; // Commant to check cell network registration. result: +CREG: 0,1 or 0,5 for roaming
const char REGISTER_TO_NET[] = "AT+CREG=0\r\n"; // register to the network
const char SEND_SMS[] = "AT+CMGS=\"+1234567890\"\r\n"; // Send SMS
//
// Responses to parse
const int8 GSM_OK = 10;
const int8 GSM_Ready_To_Receive_Message = 11;
const int8 GSM_ERROR = 12;
const int8 GSM_CONN_OK = 14;
const int8 GSM_REGISTERED = 15;
const int8 SMS_SENT = 16;
// State machine control variables
//char gsm_state = 0; // initial state of decoding routine
int16 gsm_state = 0;
char response_received = 0; // 0-no response, 1-response from module
signed int responseID = -1, response = -1, rsp;
#define BOOT_GSM 1 // boot state machine states
#define SEND_AT 2
#define SEND_ECHO 3
#define SET_TXT 4
#define SET_GSM 5
#define SET_ALERT 6
#define SET_STORAGE 7
#define DEL_MSG 8
#define CFUN 9
#define CONNECT 10
#define WAIT_CELL 11
#define GSM_ERROR 12
#define BOOT_TIME 10 // time to wait for the module to be ready, in seconds
int8 StartGSM = 1;
int8 Not_Initialized = 1;
int8 NotResponding = 0; // timer for GSM response time
#define MaxResponseTime 100 // GSM timeout = MaxResponseTime * 100ms ie 10s
char tmp;
int8 SMS_Was_Sent = 0;
#define BOOT PIN_D2 // GSM boot pin. A logic level FET 30N06L (source to system GND, drain to module GND) is used to turn the module ON or OFF
#define GSM_RESET PIN_D0 // sim800l reset pin, not used here. The function would be the same as above.
int8 GSM_Tilt = 0;
int16 Response_Time = 0;
int8 GSM_Doesnt_Respond = 0;
#define Max_Response_Time 200
#define Max_No_Response 200
// clear UART buffer
void Clear_UART_Buffer() { // not neccesary, used to see better and easier what is happening with PICKIT3 because the buffer is empty
next_in=0;
while (next_in < BUFFER_SIZE){
buffer[next_in] = '\0';
next_in++;
}
next_in=0;
}
//-----------------------------------------------------------------------------
//------------------------ GET RESPONSE ---------------------------------------
signed int Get_response() { // Get response from GSM, and return it to the Wait_rsponse function
if (response_received) {
response_received = 0;
return responseID;
}
else
return -1;
}
//------------ WAIT RESPONSE TO COMMAND FROM GSM ------------------------------
void Wait_response(char rspns) { // Wait for GSM response
GSM_Tilt = 0;
Response_Time = 0;
GSM_Doesnt_Respond = 0;
while(1){
delay_ms(30);
if (Get_response() == rspns){ // everything ok, this is the response we wait
GSM_Tilt = 0;
break;
}
else if(Get_response() == GSM_ERROR){ // GSM returned ERROR
GSM_Tilt = 1;
break;
}
else if(Get_response() == GSM_Ready_To_Receive_Message){ // GSM returned '> ' unexpectedlly
GSM_Tilt = 2;
break;
}
else if(Get_response() == -1){ // GSM doesn't answer
GSM_Doesnt_Respond++;
if(GSM_Doesnt_Respond > Max_No_Response){
GSM_Tilt = 3;
break;
}
}
else{ // unknown answer too many times, reset module after 6 seconds
Response_Time++;
if(Response_Time > Max_Response_Time){
GSM_Tilt = 4;
break;
}
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Send command or data to GSM module
void GSM_Send(char *s)
{
// Send command or data string
while(*s) { // as long as you don't encounter NULL
fputc(*s++); // send characters to RS232
}
}
//*******************************************************************************
//*****************************************************************************
// GSM module init sequence
// ****************************************************************************
void Init_GSM (void){
while (Not_Initialized){ // stay here as long as needed. Preset this variable to 1
switch (StartGSM) {
// *************************** BOOT *******************************************
case BOOT_GSM:{
Not_Initialized = 1;
output_low (BOOT); // turn the module OFF
delay_ms(1000);
output_high (BOOT); // and back ON
lcd_putc('\f'); //CLEAR lcd
delay_ms(100);
lcd_putc("BOOTING IN:");
int8 i = 0;
while(i<BOOT_TIME){
i++;
lcd_gotoxy(12,1);
printf(lcd_putc, "%3u", BOOT_TIME-i); // display countdown till BOOT
delay_ms(1000);
}
lcd_putc('\f'); //CLEAR lcd
delay_ms(1000);
StartGSM = SEND_AT; // next state is AT
break;
}
// ********************** SEND AT COMMAND ********************************
case SEND_AT:{
lcd_gotoxy(1,1);
lcd_putc("SENDING AT...");
GSM_Send(AT); // AT
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("AT OK..."); // display success
delay_ms(500);
StartGSM = SEND_ECHO; // next state is SEND_ECHO
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = BOOT_GSM; // boot GSM again if it doesn't even respond to AT
break;
}
else{
break; // try sending AT again after 100ms
}
}
} // end case
// ************************* SEND ECHO COMMAND ********************************
case SEND_ECHO:{
lcd_gotoxy(1,1);
lcd_putc("SET ECHO ON");
GSM_Send(ATE); //ATE0
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("ECHO ON..."); // display success
delay_ms(500);
StartGSM = CFUN; // next state is CFUN
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending ATE1 again after 100ms
}
}
} // end case
// ************************** FULL FUNCTIONALITY ******************************
case CFUN:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("CFUN = 1...");
GSM_Send(CFUN); // Set full function
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("OK..."); // display success
delay_ms(500);
StartGSM = SET_TXT; // next state is SET TXT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CFUN=1 again after 100ms
}
}
}
// ********************* SET TXT MODE *****************************************
case SET_TXT:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SET TXT MODE");
GSM_Send(TXT); // Set message type as TXT
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("TXT MODE SET..."); // display success
delay_ms(500);
StartGSM = SET_GSM; // next state is GSM MODE!!!!!!
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT+CMGF=1 again
break;
}
else{
break; // try sending AT again after 100ms
}
}
}
// *************************** SET GSM MODE ***********************************
case SET_GSM:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SET GSM MODE");
GSM_Send(GSM_MODE); // Set GSM mode
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("GSM MODE SET..."); // display success
delay_ms(500);
StartGSM = SET_STORAGE; // next state is SET ALERT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CSCS="GSM" again after 100ms
}
}
}
// ********************** SET STORAGE TO SIM CARD *****************************
case SET_STORAGE:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SET STORAGE");
GSM_Send(STORE_SIM); // Set GSM mode
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("STORE TO SIM..."); // display success
delay_ms(500);
StartGSM = DEL_MSG; // next state is DEL_MESSAGES
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CPMS="SM","SM","SM" again after 100ms
}
}
}
// ************************** DELETE MESSAGES *********************************
case DEL_MSG:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("DELETE MESSAGES");
GSM_Send(ERASE_SMS); // Delete all messages
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("MESSAGES DELETED..."); // display success
delay_ms(500);
StartGSM = CONNECT; // next state is CONNECT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CMGD=1,4 again after 100ms
}
}
}
// ************************** CONNECT TO NETWORK *********************************
case CONNECT:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("CONNECT...");
GSM_Send(REGISTER_TO_NET); // Set GSM mode
if(Get_response() == GSM_OK){ // GSM returned "OK"
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("OK..."); // display success
delay_ms(500);
StartGSM = WAIT_CELL; // next state is SET ALERT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 5 seconds (50 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CREG=0 again after 100ms
}
}
} // case brace
// ************************* WAIT REGISTRATION ********************************
case WAIT_CELL:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("WAITING CELL");
lcd_gotoxy(1,2);
lcd_putc("REGISTRATION");
lcd_gotoxy(15,2);
printf(lcd_putc,"%u", NotResponding);
GSM_Send(CHECK_REGISTERED); // query module for registration status
if(Get_response() == GSM_REGISTERED){ // GSM returned "GSM_REGISTERED", meaning +CREG: 0,1 or +CREG: 0,5 for roaming
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("REGISTERED..."); // display success
delay_ms(2000);
StartGSM = SEND_AT; // next state is SEND_AT
Not_Initialized = 0; // GSM initialized, exit loop
break;
}
else { // GSM didn't return "GSM_REGISTERED"
delay_ms(200);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't register to network for 20 seconds (100 passes with 200ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CREG? again after 100ms
}
}
}
case GSM_ERROR:{
}
} // switch brace
}
// while brace
} // function brace
// *****************************************************************************
#int_TIMER0 //interrupt every 104ms
void TIMER0_isr(void) {
// EmptyDelay++; //increment Empty wait timer
output_toggle(OK_STATUS);
Second++;
if(Second == 5){
Second = 0;
GO = 1; //set the GO flag every 520ms
BLINK = !BLINK; // toggle alarm led, if any
lcd_gotoxy (13,2);
}
}
//-----------RS232 data recieve ISR------------------------------------------------------------
#int_RDA
void RDA_isr(void){
tmp=getc(); // get received char and thus also clear interrupt flag
buffer[next_in]= tmp; // move received char to the appropriate place in buffer
++next_in; // increment IN pointer
if(next_in==BUFFER_SIZE) { // if we have 32, go back to 0
next_in=0;
};
// Process reception through state machine
//Possible data from GSM module that will be handled is:
// r1on - doesn't matter capital or not ar any mix
// r1off
// r2on
// r2off
// r3on
// r3off
// r4on
// r4off
// OK + CR +LF
// ERROR + CR + LF
// +CREG
// +CMGS
// "< " arrow-space combo! This is the response from GSM module after you send
// AT+CMGS = "some phone number" command and the module is ready for scratch message from MCU
// ERROR
//
// Commands:
// R1OFFR2ON for example, any combination works
// status? command to receive the status from GSM
// ADD: +38267600917 command to add this number to eeprom
// DEL: +38267600917 vommand to remove this number from eeprom
// NUM? command to send out currently stored GSM numbers
//
// Flags set by this state machine are:
//
// status_req = 1; inform MAIN to send status SMS
// numbers_status_req = 1; inform MAIN to send status of the numbers stored in EEPROM, response to NUM?
// Number_To_Store = 1; inform MAIN to store a new number to EEPROM, response to ADD
// Number_To_Delete = 1; inform MAIN to delete a number from EEPROM, response to DEL
switch (gsm_state) {
//get initial character, 'r','s', 'O','E' or '> ','A','D', 'N' or '+'
case 0:{
if(tmp == 'O' || tmp == 'O') //we have "O", could be "OK"
gsm_state = 3; //expecting 'K'
else
if(tmp == '>') //have arrow, vould be "> "
gsm_state = 4; //expecting space
else
if(tmp == 'E')
gsm_state = 5; // we have 'E', could be "ERROR"
else
if(tmp == '+')
gsm_state = 6; // we have '+', could be "+CREG" or "+CMGS" or telephone number
break;
}
//********WE HAVE RECIEVED 'O' AS A FIRST CHARACTER***************************
case 3:{
if(tmp == 'K') //we have 'OK'
gsm_state = 31; //expecting CR + LF
else
gsm_state = 0;
break;
}
case 31:{
if(tmp == 13) //we have OK + CR (binary 13)
gsm_state = 32; //expecting LF (binary 10)
else
gsm_state = 0;
break;
}
case 32:{
if(tmp == 10){ //we have OK + CR +LF, OK response is complete
response_received = 1; //set reception flag
response = GSM_OK;
responseID = response; // indicate OK recieved from modem
}
gsm_state = 0; //reset state machine
break;
}
// We received '>' character, could be "> " that indicates that GSM module is ready to accept message from MCU
case 4:{
if(tmp == ' '){ //we have "> ", module ready
response_received = 1; // set reception flag
response = GSM_Ready_To_Receive_Message; //set response flag
ResponseID = response; //responseID = 2
}
gsm_state = 0;
break;
}
// We received 'E', could be ERROR
case 5:{
if(tmp == 'R')
gsm_state = 51;
else
gsm_state = 0;
break;
}
case 51:{
if(tmp == 'R')
gsm_state = 52;
else
gsm_state = 0;
break;
}
case 52:{
if(tmp == 'O')
gsm_state = 53;
else
gsm_state = 0;
break;
}
case 53:{
if(tmp == 'R')
gsm_state = 54;
else
gsm_state = 0;
break;
}
case 54:{
if(tmp == 13)
gsm_state = 55;
else
gsm_state = 0;
break;
}
case 55:{
if(tmp == 10){
response_received = 1; //set reception flag
response = GSM_ERROR;
responseID = response; // indicate ERROR recieved from modem
}
gsm_state = 0; //reset state machine
break;
}
// We received '+', could be +CREG or +CMGS or telephone number
case 6:{
if(tmp == 'C')
gsm_state = 61;
else if(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'){ // we might have a phone number
gsm_state = 69;
Next_Number = 0;
GSM_NUMBER[Next_Number] = '+'; // put '+' into first location of buffer
Next_Number++;
GSM_NUMBER[Next_Number] = tmp; // put received number into second location of buffer
Next_Number++;
}
else
gsm_state = 0;
break;
}
case 61:{
if(tmp == 'R') // proceed to look for +CREG
gsm_state = 62;
else if(tmp == 'M')
gsm_state = 7; // look for +CMGS
else
gsm_state = 0;
break;
}
case 62:{
if(tmp == 'E')
gsm_state = 63;
else
gsm_state = 0;
break;
}
case 63:{
if(tmp == 'G')
gsm_state = 64;
else
gsm_state = 0;
break;
}
case 64:{
if(tmp == ':')
gsm_state = 65;
else
gsm_state = 0;
break;
}
//////////
case 65:{
if(tmp == ' ')
gsm_state = 66;
else
gsm_state = 0;
break;
}
case 66:{
if(tmp == '0' || tmp == '1' || tmp == '2')
gsm_state = 67;
else
gsm_state = 0;
break;
}
case 67:{
if(tmp == ',')
gsm_state = 68;
else
gsm_state = 0;
break;
}
case 68:{
if(tmp == '1' || tmp == '5'){
response_received = 1; //set reception flag
response = GSM_REGISTERED;
responseID = response; // indicate "+CREG: X,1" recieved from modem
disable_interrupts(INT_RDA); // disable UART receive interrupt for a while because there is also
} // an "OK" coming from GSM after +CREG and it fools the state
// machine into reporting the "OK" answer. Be sure to turn it back on.
//
gsm_state = 0; //reset state machine
break;
}
//****************RECEIVING PHONE NUMBER***************************************
case 69:{
if((tmp != '"')&&(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'|| tmp == '0')){
GSM_NUMBER[Next_Number] = tmp;
Next_Number++;
}
else if(tmp == '"'){
GSM_NUMBER[Next_Number] = '\0'; // terminate the string with NULL
Next_Number = 0;
gsm_state = 0;
break;
}
else {
Next_Number = 0;
gsm_state = 0;
}
break;
}
//*****************************************************************************
//we don't have anything good, ERROR
default:{
gsm_state = 0;
break;
}
} // switch brace
}
// ****************************************************************************
#int_AD
void AD_isr(void){
}
#int_EXT
void EXT_isr(void) {
}
//----------------------------------------------------------------------
// end interrupt
//----------------------------------------------------------------------
void main() {
setup_adc_ports(AN0_TO_AN2); //AN1 to AN2 analog input
setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_4);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8); //104 ms overflow
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //13.1 ms overflow
output_float (BOOT);
output_float(PIN_C4);
output_float(PIN_C3);
lcd_init();
Delay_ms(100);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
output_HIGH (GSM_RESET);
Clear_UART_Buffer();
Init_GSM(); // init module
// ******************** send test message ************************************
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SENDING SMS");
GSM_Send(SEND_SMS); // send a command to send SMS to the module
Wait_response(GSM_Ready_To_Receive_Message); // wait for "> "
delay_ms(200);
fputs("His followers called him Mahasamatman and said he was a god. R. Zelazny, Lord of light");
delay_cycles(1);
Delay_ms(100);
fputc(0x1A); // send CTRL+Z to send the message
Wait_response(GSM_OK);
delay_cycles(1);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SMS SENT. SUCCESS");
while(TRUE){
//TODO: User Code
}
} |
|
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
|
Posted: Sat Aug 25, 2018 8:36 pm |
|
|
Well, 50 or so messages wasn't enough. The first example was very, very buggy. Here is V 2.0, definitely way better. Still some work to do, but better.
main.c
Code: |
#include <main.h>
#include <i2c_Flex_LCD_driver.c>
//#include <defs.h> //definitions of pins and registers
#define BUFFER_SIZE 250 //create 250 byte large buffer
char buffer[BUFFER_SIZE];
int8 next_in = 0; //max. next_in = BUFFER_SIZE -1 !!!!!
// buffer to hold phone number read from EEPROM or SMS message. This is the number SMS is sent to.
#define GSM_NUMBER_SIZE 16 // GSM number buffer size
char GSM_NUMBER[GSM_NUMBER_SIZE]; // GSM number buffer
int8 Next_Number = 0; // pointer to the position in buffer
#define OK_STATUS PIN_E1 // blink LED so you know PIC does something
unsigned int8 SMSCounter = 0; //number of SMS's sent
unsigned int8 Second = 0; //sets a flag GO every second or whatever
int8 SecondOld = 0;
int1 GO; //starts the execution of the main loop
int1 BLINK; //holds the state for the blinking LEDs
int8 gsm_init= 0;
// Set of AT commands
const char AT[] = "AT\r\n"; // Every AT command starts with "AT"
const char ATE[] = "ATE1\r\n"; // enable command echo
const char CFUN[] = "AT+CFUN=1\r\n"; // full phone functionality
const char IPR[] = "AT+IPR=57600\r\n"; // Set COM speed, not used in this program. Change COM settings if you use it
const char TXT[] = "AT+CMGF=1\r\n"; // set TXT messages
const char GSM_MODE[] = "AT+CSCS=\"GSM\"\r\n"; // Set GSM_MODE
const char STORE_SIM[] = "AT+CPMS=\"SM\",\"SM\",\"SM\"\r"; // Store on SIM Card
const char READ_SMS[] = "AT+CMGR=1\r\n"; // Command for reading message from location 1 from inbox
const char ERASE_SMS[] = "AT+CMGD=1,4\r\n"; // Erasing all messages from inbox
const char CHECK_REGISTERED[] = "AT+CREG?\r\n"; // Commant to check cell network registration. result: +CREG: 0,1 or 0,5 for roaming
const char REGISTER_TO_NET[] = "AT+CREG=0\r\n"; // register to the network
const char SEND_SMS[] = "AT+CMGS=\"+38267600917\"\r\n"; // Send SMS
//
// Responses to parse
const int8 GSM_OK = 10;
const int8 GSM_Ready_To_Receive_Message = 11;
const int8 GSM_ERROR = 12;
const int8 GSM_CONN_OK = 14;
const int8 GSM_REGISTERED = 15;
const int8 SMS_SENT = 16;
// State machine control variables
//char gsm_state = 0; // initial state of decoding routine
int16 gsm_state = 0;
char response_received = 0; // 0-no response, 1-response from module
signed int responseID = -1, response = -1;
int8 rspns = 0;
int8 TMP_Response = 0;
#define BOOT_GSM 1 // boot state machine states
#define SEND_AT 2
#define SEND_ECHO 3
#define SET_TXT 4
#define SET_GSM 5
#define SET_ALERT 6
#define SET_STORAGE 7
#define DEL_MSG 8
#define FULL_FUNCTION 9
#define CONNECT 10
#define WAIT_CELL 11
#define GSM_ERROR 12
#define BOOT_TIME 10 // time to wait for the module to be ready, in seconds
int8 StartGSM = 1;
int8 Not_Initialized = 1;
int8 NotResponding = 0; // timer for GSM response time
#define MaxResponseTime 100 // GSM timeout = MaxResponseTime * 100ms ie 10s
char tmp;
int8 SMS_Was_Sent = 0;
#define BOOT PIN_D2 // GSM boot pin. A logic level FET 30N06L (source to system GND, drain to module GND) is used to turn the module ON or OFF
#define GSM_RESET PIN_D0 // sim800l reset pin, not used here. The function would be the same as above.
int8 GSM_Tilt = 0;
int16 Response_Time = 0;
int8 GSM_Doesnt_Respond = 0;
#define Max_Response_Time 200
#define Max_No_Response 200
// ***************************** functions ************************************
void Clear_ResponseID (void){
responseID = -1;
}
// clear UART buffer
void Clear_UART_Buffer() { // not neccesary, used to see better and easier what is happening with PICKIT3 because the buffer is empty
next_in=0;
while (next_in < BUFFER_SIZE){
buffer[next_in] = '\0';
next_in++;
}
next_in=0;
}
//-----------------------------------------------------------------------------
//------------------------ GET RESPONSE ---------------------------------------
signed int Get_Response(){
while (response_received == 0){ // wait for the module to answer
if(SecondOld != Second){
}
} // while
response_received = 0; // GSM responded
return responseID; // report what it answered on UART
}
//------------ WAIT RESPONSE TO COMMAND FROM GSM ------------------------------
void Wait_response(rspns) { // Wait for GSM response
GSM_Tilt = 0;
Response_Time = 0;
GSM_Doesnt_Respond = 0;
Get_response();
TMP_Response = responseID;
while(1){
// delay_ms(30);
if (TMP_Response == rspns){ // everything ok, this is the response we wait
GSM_Tilt = 0;
break;
}
else if(TMP_Response == GSM_ERROR){ // GSM returned ERROR
GSM_Tilt = 1;
break;
}
else if(TMP_Response == -1){ // GSM doesn't answer
GSM_Doesnt_Respond++;
if(GSM_Doesnt_Respond > Max_No_Response){
GSM_Tilt = 3;
break;
}
}
else{ // unknown answer too many times, reset module after 6 seconds
Response_Time++;
if(Response_Time > Max_Response_Time){
GSM_Tilt = 4;
break;
} // if
} // else
} // while
} // function
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Send command or data to GSM module
void GSM_Send(char *s)
{
// Send command or data string
while(*s) { // as long as you don't encounter NULL
fputc(*s++); // send characters to RS232
}
}
//*****************************************************************************
//*****************************************************************************
// GSM module init sequence
// ****************************************************************************
void Init_GSM (void){
while (Not_Initialized){ // stay here as long as needed. Preset this variable to 1 before coming here
switch (StartGSM) {
// *************************** BOOT *******************************************
case BOOT_GSM:{
Not_Initialized = 1;
output_low (BOOT); // turn the module OFF
delay_ms(1000);
output_high (BOOT); // and back ON
lcd_putc('\f'); //CLEAR lcd
delay_ms(100);
lcd_putc("BOOTING IN:");
int8 i = 0;
while(i<BOOT_TIME){
i++;
lcd_gotoxy(12,1);
printf(lcd_putc, "%3u", BOOT_TIME-i); // display countdown till BOOT
delay_ms(1000);
}
lcd_putc('\f'); //CLEAR lcd
delay_ms(1000);
StartGSM = SEND_AT; // next state is AT
break;
}
// ********************** SEND AT COMMAND ********************************
case SEND_AT:{
lcd_gotoxy(1,1);
lcd_putc("SENDING AT...");
GSM_Send(AT); // AT
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("AT OK..."); // display success
delay_ms(500);
StartGSM = SEND_ECHO; // next state is SEND_ECHO
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = BOOT_GSM; // boot GSM again if it doesn't even respond to AT
break;
}
else{
break; // try sending AT again after 100ms
}
}
} // end case
// ************************* SEND ECHO COMMAND ********************************
case SEND_ECHO:{
lcd_gotoxy(1,1);
lcd_putc("SET ECHO ON");
GSM_Send(ATE); //ATE0
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("ECHO ON..."); // display success
delay_ms(500);
StartGSM = FULL_FUNCTION; // next state is CFUN
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending ATE1 again after 100ms
}
}
} // end case
// ************************** FULL FUNCTIONALITY ******************************
case FULL_FUNCTION:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("CFUN = 1...");
GSM_Send(CFUN); // Set full function
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("OK..."); // display success
delay_ms(500);
StartGSM = SET_TXT; // next state is SET TXT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CFUN=1 again after 100ms
}
}
}
// ********************* SET TXT MODE *****************************************
case SET_TXT:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SET TXT MODE");
GSM_Send(TXT); // Set message type as TXT
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("TXT MODE SET..."); // display success
delay_ms(500);
StartGSM = SET_GSM; // next state is GSM MODE!!!!!!
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT+CMGF=1 again
break;
}
else{
break; // try sending AT again after 100ms
}
}
}
// *************************** SET GSM MODE ***********************************
case SET_GSM:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SET GSM MODE");
GSM_Send(GSM_MODE); // Set GSM mode
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("GSM MODE SET..."); // display success
delay_ms(500);
StartGSM = SET_STORAGE; // next state is SET ALERT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CSCS="GSM" again after 100ms
}
}
}
// ********************** SET STORAGE TO SIM CARD *****************************
case SET_STORAGE:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SET STORAGE");
GSM_Send(STORE_SIM); // Set GSM mode
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("STORE TO SIM..."); // display success
delay_ms(500);
StartGSM = DEL_MSG; // next state is DEL_MESSAGES
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CPMS="SM","SM","SM" again after 100ms
}
}
}
// ************************** DELETE MESSAGES *********************************
case DEL_MSG:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("DELETE MESSAGES");
GSM_Send(ERASE_SMS); // Delete all messages
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("MESSAGES DELETED..."); // display success
delay_ms(500);
StartGSM = CONNECT; // next state is CONNECT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CMGD=1,4 again after 100ms
}
}
}
// ************************** CONNECT TO NETWORK *********************************
case CONNECT:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("CONNECT...");
GSM_Send(REGISTER_TO_NET); // Set GSM mode
if(Get_response() == GSM_OK){ // GSM returned "OK"
Clear_ResponseID();
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("OK..."); // display success
delay_ms(500);
StartGSM = WAIT_CELL; // next state is SET ALERT
NotResponding = 0;
break;
}
else { // GSM didn't return "OK"
delay_ms(100);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 5 seconds (50 passes with 100ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CREG=0 again after 100ms
}
}
} // case brace
// ************************* WAIT REGISTRATION ********************************
case WAIT_CELL:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("WAITING CELL");
lcd_gotoxy(1,2);
lcd_putc("REGISTRATION");
lcd_gotoxy(15,2);
printf(lcd_putc,"%u", NotResponding);
GSM_Send(CHECK_REGISTERED); // query module for registration status
if(Get_response() == GSM_REGISTERED){ // GSM returned "GSM_REGISTERED", meaning +CREG: 0,1 or +CREG: 0,5 for roaming
Clear_ResponseID();
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("REGISTERED..."); // display success
delay_ms(2000);
StartGSM = SEND_AT; // next state is SEND_AT
Not_Initialized = 0; // GSM initialized, exit loop
break;
}
else { // GSM didn't return "GSM_REGISTERED"
delay_ms(200);
NotResponding++; //
if(NotResponding > MaxResponseTime){ // GSM didn't register to network for 20 seconds (100 passes with 200ms delay)
NotResponding = 0;
StartGSM = SEND_AT; // send AT again
break;
}
else{
break; // try sending AT+CREG? again after 100ms
}
}
}
case GSM_ERROR:{
}
} // switch brace
}
// while brace
} // function brace
// ************************* END FUNCTIONS ************************************
#int_TIMER0 //interrupt every 104ms
void TIMER0_isr(void) {
// EmptyDelay++; //increment Empty wait timer
output_toggle(OK_STATUS); // blink LED
Second++;
if(Second == 5){ // wrong name :-)
Second = 0;
GO = 1; //set the GO flag every 520ms
BLINK = !BLINK; // toggle alarm led, if any every x*104ms
lcd_gotoxy (13,2);
}
}
//---------------------- RS232 data recieve ISR -------------------------------
#int_RDA
void RDA_isr(void){
tmp=getc(); // get received char and thus also clear interrupt flag
buffer[next_in]= tmp; // move received char to the appropriate place in buffer
++next_in; // increment IN pointer
if(next_in==BUFFER_SIZE) { // if we have 32, go back to 0
next_in=0;
};
// Process received data from GSM through state machine
// Possible data from GSM module that will be handled is:
// r1on - doesn't matter capital or not ar any mix
// r1off
// r2on
// r2off
// r3on
// r3off
// r4on
// r4off
// OK + CR +LF
// ERROR + CR + LF
// +CREG
// +CMGS
// "> " arrow-space combo! This is the response from GSM module after you send
// AT+CMGS = "some phone number" command and the module is ready for scratch message from MCU
// ERROR
//
// Commands:
// R1OFFR2ON for example, any combination works
// status? command to receive the status from GSM
// ADD: +38267600917 command to add this number to eeprom
// DEL: +38267600917 vommand to remove this number from eeprom
// NUM? command to send out currently stored GSM numbers
//
// Flags set by this state machine are:
//
// status_req = 1; inform MAIN to send status SMS
// numbers_status_req = 1; inform MAIN to send status of the numbers stored in EEPROM, response to NUM?
// Number_To_Store = 1; inform MAIN to store a new number to EEPROM, response to ADD
// Number_To_Delete = 1; inform MAIN to delete a number from EEPROM, response to DEL
// response_received = 1; got some kind of a response from GSM
switch (gsm_state) {
//get initial character, 'r','s', 'O','E' or '> ','A','D', 'N' or '+'
case 0:{
if(tmp == 'O' || tmp == 'O') //we have "O", could be "OK"
gsm_state = 3; //expecting 'K'
else
if(tmp == '>') //have arrow, vould be "> "
gsm_state = 4; //expecting space
else
if(tmp == 'E')
gsm_state = 5; // we have 'E', could be "ERROR"
else
if(tmp == '+')
gsm_state = 6; // we have '+', could be "+CREG" or "+CMGS" or telephone number
break;
}
//********WE HAVE RECIEVED 'O' AS A FIRST CHARACTER***************************
case 3:{
if(tmp == 'K') //we have 'OK'
gsm_state = 31; //expecting CR + LF
else
gsm_state = 0;
break;
}
case 31:{
if(tmp == 13) //we have OK + CR (binary 13)
gsm_state = 32; //expecting LF (binary 10)
else
gsm_state = 0;
break;
}
case 32:{
if(tmp == 10){ //we have OK + CR +LF, OK response is complete
response_received = 1; //set reception flag
response = GSM_OK;
responseID = response; // indicate OK recieved from modem
}
gsm_state = 0; //reset state machine
break;
}
// We received '>' character, could be "> " that indicates that GSM module is ready to accept message from MCU
case 4:{
if(tmp == ' '){ //we have "> ", module ready
response_received = 1; // set reception flag
response = GSM_Ready_To_Receive_Message; //set response flag
ResponseID = response; //
}
gsm_state = 0;
break;
}
// We received 'E', could be ERROR
case 5:{
if(tmp == 'R')
gsm_state = 51;
else
gsm_state = 0;
break;
}
case 51:{
if(tmp == 'R')
gsm_state = 52;
else
gsm_state = 0;
break;
}
case 52:{
if(tmp == 'O')
gsm_state = 53;
else
gsm_state = 0;
break;
}
case 53:{
if(tmp == 'R')
gsm_state = 54;
else
gsm_state = 0;
break;
}
case 54:{
if(tmp == 13)
gsm_state = 55;
else
gsm_state = 0;
break;
}
case 55:{
if(tmp == 10){
response_received = 1; //set reception flag
response = GSM_ERROR;
responseID = response; // indicate ERROR recieved from modem
}
gsm_state = 0; //reset state machine
break;
}
// We received '+', could be +CREG or +CMGS or telephone number
case 6:{
if(tmp == 'C')
gsm_state = 61;
else if(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'){ // we might have a phone number
gsm_state = 69;
Next_Number = 0;
GSM_NUMBER[Next_Number] = '+'; // put '+' into first location of buffer
Next_Number++;
GSM_NUMBER[Next_Number] = tmp; // put received number into second location of buffer
Next_Number++;
}
else
gsm_state = 0;
break;
}
case 61:{
if(tmp == 'R') // proceed to look for +CREG
gsm_state = 62;
else if(tmp == 'M')
gsm_state = 7; // look for +CMGS
else
gsm_state = 0;
break;
}
case 62:{
if(tmp == 'E')
gsm_state = 63;
else
gsm_state = 0;
break;
}
case 63:{
if(tmp == 'G')
gsm_state = 64;
else
gsm_state = 0;
break;
}
case 64:{
if(tmp == ':')
gsm_state = 65;
else
gsm_state = 0;
break;
}
//////////
case 65:{
if(tmp == ' ')
gsm_state = 66;
else
gsm_state = 0;
break;
}
case 66:{
if(tmp == '0' || tmp == '1' || tmp == '2')
gsm_state = 67;
else
gsm_state = 0;
break;
}
case 67:{
if(tmp == ',')
gsm_state = 68;
else
gsm_state = 0;
break;
}
case 68:{
if(tmp == '1' || tmp == '5'){ // we are registered, handle also the OK that is comming from the module after this
gsm_state = 681;
}
else //
gsm_state = 0; //reset state machine
break;
}
case 681:{
if(tmp != 'K'){
gsm_state = 681;
}
else{
response_received = 1; //set reception flag
response = GSM_REGISTERED;
responseID = response; // indicate "+CREG: 0,1" or "+CREG: 0,5" recieved from modem, followed by "K" for "OK"
gsm_state = 0; //reset state machine
}
break;
}
//**************** RECEIVING PHONE NUMBER *************************************
case 69:{
if((tmp != '"')&&(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'|| tmp == '0')){
GSM_NUMBER[Next_Number] = tmp;
Next_Number++;
}
else if(tmp == '"'){
GSM_NUMBER[Next_Number] = '\0'; // got NULL, end of string
Next_Number = 0;
gsm_state = 0;
break;
}
else {
Next_Number = 0;
gsm_state = 0;
}
break;
}
// ****************************************************************************
case 7:{ // catch "+CMGS: XXXX" followed by "OK"
if(tmp == 'G') // that tells that an SMS was actually sent
gsm_state = 71;
else
gsm_state = 0;
break;
}
case 71:{
if(tmp == 'S'){
gsm_state = 72;
} //
else
gsm_state = 0;
break;
}
case 72:{
if(tmp == ':'){ // this one is to escape "AT+CMGS=...." command
gsm_state = 73;
} //
else
gsm_state = 0;
break;
}
case 73:{
if(tmp != 'K'){ // hang here until "K" comes as the end of the required sequence
gsm_state = 73;
}
else{
response_received = 1; //set reception flag
response = SMS_SENT;
responseID = response; // indicate "+CMGS: XXXX" recieved from modem, followed by an "OK" XXX is the number of SMS-ses sent
gsm_state = 0;
}
break;
}
//*****************************************************************************
//we don't have anything good, ERROR
default:{
gsm_state = 0;
break;
}
} // switch brace
}
// ****************************************************************************
#int_AD
void AD_isr(void){
}
#int_EXT
void EXT_isr(void) {
}
//----------------------------------------------------------------------
// end interrupt
//----------------------------------------------------------------------
void main() {
setup_adc_ports(AN0_TO_AN2); //AN1 to AN2 analog input
setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_4);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8); //104 ms overflow
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //13.1 ms overflow
output_float (BOOT);
output_float(PIN_C4);
output_float(PIN_C3);
lcd_init();
Delay_ms(100);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
output_HIGH (GSM_RESET);
Clear_UART_Buffer();
Init_GSM(); // init module
while(TRUE){
// ******************** send test message ************************************
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SENDING SMS");
GSM_Send(SEND_SMS); // send a command to send SMS to the module
Delay_ms(10);
delay_cycles(1);
Wait_response(GSM_Ready_To_Receive_Message); // wait for "> "
if(GSM_Tilt == 0){ // everything ok so far
delay_cycles(1);
delay_ms(200);
fputs("His followers called him Mahasamatman and said he was a god. R. Zelazny, Lord of light");
delay_cycles(1);
Delay_ms(100);
fputc(0x1A); // send CTRL+Z to send the message
}
else{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("ready to rec tilt"); // wromg answer from GSM
while(1){
delay_cycles(1); // stay here
}
}
Wait_response(GSM_Ready_To_Receive_Message); // module returns "> " first after message was sent
Wait_response (SMS_SENT); // and then " +CMGS: XX" , followed by "OK"
if(GSM_Tilt == 0){
delay_cycles(1);
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SMS SENT. SUCCESS");
}
else{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("sent tilt"); // wromg answer from GSM
while(1){
delay_cycles(1); // stay here
}
}
Delay_ms(10000); // send an SMS every 10s
}
}
|
|
|
|
jgschmidt
Joined: 03 Dec 2008 Posts: 184 Location: Gresham, OR USA
|
SIM800L Implementation |
Posted: Tue Jul 30, 2019 11:34 am |
|
|
Hi,
Thank you for all your work on this. I'm getting ready to use this on my own project. Have you made any improvements on this since your last posting?
Thanks _________________ Jürgen
www.jgscraft.com |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
|
Posted: Sat Aug 10, 2019 6:35 pm |
|
|
I have abandoned SIM800 module since I found it to be very unreliable. You have to change the firmware to work in Europe and even with that they seem to drop the connection all the time. I moved to an A6 based module (5€), which by my experience works much better. The same project, though. Tweaked for their AT set and their answers. The project works 99% of the time, currently I'm working on error recovery, if the modem looses connection or fails to send an SMS. So yes, there are improvements. On the hardware side, I'm also moving to a different PIC (18f46k22), different battery charger and different step-up regulators, because I need 3 different voltages for this to work. I can send you the code and the schematics for the current thing.
Regards |
|
|
jgschmidt
Joined: 03 Dec 2008 Posts: 184 Location: Gresham, OR USA
|
|
Posted: Mon Aug 12, 2019 11:38 am |
|
|
Thanks for the reply. I did get some code working for my SIM800 module, using ideas from your post and Gabriel's. I haven't run it very long so I don't know about reliability yet. I'm in the US.
I also use the 18F46K22 family for most of my projects and I also have some A6 modules. Agreed, the multiple voltages is a nuisance. Yes, I am interested in the code and schematics.
Cheers. _________________ Jürgen
www.jgscraft.com |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
|
Posted: Mon Aug 12, 2019 9:34 pm |
|
|
The code is in the topics A6 GSM, posted two days ago. Schematics is made in Proteus, if you can open that. Else I'll post images. If you are interested in PCB to avoid breadboard, I can send it to you for the price of postage, along with the specific parts used there (charger, step-up, battery holder and FET. And 4520 PIC, if you need it), so you just plug in USB charger and you are good to go.
Regards,
Samo |
|
|
jgschmidt
Joined: 03 Dec 2008 Posts: 184 Location: Gresham, OR USA
|
|
Posted: Tue Aug 13, 2019 12:40 am |
|
|
Thanks, Samo, I will look at your code in the library. I don't have Proteus, but I would appreciate a picture of your circuit. I don't know if you can post it here but you can send direct to me at jurgen(at)jgscraft.com
Thank you for offer of PCB and parts. Let me know the cost and how to pay you. For me paypal would be easiest. I am in USA.
Kind regards, Jurgen _________________ Jürgen
www.jgscraft.com |
|
|
microjack64
Joined: 10 Apr 2020 Posts: 7
|
working this code in proteus |
Posted: Sun Apr 19, 2020 10:45 am |
|
|
Hi,
Thank you for all your work on this code. I'm getting ready to use in Proteus.
I am working on the same project in Arduino Proteus, but i am trying same code in my project. I also connect rtc in this project. I am intern engineer.
Thanks. _________________ mini engineer at https://projectiot123.com |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|