7 7
chwe

tutorial IoT with an OrangePi Zero: Node-Red + Mosquitto + ESP8266/NRF24l01

Recommended Posts

For those of you who are interested in using a OPI zero as a small IoT-Server. I have some hints to get it working. It's more or less a lmgtfy How To plus some arduino code to test if it works.

Hardware:

  • OrangePi 0 with Armbian 5.25 connected over lan to my router
  • DHT11 Module on a Wemos D1 mini (a small cheap wlan MCU for ~3$ which can be programmed via the Arduino IDE)

Installation:

First of all we install node-red on the OPI. Instead of rewrite how to do that again I just give you the link who to do that: Node-Red on armbian
Second we install Mosquitto as a mqtt broker. If I have it right in mind I followed this instructable (I'm not shure, it's more than 2 weeks ago and I didn't save the link then): Mosquitto

To represent the data of our DHT sensor-node graphically we install the node red dashboard module in: /usr/lib/node_modules/
with npm i node-red-dashboard

If everything goes right you should have access to node-red via browser on port 1880:
192.168.1.xx:1880
and to the UI of dashboard:
192.168.1.xx:1880/ui/

Setting up everything:

Now we're setting up the Wemos D1 mini. DHT11 wiring (DHT-->Wemos):
VCC -->3.3V 
Signal --> D4
GND -->GND
Some of the Wemos pins are capable for 5V (A0 definitly not!) but the DHT readings gets noisier when the device is powered through 5V (don't ask me why, I'm not en electronic engineer...)

For the testprogramm we need two libraries which can be installed via the arduino IDE lib manager (+ ESP8266WiFi.h which comes when adding the generic ESP8266 board via Boardmanager):

  • PubSubClient.h (PubSubClient by Nick O'Leary)
  • DHT.h (DHT sensor library by Adafruit)

And here comes the simplyfied code publishing to the mqtt broker:

Spoiler

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <DHT.h>

//Server settings 
const char* ssid = "SSID";
const char* password = "Password";
const char* mqqt_server = "OPI IP"; // Address of my server on my network, substitute yours!

// variables for sending intervals
long lastMsg = 0;
int value = 0;

//DHT variables & settings
#define DHTTYPE DHT11 //DHT21 recommended for useful data
#define DHTPIN D4
DHT dht(DHTPIN, DHTTYPE, 11);
float humidity, temp_c; //float vars for DHT.h lib
char hum [5]; //char vars for publish to mqqt broker
char temp [5];  //char vars for publish to mqqt broker

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  dht.begin(); //Initialize DHT senosor
  Serial.begin(115200);
  delay(10);
  
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

 client.setServer(mqqt_server, 1883);

}

void loop() {
  //check if it is connectet to mqqt broker
  if (!client.connected()){
    reconnect();
    }
client.loop();
delay(1000); // 
dht_reading();

  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    ++value;
   client.publish("temp", temp);
   client.publish("hum", hum);
  }

}
void dht_reading(){

  humidity = dht.readHumidity();          // Read humidity (percent)
  temp_c = dht.readTemperature();     // Read temperature as Celcius
  dtostrf(humidity, 2, 2, hum);     //float to char humidity
  dtostrf(temp_c, 3, 2, temp);      //float to char temperature

  }

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

 

The code is more or less a combination of the examples which comes with the PubSubClient & DHT libraries + throw away all the stuff that we don't need (I had also a version of code where the Wemos D1 mini subscribe to the mqtt broker and gets a timestamp injected from node-red which was then added to the published sensor data).
Humidity data is stored in the "hum" topic, temperature in "temp". Keep in mind that if you plan use more than one senor-node, you should name the topics properly (see: MQTT topics best practices for more information about proper topic nameing)

We can now generate our test-flow on the node-red webpage (See printscreen). Subscribe to the mqtt topics and publish it on the chart and gauge (more information about Dashboard can be found on: Node-Red & Dashboard). 

Powering the Wemos and deploy the created flow shoud show us the graphs on 192.168.1.xx:1880/ui/ (see picture)

To call me an IoT expert is like someone calling tkaiser a fan of micro USB powered SBCs. According to the MIT licence this HowTo  is provided "as is", without warranty etc. :P

example.jpg

Share this post


Link to post
Share on other sites

I also started to get the cheap nrf24l01 boards to work. when I followed this tutorial, I always get the error that something with the gpio was wrong.

mysgw: Starting gateway...
mysgw: Protocol version - 2.2.0-beta
mysgw: MCO:BGN:INIT GW,CP=RNNG----,VER=2.2.0-beta
mysgw: TSF:LRT:OK
mysgw: TSM:INIT
mysgw: TSF:WUR:MS=0
mysgw: Could not open /sys/class/gpio/gpio24/direction


