• Skip to main content
  • Skip to primary sidebar

RNTLab.com

The Ultimate Shortcut to Learn Electronics and Programming with Open Source Hardware and Software

  • Courses
  • Forum
    • Forum
    • Ask Question
  • Shop
  • Account
  • Blog
  • Login

High Charts multiple series with DHT sensor

Q&A Forum › Category: ESP32 › High Charts multiple series with DHT sensor
0 Vote Up Vote Down
Dylan Paterson asked 4 years ago

Hello, I’ve been trying to manipulate the code from the web server ebook 3_4_charts from file. I want to compare temperature and humidity as separate series but on the same graph. I’ve tried looking at the high charts examples but they’re too simple for me to manipulate with the code in the book. Wondering what a good fix would be.
 
Thanks!

Question Tags: DHT!!, graph, highcharts, humidity, series, Temperature
3 Answers
0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi Dylan.
This tutorial shows how to plot multiple series: https://randomnerdtutorials.com/esp32-plot-readings-charts-multiple/
You just need to modify to use temperature and humidity.
Let me know if you need further help.
Regards,
Sara

0 Vote Up Vote Down
Dylan Paterson answered 4 years ago

Thanks Sara,
I managed to get both values on the same graph, but now the old values don’t show up when I reload the page. I’m not sure if the error is in my main code or in the javascript code. 

// Get current sensor readings when the page loads  
window.addEventListener(‘load’, getReadings);
Highcharts.setOptions({
  time: {
    timezoneOffset: 420 //Add your time zone offset here in minutes
  }
});
// Create Temperature Chart
var chartT = new Highcharts.Chart({

  chart:{ 
    renderTo:’chart-temperature’ 
  },
  series: [
    {
      name: ‘Temperature’,
      type:’line’,
      
    },
    {
      name:’humidity’,
      type:’line’,
    }
  ],
  title: { 
    text: undefined
  },
  plotOptions: {
    line: { 
      animation: false,
      dataLabels: { 
        enabled: true 
      }
    }
  },
  xAxis: {
    type: ‘datetime’,
    dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
  },
  yAxis: {
    title: { 
      text: ‘Temperature Celsius Degrees’ 
    }
  },
  credits: { 
    enabled: false 
  }
});
  
// Create Humidity Chart
var chartH = new Highcharts.Chart({
  chart:{ 
    renderTo:’chart-humidity’ 
  },
  series: [{
    name: ‘Humidity’
  }],
  title: { 
    text: undefined
  },    
  plotOptions: {
    line: { 
      animation: false,
      dataLabels: { 
        enabled: true 
      }
    },
    series: { 
      color: ‘#50b8b4’ 
    }
  },
  xAxis: {
    type: ‘datetime’,
    dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
  },
  yAxis: {
    title: { 
      text: ‘Humidity (%)’ 
    }
  },
  credits: { 
    enabled: false 
  }
});

/* Plot temperature in the temperature chart
function plotTemperature(timeValue, value){
  console.log(timeValue);
  var x = new Date(timeValue*1000).getTime();
  console.log(x);
  var y = Number(value);
  if(chartT.series[0].data.length > 40) {
    chartT.series[0].addPoint([x, y], true, true, true);
  } else {
    chartT.series[0].addPoint([x, y], true, false, true);
  }
}
*/
function plotTemperature(jsonValue) {

  var keys = Object.keys(jsonValue);
  console.log(keys);
  console.log(keys.length);

  for (var i = 0; i < keys.length; i++){
    var x = (new Date()).getTime();
    console.log(x);
    const key = keys[i];
    var y = Number(jsonValue[key]);
    console.log(y);
    
    if(chartT.series[i].data.length > 40) {
      chartT.series[i].addPoint([x, y], true, true, true);
    } else {
      chartT.series[i].addPoint([x, y], true, false, true);
    }
 
  }
}
// Plot humidity in the humidity chart
function plotHumidity(timeValue, value){
  console.log(timeValue);
  var x = new Date(timeValue*1000).getTime();
  console.log(x);
  var y = Number(value);
  if(chartH.series[0].data.length > 40) {
    chartH.series[0].addPoint([x, y], true, true, true);
  } else {
    chartH.series[0].addPoint([x, y], true, false, true);
  }
}

