Page 1 of 1

Advice to improve the stability of my script?

Posted: Tue Sep 24, 2019 1:08 am
by wrybread
I'm reading 5 DS18B20 temperature sensors from an MELIFE ESP32-ESP-32S dev board, and getting crashes about once a minute. Sometimes it'll trigger the watchdog and reboot, sometimes it'll just stop responding.

I'm hitting it pretty hard, reading the temps of all 5 sensors every 2 seconds. And I'm powering all 5 sensors from the 3.3v pin of the ESP32. Should it be able to handle that?

I've read some posts suggesting that switching to ESP IDF can be more stable, but I'm new to the ESP32 (but not Arduino) and don't understand what that means. Could someone possibly explain that?

And I've read that switching to Stickbreaker's Arduino-ESP32 can improve stability (github.com/stickbreaker/arduino-esp32). Is that something that might help? Any tips on switching to that if so?

In the Arduino IDE I have the board set to "ESP Dev Module".

Here's a sample error message when it reboots:

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1100
load:0x40078000,len:9564
ho 0 tail 12 room 4
load:0x40080400,len:6320
entry 0x400806a8

Posting my script, and let me know if any other info would help diagnose the issue.

Code: Select all


/*



Connections:
- black to ground
- red to 3.3v +
- yellow to data
- 4.8k resistor between red and yellow
- to connect extras, just connect to each other (another yellow to the end of the resistor, another red to the other end of the resistor, black to ground)!


  
*/




// Import required libraries for ESP32
#include <WiFi.h>
#include <WiFiMulti.h>
#include <ESPAsyncWebServer.h>


#include <OneWire.h>
#include <DallasTemperature.h>


// Data wire is plugged TO GPIO 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);


// init wifimulti (so can use multiple ssid's)
WiFiMulti wifiMulti;
IPAddress last_ip;


// Create AsyncWebServer object on port 80
AsyncWebServer server(80);


// Number of temperature devices found
int numberOfDevices;


// We'll use this variable to store a found device address
DeviceAddress tempDeviceAddress; 




// read a specific thermometer
String readThermometer( int num) {
  
  sensors.requestTemperatures(); 
  float temp = sensors.getTempFByIndex(num);

  if(int(temp) < -100){
    Serial.print("Failed to read from DS18B20 sensor: ");
    Serial.print(num+1);
    Serial.println("");
    return "--";
  } else {
    Serial.print("Temperature");
    Serial.print(num+1);
    Serial.print(": ");
    Serial.println(temp);
    return String(temp);  
  }
  
}


// read all thermometers
String readAllThermometers() {

  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();
  
  sensors.requestTemperatures(); 

  String message = "";

  // Loop through each device, print out temperature data
  for(int i=0;i<numberOfDevices; i++){

    Serial.print("Reading ");
    Serial.print(i+1);
    Serial.print(": ");
    float temp = sensors.getTempFByIndex(i);
    Serial.println(temp);
    message += temp;
    message += "\n";
    delay(100);
      
  }

  return message;
  
}





/////////////////
// THE WEBPAGE
/////////////////

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <!-- <meta http-equiv="refresh" content="10"> -->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2></h2>

  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels"># 1</span>
    <span id="temp1">%TEMP1%</span>
    <sup class="units">&deg;F</sup>
  </p>

  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels"># 2</span>
    <span id="temp2">%TEMP2%</span>
    <sup class="units">&deg;F</sup>
  </p>

  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels"># 3</span>
    <span id="temp3">%TEMP3%</span>
    <sup class="units">&deg;F</sup>
  </p>

  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels"># 4</span>
    <span id="temp4">%TEMP4%</span>
    <sup class="units">&deg;F</sup>
  </p>

  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels"># 5</span>
    <span id="temp5">%TEMP5%</span>
    <sup class="units">&deg;F</sup>
  </p>


</body>

<script>


var response_number = 0;

