I am writing a data logging application using the ESP32-Wroom with microsd drive under Visual Micro/Visual Studio.
The code is below. ssid and password have been removed.
My problem is that the file open (for write) and subsequent file close in the setup section functions perfectly, when I try and re-open the same file (again for write) within the loop section (in the Write_Record subroutine) the open fails.
All the information I have read suggests that what I am trying to do is legitimate, open for write effectively moving to the end of the file, subsequent writes being added to the end of the file. I do not get to the write as the file begin fails (returns false). Trying to open the file for append makes no difference.
It is almost as if the file.close is not working but the return code from the file open can only be true or false, not really giving me any indication what is causing the fail.
Please ignore the section on web server, it is incomplete and excluded at compile time.
Any suggestions?
Regards
Steve
[code]
#include <sd_diskio.h>
#include <sd_defines.h>
#include <SD.h>
#include <Wire.h>
#include <WiFiUdp.h>
#include <WiFiServer.h>
#include <WiFiClient.h>
#include <WiFi.h>
#include "time.h"
#include <Bounce2.h>
#include <ADS1115_WE.h>
#define console Serial
const char* ssid = "";
const char* password = "";
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 0;
const int daylightOffset_sec = 3600;
struct tm timeinfo;
String LogFileName = "";
constexpr int Reset_switch_pin = 32;
constexpr int Start_switch_pin = 33;
constexpr int Running_led_pin = 26;
constexpr int SD_Active_led_pin = 25;
constexpr int SS_pin = 5;
constexpr int SCK_pin = 18;
constexpr int MISO_pin = 19;
constexpr int MOSI_pin = 23;
constexpr int I2C_SCL = 21;
constexpr int I2C_SDA = 22;
constexpr int ALERT_pin = 35;
constexpr int ONBOARDLED = 2;
constexpr int I2C_ADDRESS = 0x48;
constexpr int Time_between_readings = 1000; // number of milli seconds between readings
String This_Year = "";
String This_Month = "";
String This_Day = "";
String This_Hour = "";
String This_Minute = "";
String This_Second = "";
volatile double current_ADC_A1 = 0;
volatile double current_ADC_A2 = 0;
volatile double current_ADC_A3 = 0;
volatile double current_ADC_A4 = 0;
unsigned long previous_millis = millis();
unsigned long currenttime = millis();
unsigned long previoustime = millis();
const long timeouttime = 2000;
bool started = false;
String header; // Variable to store the HTTP request
// Instantiations
Bounce Reset = Bounce();
Bounce Start = Bounce();
ADS1115_WE adc = ADS1115_WE(); // default address = 48
WiFiServer server(80); // WebServer(HTTP port, 80 is defult)
File Logfile;
void setup() {
console.begin(115200);
console.print(millis(), DEC); console.println("\t\tCommencing Setup");
console.print(millis(), DEC); console.print("\t\tConnecting to "); console.println(ssid);
WiFi.begin(ssid, password);
pinMode(ONBOARDLED, OUTPUT);
digitalWrite(ONBOARDLED, HIGH);
console.print(millis(), DEC); console.print("\t\tWiFi Status: "); console.println(WiFi.status());
console.print(millis(), DEC); console.print("\t\t");
int wifi_error_cnt = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
console.print(wifi_error_cnt); console.print(",");
if (wifi_error_cnt++ > 50) {
console.print(millis(), DEC); console.println("\t\tNetwork Error, Restarting");
ESP.restart();
}
}
console.println("");
console.print(millis(), DEC); console.println("\t\tConnected");
console.print(millis(), DEC);
console.print("\t\tWiFi IP Address: "); console.println(WiFi.localIP());
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
#ifdef dowebpage
// server.begin("/", handle_root);
// server.begin();
console.print(millis(), DEC); console.println("\t\tHTTP server started");
delay(100);
#endif
console.print(millis(), DEC); console.println("\t\tInitialising Switches and LEDs");
pinMode(Reset_switch_pin, INPUT_PULLDOWN);
pinMode(Running_led_pin, OUTPUT);
pinMode(SD_Active_led_pin, OUTPUT);
pinMode(Start_switch_pin, INPUT_PULLDOWN);
Reset.attach(Reset_switch_pin); // setup defaults for debouncing switches
Start.attach(Start_switch_pin);
Reset.interval(0.5); // sets debounce time
Start.interval(5);
digitalWrite(Running_led_pin, LOW);
digitalWrite(SD_Active_led_pin, LOW);
console.print(millis(), DEC);
console.println("\t\tSwitches and LEDs Initialised");
console.print(millis(), DEC); console.println("\t\tSD Drive Configuration");
// SPIClass spi = SPIClass(VSPI);
// spi.begin();
console.print(millis(), DEC); console.print("\t\tSS pin:["); console.print(SS); console.println("]");
console.print(millis(), DEC); console.print("\t\tMOSI pin:["); console.print(MOSI); console.println("]");
console.print(millis(), DEC); console.print("\t\tMISO pin:["); console.print(MISO); console.println("]");
console.print(millis(), DEC); console.print("\t\tSCK pin:["); console.print(SCK); console.println("]");
if (!SD.begin()) {
console.print(millis(), DEC); console.println("\t\tSD Drive Begin Failed");
while (true) {
digitalWrite(Running_led_pin, !digitalRead(Running_led_pin));
delay(500);
}
}
else {
console.print(millis(), DEC); console.println("\t\tSD Drive Begin Succeeded");
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
console.print(millis(), DEC); console.println("\t\tNo SD card attached");
while (true) {
digitalWrite(Running_led_pin, !digitalRead(Running_led_pin));
delay(500);
}
}
console.print(millis(), DEC); console.print("\t\tSD Card Type: ");
if (cardType == CARD_MMC) {
console.println("MMC");
}
else if (cardType == CARD_SD) {
console.println("SDSC");
}
else if (cardType == CARD_SDHC) {
console.println("SDHC");
}
else {
console.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
console.print(millis(), DEC); console.print("\t\tSD Card Size: "); console.print(cardSize); console.println("MBytes");
console.print(millis(), DEC); console.print("\t\tTotal Bytes: "); console.println(SD.totalBytes());
console.print(millis(), DEC); console.print("\t\tUsed bytes: "); console.println(SD.usedBytes());
console.print(millis(), DEC); console.println("\t\tSD Card Initialisation Complete");
console.print(millis(), DEC); console.println("\t\tCreate Logging File");
}
if (!getLocalTime(&timeinfo)) {
console.print(millis(), DEC); console.println("\t\tFailed to obtain time");
while (true) {
delay(500);
digitalWrite(Running_led_pin, !digitalRead(Running_led_pin));
}
}
This_Year = (String)(timeinfo.tm_year + 1900);
This_Month = (String)(timeinfo.tm_mon + 1);
if (This_Month.length() < 2) This_Month = "0" + This_Month;
This_Day = (String)timeinfo.tm_mday;
if (This_Day.length() < 2) This_Day = "0" + This_Day;
This_Hour = (String)timeinfo.tm_hour;
if (This_Hour.length() < 2) This_Hour = "0" + This_Hour;
This_Minute = (String)timeinfo.tm_min;
if (This_Minute.length() < 2) This_Minute = "0" + This_Minute;
This_Second = (String)timeinfo.tm_sec;
if (This_Second.length() < 2) This_Second = "0" + This_Second;
LogFileName = "/Energy_";
LogFileName += This_Year + This_Month + This_Day;
LogFileName += This_Hour + This_Minute + This_Second;
LogFileName += ".csv";
console.print(millis(), DEC); console.print("\t\t(setup) File Name: "); console.println(LogFileName);
Logfile = SD.open(LogFileName, FILE_WRITE);
if (!Logfile) { // log file not opened
console.print(millis(), DEC);
console.print("\t\tError opening Logfile: ["); console.print(LogFileName); console.println("]");
while (true) {
digitalWrite(Running_led_pin, !digitalRead(Running_led_pin));
delay(500);
}
}
Logfile.println("Start File"); // write something to the file
Logfile.close();
console.print(millis(), DEC); console.println("\t\t(Log File Created");
console.print(millis(), DEC); console.println("\t\tInitialising I2C bus");
console.print(millis(), DEC);
console.print("\t\tSDA pin:["); console.print(SDA); console.print("]");
console.print(",SCL pin:["); console.print(SCL); console.print("]");
console.print(",MISO pin:["); console.print(MISO); console.println("]");
Wire.begin();
if (!adc.init()) {
Serial.println("ADS1115 not connected!");
while (true) {
digitalWrite(Running_led_pin, !digitalRead(Running_led_pin));
delay(500);
}
}
console.print(millis(), DEC); console.println("\t\tI2C bus Initialised");
console.print(millis(), DEC); console.println("\t\tADC Setup Started");
adc.setVoltageRange_mV(ADS1115_RANGE_4096); // +/- .4096 mV
adc.setCompareChannels(ADS1115_COMP_0_GND); // compare channel 0 to ground
adc.setCompareChannels(ADS1115_COMP_1_GND); // compare channel 1 to ground)
adc.setAlertPinMode(ADS1115_ASSERT_AFTER_4); // disable = default
adc.setConvRate(ADS1115_128_SPS); // 128 = default
adc.setMeasureMode(ADS1115_CONTINUOUS); //
adc.setAlertLatch(ADS1115_LATCH_ENABLED); //
adc.setAlertPol(ADS1115_ACT_LOW); //
adc.setAlertPinToConversionReady(); //
console.print(millis(), DEC); console.println("\t\tADC Setup Complete");
} // end of Setup
void loop() {
#ifdef dowebpage
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
currenttime = millis();
previoustime = currenttime;
console.print(millis(), DEC); console.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currenttime - previoustime <= timeouttime) { // loop while the client's connected
currenttime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// turns the GPIOs on and off
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #555555;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP32 Web Server</h1>");
// Display current state, and ON/OFF buttons for GPIO 26
client.println("<p>Analogue A1: </p>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
}
else { // if you got a newline, then clear currentLine
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
#endif
Check_Switches();
if (started) {
if (Get_ADC()) {
Write_Record();
}
}
digitalWrite(Running_led_pin, HIGH); // turn running led on solid
}
void Check_Switches() {
Start.update();
if (Start.fell()) {
started = !started;
console.print(millis(), DEC); console.println("\t\tStart Depressed");
digitalWrite(Running_led_pin, HIGH);
}
Reset.update();
if (Reset.fell()) {
console.print(millis(), DEC); console.println("\t\tReset Depressed");
ESP.restart();
}
}
bool Get_ADC() {
if ((previous_millis + Time_between_readings) <= millis()) {
previous_millis = millis();
current_ADC_A1 = readChannel(ADS1115_COMP_0_GND);
current_ADC_A2 = readChannel(ADS1115_COMP_1_GND);
current_ADC_A3 = readChannel(ADS1115_COMP_2_GND);
current_ADC_A4 = readChannel(ADS1115_COMP_3_GND);
return true;
}
return false;
}
double readChannel(ADS1115_MUX channel) {
adc.setCompareChannels(channel);
return adc.getResult_mV();
}
void Write_Record() {
console.print(millis(), DEC); console.println("\t\tObtain Current Date and Time: ");
if (!getLocalTime(&timeinfo)) {
console.print(millis(), DEC); console.println("\t\tFailed to obtain time");
while (true) {
delay(500);
digitalWrite(Running_led_pin, !digitalRead(Running_led_pin));
}
}
console.print(millis(), DEC); console.print("\t\t"); console.println(&timeinfo, "%A %B %d %Y %H:%M:%S");
This_Year = (String)(timeinfo.tm_year + 1900);
This_Month = (String)(timeinfo.tm_mon + 1);
if (This_Month.length() < 2) This_Month = "0" + This_Month;
This_Day = (String)timeinfo.tm_mday;
if (This_Day.length() < 2) This_Day = "0" + This_Day;
This_Hour = (String)timeinfo.tm_hour;
if (This_Hour.length() < 2) This_Hour = "0" + This_Hour;
This_Minute = (String)timeinfo.tm_min;
if (This_Minute.length() < 2) This_Minute = "0" + This_Minute;
This_Second = (String)timeinfo.tm_sec;
if (This_Second.length() < 2) This_Second = "0" + This_Second;
console.print(millis(), DEC); console.println("\t\tData record being asembled");
String message = This_Day + "/" + This_Month + "/" + This_Year + " " + This_Hour + ":" + This_Minute + ":" + This_Second + ",";
message += (String)current_ADC_A1 + ",";
message += (String)current_ADC_A2 + ",";
message += (String)current_ADC_A3 + ",";
message += (String)current_ADC_A4;
console.print(millis(), DEC); console.print("\t\tRe-Opening: ["); console.print(LogFileName); console.println("]");
console.print(millis(), DEC); console.print("\t\tAppending Record: ["); console.print(message); console.println("]");
Logfile = SD.open(LogFileName, FILE_WRITE);
if (!Logfile) {
console.print(millis(), DEC);
console.print("\t\tError re-opening Logfile:"); console.print(LogFileName);
console.print(" Return: ["); console.print(Logfile); console.println("]");
while (true) {
digitalWrite(Running_led_pin, !digitalRead(Running_led_pin));
delay(500);
}
}
digitalWrite(SD_Active_led_pin, !digitalRead(SD_Active_led_pin)); // flash the sd active led
Logfile.print(message);
Logfile.close();
console.print(millis(), DEC); console.println("\tReadings Written to SD Card");
}
[code end]