15
votes

I've hooked up a ADH8066 (Sparkfun) GSM Module to my Arduino Uno, and am trying to get some correct serial going between the Arduino and the GSM module. It works fine when I connect to it directly (via USB or just the TTL lines) but not when being controlled via the Arduino. Some text will output correctly, the rest will be garbled, almost as if the baud rate is wrong, but I'm just using the same baud (115200) I do as when I connect from a PC.

Here is the Arduino code I'm using:

#include <SoftwareSerial.h>

#define rxPin 7
#define txPin 8
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

// EN: String buffer for the GPRS shield message
String SmsStorePos = String("");
String msg = String("");
String snTmp = String("");
String snFull = String("");

// EN: Set to 1 when the next GPRS shield message will contains the SMS message
int SmsContentFlag = 0;

// EN: Pin of the LED to turn ON and OFF depending on the received message
int ledPin = 5;
int powerPin = 6;

void setup()
{
  mySerial.begin(115200);               // the GPRS baud rate   
  mySerial.print("\r");
  delay(1000);
  Serial.begin(115200);                 // the Arduino IDE serial
  Serial.println("Started!");

  pinMode( ledPin, OUTPUT ); 
  digitalWrite( ledPin, LOW ); 

  pinMode( powerPin, OUTPUT);
  digitalWrite(powerPin, LOW);    // brings ONKEY low to turn on the modem (aka pressing the ONKEY)
  delay(3000);
  digitalWrite(powerPin, HIGH);    // sets the pin HIGH again (restore 5V)
  delay(5000);

  // test LED pin
  digitalWrite ( ledPin, HIGH);
  delay(1000);
  digitalWrite( ledPin, LOW); 
}

void loop()
{
    char SerialInByte;

    // Send anything we receive from the IDE to the modem
    if(Serial.available())
    {
       mySerial.print((unsigned char)Serial.read());
     }  
    else  if(mySerial.available())
    {
        char SerialInByte;
        SerialInByte = (unsigned char)mySerial.read();
        //SerialInByte = mySerial.read();

        // EN: Relay to Arduino IDE Monitor
        Serial.print( SerialInByte );

        // -------------------------------------------------------------------
        // EN: Program also listen to the GPRS shield message.
        // -------------------------------------------------------------------

        // EN: If the message ends with <CR> then process the message
        if( SerialInByte == 13 ){
          // EN: Store the char into the message buffer
          ProcessGprsMsg();
         }
         if( SerialInByte == 10 ){
            // EN: Skip Line feed
         }
         else {
           // EN: store the current character in the message string buffer
           msg += String(SerialInByte);
         }
     }   
}

// EN: Make action based on the content of the SMS. 
//     Notice than SMS content is the result of the processing of several GPRS shield messages.
void ProcessSms( String sms ){
  sms.toLowerCase();
  Serial.print( "ProcessSms for [" );
  Serial.print( sms );
  Serial.println( "]" );

  if( sms.indexOf("on") >= 0 ){
    digitalWrite( ledPin, HIGH );
    Serial.println( "LED IS ON" );
    return;
  }
  if( sms.indexOf("off") >= 0 ){
    digitalWrite( ledPin, LOW );
    Serial.println( "LED IS OFF" );
    return;
  } else {
    mySerial.print("AT+CMGF=1\r");    //Because we want to send the SMS in text mode
    delay(1000);
    mySerial.print("AT+CMGS=\"");
    mySerial.print(snFull);
    mySerial.print("\"\r");
    delay(1000);
    mySerial.print("Unknown Command: ");
    mySerial.print(sms);
    mySerial.print("\r");
    delay(1000);
    mySerial.write(0x1A);  //Equivalent to sending Ctrl+Z     
    return;
  }
}
// EN: Request Text Mode for SMS messaging
void GprsTextModeSMS(){
  mySerial.println( "AT+CMGF=1" );
}

void GprsReadSmsStore( String SmsStorePos ){
  // Serial.print( "GprsReadSmsStore for storePos " );
  // Serial.println( SmsStorePos ); 
  mySerial.print( "AT+CMGR=" );
  mySerial.println( SmsStorePos );
}

// EN: Clear the GPRS shield message buffer
void ClearGprsMsg(){
  msg = "";
}

