Being a comics fan, I couldn’t resist publishing a crossover between my “famous” tutorial about using the enc28j60 driver with Arduino and the fresh new tutorial about the MQTT protocol.
So, after having introduced the MQTT protocol and explained how to use mosquitto, today I’ll show you how to send data to an MQTT broker using the enc28j60 ethernet controller.
Libraries
We’re going to use the PubSubClient library by Nick O’Leary to “talk” with our MQTT broker (mosquitto). You can install the library using the Library Manager in the Arduino IDE (Sketch menu – Include Library – Manage Libraries…):
The library I chose is based on the Ethernet Client API of Arduino, usually available if you use the “official” ethernet chip (W5100). I’ve already blogged about the UIPEthernet library that allows to use sketches and libraries designed for the W5100 chip also with the enc28j60 one. After having installed also this library in the IDE, you’re ready to write your first MQTT sketch…
For this tutorial I decided to connect to the Arduino a temperature (and humidity sensor): the DHT11. I’m going to use the DHT sensor library by Adafruit to read values from that sensor, this library too can be installed through the Library Manager.
Sketch
The full sketch is available in my Github’s repository.
Let’s see the most important lines of code. After having included the required libraries, the sketch defines some constants, like the topic to send data to, the identifier of the MQTT client, the interval between two transmissions and the configuration of the sensor:
#define CLIENT_ID "ArduinoMQTT" #define TOPIC "temperature" #define PUBLISH_DELAY 5000 #define DHTPIN 3 #define DHTTYPE DHT11 |
then it configures the MAC address of the network interface and the IP address of the MQTT broker (= the IP address of the PC where mosquitto runs on):
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; IPAddress mqttServer(192,168,1,4); |
the MQTT client is configured passing the Ethernet client to be used and the server (and its port) to connect to:
mqttClient.setClient(ethClient); mqttClient.setServer(mqttServer, 1883); Serial.println(F("MQTT client configured")); |
in the main loop() the sketch checks is the interval between two transmissions is passed; if so it reads the new temperature value and sends it to the broker:
if(millis() - previousMillis > PUBLISH_DELAY) { sendData(); previousMillis = millis(); } |
it’s very important to call the loop() command of the MQTT Client frequently to let it process the different incoming packets and commands:
mqttClient.loop(); |
float t = dht.readTemperature(); Serial.print("Temperature: "); Serial.println(t); if(mqttClient.connect(CLIENT_ID)) { mqttClient.publish(TOPIC, dtostrf(t, 6, 2, msgBuffer)); } |
Test
Before running the sketch, first you have to start mosquitto on your PC. Open a second command prompt and run mosquitto_sub to subscribe the temperature topic:
mosquitto_sub.exe -t temperature
if you now run the sketch, you should be able to see the temperature values sent to the broker and, from this one, to the subscriber:
Salve scusa mi rendo conto che il post è un po vecchiotto ma volevo chiedere se c’è un modo di sfruttare il protocollo mqtt senza lo shield ethernet, ho letto un po in giro e ho trovato la libreria per arduino SerialIp, ma è una libreria del 2010, volevo sapere se andava bene per arduino due, e se è una libreria valida.
Grazie
Ciao Vincenzo, la libreria SerialIP funziona ma richiede un PC collegato ad Arduino… non l’ho provata con Arduino Due
Scusate se rispondo solo ora ma sono stato fuori casa per lavoro, si lo che ci vuole un pc infatti pensavo di usarlo con un raspberry collegato tramite la seriale e quindi il raspi avrebbe fatto da gateway ip.
Pensi che sia possibile, e sarebbe facile da mettere su?
Grazie
Buona sera Luca, per prima cosa vorrei farti i complimenti, spero che sei consapevole che hai la migliore guida di tutto il web sull mqtt e arduino.
Ho un piccolo problema con questo sketch:
nel monitor seriale tutto ok
nel promp dove eseguo mosquitto sembra tutto ok
1504127457: Opening ipv6 listen socket on port 1883.
1504127457: Opening ipv4 listen socket on port 1883.
1504127497: New connection from ::1 on port 1883.
1504127497: New client connected from ::1 as mosqsub|14864-Hp-Cristi (c1, k60).
1504127497: Sending CONNACK to mosqsub|14864-Hp-Cristi (0, 0)
1504127497: Received SUBSCRIBE from mosqsub|14864-Hp-Cristi
1504127497: temp (QoS 0)
1504127497: mosqsub|14864-Hp-Cristi 0 temp
1504127497: Sending SUBACK to mosqsub|14864-Hp-Cristi
1504127557: Received PINGREQ from mosqsub|14864-Hp-Cristi
1504127557: Sending PINGRESP to mosqsub|14864-Hp-Cristi
ma nel promp dove eseguo il sub non ricevo nessun valore
Riesci ad aiutarmi.
Grazie in anticipo
Cristian, dai logs sembra che Arduino non stia spedendo nulla… vedi infatti che il sub si collega (“new client connected as mosqsub…”). Lo sketch che output ti da?
Buona sera Luca, questo è il log da seriale arduino:
MQTT Arduino Demo
MQTT Arduino Demo
Ethernet configured via DHCP
Ip address: 192.168.1.102
MQTT client configured
Dht sensor initialized
Ready to send data
la serie delle letture.
Io utilizzo la ethernet shield e non il modulo enc28j60, può cambiare qualcosa?
Ho notato che l’ip segnato sul log di arduino è lo stesso del server dove è in funzione mosquitto, ma dovrebbe essere l’ip preso con il dhcp giusto?
Grazie mille
Buona sera Luca, ho trovato il problema…i FIREWALL…se attivi su windows, bloccano, giustamente, le connessioni alla porta 1883.
Ora funziona tutto.
Grazie
Sei davvero un grande.
ottimo, grazie a te per aver condiviso la soluzione al tuo problema!
Hi Cristian, First of all thank you for sharing the issue.
I have the similar issue and i tried creating inbound and outbound rules in firewall to allow port 1883. But it did not work.
Could you share your findings
Thank you in advance
Buonasera Luca,
innanzitutto complimenti per il blog!
Sto provando ad utilizzare MQTT su un Arduino Nano e uno shield basato su ENC28J60. Nessun problema in fase di publish mentre continuo ad avere problemi nella lettura dei messaggi sul topic.
La callback viene correttamente scatenata con il topic valorizzato come mi aspetto mentre il valore della variabile “length” continua ad essere sempre 0, quindi payload vuoto.
Ho fatto vari test ma nulla.
Qualche consiglio?
P.S. Sto utilizzando PubSubClient e UIPEthernet.
Grazie mille in anticipo.
ciao Simone, molto strano… non ho mai avuto problemi a “leggere” un topic con quella libreria. Hai provato l’esempio incluso? Anche questo ti da sempre length=0?