How to log the time of multiple valves with esp and sd card?

Im using the esp32s, an rtc3231 and an sd card
The overview of the project is:
I have 8 valves which i want to time for how long they have been on and save the times of each valve in an sd card. But how can I make it so that it writes in a different file for every valve.

The code is probably horrible sorry for that, but it is as follows

I've declared the pins in an array

int valvePins[8] = {0, 4, 15, 16, 17, 32, 34, 35};
int lastValveState[8];

then I set them as inputs and get their state in a forloop inside the void setup()

     for (int i = 0; i < 8; i++) {
    pinMode(valvePins[i], INPUT);
    lastValveState[i] = digitalRead(valvePins[i]);
  }

and in the void loop I use another for loop to go trough each pin and check if the state has changed, if it has then the code checks which valve its reading and writes it to the sd card and the time when the state has changed when it turns off then the time is also written to it.

void loop() 
{
  //RTC start
  for (int i = 0; i < 8; i++) 
  {
      int currentValveState = digitalRead(valvePins[i]);

      if (currentValveState != lastValveState[i]) 
      {
          DateTime now = rtc.now();

          if (currentValveState == HIGH){
              myFile = SD.open("times.txt", FILE_WRITE);
              if (myFile) 
              {
                  myFile.print("valve: ");
                  myFile.print(valvePins[i]);

                  // Format the time using sprintf
                  char timeBuffer[12];
                  sprintf(firsttimeBuffer, " %02u:%02u:%02u", now.hour(), now.minute(), now.second());
                  myFile.print(" ");
                  myFile.print(now.day());
                  myFile.print("/");
                  myFile.print(now.month());
                  myFile.print(" from ");
                  myFile.print(timeBuffer);

              } else { Serial.println("error opening times.txt");}
          }
          else{
          if (myFile) {
                  // Format the start time using sprintf
                  char startTimeBuffer[12];
                  sprintf(lastTimeBuffer, " %02u:%02u:%02u", now.hour(), now.minute(), now.second());
                  myFile.print(" to ");
                  myFile.println(startTimeBuffer);

                  myFile.close();
              } else { Serial.println("error opening times.txt"); }
          }

          delay(100);
          lastValveState[i] = currentValveState;
       }
  }

It is currently writing everything in the same file. To make it write in different ones i thought of just checking with if which valve it is and write in the file for that valve. Is there a shorter way of doing it?

Thanks in advance to everyone who is going to help! I'll be happy to explain further if i have missed somthing.

What is the point of having a separate file for each valve? That just multiplies the amount of work you have to do to get the data.

Write one file, with the valve number at the start of each start/stop timestamp record, and analyze the data in that file for any valve of interest. I would write the millis value rather than (or along with) the time of day, as it is so much easier to compute time differences.

If you write the file is .csv format, it can be directly read into any spreadsheet program, then sorted by valve number, etc.

A CSV-file can be imported in that way

timestamp, valvle1, valvle2, valve3
4653876,X,0,0
4708890,0,1,0
4845664,1,0,0
4945007,0,0,1

First columm the timestamp
second columm the values of valve1
third columm the values of valve2
fourth columm the values of valve3
etc.
etc.

or if you would prefer for each valve the ontime
whenever a valvle changes from opened to close set the ontime of this valvle to "ontime"
and all others to zero or a "blank space"

And then you have the states of all valves on one file

I bet it will be much easier to process the data if all data is in one file

best regards Stefan

I wanted them to be in different files so its easier for me to get the information, but knowing i can use spreadsheets that makes it a lot easier.

Thanks!

4945007,0,0,1

is this showiing the time and then the position of the 1 indicates which valve has been on

Yes.

This example shows the basic principle the name is program:

CSV: Comma Separated Values

You just insert commas ",", or semicolons ";" or any other special character that does not appear in the data itself and the import-function of Excel, LibreOffice-Calc or whatever table-calculation-software or database you would like to use can separate the values at the commas

Which means the import function puts all characters between two commas in its own columm

You can write whatever you want into the text-file
so another example would be

2023.07.12 , 15:38:42 , V1O, V2C, V3O, V4O
2023.07.12 , 16:07:10 , V1C, V2O, V3C, V4C

that will be imported this way

or

2023.07.12 ,  Hi Mom, at , 09:13:15 , valve 1 is opened , 
2023.07.12 ,  Hi Mom, at , 11:32:40 , valve 2 is opened , 

.
will be imported this way

You can add whatever characters and values you like to a String or an array of char or what I personally recommend a SafeString because the name is program too.

Using the String-variable-type eats up all RAM over time
and with arrays of chars you have to take care about array-boundaries very exactly to avoid memory corruption.

SafeString offer almost the same comfort as String but is safe to use

here is a little democode on how to use it

// SafeStrings are based on array of chars
// SafeStrings offer almost the same comfort as Strings
// but avoid some dis-advantages of varable-type String
// the name SafeString is PROGRAM They are safe to use

// with the alternatives "String" must not awlays but CAN 
// eat up memory over time which will make the code crash

// with zero-terminated array of chars (c_string)
// you have to take care of boundary checking yourself 
// otherwise your code will start to behave weird and this kind of bug is very hard to find
// you can read more about this here https://www.forward.com.au/pfod/ArduinoProgramming/ArduinoStrings/index.html#safestring
// and here https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

// very basic demo-code to show how to declare a SafeString-variable
// and how to assign text to them

// as a personal convention I use the suffix "_SS" to indicate 
// THIS IS A SAFESTRING-VARIABLE
// but you can name it whatever you like

#include "SafeString.h"
createSafeString(myTitle_SS, 64);  // reserve 64 bytes for the SafeString-variable
createSafeString(myString_SS, 32); // reserve 32 bytes for the SafeString-variable

int myInteger = -1234;
float myFloat = -987.009;


void setup() {
  Serial.begin(115200);
  Serial.println( F("Setup-Start") );
  Serial.println();

  myString_SS = F("fixed text directly assigned");
  Serial.print( F(" #") ); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println(F("#") ); // trailing double-cross "#" to show where the string REALLY ends


  myTitle_SS = F("content of an integer:");
  myString_SS = myInteger;

  Serial.println(myTitle_SS);
  Serial.print( F(" #" )); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println( F("#") ); // trailing double-cross "#" to show where the string REALLY ends



  myTitle_SS = F("content of a float:");
  myString_SS = myFloat;

  Serial.println(myTitle_SS);
  Serial.print( F(" #" )); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println( F("#") ); // trailing double-cross "#" to show where the string REALLY ends

  myTitle_SS = F("you can append more text with the +=-operator ");
  myString_SS = F("text ");
  myString_SS += myInteger;
  myString_SS += F(" ,");
  myString_SS += myFloat;

  Serial.println(myTitle_SS);
  Serial.print( F(" #" )); // leading double-cross "#" to show where the string starts
  Serial.print(myString_SS); 
  Serial.println( F("#") ); // trailing double-cross "#" to show where the string REALLY ends  
}

void loop() {

}

best regards Stefan

1 Like

just a thought but can i somehow send the file trough bluetooth using an app like serial bluetooth terminal or would i be able to just send the data inside the file.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.