ADAFRUIT Stops Sending Data

So I'm trying to use an ADAFRUIT Feather ESP32 connected to an MM8451 Accelerometer to send data to firebase. However I have an issue where the data just, stops sending. I really don't know what it is. I know it isn't firebase because this issue was happening before I was even sending data to my firebase. I was previously using a NodeMCU, which had the same issue, and I thought that switching to the feather would solve my problem but it did not. So I don't know if it's my code, my computer, faulty wiring on my breadboard, or something else.
I'll add the code below, but one thing to note is this image which might provide some more insight. Hopefully the image sends, but the "set json" works for about 10 seconds and then loses connection. I don't really know what that means though, and google isn't helping me.

//Firebase Parameters
#include <Arduino.h>
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "time.h"
// Provide the token generation process info.
#include "addons/TokenHelper.h"
// Provide the RTDB payload printing info and other helper functions.
#include "addons/RTDBHelper.h"
// Insert your network credentials
#define WIFI_SSID "[REMOVED FOR PRIVACY]"
#define WIFI_PASSWORD "[REMOVED FOR PRIVACY]"
// Insert Firebase project API Key
#define API_KEY "[REMOVED FOR PRIVACY]"
// Insert Authorized Email and Corresponding Password
#define USER_EMAIL "[REMOVED FOR PRIVACY]"
#define USER_PASSWORD "[REMOVED FOR PRIVACY]"
// Insert RTDB URLefine the RTDB URL
#define DATABASE_URL "[REMOVED FOR PRIVACY]"
// Define Firebase objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
// Variable to save USER UID
String uid;
// Database main path (to be updated in setup with the user UID)
String databasePath;
// Database child nodes
String XPath = "/AccelerationX";
String YPath = "/AccelerationY";
String ZPath = "/AccelerationZ";
String timePath = "/timestamp";
// Parent Node (to be updated in every loop)
String parentPath;
int timestamp;
FirebaseJson json;
const char* ntpServer = "pool.ntp.org";

//MMA8451 Parameters
#include <Wire.h>
#include <Adafruit_MMA8451.h>
#include <Adafruit_Sensor.h>

Adafruit_MMA8451 mma = Adafruit_MMA8451();
float AccelerationX;
float AccelerationY;
float AccelerationZ;

//Initialize MMA8451
void initMMA8451(){
  Serial.println("Adafruit MMA8451 test!");
  if (! mma.begin()) {
    Serial.println("Couldnt start");
    while (1);
  }
  Serial.println("MMA8451 found!");
  
  mma.setRange(MMA8451_RANGE_2_G);
  
  Serial.print("Range = "); Serial.print(2 << mma.getRange());  
  Serial.println("G");
}

// Initialize WiFi
void initWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
  Serial.println();
}

// Function that gets current epoch time
unsigned long getTime() {
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    //Serial.println("Failed to obtain time");
    return(0);
  }
  time(&now);
  return now;
}

void setup()
{
  Serial.begin(115200);

  // Initialize MMA8451 sensor
  initMMA8451();
  initWiFi();
  configTime(0, 0, ntpServer);

  // Assign the api key (required)
  config.api_key = API_KEY;

  // Assign the user sign in credentials
  auth.user.email = USER_EMAIL;
  auth.user.password = USER_PASSWORD;

  // Assign the RTDB URL (required)
  config.database_url = DATABASE_URL;

  Firebase.reconnectWiFi(true);
  fbdo.setResponseSize(4096);

  // Assign the callback function for the long running token generation task */
  config.token_status_callback = tokenStatusCallback; //see addons/TokenHelper.h

  // Assign the maximum retry of token generation
  config.max_token_generation_retry = 5;

  // Initialize the library with the Firebase authen and config
  Firebase.begin(&config, &auth);

  // Getting the user UID might take a few seconds
  Serial.println("Getting User UID");
  while ((auth.token.uid) == "") {
    Serial.print('.');
    delay(1000);
  }
  // Print user UID
  uid = auth.token.uid.c_str();
  Serial.print("User UID: ");
  Serial.println(uid);

  // Update database path
  databasePath = "/UsersData/" + uid + "/readings";
}

