Esp8266 and multiple ds18b20's with mqtt

Ok i have been going through the forums.
i find plenty on how to use multiple ds18b20s, using a specific node.
but as most forums suggest node red crashes.
so im trying to use them now on an esp8266,
i have been all over trying to get my temps to be reliable enough for temp control but until i have the temps displaying in chart and a gauge without crashing node red i cant move on to next stage of my flows.
I have no programming training. my only source is copy and past and tweaking something there.
how ever i need help to understand and to manipulate some code.
I have found tutorials on multiple sensors with esp8266 but they do a little web server that you can look at phone like a dashboard.
and i have found tutorials on how to hook up one ds18b20 to mqtt from esp8266,
what i need is esp8266, with 7 sensors. sending info to mqtt. but having enough so i know which sensor is which. so i can connect to the mqtt node in flow.

#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include "ESPAsyncWebServer.h"

// Replace with your network credentials
const char* ssid = "Enter Your WiFi Name";
const char* password = "Enter your WiFi Password";

const int SensorDataPin = 14;   //D5 pin
  
OneWire oneWire(SensorDataPin);
DallasTemperature sensors(&oneWire);

float temperature_Celsius;
float temperature_Fahrenheit;

AsyncWebServer server(80);
AsyncEventSource events("/events");

unsigned long lastTime = 0;  
unsigned long timerDelay = 30000;  // send readings timer

void getDS18B20Readings(){
 
  sensors.requestTemperatures(); 
  temperature_Celsius = sensors.getTempCByIndex(0);
  temperature_Fahrenheit = sensors.getTempFByIndex(0);
}

String processor(const String& var){
  getDS18B20Readings();
  //Serial.println(var);
  if(var == "TEMPERATURE_C"){
    return String(temperature_Celsius);
  }\
  else if(var == "TEMPERATURE_F"){
    return String(temperature_Fahrenheit);
  }
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>DS18B20 Web Server</title>
  <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">
  <link rel="icon" href="data:,">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    p {  font-size: 1.2rem;}
    body {  margin: 0;}
    .topnav { overflow: hidden; background-color: #4B1D3F; color: white; font-size: 1.7rem; }
    .content { padding: 20px; }
    .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
    .cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
    .reading { font-size: 2.8rem; }
    .card.temperature { color: #0e7c7b; }
  </style>
</head>
<body>
  <div class="topnav">
    <h3>DS18B20 WEB SERVER</h3>
  </div>
  <div class="content">
    <div class="cards">
      <div class="card temperature">
        <h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp_celcius">%TEMPERATURE_C%</span> &deg;C</span></p>
      </div>
      <div class="card temperature">
        <h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp_fahrenheit">%TEMPERATURE_F%</span> &deg;F</span></p>
      </div>
    </div>
  </div>
<script>
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('temperature_Celsius', function(e) {
  console.log("temperature", e.data);
  document.getElementById("temp_celcius").innerHTML = e.data;
 }, false);
 
 source.addEventListener('temperature_Fahrenheit', function(e) {
  console.log("temperature", e.data);
  document.getElementById("temp_fahrenheit").innerHTML = e.data;
 }, false);
 
}
</script>
</body>
</html>)rawliteral";

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

  // Set the device as a Station and Soft Access Point simultaneously
  //WiFi.mode(WIFI_AP_STA);
  
  // Set device as a Wi-Fi Station
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Setting as a Wi-Fi Station..");
  }
  Serial.print("Station IP Address: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  
  // Handle Web Server
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Handle Web Server Events
  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);
  server.begin();
}

void loop() {
  if ((millis() - lastTime) > timerDelay) {
    
getDS18B20Readings();
    Serial.printf("Temperature = %.2f ºC \n", temperature_Celsius);
    Serial.printf("Temperature = %.2f ºF \n", temperature_Fahrenheit);
    Serial.println();

    // Send Events to the Web Server with the Sensor Readings
    events.send("ping",NULL,millis());
    events.send(String(temperature_Celsius).c_str(),"temperature_Celsius",millis());
    events.send(String(temperature_Fahrenheit).c_str(),"temperature_Fahrenheit",millis());
    
    lastTime = millis();
  }
}
/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp8266-nodemcu-mqtt-publish-ds18b20-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

