datalogger for counter sensor with RTC HELP!

Good day everyone i prepared a code for a datalogger to determine honeybees entering a feeding station. It supposed to have a real time clock but as of now i want to fix some bugs on my present code. thanks!!

  1. On my csv format on the excel. lots of data are being stored because it logs every data repeatedly. I only want to log the number the counter was sensing.

  1. On my sensor B when one passes it counts two times. But same code as with sensor A i don't know why?

here's my code have patience please

//Program by Jeremy Blum
//www.jeremyblum.com
//SD Card Demonstration
//Some code from public domain work by Tom Igoe
//Assisted by Inigo D. Villanueva III
//Edited by Ignacio D. Villanueva III
//For thesis purpose entitled "
//Thesis members: James Santiago. Belen Cruz. Franzes Francisco, Kaye Agut

#include <SD.h>         //SD Card Library

//SPI SD Card Pins
  //MOSI = Pin 11
  //MISO = Pin 12
  //SCLK = PIN 13
  int CS_pin = 10;
  int pow_pin = 8;
  
// this constant won't change:
const int  buttonPin1 = 2;    // the pin that the pushbutton is attached to
const int  buttonPin2 = 5;

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
int buttonPushCounter1 = 0;   // counter for the number of button presses
int buttonState1 = 0;         // current state of the button
int lastButtonState1 = 0;     // previous state of the button


long lastEvent= 0; // The last time a bee has entered the feeding station
long interval= 300; // The debounce time



void setup() {

Serial.begin(9600);
  Serial.println("Initializing Card");
  //CS Pin is an output
  pinMode(CS_pin, OUTPUT);
  
  //SD Card will Draw Power from Pin 8, so set it high
  pinMode(pow_pin, OUTPUT);  
  digitalWrite(pow_pin, HIGH);
  
  //Initialize Card
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  // initialize the button pin as a input:
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  
  // initialize serial communication:
  Serial.begin(9600);
  
  //Write Log File Header
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", ,"); //Just a leading blank line, incase there was previous data
    String header = "FEEDING_STATION_1, FEEDING_STATION_2";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }  
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin1);
 
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) 
  {
    // if the state has changed, increment the counter
    if (buttonState == HIGH && millis() - lastEvent > interval)// Ignore this reading if it is too close to the last one
 {
	lastEvent= millis(); // a bee can be recorded) 
      // if the current state is HIGH then the button
      // wend from off to on:
     
      buttonPushCounter++;
      Serial.println("Bees are being detected entering Feeding Station A");
      Serial.print("number of bees that entered Feeding Station A:  ");
      Serial.println(buttonPushCounter);
    } 
    lastButtonState= buttonState;
  }
     buttonState1 = digitalRead(buttonPin2);
     if (buttonState1 != lastButtonState1)
   {    
    // if the state has changed, increment the counter
    if (buttonState1 == HIGH && millis() - lastEvent > interval)// Ignore this reading if it is too close to the last one
 {
	lastEvent= millis(); // a bee can be recorded) 
      // if the current state is HIGH then the button
      // wend from off to on:
   }  
      buttonPushCounter1++;
      Serial.println("Bees are being detected entering Feeding Station B");
      Serial.print("number of bees that entered Feeding Station B:  ");
      Serial.println(buttonPushCounter1);
   }

      lastButtonState1= buttonState1;
   
  
  
//Create Data string for storing to SD card
  //We will use CSV Format  
  String dataString = String(buttonPushCounter) + ", " + String(buttonPushCounter1); 
  
  
  //Open a file to write to
  //Only one file can be open at a time
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    Serial.println(dataString);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
 }

I don't know if these will address the problems you're seeing, but I see a few things that could be improved with your code:

  • Don't use the String class. It's buggy and eats up memory. Use character arrays instead, if you really need to store strings, or don't even bother (I don't see anything in your code that needs strings to work at all).
  • Use more descriptive and consistent variable names. Why, for example, are you using buttonPushCounter to count bees? Why is buttonPushCounter1 used for buttonPin2 for feeding station B? Try, for example, beeCounterA for beeSensorPinA for feeding station A.
  • Add variables for lastBeeCounterA and lastBeeCounterB.