Using this configuration settings showed that the nrf24l01 should work on orange pi zero side:

root@orangepizero:/home/opi/MySensors# ./configure --spi-spidev-device=/dev/spidev1.0 --my-transport=nrf24 --my-rf24-ce-pin=2 --my-rf24-cs-pin=13 --my-gateway=mqtt --my-controller-ip-address=127.0.0.1 --my-mqtt-publish-topic-prefix=mysensors-out --my-mqtt-subscribe-topic-prefix=mysensors-in --my-mqtt-client-id=mygateway1

followed by make should give you something like this:

Spoiler

root@orangepizero:/home/opi/MySensors# sudo ./bin/mysgw -d
mysgw: Starting gateway...
mysgw: Protocol version - 2.2.0-beta
mysgw: MCO:BGN:INIT GW,CP=RNNG----,VER=2.2.0-beta
mysgw: TSF:LRT:OK
mysgw: TSM:INIT
mysgw: TSF:WUR:MS=0
mysgw: TSM:INIT:TSP OK
mysgw: TSM:INIT:GW MODE
mysgw: TSM:READY:ID=0,PAR=0,DIS=0
mysgw: MCO:REG:NOT NEEDED
mysgw: MCO:BGN:STP
mysgw: MCO:BGN:INIT OK,TSP=1
mysgw: Attempting MQTT connection...
mysgw: connected to 127.0.0.1
mysgw: MQTT connected
mysgw: Sending message on topic: mysensors-out/0/255/0/0/18
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SRT:OK
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SRT:OK
mysgw: TSF:SAN:OK
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SRT:OK
mysgw: TSF:SAN:OK
root@orangepizero:/home/opi/MySensors# sudo ./bin/mysgw -d
mysgw: Starting gateway...
mysgw: Protocol version - 2.2.0-beta
mysgw: MCO:BGN:INIT GW,CP=RNNG----,VER=2.2.0-beta
mysgw: TSF:LRT:OK
mysgw: TSM:INIT
mysgw: TSF:WUR:MS=0
mysgw: TSM:INIT:TSP OK
mysgw: TSM:INIT:GW MODE
mysgw: TSM:READY:ID=0,PAR=0,DIS=0
mysgw: MCO:REG:NOT NEEDED
mysgw: MCO:BGN:STP
mysgw: MCO:BGN:INIT OK,TSP=1
mysgw: Attempting MQTT connection...
mysgw: connected to 127.0.0.1
mysgw: MQTT connected
mysgw: Sending message on topic: mysensors-out/0/255/0/0/18
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SRT:OK
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SRT:OK
mysgw: TSF:SAN:OK
mysgw: TSF:SAN:OK
mysgw: TSM:READY:NWD REQ
mysgw: TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
mysgw: TSF:SRT:OK
mysgw: TSF:SAN:OK

 

The evening would show if I also get it to run on the sensor node side (don't have time at the moment).

Share this post


Link to post
Share on other sites

Great posts @chwe! I have been meaning to get my OPi Zero up and running for MQTT duty, and this post pulls together both the ESP8266 and NRF24L01 stuff that I wanted to use with it! And now I have a reason to finally use node-rode... I didn't realise it would make that nice dashboard! Thanks!!!! And this link just cracked me up... nice!

 

To call me an IoT expert is like someone call[ing] tkaiser a fan of micro USB powered SBCs. 

Share this post


Link to post
Share on other sites

Added the -ings for you.. :P

 

The dashboard things came from a add-on. At the moment I'm a little bit annoyed from the mysensor stuff. So much of their sensor nodes are fix configured which makes it hard to me to understand, how their library work. My purposes for the hole IoT thing isn't that my opi recognizes when go to the toilet or other senseless homeautomatization stuff (senseless to me, if someone else needs this feel free to make a toilet node :D). I want to use it in lab-automatization (mostly chemistry labs). So most of their predefined nodes are useless to me. Nevertheless, I'll start with things, where an error doesn't burn my labratory.

IMO knowlege should be shared to give something back to the armbian community who makes it possible to me, even thinking about doing lab-automatization on an sbc. 

 

Share this post


Link to post
Share on other sites

lol... it wasn't needed, but is appreciated (I could have just used my super cow privileges and edited it you know! :-P )... :D

 

Indeed. Knowledge is something we have learnt from the community around us, so it is only right that we shared it... we didn't 'create it from a vacuum' after all ;). And what's wrong with a good toilet sensor... although I'm not sure it makes sense to detect when toilet is running (sorry, couldn't resist). My use case is lest sophisticated atm... good 'ol weather logging... but if I get it running how I like it, then who knows... maybe it'll become a bit of home automation... turn on the lights, that sort of thing...

 

