I have tried Below 2 codes which record audio and save it as .raw file. and upload it to firebase.
but in this both 2 code, after recording completed, it show nothing in serial monitor. whether it uploading to firebase or not. i have tried so many times to modify these 2 codes and try. but none of methods are working.
1 code is using SPIFFS. 2nd code is using LittleFS. I want to use one of this code for my project. but none of it correctly uploading recorded file to firebase.
can someone help me to fix this.
gps and mic code which use SPIFFS
#include <driver/i2s.h>
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include <WiFiClientSecure.h>
#include <LittleFS.h> // Include LittleFS instead of SPIFFS
#include <Preferences.h> // Include Preferences library
#include <Arduino.h>
#include <TinyGPS++.h>
// Firebase configuration
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
// I2S configuration for recording
#define I2S_WS 25
#define I2S_SD 33
#define I2S_SCK 32
#define I2S_PORT I2S_NUM_0
#define I2S_SAMPLE_RATE (16000)
#define I2S_SAMPLE_BITS (16)
#define I2S_READ_LEN (16 * 1024)
#define RECORD_TIME (20) // Seconds
#define I2S_CHANNEL_NUM (1)
#define FLASH_RECORD_SIZE (I2S_CHANNEL_NUM * I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 * RECORD_TIME)
// Wi-Fi and Firebase configurations
#define WIFI_SSID "{redacted}"
#define WIFI_PASSWORD "{redacted}"
#define API_KEY "{redacted}"
#define USER_EMAIL "{redacted}"
#define USER_PASSWORD "{redacted}"
#define STORAGE_BUCKET_ID "{redacted}"
#define DATABASE_URL "{redacted}"
// Define the push button pin
#define BUTTON_PIN 23
File file;
char filename[50]; // To store dynamically generated filename
// Create object for HardwareSerial and GPS
HardwareSerial GPS_Serial(2); // (Rx, Tx)
TinyGPSPlus gps;
// Firebase objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
Preferences preferences; // Create Preferences object
// File counter
int fileCounter; // Declare fileCounter
// Task flags
bool recordingComplete = false;
bool taskCompleted = false;
unsigned long sendDataPrevMillis = 0;
bool signupOK = false;
int buttonState = 0;
// Function prototypes
void LittleFSInit();
void i2sInit();
void i2s_adc(void* arg);
void uploadToFirebase();
bool fileExists(const char* path);
void generateNewFileName();
void clearLittleFS();
void setup() {
Serial.begin(115200);
GPS_Serial.begin(9600, SERIAL_8N1, 16, 17); // Use pins 16 and 17 for RX and TX
// Set up the push button pin
pinMode(BUTTON_PIN, INPUT_PULLUP);
preferences.begin("counter", false); // Open preferences with the namespace "counter"
// Retrieve the counter from preferences (default to 1 if not set)
fileCounter = preferences.getInt("fileCounter", 1);
Serial.printf("Starting with fileCounter: %d\n", fileCounter);
// Initialize Wi-Fi connection
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(300);
Serial.println("Connecting to Wi-Fi...");
}
Serial.println("Connected to Wi-Fi!");
// Initialize LittleFS
LittleFSInit();
// Initialize Firebase
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
// Sign up for Firebase
if (Firebase.signUp(&config, &auth, "", "")) {
Serial.println("Firebase signup successful");
signupOK = true;
} else {
Serial.printf("Firebase signup failed: %s\n", config.signer.signupError.message.c_str());
}
// Token status callback function
config.token_status_callback = tokenStatusCallback;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
}
void loop() {
smartDelay(1000); // Handle GPS communication
if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 5000 || sendDataPrevMillis == 0)) {
sendDataPrevMillis = millis();
if (gps.location.isValid()) {
double latitude = gps.location.lat();
double longitude = gps.location.lng();
double altitude = gps.altitude.meters();
// Send latitude to Firebase
if (Firebase.RTDB.setFloat(&fbdo, "/gps/latitude", latitude)) {
} else {
Serial.println("Failed to update latitude.");
Serial.println(fbdo.errorReason());
}
// Send longitude to Firebase
if (Firebase.RTDB.setFloat(&fbdo, "/gps/longitude", longitude)) {
} else {
Serial.println("Failed to update longitude.");
Serial.println(fbdo.errorReason());
}
// Send altitude to Firebase
if (Firebase.RTDB.setFloat(&fbdo, "/gps/altitude", altitude)) {
} else {
Serial.println("Failed to update altitude.");
Serial.println(fbdo.errorReason());
}
} else {
Serial.println("Invalid GPS data");
}
}
// Handle push button state and update Firebase
if (Firebase.ready() && signupOK) {
buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW) { // Button pressed
if (Firebase.RTDB.setInt(&fbdo, "/alertStatus", 1)) {
Serial.println("Button pressed! Alert sent to Firebase.");
// Initialize I2S and start recording task
i2sInit();
xTaskCreate(i2s_adc, "i2s_adc", 1024 * 4, NULL, 1, NULL);
if (Firebase.ready() && recordingComplete && !taskCompleted) {
taskCompleted = true;
if (fileExists(filename)) {
uploadToFirebase();
} else {
Serial.println("File not found, cannot upload.");
}
}
} else {
Serial.println("Failed to write to Firebase");
Serial.println(fbdo.errorReason());
}
} else { // Button not pressed
if (Firebase.RTDB.setInt(&fbdo, "/alertStatus", 0)) {
// Serial.println("No alert. Button not pressed.");
} else {
Serial.println("Failed to write to Firebase");
Serial.println(fbdo.errorReason());
}
}
// Small delay to avoid flooding Firebase
delay(500);
}
}
static void smartDelay(unsigned long ms) {
unsigned long start = millis();
do {
while (GPS_Serial.available()) {
gps.encode(GPS_Serial.read());
}
} while (millis() - start < ms);
}
void LittleFSInit() {
if (!LittleFS.begin()) { // Initialize LittleFS
Serial.println("LittleFS initialization failed!");
while (1) yield();
}
// Generate a new filename for the current recording
generateNewFileName();
file = LittleFS.open(filename, FILE_WRITE);
if (!file) {
Serial.println("File creation failed!");
while (1) yield();
}
Serial.println("LittleFS initialized and file opened.");
}
void generateNewFileName() {
int fileNumber = 1;
// Check if the counter file exists in LittleFS
if (LittleFS.exists("/fileCounter.txt")) {
File counterFile = LittleFS.open("/fileCounter.txt", FILE_READ);
fileNumber = counterFile.parseInt();
counterFile.close();
}
// Create a new filename using the file number
sprintf(filename, "/guardianRecord%d.raw", fileNumber);
// Increment and save the new file number back to LittleFS
File counterFile = LittleFS.open("/fileCounter.txt", FILE_WRITE);
counterFile.printf("%d", fileNumber + 1);
counterFile.close();
Serial.printf("New file name generated: %s\n", filename);
}
void i2sInit() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 16,
.dma_buf_len = 1024,
.use_apll = 1
};
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
const i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = -1,
.data_in_num = I2S_SD
};
i2s_set_pin(I2S_PORT, &pin_config);
}
void i2s_adc(void* arg) {
int i2s_read_len = I2S_READ_LEN;
int flash_wr_size = 0;
size_t bytes_read;
char* i2s_read_buff = (char*)calloc(i2s_read_len, sizeof(char));
while (flash_wr_size < FLASH_RECORD_SIZE) {
i2s_read(I2S_PORT, (void*)i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
file.write((const unsigned char*)i2s_read_buff, bytes_read);
flash_wr_size += bytes_read;
Serial.printf("Recording %d%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
}
file.close();
free(i2s_read_buff);
Serial.println("Recording complete");
recordingComplete = true;
i2s_driver_uninstall(I2S_PORT);
vTaskDelete(NULL);
}
void uploadToFirebase() {
String uploadPath = "/audio/guardianRecord" + String(fileCounter) + ".raw";
Firebase.Storage.upload(&fbdo, STORAGE_BUCKET_ID, filename, mem_storage_type_flash, uploadPath.c_str(), "audio/raw");
if (fbdo.httpCode() == FIREBASE_ERROR_HTTP_CODE_OK) {
Serial.println("Upload successful!");
// Increment file counter and save to preferences
fileCounter++;
preferences.putInt("fileCounter", fileCounter);
// Clear LittleFS after successful upload
clearLittleFS();
} else {
Serial.printf("Failed to upload file, reason: %s\n", fbdo.errorReason().c_str());
}
}
bool fileExists(const char* path) {
return LittleFS.exists(path);
}
void clearLittleFS() {
LittleFS.remove(filename);
Serial.println("LittleFS cleared.");
}
gps and mic code which use LittleFS
#include <driver/i2s.h>
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include <WiFiClientSecure.h>
#include <LittleFS.h> // Include LittleFS instead of SPIFFS
#include <Preferences.h> // Include Preferences library
#include <Arduino.h>
#include <TinyGPS++.h>
// Firebase configuration
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
// I2S configuration for recording
#define I2S_WS 25
#define I2S_SD 33
#define I2S_SCK 32
#define I2S_PORT I2S_NUM_0
#define I2S_SAMPLE_RATE (16000)
#define I2S_SAMPLE_BITS (16)
#define I2S_READ_LEN (16 * 1024)
#define RECORD_TIME (20) // Seconds
#define I2S_CHANNEL_NUM (1)
#define FLASH_RECORD_SIZE (I2S_CHANNEL_NUM * I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 * RECORD_TIME)
// Wi-Fi and Firebase configurations
#define WIFI_SSID "{redacted}"
#define WIFI_PASSWORD "{redacted}"
#define API_KEY "{redacted}"
#define USER_EMAIL "{redacted}"
#define USER_PASSWORD "{redacted}"
#define STORAGE_BUCKET_ID "{redacted}"
#define DATABASE_URL "{redacted}"
// Define the push button pin
#define BUTTON_PIN 23
File file;
char filename[50]; // To store dynamically generated filename
// Create object for HardwareSerial and GPS
HardwareSerial GPS_Serial(2); // (Rx, Tx)
TinyGPSPlus gps;
// Firebase objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
Preferences preferences; // Create Preferences object
// File counter
int fileCounter; // Declare fileCounter
// Task flags
bool recordingComplete = false;
bool taskCompleted = false;
unsigned long sendDataPrevMillis = 0;
bool signupOK = false;
int buttonState = 0;
// Function prototypes
void LittleFSInit();
void i2sInit();
void i2s_adc(void* arg);
void uploadToFirebase();
bool fileExists(const char* path);
void generateNewFileName();
void clearLittleFS();
void setup() {
Serial.begin(115200);
GPS_Serial.begin(9600, SERIAL_8N1, 16, 17); // Use pins 16 and 17 for RX and TX
// Set up the push button pin
pinMode(BUTTON_PIN, INPUT_PULLUP);
preferences.begin("counter", false); // Open preferences with the namespace "counter"
// Retrieve the counter from preferences (default to 1 if not set)
fileCounter = preferences.getInt("fileCounter", 1);
Serial.printf("Starting with fileCounter: %d\n", fileCounter);
// Initialize Wi-Fi connection
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(300);
Serial.println("Connecting to Wi-Fi...");
}
Serial.println("Connected to Wi-Fi!");
// Initialize LittleFS
LittleFSInit();
// Initialize Firebase
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
// Sign up for Firebase
if (Firebase.signUp(&config, &auth, "", "")) {
Serial.println("Firebase signup successful");
signupOK = true;
} else {
Serial.printf("Firebase signup failed: %s\n", config.signer.signupError.message.c_str());
}
// Token status callback function
config.token_status_callback = tokenStatusCallback;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
}
void loop() {
smartDelay(1000); // Handle GPS communication
if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 5000 || sendDataPrevMillis == 0)) {
sendDataPrevMillis = millis();
if (gps.location.isValid()) {
double latitude = gps.location.lat();
double longitude = gps.location.lng();
double altitude = gps.altitude.meters();
// Send latitude to Firebase
if (Firebase.RTDB.setFloat(&fbdo, "/gps/latitude", latitude)) {
Serial.println("Latitude updated successfully.");
} else {
Serial.println("Failed to update latitude.");
Serial.println(fbdo.errorReason());
}
// Send longitude to Firebase
if (Firebase.RTDB.setFloat(&fbdo, "/gps/longitude", longitude)) {
Serial.println("Longitude updated successfully.");
} else {
Serial.println("Failed to update longitude.");
Serial.println(fbdo.errorReason());
}
// Send altitude to Firebase
if (Firebase.RTDB.setFloat(&fbdo, "/gps/altitude", altitude)) {
Serial.println("Altitude updated successfully.");
} else {
Serial.println("Failed to update altitude.");
Serial.println(fbdo.errorReason());
}
} else {
Serial.println("Invalid GPS data");
}
}
// Handle push button state and update Firebase
if (Firebase.ready() && signupOK) {
buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW) { // Button pressed
if (Firebase.RTDB.setInt(&fbdo, "/alertStatus", 1)) {
Serial.println("Button pressed! Alert sent to Firebase.");
// Initialize I2S and start recording task
i2sInit();
xTaskCreate(i2s_adc, "i2s_adc", 1024 * 4, NULL, 1, NULL);
if (Firebase.ready() && recordingComplete && !taskCompleted) {
taskCompleted = true;
if (fileExists(filename)) {
uploadToFirebase();
} else {
Serial.println("File not found, cannot upload.");
}
}
} else {
Serial.println("Failed to write to Firebase");
Serial.println(fbdo.errorReason());
}
} else { // Button not pressed
if (Firebase.RTDB.setInt(&fbdo, "/alertStatus", 0)) {
// Serial.println("No alert. Button not pressed.");
} else {
Serial.println("Failed to write to Firebase");
Serial.println(fbdo.errorReason());
}
}
// Small delay to avoid flooding Firebase
delay(500);
}
}
static void smartDelay(unsigned long ms) {
unsigned long start = millis();
do {
while (GPS_Serial.available()) {
gps.encode(GPS_Serial.read());
}
} while (millis() - start < ms);
}
void LittleFSInit() {
if (!LittleFS.begin()) { // Try to initialize LittleFS
Serial.println("LittleFS initialization failed, formatting...");
if (LittleFS.format()) { // Try to format if initialization fails
Serial.println("LittleFS formatted successfully.");
if (LittleFS.begin()) { // Re-attempt to mount after formatting
Serial.println("LittleFS mounted successfully after formatting.");
} else {
Serial.println("LittleFS failed to mount even after formatting!");
while (1) yield(); // Halt execution if LittleFS can't be mounted
}
} else {
Serial.println("LittleFS formatting failed!");
while (1) yield(); // Halt execution if formatting fails
}
} else {
Serial.println("LittleFS mounted successfully.");
}
// Generate a new filename for the current recording
generateNewFileName();
file = LittleFS.open(filename, FILE_WRITE);
if (!file) {
Serial.println("File creation failed!");
while (1) yield(); // Halt execution if the file can't be created
}
Serial.println("LittleFS initialized and file opened.");
}
void generateNewFileName() {
int fileNumber = 1;
// Check if the counter file exists in LittleFS
if (LittleFS.exists("/fileCounter.txt")) {
File counterFile = LittleFS.open("/fileCounter.txt", FILE_READ);
fileNumber = counterFile.parseInt();
counterFile.close();
}
// Create a new filename using the file number
sprintf(filename, "/guardianRecord%d.raw", fileNumber);
// Increment and save the new file number back to LittleFS
File counterFile = LittleFS.open("/fileCounter.txt", FILE_WRITE);
counterFile.printf("%d", fileNumber + 1);
counterFile.close();
Serial.printf("New file name generated: %s\n", filename);
}
void i2sInit() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS),
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = 16,
.dma_buf_len = 1024,
.use_apll = 1
};
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
const i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = -1,
.data_in_num = I2S_SD
};
i2s_set_pin(I2S_PORT, &pin_config);
}
void i2s_adc(void* arg) {
int i2s_read_len = I2S_READ_LEN;
int flash_wr_size = 0;
size_t bytes_read;
char* i2s_read_buff = (char*)calloc(i2s_read_len, sizeof(char));
while (flash_wr_size < FLASH_RECORD_SIZE) {
i2s_read(I2S_PORT, (void*)i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
file.write((const unsigned char*)i2s_read_buff, bytes_read);
flash_wr_size += bytes_read;
Serial.printf("Recording %d%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
}
file.close();
free(i2s_read_buff);
Serial.println("Recording complete");
recordingComplete = true;
i2s_driver_uninstall(I2S_PORT);
vTaskDelete(NULL);
}
void uploadToFirebase() {
String uploadPath = "/audio/guardianRecord" + String(fileCounter) + ".raw";
Firebase.Storage.upload(&fbdo, STORAGE_BUCKET_ID, filename, mem_storage_type_flash, uploadPath.c_str(), "audio/raw");
if (fbdo.httpCode() == FIREBASE_ERROR_HTTP_CODE_OK) {
Serial.println("Upload successful!");
// Increment file counter and save to preferences
fileCounter++;
preferences.putInt("fileCounter", fileCounter);
// Clear LittleFS after successful upload
clearLittleFS();
} else {
Serial.printf("Failed to upload file, reason: %s\n", fbdo.errorReason().c_str());
}
}
bool fileExists(const char* path) {
return LittleFS.exists(path);
}
void clearLittleFS() {
LittleFS.remove(filename);
Serial.println("LittleFS cleared.");
}