Then you can do something like this (not compiled and tested, but the concept is sound):

if ((beeCounterA != lastBeeCounterA) || (beeCounterB != lastBeeCounterB))
  {
  logFile.print(beeCounterA);
  logFile.print(", ");
  logFile.println(beeCounterB);
  lastBeeCounterA = beeCounterA;
  lastBeeCounterB = beeCounterB;
  }

This will print a new log entry only when there's been a change to either beeCounterA or beeCounterB. Note that there's no need at all to use any kind of string construction here--you can print the first variable, then print a comma and space, then println the second variable; the println adds a newline character at the end of the line.

I really haven't read the entire post, really sleepy right now... but did saw one thing that disturbed me...

//SD Card will Draw Power from Pin 8, so set it high

pinMode(pow_pin, OUTPUT); 
  digitalWrite(pow_pin, HIGH);

DO NOT use digital pins as power supplies. Use controllable voltage regulator or a MOSFET switch circuit. You could find a lot in google about those two terms. The idea is to use the digital pin as a "flag" to tell whether the "switch" should be open or closed. Using digital pins as power supplies could and probably would destroy your peripheral device (that is being powered) and definitely your arduino board.

Your SD card, depending on the speed class could draw more then the limit of 40mAh of the digital pins.

Hello!

Thanks, i was wondering also if you could give me an insight about the RTC DS1307 that i will use. I wanna log only the time when my sensor had sensed something,

thankyou! :slight_smile:

Something like this should work:

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

char logString[30];
int beeCounterA = 0;
int lastBeeCounterA = 0;
int beeCounterB = 0;
int lastBeeCounterB = 0;
time_t t;

void setup()
{
  setSyncProvider(RTC.get);
  //open the card and logfile, and do the rest of your setup
}

void loop()
{
  //do whatever you do to read the counter devices
  if ((beeCounterA != lastBeeCounterA) || (beeCounterB != lastBeeCounterB))
  {
    t = now();
    sprintf(logString,"%.2d/%.2d/%.4d %.2d:%.2d:%.2d,%.3d,%.3d",
    month(t), day(t), year(t), hour(t), minute(t), second(t), beeCounterA, beeCounterB);
    logFile.println(logString);
    lastBeeCounterA = beeCounterA;
    lastBeeCounterB = beeCounterB;
  }
}

This logs complete date and time as mm/dd/yyyy hh:mm:ss, and gives three digits for both counters--you can adjust the sprintf statement to give a different format if you prefer. This will only log to the file when there's been a change in either beeCounterA or beeCounterB, and at that time it will log the date and time, and both counters.

This code isn't complete; I don't have the library or the code in there to open the SD card, create and open the file, read the counter devices, etc. But it should get you going.

//Program by Jeremy Blum
//www.jeremyblum.com
//SD Card Demonstration
//Some code from public domain work by Tom Igoe
//Assisted by Inigo D. Villanueva III
//Edited by Ignacio D. Villanueva III
//For thesis purpose entitled "
//Thesis members: James Santiago. Belen Cruz. Franzes Francisco, Kaye Agut

#include <SD.h>         //SD Card Library

//SPI SD Card Pins
  //MOSI = Pin 11
  //MISO = Pin 12
  //SCLK = PIN 13
  int CS_pin = 10;
  int pow_pin = 8;
  
// this constant won't change:
const int  buttonPinA = 2;    // the pin that the pushbutton is attached to
const int  buttonPinB = 5;

// Variables will change:
int buttonBeeCounterA = 0;   // counter for the number of button presses
int beeCounterA = 0;         // current state of the button
int lastBeeCounterA = 0;     // previous state of the button
int buttonBeeCounterB = 0;   // counter for the number of button presses
int beeCounterB = 0;         // current state of the button
int lastBeeCounterB = 0;     // previous state of the button


long lastEvent= 0; // The last time a bee has entered the feeding station
long interval= 300; // The debounce time



