Arduino Ethernet + Grove RFID + Grove RTC

Hello,

I need to build a system for recording hours through RFID cards.

I thought then these three components:

Arduino Ethernet (not shield)
Grove - 125KHz RFID Reader
Grove Real-time clock

I developed the code but I have a problem of optimization.

The code is too long and there is not enough memory.

I need my system to present the latest read by rfid card in HTML and save (append) that record on SD card .. always followed by the time and date ..

The developed code is presented below:

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,28,150);
EthernetServer server(8080);
File myFile;

//clock
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>

//rfid
#include <SoftwareSerial.h>
SoftwareSerial rfid(2, 3);
unsigned char buffer[14];
int count=0;

void setup()
{
  Serial.begin(9600);
  // start clock:
  setSyncProvider(RTC.get);   // get the time from the RTC
  if(timeStatus()!= timeSet) 
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
  
  // Start SD
  initSD();
  delay(1);
  
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  
  // start rfid:
  rfid.begin(9600);
  // buzz:
  pinMode(8, OUTPUT);
  
}

unsigned char buff[6];

EthernetClient client;

void initSD(){ 
  Serial.print("Initializing SD card...");
  pinMode(10,OUTPUT);
  if (!SD.begin(4)) {
    Serial.println("initialization failed! - Reinsert SD");
    return;
  }
  Serial.println("initialization done.");
  
  myFile = SD.open("test.txt",FILE_WRITE);
  if (myFile) {
    Serial.print("Writing..");
    myFile.println("escrito_no_setup");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } 
  else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  // re-open the file for reading:
  myFile = SD.open("test.txt");

  if (myFile) {
    Serial.println("Confirmacao do que foi escrito no setup");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } 
  else {
    //if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
    
}


void loop()
{
  client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"2\">");
          // output the value of each analog input pin

            client.println("CLOCK TEST");  

          client.println("
");
          client.println(digitalClockDisplay());
          client.println("
"); 
         
         if(rfid.available()){
            while(rfid.available())          
            {
              buffer[count++]=rfid.read();     
              if(count == 64)break;
            }
            //print value:
            //client.write(buffer,count);  //default value
            client.print(GetInfo(buffer,count));        
            clearBufferArray();             
            count = 0;

            buzz(8, 2500, 500); // buzz the buzzer on pin 8 at 2500Hz for 500 milliseconds

    
          }
         
         
         
          
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();

    myFile = SD.open("test.txt",FILE_WRITE);

    if (myFile) {
      Serial.print("Writing..");
      myFile.println("SETUP: PRIMEIRA LINHA NO SETUP");
      // close the file:
      myFile.close();
      Serial.println("done.");
    } 
    else {
      // if the file didn't open, print an error:
      Serial.println("error opening test.txt");
    }

    myFile = SD.open("test.txt");
    if (myFile) {
      Serial.println("Mostrar o que foi escrito no final");
      // read from the file until there's nothing else in it:
      while (myFile.available()) {
        Serial.write(myFile.read());
      }
      // close the file:
      myFile.close();
    }
    else {
      // if the file didn't open, print an error:
      Serial.println("error opening test.txt");
    }
    delay(1);
  }  
}


// RFID functions:
void clearBufferArray()              // function to clear buffer array
{
  for (int i=0; i<count;i++)
  { 
    buffer[i]=NULL;
  }                  // clear all index of array with command NULL
}

String GetInfo(unsigned char buff[14], int count)
{
  // remove stx checksum and etx and get name;
  String value = GetString(buff).substring(1,11); 
  String temp = GetData(value);
  return temp;
  //sd_card_write(temp + " » " +digitalClockDisplay());
}

String GetString(unsigned char* inStrReference)
{
  // convert unsigned char to string
  unsigned char* bufPtr = inStrReference; 
  String newstring = (char*)bufPtr;
  return newstring;
}

String GetData(String id)
{                       
  String bd[5][2] = {
    {
      "0F000C9C0E","Joao Pereira"         }
    ,
    {
      "0F00088CD2","Ricardo Lopes"        }
    ,
    {
      "0F00086052","Pedro Rosas"          }
    ,
    {
      "0F00096159","Filipe Macedo"        }
    ,
    {
      "0F000CF1F5","Mariana Gomes"        }
  };

  String data = id;

  for(int i=0; i<5;i++){
    if(bd[i][0]==id){
      data = bd[i][1];
    }
  }

  return data;
}

// clock functions:
String digitalClockDisplay(){ 
  String clock = String(hour()) + ":" + String(minute()) + ":" + String(second()) + " | " + String(day())+ "/" + String(month())+ "/" + String(year());
  return clock;
}


void buzz(int targetPin, long frequency, long length) {
  long delayValue = 1000000/frequency/2; // calculate the delay value between transitions
  long numCycles = frequency * length/ 1000; // calculate the number of cycles for proper timing

  for (long i=0; i < numCycles; i++){ // for the calculated length of time...
    digitalWrite(targetPin,HIGH); // write the buzzer pin high to push out the diaphram
    delayMicroseconds(delayValue); // wait for the calculated delay value
    digitalWrite(targetPin,LOW); // write the buzzer pin low to pull back the diaphram
    delayMicroseconds(delayValue); // wait againf or the calculated delay value
  }
}

jot4p:
...
I developed the code but I have a problem of optimization.
The code is too long and there is not enough memory (ultimately give errors).
...

  1. Which memory? Ram, Flash Memory
  2. Which MCU/ArduinoBoard you are using?

EDIT:Version 1.0 of the Arduino IDE introduced the F() syntax for storing strings in flash memory rather than RAM.

REF: Arduino Playground - HomePage

(ultimately give errors)

Errors? 8)