// Raspberri Pi Mosquitto MQTT Broker
#define MQTT_HOST IPAddress(192, 168, 1, XXX)
// For a cloud MQTT broker, type the domain name
//#define MQTT_HOST "example.com"
#define MQTT_PORT 1883

// Temperature MQTT Topics
#define MQTT_PUB_TEMP "esp/ds18b20/temperature"

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;          
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);
// Temperature value
float temp;

AsyncMqttClient mqttClient;
Ticker mqttReconnectTimer;

WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;

unsigned long previousMillis = 0;   // Stores last time temperature was published
const long interval = 10000;        // Interval at which to publish sensor readings

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void onWifiConnect(const WiFiEventStationModeGotIP& event) {
  Serial.println("Connected to Wi-Fi.");
  connectToMqtt();
}

void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
  Serial.println("Disconnected from Wi-Fi.");
  mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
  wifiReconnectTimer.once(2, connectToWifi);
}

void connectToMqtt() {
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

void onMqttConnect(bool sessionPresent) {
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");

  if (WiFi.isConnected()) {
    mqttReconnectTimer.once(2, connectToMqtt);
  }
}

/*void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
  Serial.println("Subscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  Serial.print("  qos: ");
  Serial.println(qos);
}

void onMqttUnsubscribe(uint16_t packetId) {
  Serial.println("Unsubscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}*/

void onMqttPublish(uint16_t packetId) {
  Serial.print("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup() {
  sensors.begin();
  Serial.begin(115200);
  Serial.println();
  
  wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
  wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  //mqttClient.onSubscribe(onMqttSubscribe);
  //mqttClient.onUnsubscribe(onMqttUnsubscribe);
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  // If your broker requires authentication (username and password), set them below
  //mqttClient.setCredentials("REPlACE_WITH_YOUR_USER", "REPLACE_WITH_YOUR_PASSWORD");
  
  connectToWifi();
}

void loop() {
  unsigned long currentMillis = millis();
  // Every X number of seconds (interval = 10 seconds) 
  // it publishes a new MQTT message
  if (currentMillis - previousMillis >= interval) {
    // Save the last time a new reading was published
    previousMillis = currentMillis;
    // New temperature readings
    sensors.requestTemperatures(); 
    // Temperature in Celsius degrees
    temp = sensors.getTempCByIndex(0);
    // Temperature in Fahrenheit degrees
    //temp = sensors.getTempFByIndex(0);
    
    // Publish an MQTT message on topic esp/ds18b20/temperature
    uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temp).c_str());                            
    Serial.printf("Publishing on topic %s at QoS 1, packetId: %i ", MQTT_PUB_TEMP, packetIdPub1);
    Serial.printf("Message: %.2f \n", temp);
  }
}

The second article you linked to above looks fairly comprehensive.
Which parts of it have you got working?
Have you created the Node-RED flow that is described in the article?

This is the publish topic that is used at the ESP8266 end...
esp/ds18b20/temperature

So in your Node-RED flow you would need an MQTT-In node that subscribes to...
esp/ds18b20/temperature/#

I suggest you get a basic MQTT transfer working and then consider how to handle multiple sensors.

This article explains how to handle multiple one-wire sensors (e.g. DS18B20s) at the ESP8266 end.

Quickly looking at this article, I would adjust the code so the publish-topic included the sensor reference then you could easily extract it at the Node-RED end.

So the publish-topic would be...
esp/ds18b20/temperature/sensor0/
esp/ds18b20/temperature/sensor1/
etc..

yes i have done as the second link,
here are the pics of flow and the settings of the mqtt in node.
however i am not getting a temp from the message.
also i'm not really sure whats going on with debug nodes.
but i just select the one in the flow and i get a bunch of messages about other debugs that i do not have selected.


You can apply a filter so you only see the Debug for the current flow.
Screen Shot 03-30-22 at 07.38 PM
That might help to see what's going on.
You can also give each Debug node a name, which again helps to pinpoint things.