// EN: interpret the GPRS shield message and act appropiately
void ProcessGprsMsg() {
  Serial.println("");
  Serial.print( "GPRS Message: [" );
  Serial.print( msg );
  Serial.println( "]" );

  if( msg.indexOf( "Call Ready" ) >= 0 ){
     Serial.println( "*** GPRS Shield registered on Mobile Network ***" );
     GprsTextModeSMS();
  }

  // EN: unsolicited message received when getting a SMS message
  if( msg.indexOf( "+CMTI" ) >= 0 ){
     Serial.println( "*** SMS Received ***" );
     // EN: Look for the coma in the full message (+CMTI: "SM",6)
     //     In the sample, the SMS is stored at position 6
     int iPos = msg.indexOf( "," );
     SmsStorePos = msg.substring( iPos+1 );
     Serial.print( "SMS stored at " );
     Serial.println( SmsStorePos );

     // EN: Ask to read the SMS store
     GprsReadSmsStore( SmsStorePos );
  }

  // EN: SMS store read via UART (result of GprsReadSmsStore request)  
  if( msg.indexOf( "+CMGR:" ) >= 0 ){
    // get number of sender
    int snPos = msg.indexOf("+1");
    Serial.print("SMS From: ");
    snTmp = msg.substring(snPos+1);
    snFull = "";
    for (int i = 0; i < 11; i++){
      snFull += snTmp[i];    
    }
    Serial.println(snFull);

    // EN: Next message will contains the BODY of SMS
    SmsContentFlag = 1;
    // EN: Following lines are essentiel to not clear the flag!
    ClearGprsMsg();
    return;
  }

  // EN: +CMGR message just before indicate that the following GRPS Shield message 
  //     (this message) will contains the SMS body
  if( SmsContentFlag == 1 ){
    Serial.println( "*** SMS MESSAGE CONTENT ***" );
    Serial.println( msg );
    Serial.println( "*** END OF SMS MESSAGE ***" );
    ProcessSms( msg );
    delSMS();
  }

  ClearGprsMsg();
  // EN: Always clear the flag
  SmsContentFlag = 0; 
}
void delSMS() {
  mySerial.print("AT+CMGD=");
  mySerial.println(SmsStorePos);
}  

Below is what I'm seeing in the serial monitor:

http://imgur.com/i5jEPds

8
This could be a power supply / grounding issue. How are the two devices powered? Are they sharing the same supply? Do you use a DC converter or batteries? Do you have sufficient power supply decoupling (capacitors)? A good enough ground? All these things matter, especially when you have a fast baud rate - a little noise spike will throw things off.Floris
They are powered off the same 12V 2A regulated supply, going into the Arduino, then I pull the 5V/GND into the GSM module. I think I have figured it out though. I did some reading and it looks like SoftwareSerial is unreliable for bauds above 19200, so I tried swapping the serial line to be SoftwareSerial and for the Arduino to communicate with the GSM module over the hardware serial (Serial). Boom! No more garbage. Now I'm just getting garbage back from the modem, such as: GPRS Message: [ +G: 0084E9971343964396971397169716971697161009797439643969797139713]mabnz
...(continued) Now I'm just getting old long strings from modem (instead of the +CMTI I expect), such as: GPRS Message: [ +G: 0084E9971343964396971397169716971697161009797439643969797139713]mabnz
I'm facing a similar problem at 9600, talking to a 16x2 LCD display, with an app that's not doing anything extra. Unless I add significant delays (~250 ms) after each message I write to SoftwareSerial (or even Serial1), I get garbled text and eventually no response at all.Adrian McCarthy

8 Answers

9
votes

Make sure the "baud" setting matches your sketch.

Ex: Serial.begin(115200); >>>> 115200 baud in the console.

I got this solution out of a comment above from kunalbhat. But I wanted to post it as a stand-alone answer because it solved my problem, and it would have never occurred to me. So I think it will help a lot of other people.

7
votes

SoftwareSerial is notoriously picky about timing and will cause problems like you describe when "too much" is going on at the same time. It probably gets out of sync because of you are doing other stuff on the side.

I warmly recommend AltSoftSerial (http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html), which performs much better, but I still suggest you use slightly lower baud rates to increase reliability. Too high baud rates will require very exact timing to not miss a single bit and the hardware is not powerful enough to do serial traffic in software without problems.

2
votes

As was said before, the issue is with the "baud" setting (which has to do with serial communication- another answer). This can be found (typically) at the top of your sketch, and might look like this:

Serial.begin(9600);

Or this:

Serial.begin(115200);

In the case of an Arduino Uno, a "baud" setting other than 9600 will result in garbled text. As such, make sure that at the beginning of your sketch, you have the line:

Serial.begin(9600);

Feel free to ask if you need any further help.

2
votes

The reason is that, you need to set the command AT+UART_DEF=9600,8,1,0,0 to reset the baud of ESP to 9600, or you can also use AT+CIOBAUD=9600!
Try it, it's working for me!
I have tried AT+IPR on some ESP-01 and ESP-12 modules, some times it's working and sometimes no(and in really bad case, the baud change completely)!

1
votes

I was using the Arduino to program a ATtiny84 but was getting garbled output or serial was stopping after the 1st line until I reset the Arduino.

The issue was the Arduino had the 'Arduino as ISP' sketch loaded which was interfering with the serial data coming in from the ATtiny84.

Uploading a blank sketch to Arduino fixed it.

0
votes

I had to change my "baud" settings to 9600.

Serial.begin(9600);
0
votes

i had to go back to hardware serial on my mega to get it to work. never had good luck with sw serial

hardware serial sim900 to mega: //middle rx/tx pins on sim900 to pin tx1/rx1 on mega

0
votes

You should use the Serial library, not software serial. Serial is the official one in Arduino IDE and is included by default in every program. Make sure the baud rate is equal on the monitor and the program, this is a common error for garbled characters. 9600 is a recommended baud rate, and you can use commands like Serial.begin(9600), Serial.read(), Serial.print(""), and Serial.println("").