Having trouble in saving a sensor value at a specific time

Hi all,

I am using arduino Uno for displaying 100g load cell value in .96 OLED display . Communication is through I2C. I am using HX711 as ADC.

I am saving some data in csv file. The columns in csv are "millisecond", "Time (MM/DD/YYYY HH:MM:SS)" "weight (g)", "1 min weight"," Max weight(g)".

At the same time, I want to display in OLED display some information like " current value", " max value", and "file name" in the display. "Current value" is dynamic which is ever changing.
At the end of experiment, the display finally will be showing "maximum value for total 3 minute run", "value at 1 min" and "file name where the data is being saved".

But, now I am having trouble in saving 1 min(60000ms) weight data. I want to display this information at the end of experiment and save weight value at csv column that happens at 1 min(60000ms) time. But I am getting all 0 with both in csv file and in display.

I could not understand where in the code I am messing up. Attached is the code portion screenshot.

This whole data logging has some lag of around 300ms. It never saves exactly at 1 min(60000ms) time. But I can save weight value near to 1 min(60000ms+-300ms), that is okay for my case. How could I implement it?

I have attached the screenshot and code here. Can someone please help me?

excel2
excel

//TIME IS RIGHT INSIDE CSV FILE, MAX VALUE RIGHT, DISPLAY RIGHT WITH THIS PROGRAM AS OF 10/11/2011
//check font here: https://github.com/olikraus/u8g2/wiki/fntlist8x8


#include <Arduino.h>
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
  #include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
  #include <Wire.h>
#endif
#include <SD.h>
#include "RTClib.h"
#include "HX711.h"  //You must have this library in your arduino library folder


//---------------------------------------------------------------------------
#define DURATION 0.020               //3 minutes in hours=0.05hr; 4 min in hr=0.0666667 hr,5  min=0.0833333hour, 10 min=0.166667 hour                 //Number of minutes, expressed/converted into hours, here 2 hours you want this program to run once the button is pressed
#define LOG_INTERVAL 20              //Milliseconds between entries (reduce to take more/faster data)
#define SYNC_INTERVAL 50             // millis between calls to flush() - to write data to the card
#define ECHO_TO_SERIAL 1             //Echo data to serial port, Easy method to turn serial printing on and off. Set to 0 if you don't want to print to the Serial Monitor
uint32_t syncTime = 0;               // time of last sync()
uint32_t start_time;
uint32_t currentTime;
int counter = 0;

//---------------------------------------------------------------------------
RTC_DS1307 RTC;                     //define the Real Time Clock object
const int chipSelect = 10;          //SD chip select;for the data logging shield, we use digital pin 10 for the SD cs line
char timestamp[30];
char filename[30];
const int pushbutton = 8;
const int done_light = 9;
float maxi = 0;
char val1 = 0;
char time1=0;
/***All the variables for voltage reading function***/
//the logging file
File bhoomiFile;
//-------------------Hx711 pins-----------------------------------------------
#define DOUT  3
#define CLK  2
HX711 scale;
float calibration_factor =7381.000195;//7252.100097;//7311.899902;// 7311.899902;//7303.299316;//7286.200195;//6981.299804;//7037.143066;//7311.899902; //7383.399902;//7370.040039; //7370.379882; // for 100g load cell

//--------------------DISPLAY--------------------------------------------------
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);