The String class will be useful, then you replace the ATMega328 chip with one with a gig of SRAM, instead of the one with 2K SRAM.

Until you do that, get rid of the Strings in your program.

And use the F() macro around those constant strings.

Cybernetician:

jot4p:
...
I developed the code but I have a problem of optimization.
The code is too long and there is not enough memory (ultimately give errors).
...

  1. Which memory? Ram, Flash Memory
  2. Which MCU/ArduinoBoard you are using?

can give me an example?

I've tried it but it still takes up more memory.

The following code works perfectly.

However missing record to the SD card when the RDIF TAG is read ..

Any help? thanks

//rfid
#include <SoftwareSerial.h>
SoftwareSerial rfid(2, 3);
unsigned char buffer[14];
int count=0;

//Ethernet
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,28,150);
EthernetServer server(8080);

//clock
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>


void setup() {
  // start Serial:
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
 
  // start the Ethernet:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at");
  Serial.println(Ethernet.localIP());

  // start rfid:
  rfid.begin(9600); 

  // start clock:
  setSyncProvider(RTC.get);   // get the time from the RTC
  if(timeStatus()!= timeSet) 
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");

  // buzz:
  pinMode(8, OUTPUT);

 

}


void loop() {

  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"2\">");
          // output the value of each analog input pin

            client.println("CLOCK TEST");  

          client.println("
");  
          client.println(digitalClockDisplay());   
          client.println("
"); 
          //write RFID TAG:

          if(rfid.available()){
            while(rfid.available())          
            {
              buffer[count++]=rfid.read();     
              if(count == 64)break;
            }
            //print value:
            //client.write(buffer,count);  //default value
            client.print(GetInfo(buffer,count));        
            clearBufferArray();             
            count = 0;

            buzz(8, 2500, 500); // buzz the buzzer on pin 8 at 2500Hz for 500 milliseconds

    
          }

          client.println("
");       

          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
    // write_SD();
}

// RFID functions:
void clearBufferArray()              // function to clear buffer array
{
  for (int i=0; i<count;i++)
  { 
    buffer[i]=NULL;
  }                  // clear all index of array with command NULL
}

String GetInfo(unsigned char buff[14], int count)
{
  // remove stx checksum and etx and get name;
  String value = GetString(buff).substring(1,11); 
  String temp = GetData(value);
  return temp;
  //sd_card_write(temp + " » " +digitalClockDisplay());
}

String GetString(unsigned char* inStrReference)
{
  // convert unsigned char to string
  unsigned char* bufPtr = inStrReference; 
  String newstring = (char*)bufPtr;
  return newstring;
}

String GetData(String id)
{                       
  String bd[5][2] = {
    {
      "0F000C9C0E","Joao Pereira"         }
    ,
    {
      "0F00088CD2","Ricardo Lopes"        }
    ,
    {
      "0F00086052","Pedro Rosas"          }
    ,
    {
      "0F00096159","Filipe Macedo"        }
    ,
    {
      "0F000CF1F5","Mariana Gomes"        }
  };

  String data = id;

  for(int i=0; i<5;i++){
    if(bd[i][0]==id){
      data = bd[i][1];
    }
  }

  return data;

}

// clock functions:
String digitalClockDisplay(){ 
  String clock = String(hour()) + ":" + String(minute()) + ":" + String(second()) + " | " + String(day())+ "/" + String(month())+ "/" + String(year());
  return clock;
}

void buzz(int targetPin, long frequency, long length) {
  long delayValue = 1000000/frequency/2; // calculate the delay value between transitions
  long numCycles = frequency * length/ 1000; // calculate the number of cycles for proper timing

  for (long i=0; i < numCycles; i++){ // for the calculated length of time...
    digitalWrite(targetPin,HIGH); // write the buzzer pin high to push out the diaphram
    delayMicroseconds(delayValue); // wait for the calculated delay value
    digitalWrite(targetPin,LOW); // write the buzzer pin low to pull back the diaphram
    delayMicroseconds(delayValue); // wait againf or the calculated delay value
  }

}

jot4p:
The following code works perfectly.

However missing record to the SD card when the RDIF TAG is read ..

Any help? thanks

Hello,

This code already written on the card, but it still fails (random) for lack of memory.

somebody can optimize the code?

#include <SD.h>
File SDFileData;

//rfid
#include <SoftwareSerial.h>
SoftwareSerial rfid(2, 3);
unsigned char buffer[14];
int count=0;

//Ethernet
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,28,150);
EthernetServer server(8080);

//clock
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>


void setup() {
  // start Serial:
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  // start the Ethernet:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.println("Server OK");

  // start rfid:
  rfid.begin(9600); 

  // start clock:
  setSyncProvider(RTC.get);   // get the time from the RTC
  if(timeStatus()!= timeSet) 
    Serial.println("RTC FAIL");
  else
    Serial.println("RTC OK");

  // buzz:
  pinMode(8, OUTPUT);
  //sd card
 pinMode(10,OUTPUT);
  if (!SD.begin(4)) {
    Serial.println("FAIL Reinsert SD");
    return;
  }

  /* Check if the text file already exists */
  while(SD.exists("test.txt"))
  {
   SD.remove("test.txt");
   if(!SD.exists("test.txt")){
     Serial.println("Delete OK");
   } 
  }

  /* Create a new text file on the SD card */
 
  SDFileData = SD.open("test.txt", FILE_WRITE);
  if(SD.exists("test.txt")){
   Serial.println("Create OK");}
  else{
  Serial.println("Error");
  }
  
  
}


void loop() {

  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"2\">");
          // output the value of each analog input pin

            client.println("CLOCK TEST");  

          client.println("
");  
          client.println(digitalClockDisplay());   
          client.println("
"); 
          //write RFID TAG:

          if(rfid.available()){
            while(rfid.available())          
            {
              buffer[count++]=rfid.read();     
              if(count == 14)break;
            }
            //print value:
            //client.write(buffer,count);  //default value
            client.print(GetInfo(buffer,count));        
            clearBufferArray();             
            count = 0;
            
            //buzz(8, 2500, 500); // buzz the buzzer on pin 8 at 2500Hz for 500 milliseconds
             WriteOnSD(); 
          }

          client.println("
");       

          client.println("</html>");
         break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(2);
    // close the connection:
    client.stop();
    Serial.println("stop");
  }
  

}

// RFID functions:
void clearBufferArray()              // function to clear buffer array
{
  for (int i=0; i<count;i++)
  { 
    buffer[i]=NULL;
  }                  // clear all index of array with command NULL
}

String GetInfo(unsigned char buff[14], int count)
{
  // remove stx checksum and etx and get name;
  String value = GetString(buff).substring(1,11); 
  String temp = GetData(value);
  return temp;
  //sd_card_write(temp + " » " +digitalClockDisplay());
}

String GetString(unsigned char* inStrReference)
{
  // convert unsigned char to string
  unsigned char* bufPtr = inStrReference; 
  String newstring = (char*)bufPtr;
  return newstring;
}

String GetData(String id)
{                       
  String bd[5][2] = {
    {
      "0F000C9C0E","Joao Pereira"                 }
    ,
    {
      "0F00088CD2","Ricardo Lopes"                }
    ,
    {
      "0F00086052","Pedro Rosas"                  }
    ,
    {
      "0F00096159","Filipe Macedo"                }
    ,
    {
      "0F000CF1F5","Mariana Gomes"                }
  };

  String data = id;

  for(int i=0; i<5;i++){
    if(bd[i][0]==id){
      data = bd[i][1];
    }
  }

  return data;

}

// clock functions:
String digitalClockDisplay(){ 
  String clock = String(hour()) + ":" + String(minute()) + ":" + String(second()) + " | " + String(day())+ "/" + String(month())+ "/" + String(year());
  return clock;
}

//void buzz(int targetPin, long frequency, long length) {
//  long delayValue = 1000000/frequency/2; // calculate the delay value between transitions
//  long numCycles = frequency * length/ 1000; // calculate the number of cycles for proper timing
//
//  for (long i=0; i < numCycles; i++){ // for the calculated length of time...
//    digitalWrite(targetPin,HIGH); // write the buzzer pin high to push out the diaphram
//    delayMicroseconds(delayValue); // wait for the calculated delay value
//    digitalWrite(targetPin,LOW); // write the buzzer pin low to pull back the diaphram
//    delayMicroseconds(delayValue); // wait againf or the calculated delay value
//  }
//}

void WriteOnSD(){
  /* Initiliase the SD card */
  if (!SD.begin(4)) 
  {
    /* If there was an error output this to the serial port and go no further */
    Serial.println("card failed");
    delay(2);
  }
  else
  {
      SDFileData.println("OK");
      SDFileData.close();   

      Serial.println("done");
      delay(2);
  }

}

This code already written on the card, but it still fails (random) for lack of memory.

Which memory? Flash memory, where your code goes? Or, SRAM, where arrays, variables, and literal strings are stored?

I'd guess that the issue is SRAM, and you have been told how to minimize that, by keeping literal strings out (by using the F() macro).

You need to do that, regardless of whether you think it will accomplish anything, or not. If it doesn't, then post the modified code, and we'll have a look at it again (and then recommend that you get a Mega).

PaulS:

This code already written on the card, but it still fails (random) for lack of memory.

Which memory? Flash memory, where your code goes? Or, SRAM, where arrays, variables, and literal strings are stored?

I'd guess that the issue is SRAM, and you have been told how to minimize that, by keeping literal strings out (by using the F() macro).

You need to do that, regardless of whether you think it will accomplish anything, or not. If it doesn't, then post the modified code, and we'll have a look at it again (and then recommend that you get a Mega).

This method is worse ... takes more memory...

When i talk memory = sketch size.. mean:

String GetInfo(unsigned char buff[14], int count)
{
  // remove stx checksum and etx and get name;
  String value = GetString(buff).substring(1,11); 
  String temp = GetData(value);
  return temp;
  //sd_card_write(temp + " » " +digitalClockDisplay());
}

String GetString(unsigned char* inStrReference)
{
  // convert unsigned char to string
  unsigned char* bufPtr = inStrReference; 
  String newstring = (char*)bufPtr;
  return newstring;
}

String GetData(String id)
{                       
  String bd[5][2] = {
    {
      "0F000C9C0E","Joao Pereira"                 }
    ,
    {
      "0F00088CD2","Ricardo Lopes"                }
    ,
    {
      "0F00086052","Pedro Rosas"                  }
    ,
    {
      "0F00096159","Filipe Macedo"                }
    ,
    {
      "0F000CF1F5","Mariana Gomes"                }
  };

  String data = id;

  for(int i=0; i<5;i++){
    if(bd[i][0]==id){
      data = bd[i][1];
    }
  }

  return data;

}

You seem to be under the mistaken impression that wrapping a string in a String instance will somehow involving less memory than the unwrapped string. That is not possible.

The only benefit of using the String class is that it is easier to manage what goes in the string, where. But, that is not how or why you are using it.

You really need to toss that crutch aside, and learn to do without it.