How to make Arduino1 send data to Arduino2, arduino2 save data to SD card ? Help

Hi,
i am doing the project which need to log all the data to the SD card however the logging’ s time is too long for each loop. So that i have idea that send all the data to arduino2, arduino2 will log all data to the SD card.
This is my quick sketch for that concept
sending arduino uno

String data = "";
float a=1112.4544; 
float b=2221.444;
float c=333333.12;
float d=444444.1;
float e=55555;
void serial_event()
{
  data= "";
  data= "<";
  data+= a;
  data+=",";
  data+=b;
  data+=",";
  data+=c;
  data+=",";
  data+=d;
  data+=",";
  data+=e;
  data+=",";
  data+= millis();
  data+= ">";
  Serial.println(data);
}
void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
}

void loop() {
serial_event();  // put your main code here, to run repeatedly:
delay(5);
}

receiving arduino mega

#include <SPI.h>
#include <SD.h>
#define CS_PIN 53

File dataFile;
String string_buffer = "";
float data[10];
String data_log ="";
boolean newData =false; //check if new data or not for install all data from sd card to arduino
const byte numChars = 20; //maximum character the one time arduino can load from sd card
char receivedChars[numChars]; // buffer character loading from sd card to arduino 
int Setpoint1_number = 0; // Setpoint for pressure of the lung 
int count =0;

void initialize_SDcard()
{
  while (!Serial) 
 {
  ; // wait for serial port to connect. Needed for native USB port only
 }
 Serial.print("Initializing SD card...");
 if (!SD.begin(CS_PIN)) // check SD select pin
 {
  Serial.println("initialization failed!");
  while (1);
 }
 Serial.println("initialization done.");
}
void initialize_loggingData()
{
   dataFile = SD.open("aduino.txt", FILE_WRITE);
  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println("hello vudeptrai serial arduino");
    dataFile.close();
    // print to the serial port too:
    Serial.println("printed to sd card");
  }
  else 
  {
    Serial.println("card need to be initialized");
    Serial.println("CHANGE SOEMTHING");
  }
}

