Reading serial data from a GSM Shield

Hi I am currently working on a GSM noticeboard and I have managed to display short messages, but I am struggling to display longer messages. Currently if I try to display a long message, say 60 characters, it will display the first 20-30 and not show the rest. I need to be able to receive a maximum of 160 characters (length of an sms). Code posted below:

#include <LedControl.h>
#include "charmap.h" 
#include <SoftwareSerial.h>

const int numDevices = 4;      // number of MAX7219s used
const long scrollDelay = 75;   // adjust scrolling speed
unsigned long bufferLong [14];
const byte numChars = 160;
char receivedChars[numChars];
LedControl lc=LedControl(12,11,10,numDevices); // DOUT|CLK|CS|Devices
SoftwareSerial SIM900(7,8); // TX|RX
//---------------------------------------------------------------------------------------------------------
void setup(){ 
  for (int x=0; x<numDevices; x++){
      lc.shutdown(x,false);       // the MAX72XX is in power-saving mode on startup
      lc.setIntensity(x,8);       // set brightness of display
      lc.clearDisplay(x);         // clear display
  }
  digitalWrite(9, HIGH);    // turns on the shield
  delay(1000);
  digitalWrite(9, LOW);
  delay(5000);
  SIM900.begin(19200);   // sim900 operates at a baud rate of 19200
  Serial.begin(19200);   // sets the serial baud rate
  delay(10000);   // delay for GSM shield to log on
  SIM900.print("AT+CMGF=1\r");    // set sim900 to receive sms
  delay(100); 
  SIM900.print("AT+CNMI=2,2,0,0,0\r");  // sms to be sent to serial output 
  delay(100);
}
void loop(){ 
  scrollMessage();
}

void scrollMessage() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  boolean newData = false;
  int myChar = 0;
    
  while (SIM900.available() > 0 && newData == false) {
        rc = SIM900.read();
        //Serial.print(rc);
        
        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }
        else if (rc == startMarker) {
            recvInProgress = true;
        }
  }
  do {   
      for (int i = 0; i < 160; i++){
          myChar = receivedChars[i];
          if (myChar != 0){
              loadBufferLong(myChar); 
          }
      }
    }
    while (myChar != 0);
}
// Load character into scroll buffer
void loadBufferLong(int ascii){
  if (ascii >= 0x20 && ascii <=0x7f){
      for (int a=0;a<7;a++){                      // Loop 7 times for a 5x7 font
          unsigned long c = pgm_read_byte_near(font5x7 + ((ascii - 0x20) * 8) + a);     // Index into character table to get row data
          unsigned long x = bufferLong [a*2];     // Load current scroll buffer
          x = x | c;                              // OR the new character onto end of current
          bufferLong [a*2] = x;                   // Store in buffer
      }
      byte count = pgm_read_byte_near(font5x7 +((ascii - 0x20) * 8) + 7);     // Index into character table for kerning data
      for (byte x=0; x<count;x++){                                            // creates a space between characters
          rotateBufferLong();
          printBufferLong();
          delay(scrollDelay);
      }
  }
}
// Rotate the buffer
void rotateBufferLong(){
  for (int a=0;a<7;a++){                      // Loop 7 times for a 5x7 font
      unsigned long x = bufferLong [a*2];     // Get low buffer entry
      byte b = bitRead(x,31);                 // Copy high order bit that gets lost in rotation
      x = x<<1;                               // Rotate left one bit
      bufferLong [a*2] = x;                   // Store new low buffer
      x = bufferLong [a*2+1];                 // Get high buffer entry
      x = x<<1;                               // Rotate left one bit
      bitWrite(x,0,b);                        // Store saved bit
      bufferLong [a*2+1] = x;                 // Store new high buffer
  }
}  
// Display Buffer on LED matrix
void printBufferLong(){
  for (int a=0;a<7;a++){                      // Loop 7 times for a 5x7 font
      unsigned long x = bufferLong [a*2+1];   // Get high buffer entry
      byte y = x;                             // mask for first character
      lc.setRow(3,a,y);                       // send row to relevent MAX7219 chip
      x = bufferLong [a*2];                   // Get low buffer entry
      y = (x>>24);                            // mask for second character
      lc.setRow(2,a,y);                       
      y = (x>>16);                            // mask for third character
      lc.setRow(1,a,y);                       
      y = (x>>8);                             // mask for fourth character
      lc.setRow(0,a,y);                       
  }
}

I think that to start writing to the matrix before the whole massage has been received causes the Serial buffer to overrun. iow it takes to long to write to the matrixyou should not start with that task until the full message has been received. which kind of defeats the purpose of doing the Serial reception in an async task but so be it. just like this does it work ?

  if (!recvInProgress) {
    do {   
        for (int i = 0; i < 160; i++){
            myChar = receivedChars[i];
            if (myChar != 0){
                loadBufferLong(myChar); 
            }
        }
      }
      while (myChar != 0);
  }

You can also increase the buffersize of Serial of course.

Deva_Rishi:
I think that to start writing to the matrix before the whole massage has been received causes the Serial buffer to overrun. iow it takes to long to write to the matrixyou should not start with that task until the full message has been received. which kind of defeats the purpose of doing the Serial reception in an async task but so be it. just like this does it work ?

  if (!recvInProgress) {

do {  
       for (int i = 0; i < 160; i++){
            myChar = receivedChars[i];
           if (myChar != 0){
               loadBufferLong(myChar);
           }
       }
     }
     while (myChar != 0);
 }

I just gave this code a try and it does allow one full message to come through even 100 characters long, but then when I send the next message it seems to freeze.
I will try changing the buffersize and see if this fixes the problem. :slight_smile:

NAJ9:
Hi I am currently working on a GSM noticeboard and I have managed to display short messages ....

Don't add code into my recvWithStartEndMarkers() function and don't change its name, or purpose. That's not because I might be offended, but because it just causes confusion. Or, put another way - "if it works, don't fix it"

The right place to put your code is in a replacement for my showNewData() function.

...R