Noob needs help - Nano - ENC28J60 - DS18B20 - MQTT

Hello,

I am extremely new to arduino so I am sorry for any noob questions, I have been googling a few weeks now so I hope it is ok to ask a question :slight_smile:

My starting project is getting some temperature's from my boiler with a very low power/cost device and send it over ethernet (not wifi) to my Rasberry pi for further use.

I have a arduino nano with ENC28J60 ethernet shield and some DS18B20 sensors and Mosquito MQTT running on my Rasberry pi.

I am able to get my DS18B20 sensor's working and can read the temperature with the serial monitor
Working code for this part :

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

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

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

// Addresses of 2 DS18B20s
uint8_t sensor1[8] = { 0x28, 0x17, 0x56, 0x79, 0x97, 0x10, 0x03, 0xAE };
uint8_t sensor2[8] = { 0x28, 0xF6, 0x5B, 0x79, 0x97, 0x11, 0x03, 0x98 };


void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
}

void loop(void)
{
  sensors.requestTemperatures();
  
  Serial.print("Sensor 1: ");
  printTemperature(sensor1);
  
  Serial.print("Sensor 2: ");
  printTemperature(sensor2);
  
    
  Serial.println();
  delay(1000);
}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print(tempC);
  Serial.print((char)176);
  Serial.print("C  |  ");
  Serial.print(DallasTemperature::toFahrenheit(tempC));
  Serial.print((char)176);
  Serial.println("F");
}

I am also able to get a network connection to show the "Hello World" webpage, so the LAN is working also on the nano with the ENC28J60
my code (copy pasted afcourse :slight_smile: )

#include <UIPEthernet.h> // Voor Ethernet

// **** ETHERNET INSTELLINGEN ****
byte mac[] = { 0x54, 0x34, 0x41, 0x30, 0x30, 0x31 };                                      
IPAddress ip(192, 168, 15, 111);                        
EthernetServer server(80);

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

  // start de Ethernet verbinding en de server:
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.print("IP Adres: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();

  if (client)
  {  
    Serial.println("-> Nieuwe Verbinding");

    // een http request eindigt met een lege regel
    boolean currentLineIsBlank = true;

    while (client.connected())
    {
      if (client.available())
      {
        char c = client.read();

        // als je aan het einde van een regel bent (newline karakter ontvangen)
        // en de regel is leeg, dan zijn we aan het einde van een HTTP request gekomen,
        // en kunnen we een antwoord sturen
        if (c == '\n' && currentLineIsBlank)
        {
          client.println("<html><title>Hello World!</title><body><h3>Hello World!</h3></body>");
          break;
        }

        if (c == '\n') {
          // We beginnen met een nieuwe regel
          currentLineIsBlank = true;
        }
        else if (c != '\r')
        {
          // we ontvingen een karakter (niet einde regel)
          currentLineIsBlank = false;
        }
      }
    }

    // geef de browser tijd om de data te ontvangen
    delay(10);

    // sluit de verbinding:
    client.stop();
    Serial.println("   Einde verbinding\n");
  }
}

I however am not been able to combine these to send temperature readings to my MQTT server,
I can fine alot of examples for this but they are all for other sensors (DHT11 or BME280)
Like these examples ;

