#include <SD.h>
#include <SPI.h>
// Pin definition
#define SD_CS_PIN 5
#define TEMP_SENSOR_PIN 34
//Variables
File dataFile;
String filename = "/templog.csv";
int readingCount = 0;
unsigned long lastLogTimer = 0;
const unsigned long LOG_INTERVAL = 1000; // log data every 1 sec
unsigned long startTime = 0;
void setup() {
// initialize serial
Serial.begin(115200);
delay(500);
Serial.println("=========================");
Serial.println("ESP32 temperature data logger");
Serial.println("CSV format output");
Serial.println("=========================");
// initailize analog input
analogReadResolution(12);
pinMode(TEMP_SENSOR_PIN, INPUT);
// initailize SD card
Serial.print("Initializing SD card...");
// Explicit SPI initialization for ESP32
SPI.begin(18,19,23,5); // Pin SCK, MISO(DO), MOSI(DI), SS
if (!SD.begin(SD_CS_PIN)) {
Serial.println("FAILED");
Serial.println("ERROR: SD card initailization failed");
while(1){
delay(500);
}
}
Serial.println("SUCCESS");
// CHeck card type
uint8_t cardType = SD.cardType();
Serial.print("SD card type: ");
switch (cardType) {
case CARD_MMC: Serial.println("MMC");
case CARD_SD: Serial.println("SDSC");
case CARD_SDHC: Serial.println("SDHC");
default: Serial.println("UNKNOWN");
}
// Record start time
startTime = millis();
// create CSV File with header
Serial.println("==================================");
Serial.println("CSV logging started");
Serial.println("Columns: ID,DateTime,Timestamp_ms,Temp_c,Voltage_V,Raw_ADC,Status");
Serial.println("=================================\n");
}
void loop() {
unsigned long currentTime = millis();
// Log at intervals
if (currentTime - lastLogTimer >= LOG_INTERVAL) {
lastLogTimer = currentTime;
// Read sensor
int rawValue = analogRead(TEMP_SENSOR_PIN);
float voltage = rawValue * (3.3 / 4095.0);
float temperature = readTemperature(rawValue, voltage);
// Create datetime string (simulated: seconds since start)
String dateTime = formatDateTime(currentTime);
// Determine status based on temperature
String status = getStatus(temperature);
// Create CSV row
// Format: ID,DateTime,Timestamp_ms,Temp_C,Voltage_V,Raw_ADC,Status
String csvRow = String(readingCount) + "," +
dateTime + "," +
String(currentTime) + "," +
String(temperature, 2) + "," +
String(voltage, 3) + "," +
String(rawValue) + "," +
status + "\n";
// Print to Serial (for monitoring)
Serial.print("CSV Row: ");
Serial.print(csvRow);
// Write to SD card
if (appendFile(filename, csvRow)) {
Serial.println(" [SAVED TO SD]");
} else {
Serial.println(" [ERROR: SAVE FAILED]");
}
// Display CSV file contents every 5 readings
if (readingCount % 5 == 0) {
displayCSVFile();
}
readingCount++;
Serial.println();
}
delay(100);
}
// ==================== CSV FUNCTIONS ====================
void createCSVFile() {
if (!SD.exists(filename)) {
Serial.println("Creating new CSV file with headers...");
// CSV Header row
String header = "ReadingID,DateTime,Timestamp_ms,Temperature_C,Voltage_V,Raw_ADC,Status\n";
if (writeFile(filename, header)) {
Serial.println("CSV headers written successfully");
} else {
Serial.println("ERROR: Failed to write CSV headers");
}
} else {
// Count existing rows to continue numbering
readingCount = countCSVRows();
Serial.print("Existing CSV file found. Continuing from reading #");
Serial.println(readingCount);
}
}
void displayCSVFile() {
Serial.println("\n========== CSV FILE CONTENTS ==========");
Serial.println("----------------------------------------");
File file = SD.open(filename, FILE_READ);
if (!file) {
Serial.println("ERROR: Cannot open CSV file");
return;
}
int lineCount = 0;
while (file.available()) {
String line = file.readStringUntil('\n');
if (line.length() > 0) {
Serial.println(line);
lineCount++;
}
}
file.close();
Serial.println("----------------------------------------");
Serial.print("Total lines: ");
Serial.println(lineCount);
Serial.println("========================================\n");
}
int countCSVRows() {
File file = SD.open(filename, FILE_READ);
if (!file) return 0;
int rows = 0;
while (file.available()) {
if (file.read() == '\n') rows++;
}
file.close();
// Subtract 1 for header row
return (rows > 0) ? rows - 1 : 0;
}
// ==================== SENSOR FUNCTIONS ====================
float readTemperature(int rawValue, float voltage) {
// Map 0-3.3V to 0-100°C (adjust for your real sensor)
float temperature = voltage * 30.3;
// Add small random fluctuation
temperature += random(-10, 11) * 0.05;
return temperature;
}
String getStatus(float temp) {
if (temp < 10) return "COLD";
else if (temp < 25) return "NORMAL";
else if (temp < 40) return "WARM";
else return "HOT";
}
// Format time as HH:MM:SS (simulated from milliseconds)
String formatDateTime(unsigned long ms) {
unsigned long totalSeconds = ms / 1000;
int hours = (totalSeconds / 3600) % 24;
int minutes = (totalSeconds / 60) % 60;
int seconds = totalSeconds % 60;
String dt = "";
if (hours < 10) dt += "0";
dt += String(hours) + ":";
if (minutes < 10) dt += "0";
dt += String(minutes) + ":";
if (seconds < 10) dt += "0";
dt += String(seconds);
return dt;
}
// ==================== SD CARD FUNCTIONS ====================
bool writeFile(String path, String message) {
File file = SD.open(path, FILE_WRITE);
if (!file) return false;
bool result = file.print(message);
file.close();
return result;
}
bool appendFile(String path, String message) {
File file = SD.open(path, FILE_APPEND);
if (!file) return false;
bool result = file.print(message);
file.close();
return result;
}