Error handling in GSM+GPS tracker

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi freaks

I have designed a sms based GSM+GPS tracker using atmega328p + sim808 & by far,it is working as expected from a long time.I have implemented error handling too some extent like for example:

1)if Location fix not available,try consecutive 10 times in 30s interval & then stop the GPS part & initiate a sms to the user.

2)If there is some parsing error from the GPRMC sentence,then initiate the user.

 

But

 

My main concern is how to handle an unexpected error like If i don't get "OK" when issuing even the first AT command/If i don't get desired response regarding any particular AT command used/If the sim808 throws continuous garbage characters?

Should I verify every response from the sim808?How to generally overcome this kind of situation?

Please explain.....

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Usually AT driven devices are driven by a state machine where every action has pass/fail handling. It's up to you in the design how to handle fail and unexpected response scenarios. As use of such devices is so widespread there's tons of existing code to look at and compare to your own approach .

Last Edited: Mon. Aug 27, 2018 - 05:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Max of the codes which I have gone through has no error handling at all.Can you please provide some links which includes error handling?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This code in the link provided was pretty much hectic as it is written using RTOS & for STM32 platform.I am attaching my own code,please take a look if it is going in the right direction.

 

uart.h

 

#ifndef UART_H
#define UART_H

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <string.h>

#define rxbuf_length 256//256 byte buffer

//Global variables
extern volatile uint8_t uart_data;
extern volatile char rxbuf[rxbuf_length];

//uart functions
void uart_enablercv(void);
void uart_disablercv(void);
void uart_init(void);
void uart_send(char data);
void uart_sendstring(char *str);
void uart_resetflags(void);
//int uart_putchar(char c, FILE *stream);
void flush_rxbuf(void);

#endif

 

uart.c

 

#include "uart.h"

volatile uint8_t uart_data;
volatile char rxbuf[rxbuf_length];//buffer for Rx data
volatile uint8_t rxbuf_index = 0;

void uart_init(void)
{
    UCSR0B = (1<<TXEN0)|(1<<RXEN0);
    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
    UBRR0L = 0x67;//UBRRL is 0x67 for 9600 baud @ 16Mhz crystal
}

void uart_enablercv(void)
{
    UCSR0B |=(1<<RXCIE0);//receive interrupt enable
    sei();//Global enable
}

void uart_disablercv(void)
{
    UCSR0B &= ~(1<<RXCIE0);//receive interrupt disable
    cli();//Global disable
}

void uart_send(char data)
{
    while(!(UCSR0A & (1<<UDRE0)));
    UDR0 = data;
}

void uart_sendstring(char *str)
{
    while(*str)
    {
        uart_send(*str++);
    }
}