EDIT: The other thing you could try is setting the Debug node to show 'Complete message object' as you would then see the 'topic' as well as the 'payload'.

You could also try editing the Topic entry in your MQTT-In node to something like...
esp/ds18b20/#
And see what that gives you.

Another question... where is your MQTT broker?
Which platform is it running on?
I assume it is running on the same platform as the device that is running Node-RED?

...look into tasmota firmware. There is no programming skill needed to either flash the code and integrate with NR via mqtt or web-API.

2 Likes

dynamicdave

17m

Another question... where is your MQTT broker?
Which platform is it running on?
I assume it is running on the same platform as the device that is running Node-RED?

I am running mosquito on the raspberry pi 4

so i have an esp8266 but it doesnt have nodemcu on it, i have read tutorials on those and how to install but not really grasping pulling it off of a file server and knowing what to do.
i think im missing something right now when connected to arduino ide i have esp8266 generic selected

as of right now im not getting any message from it. debug is blank

What ESP model/board exactly and how do you connect it to your PC with arduino IDE?
Tasmota will work even with a small ESP01 board.
See: Getting Started - Tasmota

Edit: also see: DS18x20 temperature sensor - Tasmota ...up to 8 DS18x20 sensors are supported out of the box in the standard/defaukt firmware (on a single GPIO)

Sending from phone, I have a see picture

...then you only need the USB cable to connect and a chrome browser to perform the flash.
The tasmota web installer should work fine...see the link I provided in my posts above.
use the standard or sensors binary variant of the firmware.

ok i am installing the sensors binary on it now. its still preparing installation.
what should i be doing after that is complete?

It is taking forever 15 minutes and still says preparing installation.
is that normal?

no thats not normal.

Not sure of the board that you are using but flashing tasmota is usually straightforward

Make sure you disconnect all the sensors on the board and just connect via USB to your PC

Craig

Also you only need the standard Tasmota flash for the DS18B20

Assuming you are using Windows search for and download Tasmotizer - it is by far the easiest way

Craig

No, it is not.
You should see the process moving forward, like erasing flash, sending/flashing firmware, ...
I don't know the WROOM board and its USB component. Maybe you need to actually press a button to set the board into programming mode.
You can also try the other tools mentioned.
Basically it technically is the same method used by Arduino IDE when ESP8266 toolchain is installed.

Please read the docs carefully.
Normal behaviour - in short - is that after the board reboots it will open a wifi Accesspoint with a name indicating a new ESP board near you...use your phone to connect and use the browser to navigate to the default URL (IP: 192.168.4.1)...set the WiFi configuration to connect the board to your local WiFi AP (SSID/PWD). After that start configuration.(select module config, configure temp-sensor(s) to the correct GPIO, set MQTT-Broker connection)....basically you can always use the web-access via browser, once you know the IP of the board in your local WiFi.

Just a note that this stuff we are discussing here is not NR related. So maybe using PMs is more appropriate until you get it working. Then we can continue your topic with connecting your sensors to NR.

i actually have a din rail hat for the esp8266 its at the brewery with all the sensors wired to it. i just pull of the esp8266 and im at home right now setting it up.

Ok thats much better then

So (assuming windows) - download tasmotizer and run it

Connect the ESP to the USB serial port on your PC - your PC should automatically find it (assuming a fairly recent Windows version)

Push refresh on the Tasmotizer window next to Com Port and you should see a new com port listed (usually something like Com8)

Select that

In the middle of the screen is an option to select Release - assuming you have a web connection from your PC it will go out and download the latest (Version 11) release of Tasmota and when you press start will attempt to flash it to the board

Craig


got the wifi set up for house on it for now so this is what i see from my computer.
can i have multiple wifi's saved in it?
also this may be a silly question.
but will i still be flashing the rom with arduino ide with the programing or am i doing something different?
i am totally new to this part of an arduino

Nope this saves you from having to worry about the arduino IDE - this does everything for you

Yes you can configure two WIFI networks - it will fall over to the 2nd one if the first is not availabl

Now you need to configure your MQTT server IP in there so you can see if it is talking to mosquitto fine

Craig