Start/Stop button for writing data to card

Hello,

I have arduino pro mini (3.3V) , MicroSD breakout board, a HSC differential pressure sensor 3.3V and a DS3231. I have programmed the arduino to read the pressure values from the pressure sensor and write the values to the SD card along with the date and time from DS3231. I am using a Li ion battery 3.7V ,1200mAh to power these. I have connected a external reset button since my arduino will be in an enclosure.

When I insert a SD card to the microSD board, and press the external reset button, it starts writing the values to the SD card. To stop writing the values to the SD card, I press external reset button and it stops for few microseconds and before I remove the card from the breakout board, it continues to start writing the values again.

I have tried to program a on/off button so that when I press the button, an led should glow and only then it will start writing to the SD card . If the button is pressed again, the led should stop glowing and it should stop writing the data to the SD card. (like a start/stop button for writing data to SD card).

This doesn't seem to work when I upload the code to the arduino. I can post the pictures of the circuit if necessary.

Thank you

Wouldn't it be easier to use a toggle switch? pos1 = write data pos2 = don't write data

Yes, thats a good option.

Is the code that I am using for the push button correct? Is there something wrong with the program?

I connected the push button to pin 7 on arduino Promini and led to pin 9.

dpoornima:
I connected the push button to pin 7 on arduino Promini and led to pin 9.

Simple schematic is required.

Hello,
I will try to upload a better picture as soon as possible.

In this one, it shows the SD card breakout board, external push button (for reset), push button(pin 7) for controlling the led (at pin 9) and writing data and battery.

It sounds to me like the debounce is not working. Could you try a longer interval and see if the behavior changes?

like a longer delay time ?

It looks like the library uses a default debounce interval of 10 ms. You can set it higher like this:

button.interval(20);

You should probably put just your button code in a simple program and see if there are two button pushes being read when you only press it once. If that's the case try higher values for the interval.

Is the code that I am using for the push button correct?
Is there something wrong with the program?

I see two issues with the program. The first is writing to an SD card after removal and replacement. You must call sd.begin() after you do that. You are using reset to handle that, because it is the way to call sd.begin() multiple times with SD.h. You can use the button to turn off the logging, but do not use it to turn it back on. Press reset instead. Setup() should be written to run with logging enabled.

There are ways to call SD.begin() a second time without using reset. See this thread which discusses those issues. http://forum.arduino.cc/index.php?topic=239157.0

The second issue is that the setup and syntax for using Bounce2.h doesn’t look correct. Try these modifications to your code and see if you this doesn’t get you closer to success.

#include <Bounce2.h>
Bounce button = Bounce(); //instantiate a Bounce object

#include <SPI.h>
#include <SD.h>
#define FILE_BASE_NAME "Data"
#include <Wire.h>
#include <RTClib.h>
#define DS3231_Address 0x68
#define HSCDDRD005PD3A3_I2C 0x38
#define OUTPUT_MIN 1638.4        // 1638 counts (10% of 2^14 counts or 0x0666)
#define OUTPUT_MAX 14745.6       // 14745 counts (90% of 2^14 counts or 0x3999)
#define PRESSURE_MIN -5
#define PRESSURE_MAX +5


unsigned long time; //declaring to display milliseconds

RTC_DS3231 rtc;

int chipSelect = 10;
File file;
int BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char filename[] = FILE_BASE_NAME "00.csv";

const byte LedPin = 9;
const byte ButtonPin = 7;
//Bounce button;
//bool logFlag = false;

bool logFlag = true;//write SD on setup

void buttonCheck()
{
  button.update();
  if (button.fell())
  {
    if (logFlag == true)
    //logFlag = !logFlag;//do not toggle log flag turn off only, turn on with reset
    logFlag = false;
    digitalWrite(9, logFlag);
  }
}

