|
|
View previous topic :: View next topic |
Author |
Message |
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
A6 GSM module initialisation and send/receive an SMS |
Posted: Sun Aug 11, 2019 7:26 pm |
|
|
Hi,
below is a code to initialize an A6 based GSM module. BOOT pin has a FET transistor with drain connected to A6 ground and source to GND to turn the module on or off. At the beginning the code tries to find the baud rate of the module (115.200 by default) and sets it to 57.600. It works much better with that speed, don't know why. Then it sets some parameters: text mode and how incoming messages will be reported to PIC. In this case, GSM reports that the message arrived, but PIC has to ask for the contents. After that, it just checks if it is registered on the network and waits for an incoming message. Whenever a message comes in, the number from which it came is extracted to GSM_NUMBER buffer. If the message says: Status? (case doesn't matter), an SMS is returned to the number this request came from.
What I struggle with is error checking. Init part isn't bullet-proof if something goes wrong. Also errors when sending an SMS aren't 100% sure to be recovered from. I'd be glad if anyone sends me to the right direction. This is intended as a part of a home fire alarm system, and I just cant allow the GSM module to hang the flow of the program for too long.
Anyway, if something unexpected doesn't happen, this works.
The project:
test.c
Code: |
#include <test.h> //fuses, uses
#include <i2c_Flex_LCD_driver.c>
#include <defs.h> //definitions of pins and registers
#include <string.h>
#include <ctype.h>
#include <1Wire.c>
#include <ds1820.c>
#include <stdlib.h>
//***********************************************************************
// includes
//***********************************************************************
#include <functions.c> //all the functions
//*****************WRITE VALUES TO EEPROM WHEN PROGRAMMING PIC*******************
//#if defined (__PCM__)
//#rom 0x2100={30,0,0x58,0x02,0x20,0x1C,50,0,0xEC,0,8,0,50,0,248,0,38,0,0x58,0x02,0,0}
//#elif defined(__PCH__)
#rom int 0xf00000={"+38267600917"} // eeprom start
#rom int 0xf00010={"a38269407581"} // second block of 16 bytes
#rom int 0xf00020={"+38267600917"} // third
#rom int 0xf00030={"b38267600917"} // fourth
//#rom int 0xf00040={"+38267600917"} //
//#rom int 0xf00050={"+38267600917"} //
//#rom int 0xf00060={"+38267600917"} //
//#rom int 0xf00070={"+38267600917"} //
//#rom int 0xf00080={"+38267600917"} //
//#rom int 0xf00090={"+38267600917"} // začetek eeproma
//#define Last_Known_EEprom 0xf000ff
//#rom int8 Last_Known_EEprom = {0xf0} // to store last known good state of relays in EEprom after every change
//-----------------------------------------------------------------------
// end functions
//-----------------------------------------------------------------------
//***********************************************************************
// interrupts
//***********************************************************************
#int_TIMER0 // interrupt every 104ms @ 20MHZ or
void TIMER0_isr(void) {
ResponseTimeout++; // increment GSM response time counter
Second++;
if(Second == 10){
Second = 0;
GO = 1;
}
}
#int_TIMER1 // interrupt every 13ms
void TIMER1_isr(void) {
}
//-----------RS232 data receive ISR------------------------------------------------------------
#int_RDA
void RDA_isr(void){
#include <sms_receive.c>
}
//----------------------------------------------------------------------
// end interrupts
//----------------------------------------------------------------------
//**********************************************************************
// main
//**********************************************************************
void main() {
setup_wdt(WDT_128S);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8); //104 ms overflow @ 20MHz
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //13,1 ms overflow @ 20MHz
Delay_ms(10);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
Not_Initialized = 1;
StartGSM = BOOT_GSM;
lcd_init();
Init_GSM(); // init GSM module
lcd_putc('\f');
delay_ms(30);
enable_interrupts(INT_TIMER0); // enable interrupts
enable_interrupts(INT_TIMER1); // enable interrupts
// Clear_ADDED(); // clear buffers
// Clear_TEMPOR();
// Clear_UART_Buffer();
New_SMS = 0; // prepare for SMS
//---------------------------- END INIT ---------------------------------------
while(true){
if(GO){
GO = 0;
restart_wdt(); // WDT is set to 64s, which should be plenty
Blink_Led(); // inform user that program is running
//-----------------------------------------------------------------------------
//--------------------------- GSM RELATED -------------------------------------
// Possible problems when we come here:
// no communication with the module: No_Comm = 1;
// module not initialized from the beginning: Not_Initialized = 1;
// not registered: Registered_OK = 0;
//-----------------------------------------------------------------------------
switch (GSM_Action){
case _GET_SMS:{ // this case is set in interrupt routine
Blink_CO_Led();
New_SMS = 0;
Get_SMS(); // read SMS from module and set relevant flags, if the message was correct
GSM_Action = _DELETE_SMS;
break;
}
// ............................................................................
case _STATUS:{
Send_Status(); // STATUS requested, send it
GSM_Action = _DELETE_SMS;
break;
}
// ............................................................................
case _DELETE_SMS:{ //
Delay_ms(1000);
GSM_Send(ERASE_SMS); // delete messages
Wait_OK_Response();
if(OK_Response){
GSM_Action = _IDLE;
}
else{
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("DELETE SMS ERROR");
while(1);
}
break;
}
// ............................................................................
case _IDLE:{
if(New_SMS){
New_SMS = 0;
GSM_Action = _GET_SMS;
}
else if(Status_Requested){
Status_Requested = 0;
delay_cycles(1);
GSM_Action = _STATUS;
}
else{
GSM_Action = _COMM;
}
break;
}
// ............................................................................
case _COMM:{
Check_Registration(); // send AT+CREG? and see if GSM is registered on the network
delay_cycles(1); // if it isn't, try to register
lcd_gotoxy(14,4);
if(!Registered_OK){
lcd_putc("R:0");
Not_Connected_Timer++; // wait for 40s to see if the module reconnects
if(Not_Connected_Timer > 10){
Not_Connected_Timer = 10;
Not_Initialized = 1;
Init_GSM();
}
}
else{
delay_cycles(1); // if it isn't, try to register
lcd_putc("R:1");
Not_Connected_Timer = 0;
}
GSM_Action = _IDLE;
break;
}
} // GSM_Action switch brace
}
} // while true
}
|
LCD include is from this forum.
test.h
Code: |
#include <18F4520.h>
#device PASS_STRINGS = IN_RAM //copy all the strings to RAM to allow access with pointers
#device adc=10 //10 bit AD resolution
#device ICD=TRUE
#FUSES DEBUG //No Watch Dog Timer
//#include <stdlib.h>
#FUSES WDT //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 PUT
//#FUSES INTRC
//#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
//#FUSES NOMCLR
#use delay(crystal=20000000) //20Mhz clock
//#use delay(internal=32000000)
#use rs232(parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GSM,errors)
#use i2c(Master,slow,sda=PIN_C4,scl=PIN_C3, force_hw)
//#use pwm(output=pin_c2, timer=2, frequency=1kHz, duty=3)
//#use pwm(output=pin_a4, output=pin_b3, timer=1, frequency=1 kHz, duty=75, disable_level=low)
|
sms_receive.c
Code: |
// Flags set by this state machine are:
// New_SMS = 1; // indicates that we may have received an SMS, result of "+CIEV" unsolicited code from the module
// it can also be something else, but it doesn't matter. Program just checks if there is a new SMS.
// If there is none, it just goes on.
// GSM_ONLINE = 1; // registered to network response, result of "AT+CMGS?" query
// Status_Requested = 1; // status report requested via "Status?" command
// Got_OK = 1;
// GSM_ERROR_Flag = 1;
// ****************************************************************************
tmp=getc(); // get received char and thus also clear interrupt flag
// ............................................................................
// Not really needed, everything is done in the state machine. But nice for debugging.
buffer[next_in]= tmp; // move received char to the appropriate place in buffer
++next_in; // increment IN pointer
if(next_in==BUFFER_SIZE-1) { // 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:
// OK + CR + LF
// ERROR + CR + LF
// +CREG
// "> " arrow-space combo! This is the response from GSM module after you send a " send SMS " command
// ERROR
// +CIEV:
// status? command to receive the status message from GSM
// phone number in format +(country code)(area code)(number), ie +38267999999
// All else is ignored.
switch (gsm_state) {
//wait for initial character 's', 'O','E', '> ' or '+'
case 0:{
// STATUS?
if(tmp == 's' || tmp == 'S'){ //we have "s", could be "status?"
gsm_state = 2; //expecting t
}
// OK
else if(tmp == 'O' || tmp == 'O'){ //we have "O", could be "OK"
gsm_state = 3; //expecting 'K'
}
// ARROW - SPACE COMBO
else if(tmp == '>'){ //have arrow, would be "> "
gsm_state = 4; //expecting space
}
// ERROR
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", phone number or "+CIEV:"
}
// FORGOT WHY THIS IS HERE, MOST LIKELY NOT NEEDED :-)
else if(tmp == '\n'){
delay_cycles(1);
}
else {
gsm_state = 0;
}
break;
}
//******** 'S' WAS THE FIRST CHARACTER, EXPECTING 'STATUS?' ******************
case 2:{ //we have 's', expecting 't'
if(tmp == 't' || tmp == 'T')
gsm_state = 21; //we have "st", expecting 'a'
else
gsm_state = 0; // 'T' hasn't arrived after 'S', reset
break;
}
case 21:{ //we have 'st', expecting 'a'
if(tmp == 'a' || tmp == 'A')
gsm_state = 22; //we have "sta", expecting 't'
else
gsm_state = 0;
break;
}
case 22:{ //we have 'sta', expecting 't'
if(tmp == 't' || tmp == 'T')
gsm_state = 23; //we have "stat", expecting 'u'
else
gsm_state = 0;
break;
}
case 23:{
if(tmp == 'u' || tmp == 'U')
gsm_state = 24; //we have "statu", expecting 's'
else
gsm_state = 0;
break;
}
case 24:{ //we have 'statu', expecting 's'
if(tmp == 's' || tmp == 'S')
gsm_state = 25; //we have "status", expecting '?'
else
gsm_state = 0;
break;
}
case 25:{
if(tmp == '?'){
// ****************************************************************************
Status_Requested = 1; // send status report
// ****************************************************************************
}
gsm_state = 0;
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
// ****************************************************************************
Got_OK = 1; // OK was received from the module
// ****************************************************************************
}
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 for SMS message text
ARROW_SPACE = 1;
}
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 = 0;
//*****************************************
GSM_ERROR_Flag = 1; // GSM returned error
//*****************************************
}
}
// We've received '+', could be +CREG or +CIEV or telephone number
case 6:{
if(tmp == 'C')
gsm_state = 61; // go check if +CREG or +CMGS or +CIEV
// maybe we have a phone number, store it to a GSM_NUMBER buffer
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. 0 is not a valid first number!!!
gsm_state = 69;
Next_Number = 0;
GSM_NUMBER[Next_Number] = '+'; // put '+' into the first location of buffer
Next_Number++;
GSM_NUMBER[Next_Number] = tmp; // put the 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 == 'I'){
gsm_state = 7; // look for +CIEV
}
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') // we have +CREG: so far
gsm_state = 67;
else
gsm_state = 0;
break;
}
case 67:{ // we have +CREG: 0 or +CREG: 1 or +CREG: 2 so far
if(tmp == ',')
gsm_state = 68;
else
gsm_state = 0;
break;
}
// A6 module was sending some interesting answers to AT+CREG? when not registered, like +CREG 0,12 or +CREG 0,13
case 68:{ // we have +CREG: 0, or +CREG: 1, or +CREG: 2, so far
if(tmp == '5'){ // correct answer for roaming, just wait for OK
gsm_state = 681;
}
else if(tmp == '1'){ // correct answer for home network, but
gsm_state = 684; // check if something else than OK is coming. This module has options 12 and 13, apparently. And it isn't registered then.
}
else{
//***************************************
GSM_ONLINE = 0; // only 1 or 5 are good for registration
//***************************************
gsm_state = 0; //just inform we are NOT registered
}
break;
}
case 684:{
if(tmp == '2' || tmp == '3'){ // everything but letter O behind 1 is wrong here. we hope to catch +CREG: 0, 12
gsm_state = 0;
//***************************************
GSM_ONLINE = 0; //*********
//***************************************
}
else if (tmp == 'O')
gsm_state = 682; // we got letter O, proceed to waiting for K
break;
}
//?????
case 681:{
if(tmp != '0'){ // if it isnt "+CREG = 0,we are registered, handle also the OK that is coming from the module after this
gsm_state = 682;
}
else
gsm_state = 0; //reset state machine
break;
}
case 682:{
if(tmp != 'K'){
gsm_state = 682; //???
// ****************************************************************************
GSM_ONLINE = 0; // ***********************************
// ****************************************************************************
}
else{
// ****************************************************************************
GSM_ONLINE = 1; // registered to network
// ****************************************************************************
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')){ // stupid
GSM_NUMBER[Next_Number] = tmp;
Next_Number++;
}
else if(tmp == '"'){
GSM_NUMBER[Next_Number] = '\0'; // got ", write NULL, end of phone number
Next_Number = 0;
gsm_state = 0;
break;
}
else {
Next_Number = 0;
gsm_state = 0;
}
break;
}
// ****************************************************************************
case 7:{ // catch +CIEV, that can indicate new SMS
if(tmp == 'E')
gsm_state = 71;
else
gsm_state = 0;
break;
}
case 71:{
if(tmp == 'V'){ // we have "+CIEV"
gsm_state = 0;
// ****************************************************************************
New_SMS = 1; // indicate to MAIN that we may have an SMS
// ****************************************************************************
delay_cycles(1);
}
else
gsm_state = 0;
break;
}
//*****************************************************************************
//we don't have anything good, ERROR
default:{
gsm_state = 0;
break;
}
} // switch brace
|
Last edited by PrinceNai on Sun Aug 11, 2019 8:02 pm; edited 1 time in total |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
|
Posted: Sun Aug 11, 2019 8:00 pm |
|
|
I don't know, maybe the code is too long but it didn't let me post it whole. So here is the missing part:
functions.c
Code: |
void Blink_Led (void);
void Blink_CO_Led(void);
void Init_GSM (void);
void Get_Baudrate(void);
void Set_Baudrate ();
void Clear_UART_Buffer();
void Wait_OK_Response(void);
void Wait_ONLINE_Response(void);
void Wait_Arrow_Space(void);
void Check_Registration(void);
void GSM_Send(char *s);
unsigned ComposeMessage(char* Message);
// ************************** BLINK OK LED ************************************
void Blink_Led(){
output_low(OK_STATUS);
delay_ms(20);
output_high(OK_STATUS);
}
// ************************** BLINK CO LED ************************************
void Blink_CO_Led(){
output_low(CO_LED);
delay_ms(20);
output_high(CO_LED);
}
//*****************************************************************************
//*****************************************************************************
// GSM module init sequence
// ****************************************************************************
void Init_GSM (void){
int8 i = 0;
int j = 0;
while (Not_Initialized){ // stay here as long as needed. Preset this variable to 1 before coming here
// there are two ways for exiting, either module initializes or it fails for more than 10 times
if(j>2){
break; // if the module fails initialisation more than 10 times, quit for now
} // and let the program continue with measuring
switch (StartGSM) {
// *************************** BOOT *******************************************
case BOOT_GSM:{
output_low (BOOT); // turn the module OFF
delay_ms(2000);
output_high (BOOT); // and back ON
lcd_putc('\f'); // CLEAR lcd
delay_ms(100);
lcd_putc("GSM INIT 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);
i=0;
StartGSM = COMM_SPEED; // next state is setting baudrate to 57.600
break; //
}
// ********************** GET AND SET BAUDRATE ********************************
case COMM_SPEED:{
Get_Baudrate();
Set_Baudrate ();
if(BaudRate == _baud_rate_error_){
StartGSM = BOOT_GSM;
j++; // count GSM errors and resets
break;
}
else{
StartGSM = SEND_AT; // next state is AT
Break;
}
}
// ********************** SEND AT COMMAND ********************************
case SEND_AT:{
lcd_gotoxy(1,1);
lcd_putc("SENDING AT...");
delay_ms(300);
GSM_Send(AT);
Wait_OK_Response();
if(OK_Response){
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
break;
}
else{
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("AT error");
Delay_ms(2000);
StartGSM = BOOT_GSM; // restart GSM
j++; // count GSM errors and resets
break;
}
} // end case
// ************************* SEND ECHO COMMAND ********************************
case SEND_ECHO:{
lcd_gotoxy(1,1);
lcd_putc("SET ECHO ON");
delay_ms(300);
GSM_Send(ATE); //ATE1
Wait_OK_Response();
if(OK_Response){
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("ECHO ON..."); // display success
delay_ms(500);
StartGSM = UNSOLICITED; // next state is SET_GSM
break;
}
else{
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("ECHO error");
Delay_ms(2000);
StartGSM = BOOT_GSM; // restart GSM
j++; // count GSM errors and resets
break;
}
} // end case
// ********************** UNSOLICITED MESSAGES ********************************
case UNSOLICITED:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("UNSOLICITED...");
delay_ms(300);
GSM_Send(STOP_UNSOLICITED); //
if(OK_Response){
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("UNSOLICITED ON..."); // display success
delay_ms(500);
i = 0;
StartGSM = SET_TXT; // next state is SEND_ECHO
break;
}
else{
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("UNSOLICITED error");
Delay_ms(2000);
StartGSM = BOOT_GSM; // restart GSM
j++; // count GSM errors and resets
break;
}
}
// *********************** SET TXT MODE ***************************************
case SET_TXT:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("SET TXT MODE");
delay_ms(300);
GSM_Send(TXT); // Set message type as TXT
Wait_OK_Response();
if(OK_Response){
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("TXT MODE SET..."); // display success
delay_ms(500);
StartGSM = DEL_MSG; // next state is SET_GSM
break;
}
else{
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("TEXT error");
Delay_ms(2000);
StartGSM = BOOT_GSM; // restart GSM
j++; // count GSM errors and resets
break;
}
}
// ************************** DELETE ALL MESSAGES *****************************
case DEL_MSG:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("DELETING MESSAGES");
delay_ms(300);
GSM_Send(ERASE_SMS); // Delete all messages
Wait_OK_Response();
delay_ms(300);
Gsm_Send(READ_SMS);
Wait_OK_Response();
if(OK_Response){
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("MESSAGES DELETED");
delay_ms(500);
StartGSM = CONNECT;
break;
}
else{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("DELETION ERROR");
delay_ms(500);
StartGSM = BOOT_GSM;
break;
}
}
// ************************** CONNECT TO NETWORK *******************************
case CONNECT:{
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("CONNECT...");
delay_ms(300);
GSM_Send(REGISTER_TO_NET); // Set GSM mode
Wait_OK_Response();
if(OK_Response){
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("CONNECTED..."); // display success
delay_ms(500);
StartGSM = WAIT_CELL; // next state is SEND_ECHO
break;
}
else{
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("CONNECTION error");
Delay_ms(2000);
StartGSM = BOOT_GSM; // restart GSM
j++; // count GSM errors and resets
break;
}
} // case brace
// ************************* WAIT REGISTRATION ********************************
// the biggest problem can be here, if the module doesn't connect to the
// network
// ****************************************************************************
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);
Check_Registration(); // query module for registration status
if(Registered_OK){
Registered_OK = 0;
lcd_putc('\f'); //CLEAR lcd
lcd_gotoxy(1,1);
lcd_putc("REGISTERED..."); // display success
delay_ms(500);
StartGSM = BOOT_GSM; // next state is SEND_ECHO
Not_Initialized = 0; // module initialized, exit loop
break;
}
else{
// repair this!!!!!!!
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("REGISTRATION error");
Delay_ms(2000);
StartGSM = BOOT_GSM; // restart GSM
j++; // count GSM errors and resets
break;
}
}
} // switch brace
} // while brace
} // function brace
// ****************************************************************************
// ***************************** GET BAUDRATE *********************************
void Get_Baudrate (){
Baud_Rate_State = _115200;
Not_Found = 1;
lcd_putc('\f'); //CLEAR lcd
delay_ms(30);
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("GETTING MODEM SPEED");
// char *ret; // pointer to the first occurance of a substring in a larger string
int8 i = 0;
while(Not_Found){ // repeat until you find the baudrate of the modem
delay_ms(300);
switch(Baud_Rate_State){
// ............................................................................
case _57600:{
set_uart_speed(57600); // set UART to 57.600 and try to get an "OK"
lcd_gotoxy(1,2);
delay_ms(30);
lcd_putc("57.600 baud");
Delay_ms(300);
Clear_UART_Buffer();
while (i<6){
i++;
GSM_Send(AT);
delay_ms(100);
}
i = 0;
GSM_Send(AT);
Wait_OK_Response();
if(OK_Response){
Baud_Rate_State = BaudRateFound;
BaudRate = _57600baud_;
delay_cycles(1);
break;
}
else{
Baud_Rate_State = _115200;
delay_cycles(1);
break;
}
} // case
// .............................................................................
case _115200:{
set_uart_speed(115200); // set UART to 57.600 and try to get an "OK"
lcd_gotoxy(1,2);
delay_ms(30);
lcd_putc("115.200baud");
Delay_ms(300);
while (i<6){
i++;
GSM_Send(AT);
delay_ms(100);
}
i = 0;
GSM_Send(AT);
Wait_OK_Response();
if(OK_Response){
Baud_Rate_State = BaudRateFound;
BaudRate = _115200baud_;
delay_cycles(1);
break;
}
else{
Baud_Rate_State = _57600;
delay_cycles(1);
break;
}
}
// .............................................................................
case _38400:{
}
// .............................................................................
case _19200:{
}
// .............................................................................
case _9600:{
}
// .............................................................................
case BaudRateFound:{
Not_Found = 0;
lcd_putc('\f'); //CLEAR lcd
delay_ms(30);
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("MODEM SPEED FOUND");
delay_ms(30);
lcd_gotoxy(1,2);
delay_ms(30);
if(BaudRate == _57600baud_){
lcd_putc("57.600 baud");
}
if(BaudRate == _115200baud_){
lcd_putc("115.200 baud");
}
Delay_ms(500);
break;
}
// .............................................................................
} //switch brace
} // while brace
} // function brace
// ************************** SET BAUDRATE ************************************
void Set_Baudrate (){
int8 Baudrate_Not_Set = 1;
// We want to set the baudrate to 57600. We came here with the unknown modem's UART speed.
// If it is 57600, everything is OK. If not, first change the speed of the modem
// to 57600 and then also PIC UART speed
// char *ret; // pointer to the first occurance of a substring in a larger string
int8 i = 0;
lcd_putc('\f'); //CLEAR lcd
delay_ms(30);
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("SETTING SPEED");
delay_ms(30);
lcd_gotoxy(1,2);
delay_ms(30);
lcd_putc("57.600 BAUD");
if(BaudRate != _57600baud_){ // if the speed is wrong, set correct one
// Got_OK = 0;
GSM_Send("AT+IPR=57600\r\n");
Wait_OK_Response();
if(!OK_Response){
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("SET IPR ERROR");
while(1);
}
set_uart_speed(57600);
delay_ms(500);
}
while(Baudrate_Not_Set){
i++;
if(i>10){
BaudRate = _baud_rate_error_; // reboot GSM if for 10 consecutive times baud rate can't be set
break;
}
// Got_OK = 0;
GSM_Send(AT);
Wait_OK_Response();
if(OK_Response){
delay_cycles(1);
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
delay_ms(30);
lcd_gotoxy(1,1);
delay_ms(30);
lcd_putc("57.600 BAUD SET");
delay_ms(500);
lcd_putc('\f'); //CLEAR lcd
delay_ms(30);
Baudrate_Not_Set = 0;
}
} // while brace
} // function brace
// ****************************************************************************
//-----------------------------------------------------------------------------
//------------------------ clear UART buffer ----------------------------------
void Clear_UART_Buffer() {
next_in=0;
while (next_in < BUFFER_SIZE){
buffer[next_in] = '\0';
next_in++;
}
next_in=0;
}
//-----------------------------------------------------------------------------
//------------------ 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
}
}
//-----------------------------------------------------------------------------
//-------------------------- Send SMS------------------------------------------
void Send_Msg(char* Msg_To_Send){
SMS_In_Process = 1; // preload for error response
SMS_Sent_OK = 0;
int8 j = 0;
int8 k = 0;
SENDING_SMS = ATCMGS;
while(SMS_In_Process){
switch (SENDING_SMS){
//0
case ATCMGS:{
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("SENDING SMS TO");
delay_ms(30);
lcd_gotoxy(1,2);
printf(lcd_putc,GSM_NUMBER);
delay_ms(500);
fprintf(GSM,"AT+CMGS=\"%s\"\r\n",GSM_NUMBER); // send SEND SMS command to the module
SENDING_SMS = ARROWSPACE;
break;
}
//1
case ARROWSPACE:{
Wait_Arrow_Space(); // wait for "> "
if(ARROW_SPACE){
ARROW_SPACE = 0; // got ARROW_SPACE
lcd_gotoxy(1,3);
lcd_putc("GOT ARROW_SPACE");
Delay_ms(400);
GSM_Send(Msg_To_Send); // write message to the module
SENDING_SMS = CTRLZ;
delay_ms(50);
}
else{
SENDING_SMS = GSM_ERROR_CONDITION; // no arrow-space in 4 seconds, error
}
break;
}
//2
case CTRLZ:{
lcd_gotoxy(1,3);
lcd_putc("CTRL+Z SENT ");
Delay_ms(200);
fputc(0x1A);
SENDING_SMS = SMS_CONFIRMED;
break;
}
// The problems start about here:
//3
case SMS_CONFIRMED:{
Wait_OK_Response(); // GSM should return +CMGS:XXX followed by an OK
if(OK_Response){
SMSCounter++;
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("SMS SENT OK");
delay_ms(500);
delay_cycles(1);
lcd_putc('\f');
delay_ms(10);
lcd_gotoxy(17,4);
printf(lcd_putc,"%4Lu", SMSCounter); // display SMS count
SMS_In_Process = 0; // exit while loop
SMS_Sent_OK = 1; // signal succesfull sending
}
else{
SENDING_SMS = GSM_ERROR_CONDITION; // didn't get "OK", error
}
break;
}
//4
case GSM_ERROR_CONDITION:{
delay_ms(500); //
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("ERROR CONDITION");
delay_ms(500);
GSM_Send(AT); // try to wake up the module with AT
Wait_OK_Response();
if(OK_Response){
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("SECOND TRY");
delay_ms(500);
SENDING_SMS = ATCMGS; // GSM responded to AT, try to send the SMS once more
j++; //
}
if(j == 2){ // after second try, reboot GSM
j = 0;
SENDING_SMS = GSM_REBOOT;
k = 0;
}
break;
}
//5
case GSM_REBOOT:{
restart_wdt(); // give it time for two more tries
k++; // count how many times we came here
Init_GSM();
SENDING_SMS = ATCMGS;
if(k == 2){
SMS_In_Process = 0; // exit while loop
SMS_Sent_OK = 0; // signal unsuccesfull sending
}
break;
}
} // switch
} // while
} // function
// ********************* Wait_Arrow_Space *************************************
// uses ARROW_SPACE flag set in the receive routine
// It is to be used immediately after issuing the command to the module
// in order not to miss the "ARROW_SPACE"
// or set ARROW_SPACE = 0 before issuing the command to the module
void Wait_Arrow_Space(){
int i = 0;
delay_cycles(1);
while (i < 80){ // two ways to exit this loop
i++; // either find "ARROW_SPACE" in four seconds
if(ARROW_SPACE){
break;
}
else{
delay_ms(50); // or timeout
}
if(i >= 80){
ARROW_SPACE = 0; // ARROW_SPACE not received in 4 seconds
}
}
}
// ********************* Wait_OK_Response *************************************
// uses Got_OK flag set in the receive routine
// It is to be used immediately after issuing the command to the module
// in order not to miss the "OK"
// or set Got_OK = 0 before issuing the command to the module
void Wait_OK_Response(){
Got_OK = 0;
OK_Response = 0; // init
OK_Response_Delay = 0;
delay_cycles(1);
while (OK_Response_Delay < 200){ // two ways to exit this loop
OK_Response_Delay++; // either find "OK" in four seconds
if(Got_OK){
Got_OK = 0;
OK_Response = 1; // OK received
break;
}
else{
delay_ms(50); // or timeout
}
if(OK_Response_Delay >= 200){
OK_Response = 0; // OK not received in 4 seconds
}
}
}
// ********************* Wait_Online_Response *********************************
// uses GSM_ONLINE flag set in the receive routine
// It is to be used immediately after issuing the command to the module
// in order not to miss the "+CREG= X,Y"
// or set Got_OK = 0 before issuing the command to the module
void Wait_ONLINE_Response(){
int i = 0;
delay_cycles(1);
while (i < 80){ // two ways to exit this loop
i++; // either find "+CREG: 0,1" in four seconds
if(GSM_ONLINE){ // correct CREG received
GSM_ONLINE = 0;
Registered_OK = 1;
break;
}
else{
delay_ms(50); // or timeout
}
if(i >= 80){
GSM_ONLINE = 0; // +CREG: X,Y not received in 4 seconds
Registered_OK = 0;
}
}
}
// ****************************************************************************
// *********************** CHECK NETWORK STATUS *******************************
void Check_Registration(){
GSM_ONLINE = 0;
GSM_Send(CHECK_REGISTERED);
Wait_ONLINE_Response();
}
// ****************************************************************************
// ******************* READ SMS MESSAGE FROM THE MODULE ***********************
void Get_SMS(){
GSM_Send(READ_SMS); //Read message from location 1
Wait_OK_Response();
if(!OK_Response){
lcd_putc('\f');
lcd_gotoxy(1,1);
lcd_putc("GET SMS ERROR");
while(1);
}
}
//-----------------------------------------------------------------------------
//------ Send status SMS to the cell phone number in GSM_NUMBER ---------------
void Send_Status(){
ComposeMessage(SMS_Message);
Send_Msg(SMS_Message);
status_req = 0;
}
//-----------------------------------------------------------------------------
//----------------------- STATUS MESSAGE --------------------------------------
// Compose Status SMS
unsigned ComposeMessage(char* Message){ // compose status message
SMS_Message[0] = '\0';
// SMS header
strcat(Message, "Info:\n");
// body
strcat(Message, "Success!!!\n");
// SMS footer
strcat(Message, "End Info");
return strlen (Message); // copied from somewhere, but neither needed nor used. It could be a void function.
}
|
|
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 478 Location: Montenegro
|
|
Posted: Tue Aug 13, 2019 6:56 am |
|
|
I just realized that something else is missing:
defs.h
Code: |
//sensor inputs
#define CO_IN PIN_A0
#define PROX_SENS_IN_NPN PIN_D1
#define PROX_SENS_IN_PNP PIN_A3
#define TEMPERATURE_IN PIN_A5
#define SMOKE_IN PIN_A4
#define MQ7_SENSOR 0 // ADC channel 0
#define PWM_SENSE 1 // ADC channel 1
int16 PWM_Sense_Value = 0;
//alarm leds
#define TEMPERATURE_LED PIN_C0
#define CO_LED PIN_C1
#define SMOKE_LED PIN_E2
#define PELLET_LED PIN_E0
#define BOOT PIN_D2
#define OK_STATUS PIN_E1
#define INPUT 1
#define OUTPUT 0
//reverse logic, 0 turns the output on!!!
#define ON 0
#define OFF 1
#define Full 0
#define Empty 1
//#define TemperatureADChannel 0 //AD chanel for temperature sensor
#define COADChannel 0 //AD chanel for CO sensor
#DEFINE SIZE_BUFFER 80 // Serial Buffer Size
#DEFINE NULL '\0' // Easier to type than '\0'
float Temp = 0; //temperature from 1820 in deg. Celsius
int8 Second = 0; //sets a flag GO every second
int8 GO; //starts the execution of the main loop
int16 ResponseTimeout = 0; // gsm module response time timer
//****************GSM***********************************************************
//**************BUFFERS***************************************************************
//char limiter9[] = "*****-* RS232 buffer *";
#define BUFFER_SIZE 64 //create 255 byte large buffer
char buffer[BUFFER_SIZE];
int8 next_in = 0; //max. next_in = BUFFER_SIZE -1 !!!!!
//char limiter1[] = "&&& MESSAGE &&&"; // delimit buffer for easier debugging
#define MESSAGE_SIZE 180
char SMS_Message[MESSAGE_SIZE]; // SMS message buffer
int8 MessageBufferCounter = 0;
//char limiter2[] = "** GSM NUMBER **";
// 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
//char limiter3[] = "%%% TEMPOR %%%";
//char limiter44[] = "%%% TIME %%%";
char END[] = "* END BUFFERS ***";
//************************************************************************************
//
int8 status_req = 0; // Status request variables
#define EEprom_Max 150 // only first 10 chunks of 16 bytes are for GSM numbers (the routine check if nex
// ***************************************************************************
#define BOOT_TIME 15 // time to wait for the module to be ready, in seconds
int8 StartGSM = 1;
int8 Not_Initialized = 1; // indicates that GSM module wasn't initialized yet. preset this variable to 1
enum {BOOT_GSM, SEND_AT, SEND_ECHO, SET_TXT, DEL_MSG, UNSOLICITED, CONNECT, WAIT_CELL,COMM_SPEED}; // state machine variables
int16 SMSCounter; //number of SMS's sent
// Set of AT commands
const char AT[] = "AT\r\n"; // Every AT command starts with "AT". Sinchronise baud rate with modem.
const char ATE[] = "ATE1\r\n"; // enable command echo
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+CMGL=\"REC UNREAD\"\r\n"; // Command for reading messages from inbox
const char STOP_UNSOLICITED[] = "AT+CNMI=0,0,0,0,0\r\n"; //
// AT+CNMI=0,2,0,0,0 DELA, POŠLJE DIREKTNO: +CMT: "+38267600917",,"2019/08/03,16:45:23+02" MESSAGE
//AT+CNMI=0,1,0,0,0 DELA, POŠLJE +CMTI:, MORAŠ VPRAŠAT ZA MESSAGE
const char ERASE_SMS[] = "AT+CMGD=1,4\r\n"; // Erase all messages
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 CHECK_TIME[] = "AT+CCLK?\r\n"; // check time
int16 gsm_state = 0;
#define Max_Response_Time 200
#define Max_No_Response 100 // 10,4s
int8 NotResponding = 0; // timer for GSM response time
#define MaxResponseTime 100 // GSM timeout = MaxResponseTime * 100ms ie 5s
char tmp;
enum {_115200baud_, _57600baud_, _38400baud_, _baud_rate_error_ };
int8 BaudRate = _115200baud_;
enum {_57600, _115200, _38400, _19200, _9600, BaudRateFound };
int8 Baud_Rate_State = _57600;
int8 Not_Found = 1;
int8 Got_OK = 0;
int8 New_SMS = 0;
int8 Status_Requested = 0;
enum {_IDLE, _STATUS, _NUMBER_STATUS, _ADD_NUMBER, _DELETE_NUMBER, _DELETE_SMS, _READ_SMS, _STATUS_TO_ALL, _WRONG_COMMAND_FORMAT, _COMM};
int8 GSM_Action = _IDLE;
int8 OK_Response = 0;
#define NOT_PARENTHESIS 0
#define RECORD 1
signed int Sign = 0;
int8 GSM_ONLINE = 0;
int8 ARROW_SPACE = 0;
enum {ATCMGS, ARROWSPACE, CTRLZ, SMS_CONFIRMED, GSM_ERROR_CONDITION, GSM_REBOOT};
unsigned int8 SENDING_SMS = ATCMGS;
int1 Registered_OK = 0;
int8 Not_Connected_Timer = 0;
#define RESET_BUTTON PIN_B1
enum {WAIT_INFO, COUNT_PARENTHESIS, TIME_INFO};
int8 OK_Response_Delay = 0;
int8 GSM_ERROR_Flag = 0;
int8 SMS_In_Process = 1;
int8 SMS_Sent_OK = 0;
|
|
|
|
|
|
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
|