I am helping my daughter with her high school project. Reading data from a sensor and logging to a text file on a micro-SD card. Logging starts when a push button is pressed and released. I am using an Arduino Uno and a Hiletgo micro-SD card reader and a micro center 64 GB card.
When I tested this setup over small periods of time, it works - writes SD card with expected data. When I let this setup run for more than about 30 min, everything appears to work - on-board LED blinks every second to indicate writing int he loop. But the test.txt file has 0 bytes. All subsequent operations for any duration, appear to fail writing. Below is the code.
I am formatting the SD card on my Mac using disk utility in FAT32 format. When I used the SD association software, it forced exFAT formatting, which appears to not work for me - file open fails.
Notable - this data is collected from athletes in the field, so no PC is involved, so I connected a 9 V power supply and don't use serial debug.
So far, reading other forum entries - I will try SDFat/SDformatter as the way to format. Also, I believe I should use SD.end() at the end. Also, not sure what's the best way to close out operation - i.e. go quiescent after the button is pressed second time. My daughter researched it and included an exit() call. I would much prefer to deterministically hang in the loop on a while(1) {}. Any advice would be greatly appreciated. My daughter is getting pretty disheartened with this experience and honestly, so am I at this point after 4-5 days of heavy work.
Regards,
Vijaykam
#include <SD.h>
#include <SPI.h>
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 8; // the number of the LED pin
const long interval = 1000; // interval at which to blink (milliseconds)const int buttonPin = 2; // the number of the pushbutton pin
// variables will change:
bool startProcess = false;
int ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
int buttonState = 0; // variable for reading the pushbutton status
File myFile;
const int GSR=A0;
int sensorValue=0;
int gsr_average=0;
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
if (!SD.begin(4)) {
digitalWrite(ledPin, HIGH);
while (1);
}
}
void loop() {
if (!startProcess && buttonPressAndRelease())
{
startProcess = true;
digitalWrite(ledPin, LOW);
myFile = SD.open("test.txt", FILE_WRITE);
if (!myFile) {
digitalWrite(ledPin, HIGH);
while (1);
}
unsigned long mi = millis();
myFile.print("Start: ");
myFile.println(mi);
}
else if (startProcess && buttonPressAndRelease())
{
startProcess = false;
unsigned long mi = millis();
myFile.print("Finish: ");
myFile.println(mi);
digitalWrite(ledPin, LOW);
myFile.close();
exit(0);
}
if (startProcess)
{
toggleLED();
int data = gsrGetData();
myFile.println(data);
}
}
bool buttonPressAndRelease(){
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// Confirm button is pressed - debounce
delay(50);
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
// Confirmed - button pressed - now wait for release
while ((buttonState = digitalRead(buttonPin)) == HIGH) {
delay(50);
}
// For now, not debouncing on release
return true;
}
else {
// Glitch - return - will catch it again
return false;
}
// Should not come here
return false;
}
else {
// Not pressed
return false;
}
}
void toggleLED(){ //method for blinking the LED
if (millis() - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = millis();
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}
int gsrGetData()
{
long sum=0;
for(int i=0;i<10;i++) //Average the 10 measurements to remove the glitch
{
sensorValue=analogRead(GSR);
sum += sensorValue;
delay(5);
}
gsr_average = sum/10;
return gsr_average;
}
That is a clear indication that the file was not properly closed.
Instead of writing the line below to the SD card, write it to the serial monitor instead, so you have some confirmation that the close() action was at least attempted.
myFile.print("Finish: ");
Another safety measure is to issue myFile.flush() every few minutes or hours, which updates the file pointers. That way if myFile.close() fails, you lose only the last incomplete data buffer.
Hello jremington,
Thank you for the suggestion. I am thinking of adding a flush() every few seconds. Appreciate your input. I can't debug over serial, as this is a standalone unit int eh field. But the indicator LED does go low, which is "some" sign that close() was called on file.
That's exactly what I have - 9V smoke alarm battery. Can you suggest alternatives? I cannot connect an actual power supply, since kids will be running around a track with this gizmo in their hands.
A fresh smoke alarm battery won't last more than a few tens of minutes with many setups, especially something as power hungry as an SD card.
Some people use 5V rechargeable power banks, powering the Arduino through the 5V pin. However, many of those power banks have a minimum current draw requirement and shut down.
2x18650 Li batteries provide 7.4 V, which is enough for the Vin barrel jack of an Arduino Uno.
Are you saying that the Arduino is not capable of writing to a card that big? Can you clarify? If this is the main issue, I should be able to fix easily - hopefully!
Thanks for the suggestion. Looking at this further, I found this ...
The 9V battery will power the Arduino for about 10 hours. The AA batteries would probably power the Arduino for 40 hours, but the voltage of the batteries will start to drain before that, so it might be less than 40 hours for 4 AA batteries.
I am only looking for the battery to last up to 1.5 hours. I imagine the SD card is not a huge drain - it does not get warm. Will put an ammeter on it at work.
Look at 9v load discharge graph (above).
1/2 of 9v power is lost by vregulator down converting to +5v.
Times shown in your referrnce is with NO LOAD running Arduino only - no I/O devices.
Like I said, sd card pulls over 100mA during write!
Okay, okay I get it. So I should be able to gang up a 4xAA batteries to get this done right? If I understand correctly, it will have 1.5x4=6 V and not loose too much power regulating down to 5 V. That should be able to get me 1.5 hours of SD card capture, hopefully?
Going back to
2x18650 Li batteries provide 7.4 V, which is enough for the Vin barrel jack of an Arduino Uno.
I don't see anything online that offers a barrel jack for UNO. They are all USB - I guess I need to pick one that is intelligent enough to know when to act as a power source and when to act as power drain? Please educate me. I should be able to connect to the USB jack of UNO.
It is the black cylinder on the Uno R3, also called the "Power Jack". The input is "Vin" on all Arduinos. Allowed input voltage is 7-12V, the closer to 7 the better.
Thanks for your continued - patient - explanations! I meant to say, I didn't see any 18650 battery holder arrangements that had a barrel jack connector output. After doing more digging I did find something that would plug into the USB connector and apparently is good for powering the UNO.
I figured I would use a simpler arrangement. I am getting a 6xaa holder with a barrel jack connector. I am aiming to populate it with AA sized NiMH rechargeable batteries. At 1.25 volts each, they will gang up to 7.5 V. Their ratings are over 2000mAh. Hopefully this will get us over the finish line. Would appreciate your and other experts' feedback on this.
Of course not. You buy the barrel jack plug (or cut one from a discarded charger cable) and solder a pair of wires between it and the battery holder, or directly to the batteries themselves, if they have solder tabs. It is at most a 10 minute operation.
Discarded laptop battery packs almost always have several good 18650 batteries, with solder tabs, free for the harvesting.