So it looks defenatly possible to use the enc28j60 to use pubsub (also confirmed by pubsub maintainer that it should work with the new UIPethernet.h

but for the life of my I can not find a way or an example to send the temperature data from my DS18B20 to a MQTT broker, I do find examples like these :

but they all work with Wifi modules and not an ethernet shield and my very limited knowlidge makes it impossible to convert them to my ethernet shield :frowning:

If anyone could point me in the right direction or knows of a project/example with the ENC28J60-DS18B20-MQTT combo that would be awesome.

thank you in advance,

Hans

Ok,

I got a little bit furder now,
For the moment, I can read the temperature of two DS18B20 sensor's in my serial monitor, so that is working,
also at the same time I am publishing a test "hello world" topic to my MQTT mosquitto server on my PI, so I know that is working also (dont worry about my username and password in the code, its just for testing, but I know 100% it works.

Now can anyone tell me the code I need to write to publish those two DS18B20 temperature readings to two topics on my MQTT broker ?? I just cant find how I have to format this :frowning:

Any help is appreciated,

My code ;

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

// Update these with values suitable for your network.
byte mac[] = { 0x54, 0x34, 0x41, 0x30, 0x30, 0x31 };                                     
IPAddress ip(192, 168, 15, 111);     
IPAddress server(192, 168, 15, 101);

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

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

// Addresses of 2 DS18B20s
uint8_t sensor1[8] = { 0x28, 0x17, 0x56, 0x79, 0x97, 0x10, 0x03, 0xAE };
uint8_t sensor2[8] = { 0x28, 0xF6, 0x5B, 0x79, 0x97, 0x11, 0x03, 0x98 };

void reconnect() {
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttClient.connect("arduino", "mqtt", "ardu1n0")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      mqttClient.publish("outTopic","hello world");
      // ... and resubscribe
      mqttClient.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
 
  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
}

void loop(void)
{
  if (!mqttClient.connected()) {
    reconnect();
  }
  mqttClient.loop();


  sensors.requestTemperatures();
  
  Serial.print("Sensor 1: ");
  printTemperature(sensor1);
  
  Serial.print("Sensor 2: ");
  printTemperature(sensor2);
  
    
  Serial.println();
  delay(1000);
}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print(tempC);
  Serial.print((char)176);
  Serial.print("C  |  ");
  Serial.print(DallasTemperature::toFahrenheit(tempC));
  Serial.print((char)176);
  Serial.println("F");
}

So I want the output from printTemperature(sensor1) and printTemperature(sensor2) publishing on a topic named for instance temp1 and temp2 on the MQTT broker, but I just cant find how to do it :frowning:
(in Celcius is fine btw :slight_smile: )

thank you for any help and tips,

Hans

Welcome to the forum

I use the following variables and functions

float temperature; // global to exchange the value from the sensor to the MQTT send function.
const char topicTemperature[]  = "sensor/temperature"; // global at the beginning of my sketch so I can change all topics without searching trough the code

char cstr[16]; // local inside the function that sends the MQTT messages

dtostrf( temperature, 7, 2, cstr );
mqttClient.publish( topicTemperature, cstr );

Thank you very much Klaus,
I wont have access to my arduino toys till tuesday, but ill defenatly let you know if I get it working,

I will have to do alot of googling because I have no clue what all those functions do (hence the "noob" part :slight_smile: )

where in there do I differentiate between the different sensors ? (sensor1, sensor2) or will that code automaticaly make the topics sensor/temperature1 , sensor/temperature2 , ...
(I think this is what it is going to do :slight_smile: )

Thanks alot,

Hans

hansie9999:
I will have to do alot of googling because I have no clue what all those functions do (hence the "noob" part :slight_smile: )

My recommendation is to google into the Arduino site first. e.g. "dtostrf site:arduino.cc" This will give you hints inside the forum and the Arduino documentation.

hansie9999:
where in there do I differentiate between the different sensors ? (sensor1, sensor2) or will that code automaticaly make the topics sensor/temperature1 , sensor/temperature2 , ...

The topic is up to you. It is just a string. You need to decide what kind of scheme you want to use. You could just use random characters/numbers for each topic. I prefer to use a name for the sensor and then add the measurement. I just used the word sensor as a placeholder. It is up to the application. How many sensors do you have and what do they measure. Also do you want to automatically decode all MQTT messages on the other side. e.g. for a single house or apartment

kitchen/temperature, basement/temperature, balcony/temperature, balcony/humidity ...

You can decode the messages by searching for '/' and split the sensor and the measurement.

By using defines at the beginning of your sketch, you can use the same code for multiple sensors and just change the defines before you upload to a new sensor.

Thank you for your extra info Klaus,

I will be studieing some more code and see if I can get it working,

ill let you know next week how it went :slight_smile:

Hans

Hello,

I think I was getting progress but I think I have an aditional hardware problem,
Half of the time when I put in a sketch my ethernet port lights stop working of the ENC28J60 , than sometimes I can get them back with my simple ethernet hello world test sketch, but sometimes not,

So I think there might be something wrong with it. (or im just overloading my nano with to big sketches)

I have orderd some W5100 and W5500 ethernet addons and I think ill order one extra ENC28J60 and see if im not hitting a brick wall here because of some hardware failure,

thank you already, and ill defenatly update this if I get it working on other hardware,

Hans

Hi,
as promised just want to report here that I got it working perfectly with a W5500 connected to the Nano.

I also ordered some new ENC28J60 and im sure ill get it working on that one also later,

For reference my sketch ;

[code]
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2

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

DallasTemperature sensors(&oneWire);

// update these values with your DS18B20 sensor ID's , look online for a sketch that lets your read your sensor ID's
DeviceAddress Probe01 = { 0x28, 0x17, 0x56, 0x79, 0x97, 0x10, 0x03, 0xAE }; 
DeviceAddress Probe02 = { 0x28, 0xFE, 0x72, 0x76, 0xE0, 0x01, 0x3C, 0x2E };
DeviceAddress Probe03 = { 0x28, 0x10, 0x13, 0x76, 0xE0, 0x01, 0x3C, 0xC8 };
DeviceAddress Probe04 = { 0x28, 0x38, 0x05, 0x75, 0xD0, 0x01, 0x3C, 0x69 };
DeviceAddress Probe05 = { 0x28, 0x31, 0xC2, 0x75, 0xD0, 0x01, 0x3C, 0x8C };


// Update these with values suitable for your network.
byte mac[] = { 0x54, 0x34, 0x41, 0x30, 0x30, 0x31 };                                     
IPAddress ip(192, 168, 15, 111);     
IPAddress server(192, 168, 15, 101);
const char* mqtt_server = "192.168.15.101";

// Update these with values for your MQTT client name and access information
const char* MQTTClient = "nano1"; // MQTT client name
const char* MQTTUser = "mqtt"; // MQTT client username to login to MQTT server
const char* MQTTPassword = "password"; // MQTT client user password

// Update these with information about your topics to publish to your MQTT server
const char* Topic1 = "Boiler/Probe";
const char* Topic2 = "Boiler/Outlet";
const char* Topic3 = "Boiler/Inlet";
const char* Topic4 = "Boiler/Bottom";
const char* Topic5 = "Boiler/Top";

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);
long lastMsg = 0;
float temp1 = sensors.getTempC(Probe01);
float temp2 = sensors.getTempC(Probe02);
float temp3 = sensors.getTempC(Probe03);
float temp4 = sensors.getTempC(Probe04);
float temp5 = sensors.getTempC(Probe05);
int inPin = 5;