void setup()
{
  Wire.begin(); // wake up I2C bus
  delay (500);
  Serial.begin(9600);
  Serial.println ("Sketch has started");


  //button.attach(7,INPUT_PULLUP);
  pinMode(ButtonPin, INPUT_PULLUP); //separate pinMode from attachment
  button.attach(ButtonPin);
  button.interval(20);//20 ms debounce interval

  pinMode ( 9, OUTPUT);

  if (rtc.lostPower())
  {
    Serial.println("RTC lost power,set the time");
    //rtc.adjust(DateTime(2016,4,20,02,16,00));
  }
  delay(10);

  //if (logFlag)
  //{
  if (!SD.begin(10))
  {
    Serial.println(F("begin failed"));
    return;
  }

  while (SD.exists(filename)) {
    if (filename[BASE_NAME_SIZE + 1] != '9') {
      filename[BASE_NAME_SIZE + 1]++;
    }
    else if (filename[BASE_NAME_SIZE] != '9') {
      filename[BASE_NAME_SIZE + 1] = '0';
      filename[BASE_NAME_SIZE]++;
    }
    else {
      Serial.println(F("Can't create file name"));
      return;
    }



    File file = SD.open(filename, FILE_WRITE);
    DateTime now = rtc.now();
    file.print(now.year(), DEC);
    file.print('/');
    file.print(now.month(), DEC);
    file.print('/');
    file.print(now.day(), DEC);
    file.print(',');
    file.print(now.hour(), DEC);
    file.print(':');
    file.print(now.minute(), DEC);
    file.print(':');
    file.print(now.second(), DEC);
    file.println();
    file.print("Time( ms)");
    file.print(',');
    file.print("Presuure (mmhg)");
    file.println();
    file.close();

    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(',');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

  }
  //} //remove brace from if logFlag

}


void loop()
{

  float pressure, temperature;
  float pressure_mmhg;


  //send a request
  Wire.beginTransmission(HSCDDRD005PD3A3_I2C);
  Wire.write(1);  // send a bit asking for register one, (as specified by the pdf)
  Wire.endTransmission();
  // now get the data from the sensor
  delay (20);

  Wire.requestFrom(HSCDDRD005PD3A3_I2C, 4);

  byte a     = Wire.read(); // first received byte stored here ....Example bytes one: 00011001 10000000
  byte b     = Wire.read(); // second received byte stored here ....Example bytes two: 11100111 00000000
  byte c     = Wire.read(); // third received byte stored here
  byte d     = Wire.read(); // fourth received byte stored here
  byte status1 = (a & 0xc0) >> 6;
  int bridge_data = ((a & 0x3f) << 8) + b;
  int temperature_data = ((c << 8) + (d & 0xe0)) >> 5;
  pressure = 1.0 * (bridge_data - OUTPUT_MIN) * (PRESSURE_MAX - PRESSURE_MIN) / (OUTPUT_MAX - OUTPUT_MIN) + PRESSURE_MIN;
  pressure_mmhg = 51.71484 * pressure;
  temperature = (temperature_data * 0.0977) - 50;
  time = millis();

 
  buttonCheck(); //you must call buttonCheck in loop)
  if (logFlag)
  {
    File file = SD.open(filename, FILE_WRITE);
    if (file)
    {
      Serial.print(time);
      Serial.print(',');
      Serial.println(pressure_mmhg);

      file.print(time);
      file.print(',');
      file.print(pressure_mmhg);
      file.println();
      file.close();
    }

    else
    {
      Serial.print("Button not pressed");
    }
  }
}

Just got a PM about this but I’ll answer it here.

The code he/she send me after a heavy cleanup (ctrl+t…) because it was completely unreadable

#include <Bounce2.h>
#include <SPI.h>
#include <SD.h>
#define FILE_BASE_NAME "Data"
#include <Wire.h>
#include <RTClib.h>
#define DS3231_Address 0x68
#define HSCDDRD005PD3A3_I2C 0x38
#define OUTPUT_MIN 1638.4        // 1638 counts (10% of 2^14 counts or 0x0666)
#define OUTPUT_MAX 14745.6       // 14745 counts (90% of 2^14 counts or 0x3999)
#define PRESSURE_MIN -5
#define PRESSURE_MAX +5


unsigned long time; //declaring to display milliseconds

RTC_DS3231 rtc;

