Check to see if other function writing to SD card then wait while getting SMS?

Hello,

I am working on a project with the FONA 3G module, SD card reader, and LED Matrix. I am using an Arduino Mega.

The project does the following:

  • Receives a SMS text message
  • Saves it on the SD card with the phone number in a CSV format
  • Reads the SD card CSV with SDfat (I am using same length records to find line numbers)
  • It then sends the SMS message as a char string to the LED matrix.

So far in separate sketchesI can successfully:

  • Receive an SMS
  • Save SMS to SD
  • Read SD card at a particular line
  • Save SMS from SD card in a variable
  • Send that char variable to the LED matrix and have it scroll.

Now that i am combining my sketches together I am having problems.

  • How can I always be able to save a new SMS to the SD card? What if my SD card reading function has the file open when the SMS function wants to write new information?
  • When I cycle through saved SMS messages from the SD card, the display abruptly changes. I hope to be able have it cycle through all saved messages, scroll them on screen but wait until the previous message has completely scrolled before starting the next one.

Now I am using a combination of functions and a crude state machine to try to separate the different operations. I do not think it will be scalable or I am approaching it wrong.

Any help or advice is much appreciated.

Thank you in advance. The code is attached.

_20171125_Print_1_CSV_Line_at_a_Time.ino (13.6 KB)

What if my SD card reading function has the file open when the SMS function wants to write new information?

Random bits of code don't start running because they feel the need. Only interrupt handlers run outside of your control, and there is no way that an interrupt service routine should be writing to an SD card.

When I cycle through saved SMS messages from the SD card, the display abruptly changes.

If you wrote the code correctly, that wouldn't happen.

Any help or advice is much appreciated.

If you have specific questions, feel free to ask them. What concerns you have expressed are not legitimate, so help or advice is useless.

Paul - Thank you. I will break up my questions into smaller pieces and ask for help with the code in separate threads rather than a big code dump without specific questions.

and ask for help with the code in separate threads

Keep all your related questions in this thread, rather than starting a new thread on each one.

Ok, I will, thanks.

1.) I am familiar with the millis() do things without delay tutorial. Usually I can remove delays from sketches but I am having difficulty removing a 1 millisecond delay from the Adafruit FONA SMS example sketch.

The sketch works when it has a delay(1) in the beginning but when I replace it with a millis timer it does not seem to work. I also tried a state machine with no luck.

Here is the original section of code and the attempts at removing the delay below. I attached the full Adafruit example sketch for reference.

Original Adafruit example with delay:

void loop() {
  currentMillis = millis();
  char* bufPtr = fonaNotificationBuffer;    //handy buffer pointer
  
  if (fona.available())      //any data available from the FONA?
  {
    int slot = 0;            //this will be the slot number of the SMS
    int charCount = 0;
    //Read the notification into fonaInBuffer
    do  {
      
      *bufPtr = fona.read();
      Serial.write(*bufPtr);
      delay(1);
    } while ((*bufPtr++ != '\n') && (fona.available()) && (++charCount < (sizeof(fonaNotificationBuffer)-1)));
    
    //Add a terminal NULL to the notification string
    *bufPtr = 0;

millis timer attempt:

unsigned long FlashTime = 1; // Check for Universal Timer function
unsigned long currentMillis = 1;

////////////// Universal CheckTime() Function////////////////
boolean CheckTime(unsigned long &lastMillis, unsigned long wait)
{
  //is the time up for this task?
  if (currentMillis - lastMillis >= wait)
  {
    lastMillis += wait;  //get ready for the next iteration
    return true;
  }
  return false;
}
////////////////////// END of Universal CheckTime() Function /////////////

void loop() {
  currentMillis = millis();
  char* bufPtr = fonaNotificationBuffer;    //handy buffer pointer
  
  if (fona.available())      //any data available from the FONA?
  {
    int slot = 0;            //this will be the slot number of the SMS
    int charCount = 0;
    //Read the notification into fonaInBuffer
    do  {

      if (CheckTime(FlashTime, 1UL)) {
        FlashTime = millis(); //initialize the next wait time
        *bufPtr = fona.read();
        Serial.write(*bufPtr);
      }

      delay(1);
    } while ((*bufPtr++ != '\n') && (fona.available()) && (++charCount < (sizeof(fonaNotificationBuffer)-1)));
    
    //Add a terminal NULL to the notification string
    *bufPtr = 0;

State Machine attempt:

enum ProgramStates { StartUp, wait_1 };
ProgramStates lState = StartUp;
unsigned long FlashTime = 1; // Check for Universal Timer function
unsigned long currentMillis = 1;

////////////// Universal CheckTime() Function////////////////
boolean CheckTime(unsigned long &lastMillis, unsigned long wait)
{
  //is the time up for this task?
  if (currentMillis - lastMillis >= wait)
  {
    lastMillis += wait;  //get ready for the next iteration
    return true;
  }
  return false;
}
////////////////////// END of Universal CheckTime() Function /////////////
void loop() {
  currentMillis = millis();
  char* bufPtr = fonaNotificationBuffer;    //handy buffer pointer

  if (fona.available())      //any data available from the FONA?
  {
    int slot = 0;            //this will be the slot number of the SMS
    int charCount = 0;
    //Read the notification into fonaInBuffer
    do  {
      switch (lState) {
        case StartUp:
          *bufPtr = fona.read();
          Serial.write(*bufPtr);
          FlashTime = millis(); 
          lState = wait_1;
          break;
        case wait_1:
          if (CheckTime(FlashTime, 1UL)) {
            FlashTime = millis(); //initialize the next wait time
            lState = StartUp;
          }
          break;
      }

    } while ((*bufPtr++ != '\n') && (fona.available()) && (++charCount < (sizeof(fonaNotificationBuffer) - 1)));

    //Add a terminal NULL to the notification string
    *bufPtr = 0;

.... more code in loop ....
}

FONA_SMS_Response.ino (4.55 KB)