void loop()
{
    //Get current timestamp
    timestamp = getTime();
    Serial.print ("time: ");
    Serial.println (timestamp);

    //parentPath
    parentPath= databasePath + "/" + String(timestamp);
    
    json.set(XPath.c_str(), String(get_datax()));
    json.set(YPath.c_str(), String(get_datay()));
    json.set(ZPath.c_str(), String(get_dataz()));
    json.set(timePath, String(timestamp));
    Serial.printf("Set json... %s\n", Firebase.RTDB.setJSON(&fbdo, parentPath.c_str(), &json) ? "ok" : fbdo.errorReason().c_str());
}

float get_datax()
{
  mma.read();
  sensors_event_t event; 
  mma.getEvent(&event);
  return event.acceleration.x;
}

float get_datay()
{
  mma.read();
  sensors_event_t event; 
  mma.getEvent(&event);
  return event.acceleration.y;
}

float get_dataz()
{
  mma.read();
  sensors_event_t event; 
  mma.getEvent(&event);
  return event.acceleration.z;
}

Your screenshots are unreadable here.
Limit Your code to just exercise the nucleus that has trouble.

void loop()
{
    //Get current timestamp
    timestamp = getTime();
    Serial.print ("time: ");
    Serial.println (timestamp);

    //parentPath
    parentPath= databasePath + "/" + String(timestamp);
    
    json.set(XPath.c_str(), String(get_datax()));
    json.set(YPath.c_str(), String(get_datay()));
    json.set(ZPath.c_str(), String(get_dataz()));
    json.set(timePath, String(timestamp));
    Serial.printf("Set json... %s\n", Firebase.RTDB.setJSON(&fbdo, parentPath.c_str(), &json) ? "ok" : fbdo.errorReason().c_str());
}

This is the section which presumably has the error. The serial monitor will output "Set json... ok" for ten seconds, and then output "Set json... connection lost" even though the ESP is still connected to power. It will just refuse to output any data from that point on, until I disconnect and reconnect the system.

Is this shortly after rebooting or some time later? I see you are using the String class which causes memory problems on targets like an UNO. I wonder if the same applies to an ESP32 device.

Have you considered that the issue maybe network connection related?

Here is a WiFi callback function that I use to troubleshoot WiFi issues.

void WiFiEvent(WiFiEvent_t event)
{
   log_i( "[WiFi-event] event: %d\n", event );
  switch (event) {
        case SYSTEM_EVENT_WIFI_READY:
          log_i("WiFi interface ready");
          break;
        case SYSTEM_EVENT_SCAN_DONE:
          log_i("Completed scan for access points");
          break;
        case SYSTEM_EVENT_STA_START:
          log_i("WiFi client started");
          break;
        case SYSTEM_EVENT_STA_STOP:
          log_i("WiFi clients stopped");
          break;
    case SYSTEM_EVENT_STA_CONNECTED:
      log_i("Connected to access point");
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      log_i("Disconnected from WiFi access point");
      break;
        case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
          log_i("Authentication mode of access point has changed");
          break;
        case SYSTEM_EVENT_STA_GOT_IP:
          log_i ("Obtained IP address: %s",  WiFi.localIP() );
          break;
        case SYSTEM_EVENT_STA_LOST_IP:
          log_i("Lost IP address and IP address is reset to 0");
          //      vTaskDelay( 5000 );
          //      ESP.restart();
          break;
        case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
          log_i("WiFi Protected Setup (WPS): succeeded in enrollee mode");
          break;
        case SYSTEM_EVENT_STA_WPS_ER_FAILED:
          log_i("WiFi Protected Setup (WPS): failed in enrollee mode");
          //      ESP.restart();
          break;
        case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
          log_i("WiFi Protected Setup (WPS): timeout in enrollee mode");
          break;
        case SYSTEM_EVENT_STA_WPS_ER_PIN:
          log_i("WiFi Protected Setup (WPS): pin code in enrollee mode");
          break;
        case SYSTEM_EVENT_AP_START:
          log_i("WiFi access point started");
          break;
        case SYSTEM_EVENT_AP_STOP:
          log_i("WiFi access point  stopped");
          //      WiFi.mode( WIFI_OFF);
          //      esp_sleep_enable_timer_wakeup( 1000000 * 2 ); // 1 second times how many seconds wanted
          //      esp_deep_sleep_start();
          break;
        case SYSTEM_EVENT_AP_STACONNECTED:
          log_i("Client connected");
          break;
    case SYSTEM_EVENT_AP_STADISCONNECTED:
      log_i("WiFi client disconnected");
          break;
        case SYSTEM_EVENT_AP_STAIPASSIGNED:
          log_i("Assigned IP address to client");
          break;
        case SYSTEM_EVENT_AP_PROBEREQRECVED:
          log_i("Received probe request");
          break;
        case SYSTEM_EVENT_GOT_IP6:
          log_i("IPv6 is preferred");
          break;
        case SYSTEM_EVENT_ETH_GOT_IP:
          log_i("Obtained IP address");
          break;
    default: break;
  }
}