// Function to get current readings on the webpage when it loads for the first time
function getReadings(){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      //console.log(“[“+this.responseText.slice(0, -1)+”]”);
     // var myObj = JSON.parse(“[“+this.responseText.slice(0, -1)+”]”);
     var myObj = JSON.parse(this.responseText);
      //console.log(myObj);
      plotTemperature(myObj);
    }
  };

       /*if(len > 40) {
        for(var i = len-40; i<len; i++){
          var len = myObj.length;
          plotHumidity(myObj[i].time, myObj[i].humidity);
        }
      }
      else {
        for(var i = 0; i<len; i++){
          plotTemperature(myObj);
          plotHumidity(myObj[i].time, myObj[i].humidity);
        }
      } 
    }
  }; 
  */
  xhr.open(“GET”, “/readings”, true);
  xhr.send();
}

if (!!window.EventSource) {
  var source = new EventSource(‘/events’);
  
  source.addEventListener(‘open’, function(e) {
    console.log(“Events Connected”);
  }, false);

  source.addEventListener(‘error’, function(e) {
    if (e.target.readyState != EventSource.OPEN) {
      console.log(“Events Disconnected”);
    }
  }, false);
  
  source.addEventListener(‘message’, function(e) {
    console.log(“message”, e.data);
  }, false);
  
  source.addEventListener(‘new_readings’, function(e) {
    console.log(“new_readings”, e.data);
    var myObj = JSON.parse(e.data);
    console.log(myObj);
    plotTemperature(myObj);
    plotHumidity(myObj.time, myObj.humidity);
  }, false);
}

 
 
MAIN CODE 

/ Replace with your network credentials
const char* ssid = “Mighty Fraser Wifi”;
const char* password = “mightyfraser”;

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

// Create an Event Source on /events
AsyncEventSource events(“/events”);

// NTP server to request epoch time
const char* ntpServer = “pool.ntp.org”;

// Json Variable to Hold Sensor Readings
JSONVar readings;

// File name where readings will be saved
const char* dataPath = “/data.txt”;

// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 10000;
//
//1800000

// 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;
}

// Get Sensor Readings and return JSON object
String getSensorReadings(){
  readings[“temperature”] = String(dht.readTemperature());
  readings[“humidity”] =  String(dht.readHumidity());
  String jsonString = JSON.stringify(readings);
  return jsonString;
}

// Initialize SPIFFS
void initSPIFFS() {
  if (!SPIFFS.begin()) {
    Serial.println(“An error has occurred while mounting SPIFFS”);
  }
  Serial.println(“SPIFFS mounted successfully”);
}

// Read file from SPIFFS
String readFile(fs::FS &fs, const char * path){
  Serial.printf(“Reading file: %s\r\n”, path);

  File file = fs.open(path);
  if(!file || file.isDirectory()){
    Serial.println(“- failed to open file for reading”);
    return String();
  }

  String fileContent;
  while(file.available()){
    fileContent += file.readStringUntil(‘\n’);
    break;
  }
  file.close();
  return fileContent;
}

// Append data to file in SPIFFS
void appendFile(fs::FS &fs, const char * path, const char * message){
  Serial.printf(“Appending to file: %s\r\n”, path);

  File file = fs.open(path, FILE_APPEND);
  if(!file){
    Serial.println(“- failed to open file for appending”);
    return;
  }
  if(file.print(message)){
    Serial.println(“- message appended”);
  } else {
    Serial.println(“- append failed”);
  }
  file.close();
}

// Delete File
void deleteFile(fs::FS &fs, const char * path){
  Serial.printf(“Deleting file: %s\r\n”, path);
  if(fs.remove(path)){
    Serial.println(“- file deleted”);
  } else {
    Serial.println(“- delete failed”);
  }
}

// Get file size
int getFileSize(fs::FS &fs, const char * path){
  File file = fs.open(path);

  if(!file){
    Serial.println(“Failed to open file for checking size”);
    return 0;
  }
  Serial.print(“File size: “);
  Serial.println(file.size());

  return file.size();
}