int chipSelect = 10;
File file;
int BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char filename[] = FILE_BASE_NAME "00.csv";

const byte LedPin = 9;
const byte ButtonPin = 7;
Bounce button;
bool logFlag = false;

void buttonCheck() {

  button.update();
  if (button.fell())
  {
    logFlag = !logFlag;
    digitalWrite(9, logFlag);
  }
}



void setup()
{
  Wire.begin(); // wake up I2C bus
  delay (500);
  Serial.begin(9600);
  Serial.println ("Sketch has started");


  button.attach(7, INPUT_PULLUP);
  pinMode ( 9, OUTPUT);

  if (rtc.lostPower())
  {
    Serial.println("RTC lost power,set the time");
    //rtc.adjust(DateTime(2016,4,20,02,16,00));
  }
  delay(10);
  if (logFlag)
  {
    if (!SD.begin(10))
    {
      Serial.println(F("begin failed"));
      return;
    }

    while (SD.exists(filename)) {
      if (filename[BASE_NAME_SIZE + 1] != '9') {
        filename[BASE_NAME_SIZE + 1]++;
      }
      else if (filename[BASE_NAME_SIZE] != '9') {
        filename[BASE_NAME_SIZE + 1] = '0';
        filename[BASE_NAME_SIZE]++;
      }
      else {
        Serial.println(F("Can't create file name"));
        return;
      }



      File file = SD.open(filename, FILE_WRITE);
      DateTime now = rtc.now();
      file.print(now.year(), DEC);
      file.print('/');
      file.print(now.month(), DEC);
      file.print('/');
      file.print(now.day(), DEC);
      file.print(',');
      file.print(now.hour(), DEC);
      file.print(':');
      file.print(now.minute(), DEC);
      file.print(':');
      file.print(now.second(), DEC);
      file.println();
      file.print("Time( ms)");
      file.print(',');
      file.print("Presuure (mmhg)");
      file.println();
      file.close();

      Serial.print(now.year(), DEC);
      Serial.print('/');
      Serial.print(now.month(), DEC);
      Serial.print('/');
      Serial.print(now.day(), DEC);
      Serial.print(',');
      Serial.print(now.hour(), DEC);
      Serial.print(':');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      Serial.print(now.second(), DEC);
      Serial.println();

    }
  }

}

void loop()
{

  float pressure, temperature;
  float pressure_mmhg;


  //send a request
  Wire.beginTransmission(HSCDDRD005PD3A3_I2C);
  Wire.write(1);  // send a bit asking for register one, (as specified by the pdf)
  Wire.endTransmission();
  // now get the data from the sensor
  delay (20);

  Wire.requestFrom(HSCDDRD005PD3A3_I2C, 4);

  byte a     = Wire.read(); // first received byte stored here ....Example bytes one: 00011001 10000000
  byte b     = Wire.read(); // second received byte stored here ....Example bytes two: 11100111 00000000
  byte c     = Wire.read(); // third received byte stored here
  byte d     = Wire.read(); // fourth received byte stored here
  byte status1 = (a & 0xc0) >> 6;
  int bridge_data = ((a & 0x3f) << 8) + b;
  int temperature_data = ((c << 8) + (d & 0xe0)) >> 5;
  pressure = 1.0 * (bridge_data - OUTPUT_MIN) * (PRESSURE_MAX - PRESSURE_MIN) / (OUTPUT_MAX - OUTPUT_MIN) + PRESSURE_MIN;
  pressure_mmhg = 51.71484 * pressure;
  temperature = (temperature_data * 0.0977) - 50;
  time = millis();


  //buttonCheck();
  if (logFlag)
  {
    File file = SD.open(filename, FILE_WRITE);
    if (file)
    {
      Serial.print(time);
      Serial.print(',');
      Serial.println(pressure_mmhg);

      file.print(time);
      file.print(',');
      file.print(pressure_mmhg);
      file.println();
      file.close();
    }

    else
    {
      Serial.print("Button not pressed");
    }
  }
}