ISR (USART_RX_vect)
{
    uart_data=UDR0;

    if(rxbuf_index==0)
    {
        rxbuf[rxbuf_index]=uart_data;
        rxbuf_index++;
    }
    else if(rxbuf_index==(rxbuf_length - 1)
    {
        rxbuf[rxbuf_index] = uart_data;
        rxbuf_index = 0;
    }
    else
    {
        rxbuf[rxbuf_index]=uart_data;
        rxbuf_index++;
    }
}

void uart_resetflags(void)
{
    rxbuf_index = 0x00;
    uart_data = 0x00;
}

void flush_rxbuf(void)
{
    memset((char *)rxbuf,0x00,sizeof(rxbuf));
}

sim808.h

/*
 * sim808.h
 *
 * Created: 27-07-2018 00:11:47
 *  Author: Sharanya
 */ 

#ifndef SIM808_H_
#define SIM808_H_

#include <avr/io.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avr/eeprom.h>
#include <ctype.h>
#include "uart.h"

//global variables
extern char lati[15];
extern char longi[15];
extern uint8_t loc_valid;
extern uint8_t new_sms;
extern uint8_t track;
extern uint8_t prev_track;
extern uint8_t loc_valid;

extern char final_str[50];

void delay_s(uint16_t sec);
void rst_all(void);

void sim808_init(void);
void sim808_sendsms(char *str0);
void sim808_delallsms(void);
void sim808_chksms(void);
void sim808_prcssms(void);

//gps commands
void sim808_gpsenbl(void);
void sim808_gpsdisbl(void);
void gps_getloc(void);

#endif /* SIM808_H_ */

sim808.c

/*
 * sim808.c
 *
 * Created: 27-07-2018 00:12:00
 *  Author: Sharanya
 */ 

#include "sim808.h"

char *p_start,*p_end;

//commands send through sms
char config_sim[] = "*sim#";
char track_on[] = "track*on";
char track_off[] = "track*off";
char lock[] = "*lock#";
char unlock[] = "*unlock#";

//sms related reply & variables
char at_smsrcvd[] = "+CPMS:";
uint8_t new_sms = 0x00;

//gps related reply & variables
char gps_locked_rply[] = "Location 3D Fix";
char lati[15];
char longi[15];

uint8_t gps_locked = 0x00;
uint8_t loc_valid = 0x00;

//tracking start or stop variable
uint8_t track = 0x00;
uint8_t prev_track = 0x00;

//sms command related variable
uint8_t new_cmd = 0x00;

//Mobile no related variables & array
char mob_no[11];//array to store mobile no
char bkup_no[11];//array to backup mobile no
uint8_t no_valid = 0x00;//if mobile no is valid,raise this flag.Initially no valid no will be present
uint8_t config_no = 0x00;//if a no change request is received,raise this flag
uint8_t bkup = 0x00;

//Final array to store the coordinates in desired text format to send via sms.
char final_str[50];

//Second delay
void delay_s(uint16_t sec)
{
	while(sec--)//This loop will test the value of sec,decrement it,and then execute the body.
	{
		_delay_ms(1000);//wait for 1 sec
	}
}

//Reset uart buffer & flags
void rst_all(void)
{
	flush_rxbuf();
	uart_resetflags();
}

//sim808_init
void sim808_init(void)
{
	delay_s(30);//1/2 min delay to latch to GSM network
	uart_init();
	_delay_ms(500);
	uart_sendstring("AT\r");//send AT
	_delay_ms(500);
	uart_sendstring("ATE0\r");//stop echo
	_delay_ms(500);
	uart_sendstring("AT+CPMS=\"SM\"\r");//use sim as sms memory
	_delay_ms(500);
	sim808_delallsms();//Delete all previous sms to clear space for new sms

	//Now read the mobile no stored in the EEPROM location 10
	eeprom_read_block((void*)mob_no,(const void*)10,11);
	_delay_ms(100);
	//Check if valid mobile no i.e all the 10 digits belongs to the range between 0 to 9.
	for(uint8_t i=0;i<10;i++)
	{
		if(mob_no[i] >='0' && mob_no[i] <='9')
		{
			no_valid = 0x01;//If valid,raise flag
		}
		else
		{
			no_valid = 0x00;//If no,then clear flag
			break;
		}

	}

}

//send sms
void sim808_sendsms(char *str0)
{
	if(no_valid)
	{
		uart_sendstring("AT+CMGF=1\r");//Text mode selected.
		_delay_ms(500);
		uart_sendstring("AT+CMGS=\"+91");//Add country code
		uart_sendstring(mob_no);
		uart_sendstring("\"\r");
		_delay_ms(100);
		uart_sendstring(str0);
		uart_send(0x1A);//Send CTRL+Z at the end of the SMS to send
		_delay_ms(500);
	}

}

void sim808_delallsms(void)
{
	uart_sendstring("AT+CMGF=1\r");
	_delay_ms(500);
	uart_sendstring("AT+CPMS=\"SM\"\r");//Select SIM memory
	_delay_ms(500);
	uart_sendstring("AT+CMGDA=\"DEL ALL\"\r");//Delete all sms after reading
	_delay_ms(500);

}

//Check new sms
void sim808_chksms(void)
{
	char new_smsarr[3];

	rst_all();//Clear all uart flags & buffer
	uart_enablercv();//enable receiving
	uart_sendstring("AT+CPMS=\"SM\"\r");//Isuue a sms check command
	delay_s(2);//Wait for the reply to arrive into the uart round buffer
	uart_disablercv();//disable further receiving
	//Now retrieve the sms count,the reply from the sim808 should be +CPMS: SMS_NO,TOTAL_CAPACITY
	//now check if the "+CPMS:" string is present in the uart buffer
	if(strstr((char *)rxbuf,at_smsrcvd))
	{
		//match found,now extract the sms count
		p_start = (char *)rxbuf;//(char *) is used before to avoid the warning - "assignment discards 'volatile' qualifier from pointer target type"
		p_end = strchr(p_start,':'); //now find the location containing ':'
		p_start = p_end + 2;//make +1 as the start location of sms received
		p_end = strchr(p_start,',');
		strncpy(new_smsarr,p_start,(p_end - p_start));
		new_smsarr[(p_end - p_start)] = '\0';//insert string terminator
		new_sms = atoi(new_smsarr);
	}

	//If no match found,reset the uart buffer &
	else
	{
		rst_all();//Clear all uart flags & buffer
	}
}

//Now process the sms body
void sim808_prcssms(void)
{
	char buf1[10];

	for(uint8_t i=1;i<=new_sms;i++)
	{
		sprintf(buf1,"%d",i);//convert the current sms location to ASCII
		rst_all();//Clear all flags
		uart_enablercv();//enable receiving
		uart_sendstring("AT+CMGR=");//issue a sms read command
		uart_sendstring(buf1);//from desired location
		uart_sendstring("\r");
		delay_s(2);//wait for the characters to arrive in the uart round buffer
		uart_disablercv();//disable receive

		if(strstr((char *)rxbuf,track_on))
		{
			track = 0x01;//raise the track on flag to start tracking
		}
		else if(strstr((char *)rxbuf,track_off))//(char *) is used before to avoid the warning - "assignment discards 'volatile' qualifier from pointer target type"
		{
			track = 0x00;//clear the track on flag to stop tracking
		}
		else if(strstr((char *)rxbuf,config_sim))//(char *) is used before to avoid the warning - "assignment discards 'volatile' qualifier from pointer target type"
		{
			config_no = 0x01;//new sim number to be configured,raise this flag
		}
	}

	//Now reading done process the desired request
	if(new_sms)
	{
		if((track==0x01)&&(prev_track==0x00))
		{
			prev_track = 0x01;
			sim808_gpsenbl();
			delay_s(1);
		}

		else if((track==0x00)&&(prev_track==0x01))
		{
			prev_track = 0x00;
			sim808_gpsdisbl();
			delay_s(1);
		}

		else if(config_no)
		{
			config_no = 0x00;//clear the new config_no flag.
			//if previous no was valid
			if(no_valid)
			{
				//first,take a backup
				for(uint8_t i=0;i<11;i++)
				{
					bkup_no[i] = mob_no[i];
				}

				bkup = 0x01;//raise a valid backup taken flag
			}

			p_start = (char *)rxbuf;//(char *) is used before to avoid the warning - "assignment discards 'volatile' qualifier from pointer target type"
			p_end = strchr(p_start,'#');
			p_start = p_end + 1;
			p_end = strchr(p_start,'*');

			if((p_end - p_start)==0x0A)
			{
				//now copy the string
				strncpy(mob_no,p_start,(p_end - p_start));
				//Insert string terminator
				mob_no[p_end - p_start] = '\0';
				//now check,if the digits are valid numerical numbers
				for(uint8_t i=0;i<10;i++)
				{
					if(mob_no[i] >='0' && mob_no[i] <='9')
					{
						no_valid = 0x01;//Check every character and raise the valid flag
					}
					else
					{
						no_valid = 0x00;//if anything wrong found,clear the valid flag
						break;
					}

				}
				//now checking done,if a valid no present,update in the eeprom
				if(no_valid)
				{
					eeprom_update_block((const void*)mob_no,(void*)10,11);
					_delay_ms(100);
					delay_s(1);
					//no longer need the backup flag
					bkup = 0x00;
				}
				//if no valid no found & have a good backup
				else if((no_valid==0x00) && (bkup==0x01))
				{
					//restore the backup no to current mobile no
					for(uint8_t i=0;i<11;i++)
					{
						mob_no[i] = bkup_no[i];
						bkup = 0x00;//backup taken,clear this flag.
						no_valid = 0x01;//After backup,having a valid no,raise this flag again.
					}

						delay_s(1);

				}
			}

		}

	}

	//processing done,reset new sms flag & clear everything for uart & delete all sms to free up space.
	new_sms = 0x00;
	rst_all();
	sim808_delallsms();

}

/****************************************************GPS commands******************************************************/

//enable the gps module
void sim808_gpsenbl(void) //Enable the GPS module
{
	uart_sendstring("AT+CGPSPWR=1\r");//Turn on the GPS module
	_delay_ms(500);
	uart_sendstring("AT+CGPSRST=0\r");//Reset the module
	delay_s(60);//Give 1min to settle down the location
}

//disable the gps module
void sim808_gpsdisbl(void)
{
	uart_sendstring("AT+CGPSOUT=0\r");
	_delay_ms(500);
	uart_sendstring("AT+CGPSPWR=0\r");
	_delay_ms(500);
}

//get the gps location
void gps_getloc(void)
{
	float latf,longf;

	latf = 0x00;
	longf = 0x00;

	int firsttwodigits;
	float nexttwodigs;

	char parts[15][20];
	memset(parts,0x00,sizeof (parts[0][0]) * 15 * 20);//Fill parts with 0's

	uint8_t hvalnum,hvpunct,hvcntrl;
	hvalnum = 0x00;//have alphanumeric characters(in this case)
	hvpunct = 0x00;//have punctuation characters(in this case '.')
	hvcntrl = 0x00;//Have control characters(in this case string terminator i.e 0x00)

	for(uint8_t atmpt=0;atmpt<10;atmpt++)//Max No of attempt to check location fix is 10 times
	{
		rst_all(); //reset buffer & uart flags
		uart_enablercv();//receive uart receive
		uart_sendstring("AT+CGPSSTATUS?\r");//query if the location is fixed
		delay_s(2);//Wait for the data to come into the buffer
		uart_disablercv();//disable uart receive

		if(strstr((char *)rxbuf,gps_locked_rply))
		{
			rst_all();//We have got the location fixed,reset all
			gps_locked = 0x01;//Raise the location valid flag
			break;//Now break the for loop
		}

		//If not received,then try 10 times in total
		delay_s(30);//Wait another 30s to fix location
	}

	//Even if after 10 successive attempts,location is still unavailable

	if(gps_locked == 0x00)//If don't get a valid location fix still now
	{
		sim808_sendsms("LocUnavbl");//Alert the user to try after some time
		delay_s(1);
		sim808_gpsdisbl();//disable the gps module
		delay_s(1);
		track = 0x00;
		prev_track = 0x00;//Also clear track & prevtrack to stop gps getloc query as didn't get a valid location after 10 successive attempts.The user must try after some time
	}

	else if(gps_locked)//If valid location fix
	{
		gps_locked = 0x00;//Make location valid flag 0 for next round
		rst_all();//reset all to get incoming location data
		uart_enablercv();//enable receive
		uart_sendstring("AT+CGPSOUT=32\r");//run the command to get the location in GPRMC NMEA sentence
		delay_s(2);//Wait for the data to arrive
		uart_disablercv();//disable receive
		uart_sendstring("AT+CGPSOUT=0\r");//Disable the uart of the gps module

	//Now,parse the lat & long from the GPRMC sentence and store it.

	p_start = (char *)rxbuf;

	//parse the data upto seven ','. The required Lat & Long data is present within the first 7 ','.For ex - $GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68
	for(uint8_t i=0;i<7;i++)
	{
		p_end = strchr(p_start,',');
		if(p_end)
		{
			strncpy(parts[i],p_start,(p_end - p_start));
			parts[i][(p_end - p_start)] = 0;
			p_start = p_end + 1;
		}

		else
		{
			//no valid ',' found,no need to copy,break the for loop.
			break;

		}
	}

	//now check,if valid string is present in array location 3 & 5 regarding lat & long containing alphanumeric characters(0-9),'.' & string terminator
	//if contains all the three characters,then copy

	//First,check location 3
	for(uint8_t i=0;i<20;i++)
	{
		if(isalnum(parts[3][i]))//This will return if characters 0-9 is present
		{
			hvalnum = 0x01;
		}
		else if(ispunct(parts[3][i]))//This will check if character '.' is present
		{
			hvpunct = 0x01;
		}
		else if((parts[3][i])==0x00)//This will check if a string terminator is present
		{
			hvcntrl = 0x01;
		}

	}

	if((hvalnum)&&(hvpunct)&&(hvcntrl))//If all the conditions are true,that means valid string
	{
		memset(lati,0x00,sizeof(lati));//Fill lati with 0's
		strncpy(lati,parts[3],15);//copy upto 15 characters to NMEA latitude variable
		latf = atof(lati);//convert to float value
	}

	//Clear the flags
	hvalnum = 0x00;
	hvpunct = 0x00;
	hvcntrl = 0x00;
	//Now,check location 5
	for(uint8_t i=0;i<20;i++)
	{
		if(isalnum(parts[5][i]))
		{
			hvalnum = 0x01;
		}
		else if(ispunct(parts[5][i]))
		{
			hvpunct = 0x01;
		}
		else if((parts[5][i])==0x00)
		{
			hvcntrl = 0x01;
		}

	}

	if((hvalnum)&&(hvpunct)&&(hvcntrl))//If all the conditions are true,that mean valid string
	{
		memset(longi,0x00,sizeof(longi));//Fill longi with 0's
		strncpy(longi,parts[5],15);//copy upto 15 characters to NMEA latitude variable
		longf = atof(longi);//Convert to float value
	}

	if((latf > 0x00) && (longf > 0x00))//If got some positive values in the latf & longf,then only proceed
	{

		firsttwodigits = ((int)latf/100);
		nexttwodigs = latf - (float)(firsttwodigits * 100);
		latf = (float)(firsttwodigits + nexttwodigs/60.0);
		sprintf(lati,"%7.4f",latf);

		firsttwodigits = ((int)longf/100);
		nexttwodigs = longf - (float)(firsttwodigits * 100);
		longf = (float)(firsttwodigits + nexttwodigs/60.0);
		sprintf(longi,"%7.4f",longf);

		//Now convert everything into one string

		char str0[] = "http://maps.google.com/?q=";
		char str1[] = ",";

		memset(final_str,0x00,sizeof(final_str));//Fill the final array with 0's

		//Now,concatenete all the strings

		strcat(final_str,str0);
		strcat(final_str,lati);
		strcat(final_str,str1);
		strcat(final_str,longi);

		loc_valid = 0x01;//Valid location stored
	}

	else
	{
		loc_valid = 0x00;
	}

	rst_all();//Reset all.

	}
}

main.c

/*
 * Vehicle_tracker_v3.0.c
 *
 * Created: 27-07-2018 00:00:46
 * Author : Sharanya
 */ 

#include <avr/io.h>
#include "sim808.h"

int main(void)
{
    /* Replace with your application code */
	sim808_init();

    while (1)
    {
		sim808_chksms();//Check for new sms

		if(new_sms)//Process only if new sms is received
		{
			sim808_prcssms();
		}

		if((track==0x01)&&(prev_track==0x01))//If both the flags were raised,then a gps enable command already sent to the modem.
		{
			gps_getloc();//get the location
			//Now,if the track & prev_track got cleared during the gps_getloc function,then No valid GPS fix was found.
			//If not,then only proceed.Otherwise,system has already sent sms that GPS fix was not avbl.
			if((track==0x01)&&(prev_track==0x01))//If the flags were not cleared
			{
				//Now check,if a valid location is stored
				if(loc_valid)
				{
					loc_valid = 0x00;//Clear it for next receive
					sim808_sendsms(final_str);//Initiate the user with coordinates
					delay_s(30);//Wait for 30s before sending next sms
				}
				else
				{
					//There was an error during coodinates parsing,initiate the user
					sim808_sendsms("ParseError");
				}
			}

		}

		delay_s(5);//sms checking interval is 5 sec
	}
}

 This is the latest version of my whole code.I was unable to check the GPS part working as my SIMCOM808's gps hardware/antenna got faulty & I had only one module.I ran a live debug session using atmel ICE & everything was OK till the GPS enable part(GPS is not enabling).

 

Last Edited: Mon. Aug 27, 2018 - 07:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

My main concern is how to handle an unexpected error...

???

 

That, clearly, is part of the original design specification.

You should have that figured out before you even start to write any code.

 

You have not stated what the project is, or how "mission critical" the device is, etc.

Surely that will impact how errors are handled.

 

If the tracker is going on a vehicle, and you don't want the vehicle to run without the tracker functioning, then clearly part of the code is to verify that everything is working and then enable the vehicle's ignition.

 

If you don't care if the tracker is running or not, then perhaps put a red "idiot light", (LED indicating system fault), on the dash, and tell the driver to call Tech Support if the light comes on...

 

If you want to give the system a second chance, then have the monitoring circuit cycle power on the system and "try again".

 

Or have the system enable the backup GPS, or the back up SIM, etc...

 

Nobody here knows the mission and goals for your project, so it is impossible to give good advice about how to handle a (partial or complete) system failure.

 

JC 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't see any error handling in there - in fact, you are not even handling responses from the GSM module at all!

 

You just send the AT command, wait an arbitrary delay, and then carry on regardless!!

 

See: https://www.avrfreaks.net/commen...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

I think you need to learn about finite state machines and circular buffers. Clearly, you’ve not spent much time architecting the code - why is higher level code accessing the rx buffer? No checking of the nmea message and so on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for the lack of information.

 

You have not stated what the project is

The project is a vehicle GPS+GSM tracker which will be installed in a Bike/Car in order to trace the location of the same.On the Android side,i have built an app,which will fetch the location from the sms sent from the vehicle & plot on google map.

 

If you want to give the system a second chance, then have the monitoring circuit cycle power on the system and "try again".

The only thing i implemented with the circuit,is a MAX8212 supervisor IC which will cut off the circuit at 11v in order to save the battery from overdischarge.Although,this is not relevant here.But this is FYI...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's the reason I asked you experts so that i can get an Idea about how to do it....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And now you have some ideas!

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes...I will rewrite the whole code taking into account the responses of the modem & repost the code!Also i will implement pwr up/down the modem using the pwerkey pin of the modem to reset it using pin PD4 of the MCU depending on the responses received.

 

Powerkey.jpg

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Almost.

 

The Power Up / Down likely is a control signal.

 

If the module fails, you want to do a full power off, then power on cycle.

 

That will likely require a PFet high side driver for power, or a small relay.

 

Cycling the control signal is not likely going to do a full cold boot on the device.

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Don't be too hasty to power-cycle the modem!

 

eg,

  • if you have no network coverage, then you won't be able to do any cellular comms - and power-cycling the modem won't help!
  • if SMS fails because the SIM storage is full, power-cycling the modem won't help!
  • if you try to send 2 messages too quickly, and the 2nd fails because the modem is busy, you don't want to power-cycle the modem...

 

Check if your module supports AT+CMEE=1 to enable +CME ERROR and +CMS ERROR extended error codes

 

http://www.smssolutions.net/tutorials/gsm/gsmerrorcodes/

 

https://www.developershome.com/sms/resultCodes2.asp

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DocJC wrote:
The Power Up / Down likely is a control signal.

This is true: it tells the module to do an orderly disconnect from the network, and the power is not actually cut until that is complete, and the modem has completed an orderly shutdown.

 

DocJC wrote:
That will likely require a PFet high side driver for power, or a small relay.  

Only do that as an absolute last resort - it can upset the network, and your device can get "blacklisted" if you do it too much!

 

DocJC wrote:
Cycling the control signal is not likely going to do a full cold boot on the device.

No -  it should be a full power-cycle.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Aug 28, 2018 - 07:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My main concern is how to handle an unexpected error like If i don't get "OK" when issuing even the first AT command

So, has the modem actually connected to the network in this case or not?

 

Obviously, handling an error on power up is different than handling an error post connection...

 

JC 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not having a network connection would not affect getting a response to an AT command.

 

In many cases, AT commands do not require any connection to the network.

 

In cases that do require a connection, you would get an ERROR response when there is no connection.

 

Again, with AT+CMEE=1 you would get a specific +CMS ERROR or +CME ERROR with a code indicating the reason.

 

See your modem documentation for details.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Aug 28, 2018 - 09:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using a ready-made module where I can't use a Pfet/relay to cycle power of the sim808.The only thing that i can do is to reset the module using pwrkey.

I have written the initialization sequence(not the whole code with error handling) of the module keeping that into mind.Please take a look...

 

sim808.h

 

#ifndef SIM808_H_
#define SIM808_H_

#define sim808_port PORTD
#define sim808_ddr DDRD
#define sim808_pwrkey 4

#include <avr/io.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avr/eeprom.h>
#include <ctype.h>
#include "uart.h"

//global variables
extern char lati[15];
extern char longi[15];
extern uint8_t loc_valid;
extern uint8_t new_sms;
extern uint8_t track;
extern uint8_t prev_track;
extern uint8_t loc_valid;

extern char final_str[50];

typedef enum
{
	OFF,
	ON,
}pwrstat;

extern pwrstat sim808pwrstat;

typedef enum
{
	NONE,
	INIT_OK,
	SMS_OK
}states;

extern states sim808state;

typedef enum
{
	NO_ERR,
	INIT_ERR,
	SMS_SENDERR
}errors;

extern errors sim808err; 

void delay_s(uint16_t sec);
void rst_all(void);

uint8_t check_str(char *bufptr,char *str1,char *str2);
void sim808_init(void);
void sim808_sendsms(char *str0);
void sim808_delallsms(void);
void sim808_chksms(void);
void sim808_prcssms(void);

//gps commands
void sim808_gpsenbl(void);
void sim808_gpsdisbl(void);
void gps_getloc(void);

#endif /* SIM808_H_ */

 

sim808.c

 

/*
 * sim808.c
 *
 * Created: 27-07-2018 00:12:00
 *  Author: Sharanya
 */ 

#include "sim808.h"

//Error variables
uint8_t err_res = 0x00;
 
char *p_start,*p_end;

//commands send through sms
char config_sim[] = "*sim#";
char track_on[] = "track*on";
char track_off[] = "track*off";
char lock[] = "*lock#";
char unlock[] = "*unlock#";

//sms related reply & variables
char at_smsrcvd[] = "+CPMS:";
uint8_t new_sms = 0x00;

//gps related reply & variables
char gps_locked_rply[] = "Location 3D Fix";
char lati[15];
char longi[15];

uint8_t gps_locked = 0x00;
uint8_t loc_valid = 0x00;

//tracking start or stop variable
uint8_t track = 0x00;
uint8_t prev_track = 0x00;

//sms command related variable
uint8_t new_cmd = 0x00;

//Mobile no related variables & array
char mob_no[11];//array to store mobile no
char bkup_no[11];//array to backup mobile no
uint8_t no_valid = 0x00;//if mobile no is valid,raise this flag.Initially no valid no will be present
uint8_t config_no = 0x00;//if a no change request is received,raise this flag
uint8_t bkup = 0x00;

//Final array to store the coordinates in desired text format to send via sms.
char final_str[50];

//Initialize as the modem is off after power up

pwrstat sim808pwrstat = OFF;
states sim808state = NONE;
errors sim808err = NO_ERR;

typedef enum
{
	IDLE,
	ATOK,
	ATE0OK,
	CMGFOK,
	CPMSOK,
	CMGDAOK,
	CMGSOK
	
}reply;

reply sim808reply = IDLE;

//Second delay 
void delay_s(uint16_t sec)
{
	while(sec--)//This loop will test the value of sec,decrement it,and then execute the body.
	{		
		_delay_ms(1000);//wait for 1 sec
	}
}

//Reset uart buffer & flags
void rst_all(void)
{
	flush_rxbuf();
	uart_resetflags();
}

void sim808_sendcmd(char *str1,char *str2 )//str1 is the command,str2 is the response
{
	uint8_t attempt = 0x05;//max no of tries to send every single command is 5
	
	do
	{
		uart_resetflags();
		flush_rxbuf();
		uart_enablercv();
		uart_sendstring(str1);
		delay_s(1);
		uart_disablercv();
				
	} while (!(strstr((char *)rxbuf,str2)) && (--attempt));//Break this loop if got a valid response or maximum no of try exceeded
	
		
	
	//if max no of attempt exceeded & no proper response received,
	
	if(!(attempt))
	{
		//Check if the receive buffer is empty,if so,then the modem is OFF
		if(strlen((char *)rxbuf)==0x00)
			sim808pwrstat = OFF;
		else//If the receive buffer is not empty
			err_res = 0x01;//Then surely the characters are garbage,raise error response flag
	}
	else
		err_res = 0x00;
		
}


void sim808_pulse(void)
{
	sim808_port |= (1<<sim808_pwrkey);
	delay_s(2);
	sim808_port &= ~(1<<sim808_pwrkey);
}


//sim808_init
void sim808_init(void)
{
	do 
	{
		
		if(sim808pwrstat == OFF)
		{
			err_res = 0x00;//reset error response
			sim808err = NONE;//reset error
			sim808reply = IDLE;//reset the reply state
			
			//Give H-L pulse to On/Off
			sim808_pulse();
			if(sim808pwrstat==OFF)//If the modem was previously off,now it should turn on
				sim808pwrstat = ON;//change the state
			//Now suppose,if got an error response,simply turn off the modem
			else if(sim808pwrstat==ON)//If the modem was on,now it is turned off
				sim808pwrstat = OFF;
				
			delay_s(30);//wait for the module to initialize						
		}
		
		//Now run the init command sequence
		
		switch(sim808reply)
		{		
			case IDLE:
				sim808_sendcmd("AT\r","OK");
				if((!err_res) && (sim808pwrstat == ON))//proceed only if no error received & the modem is powered on
				{	
					sim808reply = ATOK;
					delay_s(1);
				}
				
				break;
			
			case ATOK:
				sim808_sendcmd("ATE0\r","OK");		
				if((!err_res) && (sim808pwrstat == ON))
				{	
					sim808reply = ATE0OK;
					delay_s(1);
				}
				
				break;
				
			case ATE0OK:
				sim808_sendcmd("AT+CMGF=1\r","OK");
				if((!err_res) && (sim808pwrstat == ON))
				{	
					sim808reply = CMGFOK;
					delay_s(1);
				}
				
				break;
		
			case CMGFOK:
				sim808_sendcmd("AT+CPMS=\"SM\"\r","+CPMS:");
				if((!err_res) && (sim808pwrstat == ON))
				{	
					sim808reply = CPMSOK;
					delay_s(1);
				}
				
				break;
		
			case CPMSOK:
				sim808_sendcmd("AT+CMGDA=\"DEL ALL\"\r","OK");
				if((!err_res) && (sim808pwrstat == ON))
				{	
					sim808reply = CMGDAOK;//set the reply to 
					delay_s(1);
				}
				
				break;
				
			case CMGDAOK:
				sim808reply = IDLE;//reset the reply
				sim808state = INIT_OK;//change the state to Init OK	
				
				break;		
				
		}
						
		
	} while ((err_res) || (sim808state != INIT_OK ));//run the loop until error response is 0 or Initialization is OK
	
		
	eeprom_read_block((void*)mob_no,(const void*)10,11);
	_delay_ms(100);
	//Check if we have a valid mobile no i.e all the 10 digits belongs to the range between 0 to 9.
	for(uint8_t i=0;i<10;i++)
	{
		if(isdigit(mob_no[i]))//This will check if the character is an ASCII digit
			no_valid = 0x01;
		else
		{	
			no_valid = 0x00;//If no,then clear flag
			break;
		}
	}
	
	sim808_sendsms("Booting completed");
	
}

 

Last Edited: Wed. Sep 19, 2018 - 07:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have a global error var but all your functions return void. Why do you not return the error status?
All those vars marked extern suggests bad design. Instead of using extern, use an accessor function - like getLastError().

Why do you have code dealing with phone numbers in eeprom in that function? Separate it out. One rule is: one function does one thing properly.