void reconnect() {
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttClient.connect(MQTTClient, MQTTUser, MQTTPassword)) {
      Serial.print("connected as MQTT client : ");
      Serial.println(MQTTClient);
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
 
void setup()
{
  Serial.begin(9600);
  mqttClient.setServer(server, 1883);
  delay(1500);
  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  delay(500);
  pinMode(inPin, INPUT);
  sensors.begin();
}

void loop()
{
  if (!mqttClient.connected()) {
    reconnect();
  }
  mqttClient.loop();

  long now = millis();
  if (now - lastMsg > 30000) {
    lastMsg = now;
    sensors.setResolution(Probe01, 12); // set reading resolution on 9,  10,  11,  or  12  bits
    sensors.setResolution(Probe02, 12);
    sensors.setResolution(Probe03, 12);
    sensors.setResolution(Probe03, 12);
    sensors.setResolution(Probe03, 12);
    sensors.requestTemperatures(); // Send the command to get temperatures
    temp1 = sensors.getTempC(Probe01);
    Serial.print("Sensor 1 : ");
    Serial.print(temp1);
    Serial.print(" °C - MQTT topic : ");
    Serial.println(Topic1);
    if((temp1 > -126) && (temp1 <125))
      {
      mqttClient.publish(Topic1, String(temp1).c_str());
      }
    else
    {
      mqttClient.publish(Topic1, "sensor error");
      }  
    temp2 = sensors.getTempC(Probe02);
    Serial.print("Sensor 2 : ");
    Serial.print(temp2);
    Serial.print(" °C - MQTT topic : ");
    Serial.println(Topic2);
    if((temp2 > -126) && (temp2 <125))
      {
      mqttClient.publish(Topic2, String(temp2).c_str());
      }
    else
    {
      mqttClient.publish(Topic2, "sensor error");
      }  
    temp3 = sensors.getTempC(Probe03);
    Serial.print("Sensor 3 : ");
    Serial.print(temp3);
    Serial.print(" °C - MQTT topic : ");
    Serial.println(Topic3);
   if((temp3 > -126) && (temp3 <125))
      {
      mqttClient.publish(Topic3, String(temp3).c_str());
      }
    else
    {
      mqttClient.publish(Topic3, "sensor error");
      }  
    temp4 = sensors.getTempC(Probe04);
    Serial.print("Sensor 4 : ");
    Serial.print(temp4);
    Serial.print(" °C - MQTT topic : ");
    Serial.println(Topic4);
    if((temp4 > -126) && (temp4 <125))
      {
      mqttClient.publish(Topic4, String(temp4).c_str());
      }
    else
    {
      mqttClient.publish(Topic4, "sensor error");
      }  
    temp5 = sensors.getTempC(Probe05);
    Serial.print("Sensor 5 : ");
    Serial.print(temp5);
    Serial.print(" °C - MQTT topic : ");
    Serial.println(Topic5);
    Serial.println("-------");
    if((temp5 > -126) && (temp5 <125))
      {
      mqttClient.publish(Topic5, String(temp5).c_str());
      }
    else
    {
      mqttClient.publish(Topic5, "sensor error");
      }  
  }
}
[/code]

This sends the temperature data in °C for 5 specific sensors (sensor ID is needed) to a MQTT server, when the sensor is defect or disconnected it will send a "sensor error" message.
I have made it so that you can easely adjust all the data to uses multiple arduinos with minimal changes to the sketch.

I hope it helps anyone for there projects.

Hans

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.