void setup() {

Serial.begin(9600);
  Serial.println("Initializing Card");
  //CS Pin is an output
  pinMode(CS_pin, OUTPUT);
  
  //SD Card will Draw Power from Pin 8, so set it high
  pinMode(pow_pin, OUTPUT);  
  digitalWrite(pow_pin, HIGH);
  
  //Initialize Card
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  // initialize the button pin as a input:
  pinMode(buttonPinA, INPUT);
  pinMode(buttonPinB, INPUT);
  
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  beeCounterA = digitalRead(buttonPinA);
 
  // compare the buttonState to its previous state
  if (beeCounterA != lastBeeCounterA) 
  {
    // if the state has changed, increment the counter
    if (beeCounterA == HIGH && millis() - lastEvent > interval)// Ignore this reading if it is too close to the last one
 {
	lastEvent= millis(); // a bee can be recorded) 
      // if the current state is HIGH then the button
      // wend from off to on:
     
      buttonBeeCounterA++;
      Serial.println("Bees are being detected entering Feeding Station A");
      Serial.print("number of bees that entered Feeding Station A:  ");
      Serial.println(buttonBeeCounterA);
    } 
    lastBeeCounterA= beeCounterA;
  }
     beeCounterB = digitalRead(buttonPinB);
     if (beeCounterB != lastBeeCounterB)
   {    
    // if the state has changed, increment the counter
    if (beeCounterB == HIGH && millis() - lastEvent > interval)// Ignore this reading if it is too close to the last one
 {
	lastEvent= millis(); // a bee can be recorded) 
      // if the current state is HIGH then the button
      // wend from off to on:
   }  
      buttonBeeCounterB++;
      Serial.println("Bees are being detected entering Feeding Station B");
      Serial.print("number of bees that entered Feeding Station B:  ");
      Serial.println(buttonBeeCounterB);
   }

      lastBeeCounterB= beeCounterB;
   
  
  //Write Log File Header
  File logFile = SD.open("DATALOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.print(buttonBeeCounterA);
    logFile.print(",");
    logFile.println(buttonBeeCounterB);
   

    Serial.print(buttonBeeCounterA);
    Serial.print(",");
    Serial.println(buttonBeeCounterB);






    		
 }
else

{
    logFile.print("LogFile cannot be opened");

	}

}

i wonder why there is no data being stored in my SD card, i have deleted the string and state it this way.. :cold_sweat: :cold_sweat: :cold_sweat: :cold_sweat:

This part:

logFile.print("LogFile cannot be opened");

Doesn't look like it will work--if the log file can't be opened, how are you going to print the error message to the log file?

danb35:
This part:

logFile.print("LogFile cannot be opened");

Doesn't look like it will work--if the log file can't be opened, how are you going to print the error message to the log file?

oh my, it must be Serial.println

anyway tried doing that. but still no data was being stored on the file name DATALOG.CSV
i wonder because when i use string it actually works, the only problem is that the data keep repeating so there's a lot of data being stored

You open the file. Where do you close it?

PaulS:
You open the file. Where do you close it?

 File logFile = SD.open("DATALOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.print(buttonBeeCounterA);
    logFile.print(",");
    logFile.println(buttonBeeCounterB); 
    logFile.close();
    
	
   

    Serial.print(buttonBeeCounterA);
    Serial.print(",");
    Serial.println(buttonBeeCounterB);






    		
 }
else

{
    Serial.println("LogFile cannot be opened");

	}

}

i followed it but same result as the string does. so many data being stored, tons of data. i wonder why?

same result as this

im thinking of using delay? refresh rate?
but my data will not be accurate i think.. arghh :cold_sweat: :cold_sweat:

iNgine:
i followed it but same result as the string does. so many data being stored, tons of data. i wonder why?

Because you're storing the two variables to your log file every time you run through the loop, without regard to whether either of them has changed. You'd want something like this:

