Problem sending sim800 commands using atmega32

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

Hi, so i've being really struggling to send a simple SMS using the atmega32 MCU and SIM800. Here is my code below,

#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
#include <math.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>
#define BAUD 9600                           // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)

int size = 0;
char rxBuffer[100];
int messageFlag = 0;
char str[100];
int okFlag = 0;
int errorFlag = 0;
void USARTInitialize();
void transmitData(char*s);

int main(void)
{
	_delay_ms(5000);
	sei();
	USARTInitialize();

	sprintf(str,"%s","AT\r"); //Check if modem responds
	transmitData(str);
	while(okFlag==0) //Waits for okFlag to change to one
	{
		if(errorFlag==1) //If error is reported, send "AT" again
		{
			errorFlag=0;
			size=0;
			memset(rxBuffer,0,100);
			sprintf(str,"%s","AT\r");
			transmitData(str);
		}
	}
	okFlag=0;
	size=0;
	memset(rxBuffer,0,100); //Clear buffer

    sprintf(str,"%s","AT+CMGF=1\r"); //Send next command
	transmitData(str);
	while(okFlag==0) //Wait for response
	{
	}
	okFlag=0;
	size=0;
	memset(rxBuffer,0,100);

	sprintf(str,"%s","AT+CMGS=\"0785423217\"\r"); //Send next command
	transmitData(str);
	while(messageFlag==0) //Wait for ">"
	{
	}
	messageFlag=0;
	size=0;
	memset(rxBuffer,0,100);

	sprintf(str,"%s","Hello\32"); //Send SMS
	transmitData(str);

    while (1)
    {
    }
}

void USARTInitialize()
{
	UBRRL = BAUDRATE; //Set baud rate
	UCSRB |= (1<<TXEN)|(1<<RXEN)|(1<<RXCIE); // Enable transmitter, receiver
	UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); //8 bit data
}

void transmitData(char *s)
{
	while (*s)   // Send data till first null (zero) encountered
	{
		while (!( UCSRA & (1<<UDRE))) //Check if USART buffer is empty
		{

		}
		UDR = (*s++); //Send data
	}
}

ISR(USART_RXC_vect) //Recieve interrupt
{
	rxBuffer[size] = UDR; //Get one byte
	if(rxBuffer[size]=='>')
	{
		messageFlag = 1;
	}
	else if(strcmp(rxBuffer,"\r\nOK\r\n")==0) //Check if "OK" is sent by modem
	{
		okFlag = 1;
	}
	else if(strcmp(rxBuffer,"\r\nERROR\r\n")==0) //Check if "ERROR" is sent by modem
	{
		errorFlag = 1;
	}
	else
	{
		size++; //Next bytes position
	}
}

So basically, im trying to do this the right way by waiting for the "OK" command to be sent by the modem before sending the next command. Though, when I test it, the MCU sends "AT" and the modem responds with "OK" just fine. But thats the problem, it just doesnt execute the rest of the code since it's probably stuck in my while loop with the OK flag. Somehow its not finding a match with the rxBuffer and the "OK" command.

 

I read the datasheet for the SIM800 and it says,

"Commands are usually followed by a response that includes."

"<CR><LF><response><CR><LF>", which is what I am checking 

 

Heres the link to the datasheet, its under section 1.4

https://www.elecrow.com/download/SIM800%20Series_AT%20Command%20Manual_V1.09.pdf

 

Does anyone know what I am doing wrong in my code ?, thanks

 

 

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

Sgt123 wrote:
since it's probably stuck in my while loop with the OK flag
Why do you say "probably"? Surely you can find out if that really us where it is "stuck"? If nothing else do something like lighting an LED before it enters:

	while(okFlag==0) //Wait for response
	{
	}

and turn it off when it leaves. Then you will know for definite where it is stuck.

 

It is probably stuck there because:

int okFlag = 0;

*MUST* be

volatile int okFlag = 0;

Also why have you used "int" for this? Surely it is a 0/1 flag that would fit into uint8_t ?

 

In your code you also have this:

#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>

Because of "header guards" it won't matter that you include avr/io.h twice but it's not a good habit!

 

Finally the use of SIM300 and SIM800 with micros has been done for years and tons of good code has been written and shared. Why not use that? In most good solutions they will probably process responses character by character in a state machine rather than waiting for whole strings and doing strcmp()s

 

There's also an argument to say that you should not be doing strcmp()s in the RXC ISR anyway. It would be better to just have it do a generic operation like pushing received bytes (with error status flags) into a ring buffer then have code at a higher layer extract and process those rather than putting all the work into the interrupt handler. Again, good examples of existing code will likely have been constructed to operate this way.

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

clawson wrote:
 Surely you can find out if that really is where it is "stuck"?

 

Of course you can: the ATmega32 has on-chip debug - use it !!

 

 

Also why have you used "int" for this? Surely it is a 0/1 flag that would fit into uint8_t ?

or even  bool.

 

the use of SIM300 and SIM800 with micros has been done for years and tons of good code has been written and shared. Why not use that?

eg, see: http://www.avrfreaks.net/comment...

 

and: http://www.avrfreaks.net/comment...

 

In most good solutions they will probably process responses character by character in a state machine

Indeed - see: http://www.avrfreaks.net/comment... (the first of the above 2 links)

 

 

It would be better to just have it do a generic operation like pushing received bytes (with error status flags) into a ring buffer then have code at a higher layer extract and process those rather than putting all the work into the interrupt handler.

Indeed.

 

 

EDIT.

 

But if you really do want to re-invent this wheel yourself, here are some links on AT commands - including V.250, the ITU standard which formalises the protocol:

 

http://www.avrfreaks.net/comment...

 

 

Last Edited: Fri. Sep 22, 2017 - 01:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the responses,

 

How do I use that "attentive AT/GSM stack" in my code ?. I downloaded it but have no idea how to use it

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

My comments from your semi-related thread a few weeks ago still apply, about the AVR's actual speed and clock source:

theusch wrote:

Show more code, including the USART setup.  Show your connections.

 

What speed is your AVR running at?  Have you proven it is running at that speed?  What is the clock source for your AVR?

 

 

http://www.avrfreaks.net/forum/s...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Sgt123 wrote:
How do I use that "attentive AT/GSM stack" in my code ?. I downloaded it but have no idea how to use it
If it's this:

 

https://github.com/cloudyourcar/...

 

then the most telling line is Line 42 here:

 

https://github.com/cloudyourcar/...

 

It says:

src/example-sim800: src/example-sim800.o src/modem/sim800.o src/modem/common.o src/cellular.o src/at-unix.o src/parser.o

which seems to be saying that example-sim800 is built from:

 

src/example-sim800.c

src/modem/sim800.c

src/modem/common.c

src/cellular.c

src/at-unix.c

src/parser.c

 

The first of those is the "glue" that binds the rest together - that would be replaced with your own code but after that you probably want to use the rest.

 

Looking at at-unix.c (I wondered why it had "unix" in the name) that seems very OS dependent as it is using Posix features like pthreads. So that part of it probably needs to be replaced by something simpler for an AVr micro.

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

Actually, looking at more of the files I think it's only really parser.c that would be "reusable" in a micro environment.