Perhaps you can use it as a model to determine if the issue is WiFi.

I don't think it is WIFI related, because I've changed WIFI connections and yet the issue still happened. However I will try this and get back to you.

The data will stop sending after I have the system plugged in for a few seconds. I'll disconnect, and reconnect, and the same thing will happen again.
I did see some stuff about string classes causing memory leaks. Is there anything I could use instead which has the same functionality? I'm new to Arduino code so I don't know too much.

Ok. Sorry to had bothered you, good luck.

1 Like

There's always good old c strings - note the lower case 's'. These are simply 1 dimensional arrays of char terminated with a null (or zero).

Okay, let me look into those and I will get back to you when I try changing it up.

What happens if you slow down your loop?

Like if I change the baud rate? I can try that. Also I tried changing the strings to chars but it messed a bunch of things up later in the code.. I'll have to keep looking into it

No, like introduce a delay(1000) or similar into the beginning of your loop so you are only reading/transmitting once per second

Oh okay, gotcha
I've been running it for a minute or so, and the issue has not appeared. Does this mean it could be a memory thing? Ideally, I would want multiple samples per second, so I don't know how I should go about fixing this. Maybe I could add a smaller delay, or just fix the memory issue.

update, it stopped again. It ran for about 2 and a half minutes before stopping.

So, as to where we are at this point:
I added a delay of 1000 at the start of the loop, and I changed the XPATH, YPATH, and ZPATH variables to be char instead of strings. This gets the code to run for about 2 minutes before the same problem happens, and it says connection lost. Could it be that there is still a memory issue, but it is happening later because not as much data is going in?
I could try changing more things from strings to chars, but it will take me a bit to change everything else that might get an error because of that.

I'm not that familiar with the ESP32, but I wonder if something like the following DFRobot tutorial may help:

It seems to be a simple 1 line of code like this:

Serial.println(ESP.getFreeHeap());

If you were to insert this into your loop() function, then I think if you see the value printed going down over time and your setup stops responding when it gets close to zero, then that would indicate a memory leak - I think ......

You are using an ESP32 which has a lot more memory than AVR boards. Also, the wifi library uses a lots of Strings so it is unlikely that your problem is due to memory issues. More likely, the wifi connection is a bit flakey. I would concentrate on detecting it and re-connecting as needed.

Okay so, if this is supposed to indicate a memory leak then that isn't what this is, because the heap number didn't change most of the time. It changed near the beginning and close to when the connection got lost, but it didn't drop to zero.

I wouldn't think that it's a wifi issue because I was having this similar problem on a different network, but I guess I should try. I could maybe use the wifi callback function that a user above suggested? I'm not sure how else I would try and fix it.