// Initialize WiFi
void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print(“Connecting to WiFi ..”);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(‘.’);
    delay(1000);
  }
  Serial.println(WiFi.localIP());
}

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.print(“ok”);
  u8x8.begin();
 dht.begin();
  initWiFi();
  initSPIFFS();

  // Create a data.txt file
  bool fileexists = SPIFFS.exists(dataPath);
  Serial.print(fileexists);
  if(!fileexists) {
    Serial.println(“File doesn’t exist”);
    Serial.println(“Creating file…”);
    // Prepare readings to add to the file
    String message = getSensorReadings() + “,”;
    // Apend data to file to create it
    appendFile(SPIFFS, dataPath, message.c_str());
  }
  else {
    Serial.println(“File already exists”);
  }

  // Web Server Root URL
  server.on(“/”, HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, “/index.html”, “text/html”);
  });

  server.serveStatic(“/”, SPIFFS, “/”);

  // Request for the latest sensor readings
  server.on(“/readings”, HTTP_GET, [](AsyncWebServerRequest *request){
    String json = getSensorReadings();
    request->send(200, “application/json”, json);
    json = String();
  });

  // Request for the latest sensor readings
  server.on(“/view-data”, HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, “/data.txt”, “text/txt”);
  });

  // Request for the latest sensor readings
  server.on(“/delete-data”, HTTP_GET, [](AsyncWebServerRequest *request){
    deleteFile(SPIFFS, dataPath);
    request->send(200, “text/plain”, “data.txt has been deleted.”);
  });

  events.onConnect([](AsyncEventSourceClient *client){
    if(client->lastId()){
      Serial.printf(“Client reconnected! Last message ID that it got is: %u\n”, client->lastId());
    }
    // send event with message “hello!”, id current millis
    // and set reconnect delay to 1 second
    client->send(“hello!”, NULL, millis(), 10000);
  });
  server.addHandler(&events);

  configTime(0, 0, ntpServer);

  // Start server
  server.begin();

  events.send(getSensorReadings().c_str(),”new_readings” ,millis());
}

void loop() {
   float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  u8x8.clearDisplay();
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_r);
  u8x8.setCursor(0, 0);
  u8x8.print(“Temperature”);
  u8x8.setCursor(0, 2);
  u8x8.print(t);
  u8x8.print(“*C”);
  u8x8.setCursor(0, 4);
  u8x8.print(“Humidity”);
  u8x8.setCursor(0, 6);
  u8x8.print(h);
  u8x8.print(“%”);
delay(2000);

if ((millis() – lastTime) > timerDelay) {

    // Send Events to the client with the Sensor Readings
    events.send(“ping”,NULL,millis());
    events.send(getSensorReadings().c_str(),”new_readings” ,millis());

    String message = getSensorReadings() + “,”;
    if ((getFileSize(SPIFFS, dataPath))>= 3400){
      Serial.print(“Too many data points, deleting file…”);
      // Comment the next two lines if you don’t want to delete the data file automatically.
      // It won’t log more data into the file
      deleteFile(SPIFFS, dataPath);
      appendFile(SPIFFS, “/data.txt”, message.c_str());
    }
    else{
      // Append new readings to the file
      appendFile(SPIFFS, “/data.txt”, message.c_str());
    }

    lastTime = millis();

    Serial.print(readFile(SPIFFS, dataPath));

  }
}

0 Vote Up Vote Down
Sara Santos Staff answered 4 years ago

Hi.
That’s how the project works.
It only collects data as long as your web browser is opened.
If you close it, and open it again it will not remember the previous values.
To remember old values you need to save your values locally on your ESP32 filesystem, or in a file on a microSD card, or database.
Regards,
Sara

Primary Sidebar

Login to Ask or Answer Questions

This Forum is private and it’s only available for members enrolled in our Courses.

Login »

Latest Course Updates

  • [eBook Updated] Learn Raspberry Pi Pico/Pico W with MicroPython eBook – Version 1.2 May 26, 2025
  • [New Edition] Build ESP32-CAM Projects eBook – 2nd Edition April 16, 2025

You must be logged in to view this content.

Contact Support - Refunds - Privacy - Terms - MakerAdvisor.com - Member Login

Copyright © 2013-2025 · RandomNerdTutorials.com · All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.