0

new to C - I am struggling with a memory management issue which I think is related to the char array variable Cars in the following code.

I can run this program once or twice just fine and print my results to serial, but after that I start getting garbage printed to serial. Which I assume means I am not handling my char arrays in memory correctly.

#include <SPI.h>
#include <MFRC522.h>
#include <SoftwareSerial.h> 
#include <SparkFunESP8266WiFi.h>

// PIN Numbers : RESET + SDAs
#define RST_PIN         4  
#define SS_1_PIN        10
#define SS_2_PIN        7
#define SS_3_PIN        5
#define SS_4_PIN        6


const char mySSID[] = "SSID";
const char myPSK[] = "pass";
const char destServer[] = "URL.azurewebsites.net";



#define NR_OF_READERS   4
byte ssPins[] = {SS_1_PIN, SS_2_PIN,SS_3_PIN, SS_4_PIN};
// Create an MFRC522 instance :
MFRC522 mfrc522[NR_OF_READERS];


char Cars[][11] = // 10 is the length of the longest string + 1 ( for the '\0' at the end )
{
  "",
  "",
  "",
  ""
};


//first line is lane, second is place - use 0 if there if lane is not used
//Communiction from second arduino will be needed to populate
int FinishOrder[2][4] = {
  {1,  2,  3, 4  },
  {2,  1,  4, 3  } 
};


/**
   Initialize.
*/
void setup() {

  Serial.begin(9600);           // Initialize serial communications with the PC
  while (!Serial);              // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)

  SPI.begin();                  // Init SPI bus

  //connect to WiFi
  initializeESP8266();
  connectESP8266();
  displayConnectInfo();


  /* looking for MFRC522 readers */
  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN);
    Serial.print(F("Reader "));
    Serial.print(reader);
    Serial.print(F(": "));
    mfrc522[reader].PCD_DumpVersionToSerial();
    //mfrc522[reader].PCD_SetAntennaGain(mfrc522[reader].RxGain_max);
  }
}

/*
   Main loop.
*/
//void(* resetFunc) (void) = 0;//declare reset function at address 0

void loop() {

 for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {

    // Looking for new cards
    if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {

      String rfid_uid = "";
      for (byte i = 0; i < mfrc522[reader].uid.size; i++) {
        String uid_part = String(mfrc522[reader].uid.uidByte[i], HEX); 
        rfid_uid += uid_part;
      }
      char rfid[11];
      rfid_uid.toCharArray(rfid, 11);
      RecordRacer(reader,rfid, 0);
         if(reader == 1) //trigger winner if reader 1 is triggered, will need to adjust so that the second arduino tells when race is done
         {
         RecordRacer(reader,rfid, 1);
        //   resetFunc();  //call reset function which fixes the memory management issue but not in a good way

         }
         memset(rfid, 0, sizeof(rfid)); //reset rfid char

      // Halt PICC
      mfrc522[reader].PICC_HaltA();
      // Stop encryption on PCD
      mfrc522[reader].PCD_StopCrypto1();
    } //if (mfrc522[reader].PICC_IsNewC..
  } //for(uint8_t reader..
}



void PostData(const char* httpRequest)
{
  // To use the ESP8266 as a TCP client, use the 
  // ESP8266Client class. First, create an object:
  ESP8266Client client;

  // ESP8266Client connect([server], [port]) is used to 
  // connect to a server (const char * or IPAddress) on
  // a specified port.
  // Returns: 1 on success, 2 on already connected,
  // negative on fail (-1=TIMEOUT, -3=FAIL).
  int retVal = client.connect(destServer, 80);
  if (retVal <= 0)
  {
    Serial.println(F("Failed to connect to server."));
    return;
  }

  // print and write can be used to send data to a connected
  // client connection.
  Serial.println("right before request");
  Serial.println(httpRequest);
  client.print(httpRequest);

  // available() will return the number of characters
  // currently in the receive buffer.
  while (client.available())
    Serial.write(client.read()); // read() gets the FIFO char

  // connected() is a boolean return value - 1 if the 
  // connection is active, 0 if it's closed.
  if (client.connected())
    client.stop(); // stop() closes a TCP connection.


}