Only good thing I got from mysensors so far was a link to a nice DIY atmega328 nrf sensor node board, with screw-header expansion option... was much neater than my breadboard to breadboard PCB version :o. That and from the same author, a nice nrf -> rpi header adapter module. I have yet to go near their abomination of a codebase (it can't be that bad, can it?) ... wish me luck! :D 

 

 

Share this post


Link to post
Share on other sites
On 22.6.2017 at 3:52 AM, pfeerick said:

it can't be that bad, can it?

I think, it depends on your needs. If I understood everything right, the NRF24l01 driver of the MySensors package comes from RF24 lib which was firstly developed for arduino and so on. I think, the code was never cleaned up. 
And also to mention, when they presented their software years ago on the arduino.cc forum they mentioned that librarys which they include in their own stuff aren't updated. I think this is a reason why I don't get my DHT to work properly. Seems that they use a very old DHT.h library and I'm too annoyed to figure out which one.  I'll give it a try later...

Something very similar is the RF24SN (I'm not shure if MySensors is a fork of it). Anyway, hope that you don't get in trouble with it.

Share this post


Link to post
Share on other sites

I finally gave up playing arround with the MySensors lib.  Main reasons are:

  • For every example they use predefined libs (DS18b20, DHT etc.) sometimes no support for updates of these libs. 
  • Things like "This example uses a modified version of the external DTH library, which is included in the MySensors external examples." indicates to me, that this lib has some 'problems', otherwise this should work with the standard DHT lib. 
  • The hole project seems a little bit predefined to me: Use the nodes we think you need, and since I'm not interessted in their nodes it does not make sense for me. 
  • They presented so many examples of nodes, but I never found a example like: how to build your one node (for IoT stuff, where every one, including me, thinks that he would have a better idea how his node should look like, this is IMO the most important tutorial that you should have on your webpage). 

I tried to get a DHT11/DS18b20 working on an arduino nano just to give you an example that this setup works, but I failed several times.  Since im not really interessted in the MySensors stuff anymore I would not waste my time for this. If someone tries it and it works, please add it to this thread, it would be cool for others which are interessted in the MySensors stuff!

 

On 22.6.2017 at 3:52 AM, pfeerick said:

And what's wrong with a good toilet sensor...

@pfeerick the finally made it! (ok, not for the toilett, but would not be hard to adapt this.. :P )

 

Found on CNXSoft that  BLE is now able to implement mesh networking.  If this will be implemented on the cheap BLE modules (e.g. CC2541) this would be a game changer for IoT thingies... 

Share this post


Link to post
Share on other sites

Right, why did you post to this topic while I had it open? :P I think I need to go check my network security now!  :D:D 

 

Anyway, indeed... if this is node red and MQTT running, there is nothing to stop an ESP8266 with screen... say a 1.3" OLED or a 2.2" TFT, etc, from also polling the orange pi / etc and showing the data. 

 

 

Share this post


Link to post
Share on other sites
8 hours ago, Tido said:

and what does stop you of doing so ?

probably the fact that PubSubClient.h is a bit bitchy when you receive messages with more than one character.. :lol:

It's not a big issue, but you need a little workaround.. I had a code snippet somewhere laying around but me and the arduino IDE are fighting hard to upset each other (I always use the false board when flashing and the IDE saves things where I don't want that it saves... :P - so this snippet is probably lost....)

 

Anyway, I moved away from 'arduino' to micropython. The project is a bit more 'buggy' there are a way less libs/modules written for it but it grows & things are sometimes a way easier solved in (micro)python that I can solve it in c++ (I'm sure, a 'real' professional will laugh at me... :lol:).

 

In case you work a bit more with node-red-dashboard, you'll notice that the graph slows down the UI as soon as you have too much data-points which makes it 'useless' . So, let's assume you want a fast reacting gauge or text element (for displaying the last result immediately), but you don't need this time-resolution on your graph, a function node with this code snippet should help you:

if (!context.readings) {
   context.readings = [];  //fill an array
}
context.readings.push(msg.payload);
//collect 60 samples and callculate the average of them for storage
if (context.readings.length==60){    
    var sum = context.readings.reduce(function(prev, curr){
    return (Number(prev) || 0) + (Number(curr) || 0);
    }); //ectract numbers from string and calculate sum
    avg=sum/context.readings.length;  //sum divided to array elements
    var result = Math.round(avg*10)/10; //round to one digit
    msg.payload=result;
    context.readings =  [];  //clear array
    return msg;
}

 

it collects the last 60 messages (can be changed by 'if context.readings.length==60') and calculates the average of the submitted payloads, rounds it to one digit and publishes it. Keep in mind that there's no error handling (error readings on DS18b20 are quite common when you don't care about wiring... :P ). 

Share this post


Link to post
Share on other sites
7 7