setInterval(function() {
  //console.log("running...");
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      //console.log("got a response!");
      document.getElementById("temp1").innerHTML = this.responseText;

      // split the response by newlines
      var all_temps = this.responseText.split("\n");

      //console.log( Date.now() );
      response_number += 1;
      console.log("Response #" + response_number);

      for (var i = 0; i < all_temps.length; i++) {
        var i2 = i+1; 
        var this_temp = all_temps[i];
        console.log( "Theremometer " + i2 + "=" + this_temp );
        try { document.getElementById("temp"+i2).innerHTML = this_temp; }
        catch(err) { }
      } // end iteration
      
    
    }
  };
  xhttp.open("GET", "/all", true);
  xhttp.send();
}, 2000);


</script>

</html>)rawliteral";








// Replaces placeholder with DHT values. This replaces eg %TERMPERATUREF1% with the variable. Handy.
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMP1"){
    return readThermometer(0);
  }
  else if(var == "TEMP2"){
    return readThermometer(1);
  }
  else if(var == "TEMP3"){
    return readThermometer(2);
  }
  else if(var == "TEMP4"){
    return readThermometer(3);
  }
  else if(var == "TEMP5"){
    return readThermometer(4);
  }
  return String();
}





void setup(){
  // start serial port
  Serial.begin(115200);
  delay(10);

  Serial.println("Starting up!");
  
  // Start up the library
  sensors.begin();


  
  ////////////////////
  // Connect to wifi! (using wifimulti)
  ////////////////////

  // specify SSIDs 
  wifiMulti.addAP("WryPhone", "zzzz");
  wifiMulti.addAP("WryPhone2", "zzzz");  
  

  // (Note that must run wifiMulti.run() here or it will reset in a loop...)
  Serial.println("Connecting Wifi...");
  if(wifiMulti.run() == WL_CONNECTED) {
      Serial.println("");
      Serial.print("WiFi connected! ");
      Serial.print( WiFi.SSID().c_str() );
      Serial.print(" ");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      last_ip = WiFi.localIP();
  }
  


  



  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  
  server.on("/all", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readAllThermometers().c_str());
  });

  // Start server
  server.begin();

  
}

void loop(){ 

  delay(10);
  //Serial.println("Checking...");


  /*
  if ( WiFi.localIP() != last_ip) {
    Serial.print("New IP! ");
    Serial.print( WiFi.SSID().c_str() );
    Serial.print(" ");
    Serial.println(WiFi.localIP());
  last_ip = WiFi.localIP();
  }

  if(wifiMulti.run() != WL_CONNECTED) {
      Serial.print(".");
  }  
  */

   
}




// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++){
    if (deviceAddress[i] < 16) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
  }
}

Re: Advice to improve the stability of my script?

Posted: Tue Sep 24, 2019 3:45 am
by wrybread
I made a little Python script to load test my ESP32 script, reading from the wifi interface of my ESP32 every second. I get timeouts most of the time, even with only 1 thermometer connected...

Here's my script fyi (apologies for the Python 2 print statements). It expects a response like this (this would be 3 thermometers):

72.3
72.1
72.5

Code: Select all

#!/usr/bin/python

import requests, time

# address of the ESP32
addy = "http://192.168.5.94/all"

counter_good = 0
counter_bad = 0

while True:

    try:
        s = time.time()
        response = requests.get(addy, timeout=10)
        total = time.time() - s
        total = round(total, 2)
        counter_good += 1

        content = response.content
        temps = content.strip("\n")
        temps = temps.split("\n")
        print "Got the temps (#%s) in %s secs! %s" % (counter_good, total, temps)

    except requests.exceptions.Timeout:
        counter_bad += 1
        print "Error #%s (timeout) reading temps" % counter_bad
    except Exception, e:
        counter_bad += 1
        print "Error #%s reading temps (%s)" % (counter_bad, e)

    time.sleep(1)