if (beeCounterA != lastBeeCounterA) 
{
  // if the state has changed, increment the counter
  if (beeCounterA == HIGH && millis() - lastEvent > interval)// Ignore this reading if it is too close to the last one
  {
    lastEvent= millis(); // a bee can be recorded) 
    // if the current state is HIGH then the button
    // wend from off to on:
     
    buttonBeeCounterA++;
    Serial.println("Bees are being detected entering Feeding Station A");
    Serial.print("number of bees that entered Feeding Station A:  ");
    Serial.println(buttonBeeCounterA);
    //Write Log File Header
    File logFile = SD.open("DATALOG.csv", FILE_WRITE);
    if (logFile)
    {
      logFile.print(buttonBeeCounterA);
      logFile.print(",");
      logFile.println(buttonBeeCounterB);
      Serial.print(buttonBeeCounterA);
      Serial.print(",");
      Serial.println(buttonBeeCounterB);
    }
    else
    {
      Serial.println("LogFile cannot be opened");
    }
  }
    lastBeeCounterA= beeCounterA;
}

You'll want to make sure all the braces match here, but they look right. BTW, when posting your code, please use the Auto Format tool under the Tools menu first--it'll make the code a bit easier to follow.

You'll want to make sure all the braces match here, but they look right. BTW, when posting your code, please use the Auto Format tool under the Tools menu first--it'll make the code a bit easier to follow.

can't find the tools menu, thanks a lot. ill keep you posted.

im doing it one step at a time, i wish i can make it right so i can proceed to the RTC and the temperature/ humidity sensor.. thanks!! :slight_smile:

can't find the tools menu

The IDE has a menu bar across the top - File, Edit Sketch, Tools, and Help.

thanks so much dan35, my logger now looks like this. Much better than my old one.

however, i wish i could make something like this where you don't include the data of sensor A when the sensor B was incremented, like this

i hope you guys will never get tired of helping me, sorry for being a newbie :~ :~

however, i wish i could make something like this where you don't include the data of sensor A when the sensor B was incremented, like this

Hard to see in that tiny picture, but writing out the changed value in column 1 or column 2 or both is trivial. If one or more values change, you need to write a record. For each column, determine what to put in that column - a new value or a series of spaces. Then, write the record.

Hard to see in that tiny picture, but writing out the changed value in column 1 or column 2 or both is trivial. If one or more values change, you need to write a record. For each column, determine what to put in that column - a new value or a series of spaces. Then, write the record.

I modified my post. I wish i can create a logger like the one on the second picture. Can you suggest what can i do? thanks!!

I also wonder why one of the sensor does a double count when i pressed it once. But if i unplug one pin. It actually just works right. hmmmmmm.

Im using 2 pushbuttons as my sensor. In the program i used debouncing so i don't think its the problem.

The last posted code contains:

    if (logFile)
    {
      logFile.print(buttonBeeCounterA);
      logFile.print(",");
      logFile.println(buttonBeeCounterB);
      Serial.print(buttonBeeCounterA);
      Serial.print(",");
      Serial.println(buttonBeeCounterB);
    }

inside an if test:

if (beeCounterA != lastBeeCounterA)

It's hard to tell whether you have a similar prevBeeCounterB, or not. You would need one.

The variable names used in this application are terrible. I look at a name like buttonBeeCounterA and I think of a pin that a switch is connected to. I can't imagine why writing a pin number to the output file is of any interest.

I think that the best thing, at this point, is for you to post all of your code.

Changing the whether to log code is easy:

if (beeCounterA != lastBeeCounterA || beeCoutnerB != lastBeeCounterB)

In the code to actually log data:

   if(beeCounterA != lastBeeCounterA)
   {
      logFile.print(buttonBeeCounterA);
   }
   logFile.print(",");
   if(beeCoutnerB != lastBeeCounterB)
   {
      logFile.print(buttonBeeCounterB);
   }

But, like I said, I can't tell that the correct stuff is being tested, or that the correct stiff is being written to the file, since the names are horrible.

I think that the best thing, at this point, is for you to post all of your code.

im sorry for the terrible names, i changed it a little bit i hope it will be more understandable.