//------------------------SETUP--------------------------------------------
//-------------------------------------------------------------------------
void setup(){
  scale.begin(DOUT, CLK);
  Serial.begin(9600);                         //Initialize the serial communication
  u8x8.clear();
  u8x8.begin();
  Wire.begin();                        //Wire.begin: Initiate the Wire library and join the I2C bus as a master or slave.
  
  Serial.println("Press T to tare");
  scale.set_scale(calibration_factor);  //Calibration Factor obtained from first sketch
  scale.tare();             //Reset the scale to 0
        #if ECHO_TO_SERIAL
          Serial.println("Press button to start");                                //Prompt user to press button
        #endif
  pinMode(pushbutton, INPUT);                 //Set pushbutton as Input
  pinMode(done_light, OUTPUT);                //Set the LED as an output
  digitalWrite(done_light, LOW);              //Make sure the LED is off when we start the program
  
  while (digitalRead(pushbutton)) {};  //Wait for pushbutton input
        #if ECHO_TO_SERIAL
          Serial.println("(BUTTON PRESSED!)"); //Once pressed, display a message saying so
        #endif
                                           
  SD_INIT();
  createFile();
 
  //-----------------connect to RTC----------------------
  if (!RTC.begin()){                    //RTC.begin initializes the internal RTC. It needs to be called before any other RTC library methods
      bhoomiFile.println("RTC failed");
      }
   
  //   RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));         //----uncomment this command if you need to adjust the time with RTC running----//
   
  //if (! RTC.isrunning())                                    //----uncomment this command if you need to adjust the time when RTC is not running----//
  //    {
  //     Serial.println("RTC is NOT running, let's set the time!");
  //     // When time needs to be set on a new device, or after a power loss, the following line sets the RTC to the date & time this sketch was compiled
  //     RTC.adjust(DateTime(F(__DATE__), F(__TIME__))); //This line sets the RTC with an explicit date & time, for example to set 
                                                         //RTC.adjust(DateTime(2014, 1, 21, 3, 0, 0));  January 21, 2014 at 3am you would call: 
  //     }
 
   bhoomiFile.println("millisecond,Time (MM/DD/YYYY HH:MM:SS), weight (g), 1 min weight, Max weight(g)");        //If RTC initializes successfully...set this as a header in the file
        #if ECHO_TO_SERIAL
          Serial.println("millisecond,Time (MM/DD/YYYY HH:MM:SS), weight (g), Max weight(g)");
        #endif //ECHO_TO_SERIAL
   start_time = millis();              //The very next step after this will be the data recording
   }


//-------------------------------LOOP---------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
void loop(){  
  for (start_time; (millis() - start_time) < (DURATION * 60 * 60 * 1000L); ) //Below: As long as current time - start time < required duration, keep recording the data
                                                                             //To have record time in HOURS: (DURATION * 60 * 60 * 1000L)
  doTheThing();
  u8x8.clear();
  while (1)  {
    #if ECHO_TO_SERIAL
        Serial.println("ALL DONE");           //Once the set amount of time has passed, display message saying so
    #endif //ECHO_TO_SERIAL
    digitalWrite(done_light, HIGH);
    
    //-------DISPLAY MAX VALUE--------
    u8x8.setFont(u8x8_font_8x13B_1x2_f); // big font
    u8x8.setCursor(0, 32);
    //u8x8.print("          g Max   ");                  //Unit in gram
    u8x8.print("       gMax 3min");                  //Unit in gram
    u8x8.print(maxi       , 3);  //read upto 4 decimal point

    //-------DISPLAY 1 min VALUE--------
    u8x8.setFont(u8x8_font_8x13B_1x2_f); // big font
    u8x8.setCursor(0, 2);
    //u8x8.print("          g Max   ");                  //Unit in gram
    u8x8.print("       g 1min   ");                  //Unit in gram
    u8x8.print( val1     , 3);  //read upto 4 decimal point


    //-------DISPLAY STORING DONE INFORMATION--------

//    u8x8.setFont(u8x8_font_8x13B_1x2_f); // big font
//    u8x8.setCursor(0, -32);
//    u8x8.print(" Done 3 min ");
//    u8x8.setCursor(0, 5);
    //u8x8.print(" 3 min ");
    
      u8x8.setFont(u8x8_font_8x13B_1x2_f);
      u8x8.setCursor(0, 22);
      u8x8.print(filename);
//      for (int i=0;i<sizeof(filename);i++)
//        u8x8.print(filename[i]);
        
     }
}



//------------------------------------FUNCTIONS-------------------------------------------
//------------------------------------------------------------------------------------
void error(char *str){
  Serial.print("error: ");
  Serial.println(str);
  while (1);
  }


//-----------------------FUNCTION SD CARD INITIALIZATION---------------------------------------
//------------------------------------------------------------------------------------
void SD_INIT(){
//  Serial.print("Initializing SD card...");
  pinMode(chipSelect, OUTPUT);
//  Serial.println("card initialized.");                            //If SD.begin is successful
  //Check if the card is present and can be initialized:
  if (!SD.begin(chipSelect))  {                                  //SD.begin initializes the SD library and card; Returns 1 on success, 0 on failure
       u8x8.setFont(u8x8_font_courR18_2x3_r);
       u8x8.setCursor(3, 19);                                                   
       u8x8.println("No SD");
       return;
       }
  }

