1
\$\begingroup\$

I am writing a C code for receiving battery using GSM modem SIM 800E. I am using AtMega16 uC. Here I have used AT commands to get battery info.

void uart_send(unsigned char ch)     //Function to send via UART
{
    while(!(UCSRA &(1<<UDRE)));
    UDR=ch;
}

void bat()                         //Function to get battery info and send SMS via UART
{   
    int x;
    char battery[16];
    UCSRB &= ~(1<<UDRIE);
    writecommand("AT+CBC");        //AT command to get battery status(My program stuck here)
    for(int x = 0;x<20;x++)        //Reading 20 characters by the response of AT+CBS
    {
        while(!(UCSRA & (1<<RXC)));
        battery[x] = UDR;
    }

    UCSRB |= (1<<RXCIE);

    for(int x=1;x<20;x++)          //sending 20 characters to UART
    {
       uart_send(*battery);
    }
}

int main()
{

    DDRB=0xff;                     //PORT as output port for LCD
    uart_init();                   //initializing UART
    _delay_ms(1000);
    writecommand("AT");
    writecommand("AT+CMGF=1");      //setting GSM to Text Mode
    writecommand("AT+CNMI=2,0,2,0,0");

    while(1)
    {
        bat();
        transmit("AT+CMGS=\"+9195xxxxxxxx\"\r");  //Sending SMS with values in UART buffer
        _delay_ms(10);
        uart_send(26);    // command to send SMS
}

When I run the code it stuck in the bat() function (at"AT+CBC") it displays the battery info on the LCD and terminal both but doesn't send it by sms and program doesn't proceed further. Please suggest me ways to get the info through SMS.

Edit

Regarding comments by Loongcat

I am receiving 20 characters after the comman "AT+CBC" then it should receive that. this is the loop for(int x = 0;x<20;x++)

\$\endgroup\$
  • \$\begingroup\$ What type of GSM module do you use? \$\endgroup\$ – Bence Kaulics Sep 8 '15 at 11:29
  • \$\begingroup\$ I am using SIM800E GSM module \$\endgroup\$ – Ravi Kumar Sep 8 '15 at 11:49
2
\$\begingroup\$

1) AT+CMGS must go before the body of sms (place bat() after transmit())

2) You're not detecting the end of answer to AT+CBC command, that's poor way. You must receive symbols until you've get "OK"

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I am receiving 20 characters after the comman "AT+CBC" then it should receive that. this is the loop for(int x = 0;x<20;x++) \$\endgroup\$ – Ravi Kumar Sep 8 '15 at 11:49
  • \$\begingroup\$ I think it will cause trouble if he send an AT+CMGS then an AT+CBC, the message sending may will be interrupted because of the new AT command. \$\endgroup\$ – Bence Kaulics Sep 8 '15 at 13:45
  • \$\begingroup\$ @BenceKaulics you're right, missed that. He needs to get +CBC answer first, then start sms typing with +CMGS \$\endgroup\$ – Looongcat Sep 8 '15 at 19:29
2
\$\begingroup\$

I see the following problems in your code:

  1. In the bat() function you store the battery info in a local string (char battery[16];)
    • The size of this array is 16 but you are saving 20 characters (for(int x = 0;x<20;x++)) into it. If you are expecting 20 characters you should use an array with a size of 20 + 1, plus one for the terminating null character: \0.
    • A local variable is allocated on the stack and is therefore unavailable once the function finishes execution. You may still be able to reach the stored value but there is no guarantee to that, because it will be marked as free memory space and some other function may overwrites.
    • Your uart_send function expects unsigned char as a parameter, so this call is wrong: uart_send(*battery); it should be uart_send(battery[x]);

In the current state of your program there won't be any problem since you transmit this string in the bat() function, but you should transmit it after the AT+CMGS command, where this string won't be available.

If you just call the bat() function after the AT+CMGS, it will cause problems, because the AT+CBC command will be sent to the module, which for it will answer. I think it will interrupt the execution of the AT+CMGS command.

So I suggest you to save the battery info first into a variable which won't lost, and the send it at the correct time. A correct message sending sequence should look something like this:

  1. Get the battery info from the module and save it for later use.
  2. Send the AT+CMGS="+9195xxxxxxxx" command.
  3. Wait for the module to respond with: >, this means that the module has processed the phone number and now ready to receive the SMS body, [battery info].
  4. When you received the > character, you can send the battery info to the module.
  5. Now, send the message using the <CTRL>-<Z> character, 0x26 in ASCII.
  6. On successful delivery the module will return a message ID like: +CMGS: 62
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ or *(battery+x), same things \$\endgroup\$ – Looongcat Sep 8 '15 at 19:31
  • \$\begingroup\$ Indeed, that one works too. \$\endgroup\$ – Bence Kaulics Sep 8 '15 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.