void recvWithStartEndMarkers() // store setpoint from sd care file to setpoint1 array
{
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char delimiter = ',';
    char rc;
    while (Serial3.available() > 0 && newData == false) {
        rc = Serial3.read();
        if (recvInProgress == true) {
            if (rc != endMarker) {
              if (rc != delimiter)
                {
                  receivedChars[ndx] = rc;
                  string_buffer += receivedChars[ndx];
                  ndx++;
                }
                if (rc == delimiter){
                  data[count]=  string_buffer.toFloat();
                  string_buffer="";
                  ndx = 0;
                  delay(1); 
                  for (int i =0; i< numChars; i++)
                  {
                    receivedChars[i] = 0;
                  }
                  count ++;
                }          
            }
            else {
                data[count]=  atoi(receivedChars);
                for (int i =0; i< numChars; i++)
                  {
                    receivedChars[i] = 0;
                  }
                recvInProgress = false;
                ndx = 0;
                newData = true;
                Setpoint1_number = count +1;
                count =0;
            }
        }
         else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
    if (Setpoint1_number != 6)
    {
      Serial.println ("the format is not right");
    }
}

void setup() {
  Serial.begin (115200);
  Serial3.begin(115200);
  initialize_SDcard();
  initialize_loggingData();
  delay(2000);
}

void loop() {
  recvWithStartEndMarkers();
  newData =false;
  dataFile = SD.open("aduino.txt", FILE_WRITE);
  
  if (dataFile) {
    for (int i=0; i<11;i++)
    {
     dataFile.println(data[i]);
     Serial.print(data[i]);
     Serial.print("  ");
    }
     dataFile.close();
     Serial.println("");
  }
  else 
  {
    Serial.println("card need to be initialized");
  }

}

The reason i make delay(5)(maybe longer) in sending arduino,is the example of other function process’s time .
The result is a mess, you can see in the picture i attached.
please help me to solve this

initially comment out the saving to the SD card to check you can transmit and receive OK
it may also help to make the inter frame delay longer
once it is working you can add the saving to SD card

it may also be worth adding a sequence number to each frame so you can check if frames are lost and a CRC check on the end to check for corrupt frames

There is no need to concatenate all the data in the String named data. Just send the data with a series of Serial.print() statements like this

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with ‘\0’ (NULL).

And I suggest you don’t name your function serial_event() because the name is too easily confused with the Arduino function serialEvent() which is used for receiving data, not sending it. Why not name your function for what it does e.g. sendData()

…R

Horace: Thank you so much for give me idea to solve problem. However, i dont understand thoughtfully your idea or what you said. Can you explain more about that or give me some example.
Robin2: Thank you for giving me advice and some suggestion make my programing better. But i dont think that can help me to solve the problem

to add sequence numbers and CRC to a frame have a look at post #7 of

the project which need to log all the data to the SD card however the logging' s time is too long for each loop. So that i have idea that send all the data to arduino2, arduino2 will log all data to the SD card.

It's not clear to me that the two arduino approach solves anything. If the physical card write time is long, and disrupts the data acquisition, you won't be able to just pass the data to another arduino and expect it to log faster than the data can arrive.

Continuous high speed data logging without gaps due to the physical write to the card is not simple stuff. There are several examples of advanced techniques using multiple buffers, block writes, and binary files in the SdFat library examples files.

Can you please explain more about your project. What Arduino do you have? What data is being acquired with what frequency? How much will need to be stored.? How will the stored data be accessed?

You may wish to use another storage solution like external FRAM.

Don't attempt to hack Robin's recvWithStartEndMarkers(). Follow his examples.

Call recvWithStartEndMarkers() repeatedly till newData is true. Next write it to the file and set newData to false. For just saving the data, you don't have a need to parse the received data. You will need to increase the buffer size (numChars) to something like 64 to be able to receive a full message.

Other things to consider:

Write a timing program to measure how long opening a file, writing some data and closing the file takes. You might want to open the file once and close it on request. In that case throughput will be better but you will still experience a delay once the the data is physically written to the card. Hence this test program.

The 5 ms delay might be at the edge; your data is at least 50 characters long which will take 4.5 ms to transfer.

Don't use Serial.println() in the sender; the "\r\n" that it adds to the message is ignored by the receiver code but slows down your transmission a little (52 bytes minimum message lengh versus 50 bytes minimum message length); use Serial.print() instead.

cattledog:
Can you please explain more about your project. What Arduino do you have? What data is being acquired with what frequency? How much will need to be stored.? How will the stored data be accessed?

Sorry for missing the information so I will introduce a bit about my project. The main purpose of my project is to control the pressure and flow rate in the pipe with any number of setpoint (in the limit range) I set with anytime change.
I use 1 Arduino mega

  • Compute PID and command the Odrive (https://odriverobotics.com/) to control BLDC that closing and opening the valve.
  • command to 1 ESC that control fan using the servo library.
  • input: pressure sensor (analogRead or I2C)
  • After that log all data including pressure, flowrate,setpoitn, time,... to SD card.
    I wish to run PID loop about 10 millisecond, so that the void loop() is last less than 10 millisecond. however the function to logging data take about 15-20 milliseconds
    below is logging data function i used
void loggingData()
{
  dataString = ""; 
  dataString += String(output_pressure);
  dataString += ",";
  dataString += String(flow_rate1);
  dataString += ",";
  dataString += String(flow_rate2);
  dataString += ",";
   dataString += String(flow_sfm);
   dataString += (",");
  dataString += String(volume);
  dataString += (",");
  dataString += String(Setpoint1);
  dataString += ",";
  dataString += String(millis());
 File datafile = SD.open("datalog.txt", FILE_WRITE);
 // if the file is available, write to it:
 if (datafile) {
   datafile.println(dataString);
   datafile.close();
 }
 else 
 {
   Serial.println("card need to be initialized");
 }
}

Vu_Tran_110395:
I wish to run PID loop about 10 millisecond, so that the void loop() is last less than 10 millisecond. however the function to logging data take about 15-20 milliseconds

I think what you propose merely moves the problem rather than solving it, and this:

Thank you for giving me advice and some suggestion make my programing better. But i dont think that can help me to solve the problem

is a seriously stupid response. If your problem can be solved at all, it will involve to saving time in the receiver, but it won’t be helped by gumming up the transmitter.

One of the reasons why the whole thing is a mess is that you are opening and closing the SD each time around the loop, thereby both wasting time and inviting corruption. There is a post around here that is only a week or so old, which I believe actually details the amount of time you are wasting. Further, there is other timewasting, SD related, code that, if you have it at all, should be in setup, not the loop.

Arduino<>Arduino serial is not limited to 115200, people have run serial at about 500 000.

I think the most important thing you need to divulge, but have said nothing, is how long this needs to run for. If it is a short burst, you may get some joy swapping the Arduinos around and hold the variables in RAM to be sent to SD at leisure. You might also consider using a NodeMCU instead, which is a lot faster and has a lot more memory.

Then, perhaps the greatest timewaster is all the code in the receiver that involves the serial monitor.

Vu_Tran_110395:
below is logging data function i used

Using the String class on a Mega is going to bite you in *ss when you least expect it. See Reply #2.

...R