//-----------------------FUNCTION FILE CREATION---------------------------------------
//------------------------------------------------------------------------------------
void createFile(){
      strcpy(filename, "00.CSV");
      for (uint8_t i = 0; i < 100; i++)  {                               //Make a new file every time the Arduino starts up, Goes from 00 to 199
          filename[0] = '0' + ((i / 10) % 10);
          filename[1] = '0' + ((i / 1) % 10);
//        filename[2] = '0' + ((i / 1) % 10);
//        filename[3] = '0' + (i % 10);
          if (!SD.exists(filename)) {                                    //SD.exists() tests whether a file or directory exists on the SD card
              bhoomiFile = SD.open(filename, FILE_WRITE);                //SD.open() opens a file on the SD card. If the file is opened for writing,
                                                                         //it will be created if it doesn't already exist (but the directory containing it must already exist).
                                                                        //FILE_WRITE enables read and write access to the file
              break;  // leave the loop!
              
          }
      }
      if (!bhoomiFile){                                                //If file couldn't be opened/created
              error("couldn't create file");
      }
      
      //-----------LOG FILE NAME BOTH IN SERIAL PORT AND DISPLAY-----
      Serial.print("  Logging to: ");                                   //Otherwise, display the name of the file generated
      Serial.print(filename);
      u8x8.setFont(u8x8_font_8x13B_1x2_f);
      u8x8.setCursor(2, 22);
      u8x8.print(filename);
//      delay(500);
}

//-----------------------FUNCTION DO THE THING---------------------------------------
//------------------------------------------------------------------------------------
void doTheThing() {  /*uncomment lower IF statement if you want to set up time for your RTC. IF the RTC battery is being removed, 
                     it will set the time to 1/1/00 like this. But after uncommenting and compiling,complilation time will be current time and clock will start acting*/

  //   if (! RTC.isrunning())
  //       {
  //             Serial.println("RTC is NOT running, let's set the time!");
  //             // When time needs to be set on a new device, or after a power loss, the
  //             // following line sets the RTC to the date & time this sketch was compiled
  //             RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
  //             // This line sets the RTC with an explicit date & time, for example to set
  //             // January 21, 2014 at 3am you would call:
  //             // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  //       }

    DateTime now = RTC.now();
    delay((LOG_INTERVAL - 1) - (millis() % LOG_INTERVAL));//delay for the amount of time we want between readings
    //sprintf(timestamp, "%02d:%02d:%02d %2d/%2d/%2d \n", now.hour(), now.minute(), now.second(), now.month(), now.day(), now.year() - 2000);
    //Serial.println(timestamp);
    
    bhoomiFile.println(); //WITHOUT THIS INSTRUCTION,CSV DATA WILL BE SAVED  ROWWISE,, NOT COLUMNWISE 
    
    //--------LOG ALL MILISECOND IN ONE COLUMN IN CSV FILE--------
    bhoomiFile.print("");
    bhoomiFile.print(millis(), DEC);
    bhoomiFile.print(" , ");
    
    //--------LOG DATE& TIME IN ANOTHER COLUMN IN CSV FILE--------
    bhoomiFile.print("  ");                  //This space is important. If you remove this, the seconds will not be recorded in the log file
    bhoomiFile.print(now.month(), DEC);
    bhoomiFile.print("/");
    bhoomiFile.print(now.day(), DEC);
    bhoomiFile.print("/");
    bhoomiFile.print(now.year(), DEC);
    bhoomiFile.print(" ");
    bhoomiFile.print(now.hour(), DEC);
    bhoomiFile.print(":");
    bhoomiFile.print(now.minute(), DEC);
    bhoomiFile.print(":");
    bhoomiFile.print(now.second(), DEC);
    bhoomiFile.print("");
    bhoomiFile.print(millis(), DEC);
    bhoomiFile.print("");
    
    //---------- Log LOAD CELL MAXIMUM reading---------------------------
    bhoomiFile.print(", ");                           //Unit in gram
    float currentReading = scale.get_units();
    currentTime=millis();
    bhoomiFile.print(currentReading * 1, 4);        //read upto 4 decimal
      if (currentReading < maxi)  {
        maxi = maxi;
        }
      else if (currentReading >= maxi)  {
        maxi = currentReading;
        }
        
    if (currentTime >50800 && currentTime <60200) {
              val1=currentReading;
     }
   
    bhoomiFile.print(", ");                           //Unit in gram
    bhoomiFile.print(val1, 4);      //read upto 4 decimal
        
    //----LOG LOAD CELL MAX READING IN CSV FILE AND DISPLAY ---------------
    
    bhoomiFile.print(", ");                           //Unit in gram
    bhoomiFile.print(maxi, 4);      //read upto 4 decimal
    u8x8.setFont(u8x8_font_8x13B_1x2_f);//small font
    u8x8.setCursor(0, 3);
    u8x8.print("          g Max   ");                  //Unit in gram
    u8x8.print(maxi, 3);  //read upto 4 decimal point
    
    
    //----LOG LOAD CELL IN CSV FILE AND DISPLAY LOAD CELL MAX READING---------------
          #if ECHO_TO_SERIAL
            Serial.print(", ");
            Serial.println(scale.get_units() * 1, 4);       //read upto 4 decimal
            Serial.print("g ");                           //Unit in gram
          #endif //ECHO_TO_SERIAL
    
    u8x8.setFont(u8x8_font_courR18_2x3_r); // big font
    u8x8.setCursor(90, 32);
    u8x8.print("         g ");                 //Unit in gram
    u8x8.print(scale.get_units() * 1, 3);  //read upto 4 decimal point
    
          #if ECHO_TO_SERIAL
            Serial.print(", ");
            Serial.print(maxi, 4);      //read upto 4 decimal
            Serial.print("g ");                           //Unit in gram
          #endif //ECHO_TO_SERIAL
    delay(100);


    
    //--------------CLOSE CSV FILE BY FLUSHING---------------------------------------
    if ((millis() - syncTime) < SYNC_INTERVAL) return;
    syncTime = millis();
    bhoomiFile.flush();               //flush() ensures that any bytes written to the file are physically saved to the SD card
                                      //When you use file.write(), it doesn't write to the card until you flush() or close().
                                      //Whenever you open a file, be sure to close it to save your data.
                                  
    }