//Program by Jeremy Blum
//www.jeremyblum.com
//SD Card Demonstration
//Some code from public domain work by Tom Igoe
//Assisted by Inigo D. Villanueva III
//Edited by Ignacio D. Villanueva III
//For thesis purpose entitled "
//Thesis members: James Santiago. Belen Cruz. Franzes Francisco, Kaye Agut

#include <SD.h>         //SD Card Library

//SPI SD Card Pins
//MOSI = Pin 11
//MISO = Pin 12
//SCLK = PIN 13
int CS_pin = 10;
int pow_pin = 8;

// this constant won't change:
const int  buttonPinA = 3;    // the pin that the pushbutton is attached to
const int  buttonPinB = 5;

// Variables will change:
int CurrentNumberofBeesA = 0;   // counter for the number of button presses
int ActualStateofCounterA = 0;         // state of the button (Either HIGH or LOW)
int PreviousStateofCounterA = 0;     // previous state of the button (Either HIGH or LOW)
int CurrentNumberofBeesB = 0;   // counter for the number of button presses
int ActualStateofCounterB = 0;         // state of the button (Either HIGH or LOW)
int PreviousStateofCounterB= 0;     // previous state of the button (Either HIGH or LOW)


long lastEvent= 0; // The last time a bee has entered the feeding station
long interval= 300; // The debounce time



void setup() {

  Serial.begin(9600);
  Serial.println("Initializing Card");
  //CS Pin is an output
  pinMode(CS_pin, OUTPUT);

  //SD Card will Draw Power from Pin 8, so set it high
  pinMode(pow_pin, OUTPUT);  
  digitalWrite(pow_pin, HIGH);

  //Initialize Card
  if (!SD.begin(CS_pin))
  {
    Serial.println("Card Failure");
    return;
  }
  Serial.println("Card Ready");

  // initialize the button pin as a input:
  pinMode(buttonPinA, INPUT);
  pinMode(buttonPinB, INPUT);

  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  ActualStateofCounterA= digitalRead(buttonPinA);
  ActualStateofCounterB = digitalRead(buttonPinB);

  // compare the buttonState to its previous state
  if ((ActualStateofCounterA != PreviousStateofCounterA ) || (ActualStateofCounterB != PreviousStateofCounterB))
  {
    // if the state has changed, increment the counter
    if (ActualStateofCounterA == HIGH && millis() - lastEvent > interval)// Ignore this reading if it is too close to the last one
    {
      lastEvent= millis(); // a bee can be recorded) 
      // if the current state is HIGH then the button
      // wend from off to on:

      CurrentNumberofBeesA++;
      Serial.println("Bees are being detected entering Feeding Station A");
      Serial.print("number of bees that entered Feeding Station A:  ");
      Serial.println(CurrentNumberofBeesA);

    }
    {    
      // if the state has changed, increment the counter
      if (ActualStateofCounterB == HIGH && millis() - lastEvent > interval)// Ignore this reading if it is too close to the last one
      {
        lastEvent= millis(); // a bee can be recorded) 
        // if the current state is HIGH then the button
        // wend from off to on:
      }  
      CurrentNumberofBeesB++;
      Serial.println("Bees are being detected entering Feeding Station B");
      Serial.print("number of bees that entered Feeding Station B:  ");
      Serial.println(CurrentNumberofBeesB);
    }




    //Write Log File Header
    File logFile = SD.open("DATALOG.csv", FILE_WRITE);
    if (logFile)


    {

      if(ActualStateofCounterA != PreviousStateofCounterA)

        logFile.print(CurrentNumberofBeesA);
      logFile.print(", ");
      logFile.println(CurrentNumberofBeesB); 
      logFile.close();

      Serial.print(CurrentNumberofBeesA);
      Serial.print(", ");
      Serial.println(CurrentNumberofBeesB);

    }
    else

    {
      Serial.println("LogFile cannot be opened");

    }

    CurrentNumberofBeesA= ActualStateofCounterA;
    CurrentNumberofBeesB= ActualStateofCounterB;


  }

}