//go is a variable that if set to true will record the race
void RecordRacer(int track, char* car, int go)
{


//Which car is on which track, fill the array
switch (track) {
  case 0:
    strcpy(Cars[track],car);
      Serial.print("Car: ");
      Serial.println(car);
      Serial.print("Track: ");
      Serial.println(track);

    break;
  case 1:
    strcpy(Cars[track],car);
    Serial.print("Car: ");
      Serial.println(car);
      Serial.print("Track: ");
      Serial.println(track);
    //Serial.println(Cars[track]);
    break;
  case 2:
    strcpy(Cars[track],car);
    Serial.print("Car: ");
      Serial.println(car);
      Serial.print("Track: ");
      Serial.println(track);
    //Serial.println(Cars[track]);
  break;
  case 3:
    strcpy(Cars[track],car);
    Serial.print("Car: ");
      Serial.println(car);
      Serial.print("Track: ");
      Serial.println(track);
    //Serial.println(Cars[track]);
  break;
  default:
    // statements
  break;
    }
    for (int i = 0; i < 4; i++)
    {
     // Serial.print("Car: ");
     // Serial.println(Cars[i]);
     // Serial.print("Track: ");
     // Serial.println(i+1);

    }
if(go) //if race is over start here
  {
    char url[9] = "/adddata";
    char FullURL[100] = "";
    char hts[200] = "GET ";
    strcpy(FullURL, url);
    //FullURL[8] = '\0';
    Serial.println("race is over");

   //Loop through each lane
    for (int i = 0; i < 4; i++) {

      if(i == 0)//first variable in URL is ? //others are &
      {
        strcat(FullURL,"?");
      }
      else
      {
          if(strlen(Cars[FinishOrder[0][i]-1])== 0)
            {
            } 
          else
            {
              strcat(FullURL,"&");
            }

      }


        //printing for debuging
       Serial.print("Lane: ");
       Serial.println(FinishOrder[0][i]);
       Serial.print("Place: ");
       Serial.println(FinishOrder[1][i]);
      //Look in the array for the finish order of each lane
     switch (FinishOrder[1][i]) {
        case 1: //Lane 1
          if(strlen(Cars[FinishOrder[0][i]-1])== 0)
          {
          //if no racer dont add to url  
          }    
          else
          {
             strcat(FullURL,"first=");
             strcat(FullURL,Cars[FinishOrder[0][i]-1]);    
             Serial.print("Car: ");
             Serial.println(Cars[FinishOrder[0][i]-1]);
             Serial.println(FullURL);
          }
          break;
       case 2:
         if(strlen(Cars[FinishOrder[0][i]-1])== 0)
         {
         }    
         else
         {
            strcat(FullURL,"second=");
            strcat(FullURL,Cars[FinishOrder[0][i]-1]);    
            Serial.print("Car: ");
            Serial.println(Cars[FinishOrder[0][i]-1]);
            Serial.println(FullURL);
         }
         break;
       case 3:
         if(strlen(Cars[FinishOrder[0][i]-1])== 0)
         {
         }    
         else
         {
           strcat(FullURL,"third=");
           strcat(FullURL,Cars[FinishOrder[0][i]-1]);
           Serial.print("Car: ");
           Serial.println(Cars[FinishOrder[0][i]-1]);
           Serial.println(FullURL);
         }
         break;
       case 4:
        if(strlen(Cars[FinishOrder[0][i]-1])== 0)
        {
        }    
        else
        {
          strcat(FullURL,"fourth=");
          strcat(FullURL,Cars[FinishOrder[0][i]-1]);
          Serial.print("Car: ");
          Serial.println(Cars[FinishOrder[0][i]-1]);
          Serial.println(FullURL);
        }
         break;
        default:
          // statements
        break;
      }
     }

      //This string always shows what I expect
      Serial.println(FullURL);

      strcat(hts,FullURL);
      strcat(hts," HTTP/1.1\n");
      strcat(hts,"Host: url.azurewebsites.net\n");
      strcat(hts,"Connection: close\n\n"); 

      Serial.println("add to http");
      //This will display wierd characters in what use to be the FullURL part of the now bigger string
      Serial.println(hts);

      //Post to website
      PostData(hts);

     //Reset our variables for the next race
      go = 0;
      memset(FullURL, 0, sizeof(FullURL));
      memset(Cars, 0, sizeof(Cars));
      memset(hts, 0, sizeof(hts));
  }
}
  • I have to admit I didn't study your code in detail. But I had also memory problems. Then I discovered F() and String.reserve() These functions saved a lot of RAM for me and I am sure you will use them. – Edgar Feb 15 at 3:32

Your Answer

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

Browse other questions tagged or ask your own question.