Well that's an unconventional way to handle blink without delay.

Why not just:

while((millis() - start_time) < (DURATION * 60 * 60 * 1000L))

But then it hits the while(1) right after that and the program is done.

I don't understand your flow. Can you explain in plain english how you think this code works?

1 Like

Thanks for your reply.
I want to save weight data in excel file. The columns in excel file will be "millisecond", "Time (MM/DD/YYYY HH:MM:SS)" "weight (g)" "1 min weight"," Max weight(g)".

At the same time, I want to display " current value", " max value upto current time", and file name in the display.
At the end of experiment, the display finally will be showing "maximum value for total 3 minute run", "value at 1 min" and "file name where the data is being saved".

I wanted to implement all of these things.

That's a great explanation of what you want. Now explain how you think this code does that. Walk through it and explain each part.

Don't you already have a thread open on this project?

Yes, I have another thread with same project with another issue. But that issues are already solved and this thread is with different issue. Here is the link of the thread Help need to display file name after experiment finishes


#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>
#include <SD.h>
#include "RTClib.h"
#include "HX711.h"  

#define DURATION (1 * 60 * 1000L)   //Number of minutes

RTC_DS1307 RTC;
const int chipSelect = 10;          //SD chip select;for the data logging shield, we use digital pin 10 for the SD cs line
char filename[10];
const int pushbutton = 8;
const int done_light = 9;
float maxi = 0;
float currentReading = 0;

File bhoomiFile;

#define DOUT  3
#define CLK  2
HX711 scale;
const float calibration_factor = 7381.000195;

U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);


void setup() {     //-------------------------------------------------------------------------
  scale.begin(DOUT, CLK);
  u8x8.clear();
  u8x8.begin();
  Wire.begin();

  scale.set_scale(calibration_factor);  //Calibration Factor obtained from first sketch
  scale.tare();             //Reset the scale to 0
  pinMode(chipSelect, OUTPUT);
  pinMode(pushbutton, INPUT_PULLUP);                 //Set pushbutton as Input
  pinMode(done_light, OUTPUT);                //Set the LED as an output
  digitalWrite(done_light, LOW);              //Make sure the LED is off when we start the program

  while (digitalRead(pushbutton));  //Wait for pushbutton input

  if (!SD.begin(chipSelect) || !RTC.begin())  {
    u8x8.setFont(u8x8_font_courR18_2x3_r);
    u8x8.setCursor(3, 19);
    u8x8.println("No SD or RTC");
  }

  createFile();
  start_time = millis();
}

void error(char *str) {
  Serial.print("error: ");
  Serial.println(str);
  while (1);
}