A few thing a spot right away:

  button.attach(7, INPUT_PULLUP);
  pinMode ( 9, OUTPUT);

You give the pins nice and readable names but after that you think, fuck it, let’s never use them? You tent to do that everywhere…

  //buttonCheck();
  if (logFlag)
  {

So why never do a button check?

I’m not going to rewrite the whole code so I’ll just make the framework for you. What to read and write is up to you. But you have three states. Not writing to sd, start writing to sd (aka, make the file etc) and writing to sd. And maybe even a 4th state, stopping to write to SD (but I’ll not implement it here) To make that simple I changed the logFlag into a logState.

void buttonCheck() {

  button.update();
  if (button.fell())
  {
    if(logState)
    {
      logState = 0; //stop logging
    }
    else
    {
      logState = 1; //let's start
    }
    digitalWrite(LedPin, logState);
  }
}

void loop()
{
  buttonCheck();
  
  //we need to start logging
  if(logState == 1){
    //so open the SD card and make the file
    sdLogStart();
    
    //if that's succesfull
    mode = 2;
  }
  else if(mode == 2)
  {
    //do the SD card logging
    sdLog();
  }
  
  //don't log when mode == 0
}

Now you have to fill in the stuff that needs to be done in each state.

dpoornima: I have tried to program a on/off button so that when I press the button, an led should glow and only then it will start writing to the SD card . If the button is pressed again, the led should stop glowing and it should stop writing the data to the SD card. (like a start/stop button for writing data to SD card).

Each SD card has a write-protect switch and each SD card-holder is able to provide a write-protect signal to the circuit (when used in a reasonable circuit schematics design).

Why not just use the write-protect switch settting of the SD card card to decide whether or not to write to the SD card?

jurs: Why not just use the write-protect switch settting of the SD card card to decide whether or not to write to the SD card?

I would say because you need to remove the card to set the switch... I would not say that's a convenient user interface...

The second issue is that the setup and syntax for using Bounce2.h doesn't look correct. Try these modifications to your code and see if you this doesn't get you closer to success.

Thank you for your reply.

I have tried to use the modified code and run it. It creates mutiple files . After I connect it to power, it starts logging . Then, when I press the pushbutton to stop logging,the small led light on breakout board stops blinking (it glows when it is writing to the card). It again starts writing to the card even when I dont press the reset button. it created files from 0-99 each about 1 KB. (as per your suggestion, I used the push button only to turn off i.e., to stop writing data to the card) Also, The led connected to pin 9 does not glow when it is is writing to SD card.

How do I make the led connected to pin 9 glow when it is writing to SD card and off when it is not writing to SD card?

Setup() should be written to run with logging enabled.

Can you please explain this?

Thank you

Also, it doesnt print the pressure values to the card. It just prints date and time and the headings Time and Pressure.

It does not print the pressure values with time (milliseconds) which are in the loop.

Setup() should be written to run with logging enabled.

There are ways to call SD.begin() a second time without using reset.

So I should be calling Sd.begin the second time in the loop to print the pressure values? If I call Sd.begin () in the loop, will it write the pressure values to the same file in which date and time is printed?

How do I make the led connected to pin 9 glow when it is writing to SD card and off when it is not writing to SD card?

Here is the button code to disable the SD writes in Loop and indicate the status on LED pin 9.

You need to divide your problem into two pieces. Get the SD writes in setup and loop as you want them, without reference to the button. Then you can patch this button code and enable flag into working SD code.

#include <Bounce2.h>
Bounce button = Bounce(); //instantiate a Bounce object

const byte LedPin = 9;
const byte ButtonPin = 7;
bool logFlag = true;//default status to enable SD writes in Loop

unsigned long interval = 1000; //display interval

void buttonCheck()//debounced function to check if button pressed
{
  button.update();
  if (button.fell())
  {
    if (logFlag == true)
    {
      logFlag = false;
      Serial.println();
      Serial.println("Data Logging in Loop Disabled");
      Serial.println("Press Reset to Enable");
      Serial.println();
    }
  }
  digitalWrite(LedPin, logFlag);
}

void setup()
{
  Serial.begin(9600);
  Serial.println();
  Serial.println("SD writing in SetUp Enabled by default");
  //execute SD setup functions and writes
  Serial.println();

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

  pinMode(ButtonPin, INPUT_PULLUP); //separate pinMode from attachment
  button.attach(ButtonPin);
  button.interval(20);//20 ms debounce interval
}

void loop()
{

  static unsigned long lastDisplayOn = millis();
  static unsigned long lastDisplayOff = millis();

  buttonCheck(); //you must call buttonCheck in loop)

  if (logFlag)
  {
    if (millis() - lastDisplayOn >= interval)
    {
      lastDisplayOn = millis();
      Serial.println("Data Logging in Loop Enabled");
      //execute SD writes in loop
    }
  }
  else
  {
    if (millis() - lastDisplayOff >= interval)
    {
      lastDisplayOff = millis();
      Serial.println("Data Logging in Loop Disabled");
      Serial.println("Press Reset to Enable");
    }
  }
}

So I should be calling Sd.begin the second time in the loop to print the pressure values?

No. Sd.begin() will be called in setup when reset is pushed to reenable data logging.
You can not call Sd.begin() a second time in loop with the Sd.h library without modifications to the library.

Hello,

Get the SD writes in setup and loop as you want them, without reference to the button

I have the SD card writing one file each When I press the reset button once. In the set up, I want to print the date and time just once and in the loop, I want to print the pressure values with the millis. The program for this works good.

Now, when I try to attach the button to it, it doesnt work. I want to attach a button and control when it starts writing to the card. I am trying to have a button which when pressed starts writing to the SD card and when I press it again ,it should stop writing to the SD card. Or, a button which just stops writing to SD card when I press it. (and when I want it to start writing, I can use the reset button. While the SD card is writing, I am trying to have a led glow so that I know the data is being recorded.

When I try to do this, with the help of your suggestions, there are multiple files being written and led doesnt glow. :disappointed_relieved:

I am trying to have a button which when pressed starts writing to the SD card and when I press it again ,it should stop writing to the SD card.

You can not do this with SD.h.

Or, a button which just stops writing to SD card when I press it. (and when I want it to start writing, I can use the reset button.

This is what the button code I last posted can be used for. The indicator light was for enabled/disabled, but it can be adapted for active writing if that's what you wanted.

Post the latest code which handles the SD writing as you want, and i can help you patch in the button and an indicator light.

I think this has merged the write disable button with your sketch. I don’t about the delays and blocking functions in your sketch, so I’m not certain how responsive the button will be. You may want to go back to putting the write enable indicator to monitor the enabled status, rather than the actual writes. Or else, maybe add a second Led.

#include <SPI.h>
#include <SD.h>
#define FILE_BASE_NAME "Data"
#include <Wire.h>
#include <RTClib.h>

#define DS3231_Address 0x68
#define HSCDDRD005PD3A3_I2C 0x38
#define OUTPUT_MIN 1638.4        // 1638 counts (10% of 2^14 counts or 0x0666)
#define OUTPUT_MAX 14745.6       // 14745 counts (90% of 2^14 counts or 0x3999)
#define PRESSURE_MIN -5
#define PRESSURE_MAX +5
unsigned long time;
RTC_DS3231 rtc;
int chipSelect = 10;
File file;
int BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char filename[] = FILE_BASE_NAME "00.csv";

//added button library, variables and button function
#include <Bounce2.h>
Bounce button = Bounce(); //instantiate a Bounce object

const byte LedPin = 9;
const byte ButtonPin = 7;
bool logFlag = true;//default status to enable SD writes in Loop

void buttonCheck()//debounced function to check if button pressed
{
  button.update();
  if (button.fell())
  {
    if (logFlag == true)
    {
      logFlag = false;
      Serial.println();
      Serial.println("Data Logging in Loop Disabled");
      Serial.println("Press Reset to Enable");
      Serial.println();
    }
  }
  // digitalWrite(LedPin, logFlag); change to indicate active writing
}

void setup()
{
  Wire.begin(); // wake up I2C bus
  delay (500);
  Serial.begin(9600);
  Serial.println ("Sketch has started");

  pinMode (LedPin, OUTPUT);
  digitalWrite(LedPin, LOW);//write indicator off

  pinMode(ButtonPin, INPUT_PULLUP); //separate pinMode from attachment
  button.attach(ButtonPin);
  button.interval(20);//20 ms debounce interval


  if (rtc.lostPower())
  {
    Serial.println("RTC lost power,set the time");
    //rtc.adjust(DateTime(2016,4,20,02,16,00));
  }
  delay(10);

  if (!SD.begin(10))
  {
    Serial.println(F("begin failed"));
    return;
  }

  while (SD.exists(filename)) {
    if (filename[BASE_NAME_SIZE + 1] != '9') {
      filename[BASE_NAME_SIZE + 1]++;
    }
    else if (filename[BASE_NAME_SIZE] != '9') {
      filename[BASE_NAME_SIZE + 1] = '0';
      filename[BASE_NAME_SIZE]++;
    }
    else {
      Serial.println(F("Can't create file name"));
      return;
    }
  }

  File file = SD.open(filename, FILE_WRITE);
  digitalWrite(LedPin, HIGH);//indicate file being written
  DateTime now = rtc.now();
  file.print(now.year(), DEC);
  file.print('/');
  file.print(now.month(), DEC);
  file.print('/');
  file.print(now.day(), DEC);
  file.print(',');
  file.print(now.hour(), DEC);
  file.print(':');
  file.print(now.minute(), DEC);
  file.print(':');
  file.print(now.second(), DEC);
  file.println();
  file.print("Time( ms)");
  file.print(',');
  file.print("Presuure (mmhg)");
  file.println();
  file.close();
  digitalWrite(LedPin, LOW);//file write finished

  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(',');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

}

void loop()
{
  float pressure, temperature;
  float pressure_mmhg;

  //send a request
  Wire.beginTransmission(HSCDDRD005PD3A3_I2C);
  Wire.write(1);  // send a bit asking for register one, the data register (as specified by the pdf)
  Wire.endTransmission();
  // now get the data from the sensor
  delay (20);

  Wire.requestFrom(HSCDDRD005PD3A3_I2C, 4);

  byte a     = Wire.read(); // first received byte stored here ....Example bytes one: 00011001 10000000
  byte b     = Wire.read(); // second received byte stored here ....Example bytes two: 11100111 00000000
  byte c     = Wire.read(); // third received byte stored here
  byte d     = Wire.read(); // fourth received byte stored here
  byte status1 = (a & 0xc0) >> 6;
  int bridge_data = ((a & 0x3f) << 8) + b;
  int temperature_data = ((c << 8) + (d & 0xe0)) >> 5;
  pressure = 1.0 * (bridge_data - OUTPUT_MIN) * (PRESSURE_MAX - PRESSURE_MIN) / (OUTPUT_MAX - OUTPUT_MIN) + PRESSURE_MIN;
  pressure_mmhg = 51.71484 * pressure;
  temperature = (temperature_data * 0.0977) - 50;
  time = millis();

  buttonCheck();//update logFlag
  
  if (logFlag)//logFlag determines write enable
  {
    File file = SD.open(filename, FILE_WRITE);
    if (file)
    {
      digitalWrite(LedPin, HIGH);//indicate file being written
      Serial.print(time);
      Serial.print(',');
      Serial.println(pressure_mmhg);

      file.print(time);
      file.print(',');
      file.print(pressure_mmhg);
      file.println();
      file.close();
      digitalWrite(LedPin, LOW);//file write finished
    }
  }
}

Looks like you didn't really read my post, pity. We're here to learn so it would be better to get a concept rather then just try code others made for you... Then I think I'm out of here.

Short note about the syntax of Bounce2

  pinMode(ButtonPin, INPUT_PULLUP); //separate pinMode from attachment
  button.attach(ButtonPin);

will work fine but

button.attach(ButtonPin, INPUT_PULLUP);

Is also perfectly fine. Shorter and more readable if you ask me.