void createFile() {
  strcpy(filename, "00.CSV");
  for (uint8_t i = 0; i < 100; i++)  {                 //Make a new file every time the Arduino starts up, Goes from 00 to 99
    filename[0] = '0' + i / 10;
    filename[1] = '0' + i % 10;
    if (!SD.exists(filename)) {
      bhoomiFile = SD.open(filename, FILE_WRITE);
      bhoomiFile.println("millisecond,Time (MM/DD/YYYY HH:MM:SS), weight (g), Max weight(g)");        //If RTC initializes successfully...set this as a header in the file
      bhoomiFile.close();
      return;
    }
  }
  if (!bhoomiFile)error("couldn't create file");
}


void loop() {//----------------------------------------------------------------------------------------------------
  currentReading = scale.get_units();
  if (currentReading > maxi)maxi = currentReading;
  u8x8.clear();
  u8x8.setFont(u8x8_font_8x13B_1x2_f);//small font
  u8x8.setCursor(0, 3);
  u8x8.print(maxi, 3);
  u8x8.print("g Max   ");

  u8x8.setFont(u8x8_font_courR18_2x3_r); // big font
  u8x8.setCursor(90, 32);
  u8x8.print(scale.get_units(), 3);
  u8x8.print("g ");

  //-------DISPLAY MAX VALUE--------
  u8x8.setFont(u8x8_font_8x13B_1x2_f); // big font
  u8x8.setCursor(0, 32);
  u8x8.print(maxi       , 3);
  u8x8.print("gMax 3min");

  u8x8.setFont(u8x8_font_8x13B_1x2_f);
  u8x8.setCursor(0, 22);
  u8x8.print(filename);

  if (millis() - start_time) >= DURATION) {
    start_time += DURATION;
    Logging();
  }

  delay(100);
}

void Logging() {          //next time do not mix tasks together
  DateTime now = RTC.now();
  bhoomiFile = SD.open(filename, FILE_WRITE);

  //--------LOG ALL MILISECOND IN ONE COLUMN IN CSV FILE--------
  bhoomiFile.print(millis(), DEC);
  bhoomiFile.print(" , ");

  //--------LOG DATE& TIME IN ANOTHER COLUMN IN CSV FILE--------
  bhoomiFile.print(now.month(), DEC);
  bhoomiFile.print("/");
  bhoomiFile.print(now.day(), DEC);
  bhoomiFile.print("/");
  bhoomiFile.print(now.year(), DEC);
  bhoomiFile.print(" ");
  bhoomiFile.print(now.hour(), DEC);
  bhoomiFile.print(":");
  bhoomiFile.print(now.minute(), DEC);
  bhoomiFile.print(":");
  bhoomiFile.print(now.second(), DEC);

  bhoomiFile.print(", ");                           //Unit in gram
  bhoomiFile.print(currentReading , 4);        //read upto 4 decimal

  bhoomiFile.print(", ");                           //Unit in gram
  bhoomiFile.print(maxi, 4);      //read upto 4 decimal
  bhoomiFile.flush();               //flush() ensures that any bytes written to the file are physically saved to the SD card
  bhoomiFile.close();
}

Thanks @kolaha .
Your code looks so neat and clean. Unfortunately, it does not run and I do not know where the problem is.

what could that mean?

Sorry I need to rephrase what I said. It runs, not no file is being created.

any message on display?

nope. Just how much memory is being used.

" Sketch uses 28652 bytes (88%) of program storage space. Maximum is 32256 bytes.
Global variables use 1481 bytes (72%) of dynamic memory, leaving 567 bytes for local variables. Maximum is 2048 bytes."

TFT display, on the device

Display shows nothing. Complete black

how is display connected, SPI or I2C?

Its i2c connection

i don't think so.
insert this line:

#include <SPI.h>

Why do you think so?

i removed this line from your working code. now you has no output on screen. savvy?

It is actually with push button input. I commented

while (digitalRead(pushbutton)); 

this line and now I see the screen. Actually, i do not use any pushbutton in circuit to start the program.

Anyway, it displays something, but do not store any value in excel file. I am adding the screenshot here.
Screenshot excel

Actually what I want to do is adding another cell for 1 min value. Could you please help me how can I store just 1 min value(any near time) value in another cell in excel file?

Lets say, I am going to save a sensor data for 3 min(180000ms) in csv file. If for some reason I have to save 1 min(60000ms) data in csv in a seperate column corresponding to 1 min(60000ms) time, then, how to write the code for arduino uno?

When I try to get 60000ms data, it might need to get the value from averaging, as arduino has some lag. I have attached a screenshot to give an idea what I want to do. I want to find out what the Y value is
1 min value