Mit MQTT einen Roboter steuern - [Teil 2]

Nella prima parte di questa serie di blog hai imparato tutto quello che c'è da sapere su MQTT. Inoltre, un server, il cosiddetto broker, è stato impostato su un Raspberry Pi e i messaggi sono stati inviati e ricevuti dalla riga di comando.

In questa parte, la struttura diventa un po 'più complessa, con i dati inviati e ricevuti da vari NodeMCU e un Arduino Uno con scudo Ethernet, i cosiddetti client.

Lo sfondo sarà che puoi utilizzare un client MQTT sui micro controller più comuni venduti da AZ-Delivery. Nei requisiti hardware è possibile leggere quali parti sono necessarie per completare la serie. Alcuni componenti sono necessari solo per questa parte del blog, ma vengono utilizzati in vari altri post del blog da AZ-Delivery.

hardwareRequisiti

Hai solo bisogno di alcuni componenti per questo post del blog, vedi Tabella 1.

numero Componente
1 Raspberry Pi (richiesto)
1 Alimentazione di corrispondenza
1 Modulo NodeMCU Lua Amica V2 ESP8266 ESP-12F(necessario)
1 Scheda di sviluppo WiFi WLAN del modulo ESP32 NodeMCU (necessario)
1 Scheda micro controller con cavo USB (opzionale)
1 Schermatura Ethernet W5100 (opzionale)
1 Gamma resistenze (opzionale)
2 Potenziometro (necessario)
1 Display LCD 4x20 caratteri blu I2C (opzionale)
1 LED monocolore (opzionale)

Tabella 1: hardware richiesto

Con il Pi, tieni presente che oltre all'hardware sopra menzionato, avrai anche bisogno di una scheda microSD. Per fare ciò, è necessario installare il sistema operativo Raspberry Pi (precedentemente noto come Raspbian) come immagine sulla scheda.

Requisiti software

Il software richiesto per questo progetto è gestibile:

  • IDE Arduino (https://www.arduino.cc/en/Main/Software), è meglio scaricare la versione corrente qui
  • La Biblioteca PubSubClient con tutte le dipendenze
  • La Biblioteca LiquidCrystal_I2C con tutte le dipendenze

Come puoi installare le librerie tramite la gestione delle librerie è sotto https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/arduino-ide-programmieren-fuer-einsteiger-teil-1 Sezione Gestione della libreria, descritta in maggior dettaglio.

Requisito fondamentale

Per far funzionare questo e i seguenti post del blog è necessario un Raspberry Pi con un broker MQTT installato. Puoi leggere esattamente come funziona e quali comandi devi inserire nella Parte 1 di questa serie di blog. Controlla anche se il broker è stato avviato anche all'avvio del Raspberry Pi. A tale scopo, emettere il comando Codice 1 nel terminale.

sudo service mosquitto status

Codice 1: interroga sul terminale se mosquitto è stato avviato

L'output dovrebbe essere un file attivo (in esecuzione) spettacolo vedere illustrazione 1, non sono necessari ulteriori comandi.

Figura 1: Stato del broker mosquitto nel terminale

Se l'output è diverso, ricontrollare se mosquitto è stato installato correttamente e il servizio è stato integrato correttamente anche nell'autostart. Le istruzioni esatte possono essere trovate nella Parte 1.

Sottoscrizione MQTT semplice con il modulo NodeMCU Lua Amica V2 ESP8266

Una nota a questo punto: il modulo NodeMCU Lua Amica V2 ESP8266 viene utilizzato per l'esempio qui descritto.

Nel primo esempio, vedi Codice 2, il NodeMCU dovrebbe stabilire una connessione con il broker MQTT e ricevere tutti i dati. Questo ti dà anche una visione diretta di come funziona la comunicazione generale con la libreria PubSubClient. Ogni funzione è stata descritta in dettaglio in modo da poter comprendere meglio il codice sorgente.

Affinché il codice sorgente funzioni con voi, è necessario modificare l'ID WLAN e la password nel codice sorgente.


//-----------------------------------------------------
// Esempio 1 NodeMCU con MQTT
// Autore: Joern Weise
// Licenza: GNU GPl 3.0
// Creato: 20 ottobre 2020
// Aggiornamento: 25 ottobre 2020
//-----------------------------------------------------
#include // Lib for Wifi
#include // Lib per MQTT Pub and Sub
//
#ifndef STASSID
#define STASSID "................"
#define STAPSK "................"
#endif

#define ADVANCEDIAG 1
const char * MQTT_BROKER = "raspberrypi"; // Nome del broker mqtt
const char * SUBTOPIC = "/ #";
String clientID = "NodeMCU_1"; // Nome client per MQTT-Broker
WiFiClient espClient;
PubSubClient mqttClient (espClient);

void setup ()
{
Serial.begin (115200); // Avvia il baudrate del monitor seriale 115200
ritardo (50);
writeAdvanceDiag ("SerialMonitor abilitato", true);
setupWifi ();
writeAdvanceDiag ("Imposta server MQTT", true);
mqttClient.setServer (MQTT_BROKER, 1883);
writeAdvanceDiag ("Imposta funzione di richiamata", true);
mqttClient.setCallback (callback);
writeAdvanceDiag ("Finish setup () - Function", true);
}

/*
* =================================================================
* Funzione: setupWifi
* Resi: nulli
* Descrizione: configurazione wifi per connettersi alla rete
* =================================================================
*/
void setupWifi ()
{
Serial.println ("Connessione a:" + String (STASSID));
WiFi.mode (WIFI_STA);
WiFi.begin (STASSID, STAPSK);
while (WiFi.status ()! = WL_CONNECTED)
  {
ritardo (500);
Serial.print (".");
  }
Serial.println ("");
Serial.println ("WiFi connesso");
Serial.println ("indirizzo IP:");
Serial.println (WiFi.localIP ());
}

void loop () {
// inserisci qui il tuo codice principale, da eseguire ripetutamente:
if (! mqttClient.connected ())
reconnectMQTT ();

mqttClient.loop ();
}

/*
* =================================================================
* Funzione: richiamata
* Resi: nulli
* Descrizione: verrà chiamato automaticamente, se un argomento sottoscritto
* ha un nuovo messaggio
* topic: restituisce l'argomento da cui proviene un nuovo messaggio
* payload: il messaggio dall'argomento
* length: lunghezza del messaggio, importante per ottenere il contenuto
* =================================================================
*/
void callback (char * topic, byte * payload, unsigned int length)
{
String stMessage = "";
writeAdvanceDiag ("Messaggio arrivato dall'argomento:" + String (argomento), true);
writeAdvanceDiag ("Lunghezza messaggio:" + Stringa (lunghezza), vero);
for (int i = 0; i stMessage + = String ((char) payload [i]);
writeAdvanceDiag ("Il messaggio è:" + stMessage, true);
}

/*
* =================================================================
* Funzione: reconnectMQTT
* Resi: nulli
* Descrizione: se non c'è connessione a MQTT, questa funzione è
* chiamato. Inoltre, l'argomento desiderato viene registrato.
* =================================================================
*/
void reconnectMQTT ()
{
while (! mqttClient.connected ())
  {
writeAdvanceDiag ("Accedi a MQTT-Broker", true);
if (mqttClient.connect (clientID.c_str ()))
    {
Serial.println ("Connesso a MQTT-Broker" + String (MQTT_BROKER));
writeAdvanceDiag ("Sottoscrivi argomento '" + String (SUBTOPIC) + "'", true);
mqttClient.subscribe (SUBTOPIC, 1); // Sottoscrivi l'argomento "SUBTOPIC"
    }
altro
    {
writeAdvanceDiag ("Fallito con rc =" + String (mqttClient.state ()), true);
Serial.println ("Next MQTT-Connect in 3 sec");
ritardo (3000);
    }
  }
}

/*
* =================================================================
* Funzione: writeAdvanceDiag
* Resi: nulli
* Descrizione: scrive messaggi avanzati sul monitor seriale, se
* ADVANCEDIAG> = 1
* msg: messaggio per il monitor seriale
* newLine: messaggio con interruzione di riga (vero)
* =================================================================
*/
void writeAdvanceDiag (String msg, bool newLine)
{
if (bool (ADVANCEDIAG)) // Controlla se la diag avanzata è abilitata
  {
if (newLine)
Serial.println (msg);
altro
Serial.print (msg);
  }
}


Codice 2: Esempio NodeMCU Ricevi dati MQTT

Am Anfang vom Code wird ein Objekt espClient erzeugt und dem ebenfalls erzeugten Objekt mqttClient übergeben. Damit kann bei einer aktiven WiFi-Verbindung eine generelle Kommunikation hergestellt werden.

Startet der NodeMCU, wird zunächst das WiFi, hier in der Funktion setupWifi (), eingerichtet and anschließend in der setup () - Funktion die Verbindung zum MQTT-Broker hergestellt. Mittels "mqttClient.setServer (MQTT_BROKER, 1883);" wird die Adresse und der Port vom MQTT Broker konfiguriert und über "mqttClient.setCallback (callback);" die Funktion zur Abarbeitung der empfangenen Daten bestimmt, dazu weiter unten mehr.

Die loop () - Funktion macht genau zwei Dinge:

1. Prüfung, ob der NodeMCU mit dem MQTT-Broker verbunden ist. Sollte das nicht der Fall sein, wird die Funktion reconnectMQTT () aufgerufen.

2. La funzione mqttClient.loop () viene chiamata per eseguire la comunicazione con MQTT.

Il primo passo è registrarsi con il broker MQTT con un nome client univoco. È possibile definirlo liberamente utilizzando la variabile globale "clientID". Se la registrazione è andata a buon fine, l'argomento desiderato viene sottoscritto nel passaggio successivo. Questo viene fatto usando

"MqttClient.subscribe (SUBTOPIC, 1)"

dove in questo esempio SUBTOPIC sottoscrive l'argomento "/ #" (tutti gli argomenti) e "1" sta per una QoS maggiore di 0. Il NodeMCU viene quindi fornito con messaggi dal broker non appena ci sono modifiche a un argomento.

In caso di errore, il NodeMCU tenta di riconnettersi al broker ogni 3 secondi.

Questo ci porta al punto in cui il NodeMCU riceve i dati dal broker se il NodeMCU è connesso. Se sono presenti nuovi messaggi, questi vengono valutati utilizzando la funzione callback (). Tre parametri vengono passati alla funzione callback ():

  1. topic: che riflette il percorso dell'argomento assoluto del messaggio ricevuto
  2. payload: il messaggio, in formato byte
  3. length: la lunghezza del messaggio

Con queste tre informazioni puoi valutare a cosa ti serve l'argomento selezionato. In questo caso, emettiamo l'argomento tramite il monitor seriale. Subito dopo convertiamo il messaggio byte in una stringa usando il ciclo for mostrato nel codice 3. Hai un messaggio normalmente leggibile.

for (int i = 0; i stMessage + = String ((char) payload [i]);

Codice 3: frammento di codice per convertire il messaggio MQTT in una stringa

Questo messaggio in formato stringa viene emesso anche tramite il monitor seriale

Puoi vedere nella Figura 2 che questo schizzo funziona così bene.

Figura 2: messaggio ricevuto dal broker MQTT

Si prega di considerare prima dei messaggi che le nostre dieresi tedesche non funzionano. Questi sono poi rappresentati da altri personaggi.

Sottoscrizione MQTT semplice con ESP32 NodeMCU

Nota a questo punto, la scheda di sviluppo WiFi WLAN del modulo ESP32 NodeMCU viene utilizzata per il seguente esempio.

Nell'esempio del codice 4, ESP32 NodeMCU deve inviare i dati al broker MQTT. Poiché è molto semplice, iniziamo inviando il runtime dalla scheda di sviluppo WiFi WiFi del modulo NodeMCU ESP32 al broker ogni due secondi.

Anche in questo esempio, ci sono molti commenti nel codice per renderlo più facile da capire. Affinché il codice sorgente funzioni con voi, è necessario modificare l'ID WLAN e la password nel codice sorgente.


//-----------------------------------------------------
// Esempio 2 ESP-NodeMCU con MQTT
// Autore: Joern Weise
// Licenza: GNU GPl 3.0
// Creato: 20 ottobre 2020
// Aggiornamento: 25 ottobre 2020
//-----------------------------------------------------
#include
#include // Lib per MQTT Pub and Sub
//
#ifndef STASSID
#define STASSID "……………" // Inserisci il nome Wfi
#define STAPSK "……………" // Inserisci passkey
#endif

#define ADVANCEDIAG 1
const char * MQTT_BROKER = "raspberrypi"; // Nome del broker mqtt
const char * PubTopic = "/ Client / ESP32"; // Argomento dove pubblicare
String clientID = "ESP-DevKit_1"; // Nome client per broker MQTT
WiFiClient espClient;
PubSubClient mqttClient (espClient);

lLastMsg lungo senza segno = 0;
int iTimeDelay = 2000; // Imposta il ritardo per il prossimo messaggio a 2 secondi
#define MSG_BUFFER_SIZE (50)
char msg [MSG_BUFFER_SIZE];

void setup ()
{
Serial.begin (115200); // Avvia il baud rate del monitor seriale 115200
ritardo (50);
writeAdvanceDiag ("SerialMonitor abilitato", true);
setupWifi ();
writeAdvanceDiag ("Imposta server MQTT", true);
mqttClient.setServer (MQTT_BROKER, 1883);
writeAdvanceDiag ("Finish setup () - Function", true);
}

/*
* =================================================================
* Funzione: setupWifi
* Resi: nulli
* Descrizione: configurazione wifi per connettersi alla rete
* =================================================================
*/
void setupWifi ()
{
Serial.println ("Connessione a:" + String (STASSID));
WiFi.mode (WIFI_STA);
WiFi.begin (STASSID, STAPSK);
while (WiFi.status ()! = WL_CONNECTED)
  {
ritardo (500);
Serial.print (".");
  }
Serial.println ("");
Serial.println ("WiFi connesso");
Serial.println ("indirizzo IP:");
Serial.println (WiFi.localIP ());
}

void loop () {
// inserisci qui il tuo codice principale, da eseguire ripetutamente:
if (! mqttClient.connected ())
reconnectMQTT ();

mqttClient.loop ();

if (millis () - lLastMsg> iTimeDelay)
  {
lLastMsg = millis ();
snprintf (msg, MSG_BUFFER_SIZE, "% 1d", millis ()); // Converti il ​​messaggio in char
mqttClient.publish (PubTopic, msg, true); // Invia al broker
  }
}

/*
* =================================================================
* Funzione: reconnectMQTT
* Resi: nulli
* Descrizione: se non c'è connessione a MQTT, questa funzione è
* chiamato. Inoltre, l'argomento desiderato viene registrato.
* =================================================================
*/
void reconnectMQTT ()
{
while (! mqttClient.connected ())
  {
writeAdvanceDiag ("Accedi a MQTT-Broker", true);
if (mqttClient.connect (clientID.c_str ()))
    {
Serial.println ("Connesso a MQTT-Broker" + String (MQTT_BROKER));
    }
altro
    {
writeAdvanceDiag ("Fallito con rc =" + String (mqttClient.state ()), true);
Serial.println ("Next MQTT-Connect in 3 sec");
ritardo (3000);
    }
  }
}

/*
* =================================================================
* Funzione: writeAdvanceDiag
* Resi: nulli
* Descrizione: scrive messaggi avanzati sul monitor seriale, se
* ADVANCEDIAG> = 1
* msg: messaggio per il monitor seriale
* newLine: messaggio con interruzione di riga (vero)
* =================================================================
*/
void writeAdvanceDiag (String msg, bool newLine)
{
if (bool (ADVANCEDIAG)) // Controlla se la diag avanzata è abilitata
  {
if (newLine)
Serial.println (msg);
altro
Serial.print (msg);
  }
}

Codice 4: ESP32 MQTT-Daten empfangen lassen

Wie schon im ersten Beispiel wird ein Objekt espClient erzeugt und dem ebenfalls erzeugten Objekt mqttClient übergeben. Beim Start vom ESP32 NodeMCU Module WLAN WiFi Development Board wird das WiFi über die Funktion setupWiFi () aufgebaut. Direkt im Anschluss der setup () - Funktion wird der MQTT-Broker mittels "mqttClient.setServer (MQTT_BROKER, 1883);" vorkonfiguriert. Eine callback () - Funktion braucht es an dieser Stelle nicht, da keine Daten empfangen und verarbeitet werden müssen.

Die loop () - Funktion ist daher fast identisch zum ersten Beispiel, mit der Ausnahme von der Zeile die Codice 5 zeigt.


if (millis () - lLastMsg> iTimeDelay)
{
lLastMsg = millis ();
snprintf (msg, MSG_BUFFER_SIZE, "% 1d", millis ()); // Converti il ​​messaggio in char
mqttClient.publish (PubTopic, msg, true); // Invia al broker
}

Codice 5: Codefragment per l'invio del tempo attivo

Dieser Teil sendet alle 2 Sekunden die aktuelle Laufzeit an das Topic "/ Client / ESP32". Das dieses Beispiel funktioniert, zeigt Abbildung 3. In diesem Fall zeigt MQTT.fx die Nachrichten vom MQTT Broker an.

Abbildung 3: MQTTfx zeigt gesendete Daten vom ESP32 NodeMCU

MQTT-Beispiel mit mehreren Clients




In den letzten Beispielen, auch im ersten Blogbeitrag, sind wir immer von einem Broker und einem Client ausgegangen. Die Realität bei solchen MQTT-Projekten sieht aber oft anders aus. In der Praxis gibt es meist Clients, die Daten von Sensoren liefern, Clients, welche die gepushten Daten empfangen und weiterverarbeiten, und zu guter Letzt Clients, die ausführen.


Für das jetzt kommende Beispiel, wird ein NodeMCU Lua Amica Modul V2 einen Potentiometerwert überwachen und bei Änderung der neue Wert an den Broker gesenden.

Ein ESP32 NodeMCU Module Scheda di sviluppo WiFi WLAN sottoscritto diese Daten und mappt diese da 0-1024 auf 0-255, zudem pubblicato da zwei BME / BMP280-Sensoren die Temperatur und den Luftdruck.

Diese gesammelten Daten sottoscrivi un Arduino Uno con Ethernet-Shield, LED e I2C-LCD-Display e visualizzi i dati. Il LED mostra il segnale gemello del potenziometro e il display mostra la temperatura e la luce dei sensori.


Iniziamo con il modulo NodeMCU Lua Amica V2 e il potenziometro. Collegare entrambi come mostrato nella Figura 4. Questa parte è facile poiché ci sono solo tre fili da collegare.

 

Figura 4: Cablaggio del modulo NodeMCU Lua Amica V2 con potenziometro

Il codice per il modulo NodeMCU Lua Amica V2 è mantenuto snello e include essenzialmente l'inizializzazione della WLAN e la connessione a MQTT, nonché la trasmissione dei dati dei valori del potenziometro analogico, vedere Codice 6. In modo che anche il codice sorgente funzioni tu, devi usare il tuo WLAN Change ID e la password nel codice sorgente.

//-----------------------------------------------------
// Esempio 3 NodeMCU con trasferimento Poti a mqtt-broker
// Autore: Joern Weise
// Licenza: GNU GPl 3.0
// Creato: 20 ottobre 2020
// Aggiornamento: 25 ottobre 2020
//-----------------------------------------------------
#include // Lib for Wifi
#include // Lib per MQTT Pub and Sub

#ifndef STASSID
#define STASSID "ENTER-WIFI_HERE" // Immettere il nome Wfi
#define STAPSK "ENTER-PASS-HERE" // Inserisci Wifi-Passkey
#endif
#define ADVANCEDIAG 1
#define MSG_BUFFER_SIZE (50)
#define UPDATETIME 200
#define MINVALUECHANGE 1

const char * MQTT_BROKER = "raspberrypi"; // Nome del broker mqtt
String clientID = "NodeMCU_1"; // Nome client per broker MQTT
const char * PubTopicPoti = "/ Client / ESP32 / Poti / Value"; // Argomento dove pubblicare
const int iAnalogPin = A0; // Imposta il pin analogico
int iSensorValue = 0;
int iLastValue = 0;

// Crea oggetti per mqtt
WiFiClient espClient;
PubSubClient mqttClient (espClient);
unsigned int iLastTime = 0;
char msg [MSG_BUFFER_SIZE];
void setup ()
{
Serial.begin (115200); // Avvia il baud rate del monitor seriale 115200
ritardo (50);
writeAdvanceDiag ("SerialMonitor abilitato", true);
setupWifi ();
writeAdvanceDiag ("Imposta server MQTT", true);
mqttClient.setServer (MQTT_BROKER, 1883);
writeAdvanceDiag ("Imposta funzione di richiamata", true);
writeAdvanceDiag ("Finish setup () - Function", true);
}

/*
=================================================================
Funzione: setupWifi
Resi: nullo
Descrizione: configurazione wifi per connettersi alla rete
=================================================================
*/
void setupWifi ()
{
Serial.println ("Connessione a:" + String (STASSID));
WiFi.mode (WIFI_STA);
WiFi.begin (STASSID, STAPSK);
while (WiFi.status ()! = WL_CONNECTED)
  {
ritardo (500);
Serial.print (".");
  }
Serial.println ("");
Serial.println ("WiFi connesso");
Serial.println ("indirizzo IP:");
Serial.println (WiFi.localIP ());
}

void loop () {
// inserisci qui il tuo codice principale, da eseguire ripetutamente:
if (! mqttClient.connected ())
reconnectMQTT ();

mqttClient.loop ();

if (millis () - iLastTime> UPDATETIME)
  {
iSensorValue = analogRead (iAnalogPin); // Legge il valore analogico
if (iSensorValue! = iLastValue)
    {
if (abs (iSensorValue - iLastValue)> MINVALUECHANGE) // Controlla se il cambiamento è abbastanza alto
      {
Serial.println ("Sensorvalue:" + String (iSensorValue));
snprintf (msg, MSG_BUFFER_SIZE, "% d", iSensorValue); // Converti il ​​messaggio in caratteri
mqttClient.publish (PubTopicPoti, msg); // Invia al broker
iLastValue = iSensorValue;
      }
    }
iLastTime = millis ();
  }
}

/*
=================================================================
Funzione: reconnectMQTT
Resi: nullo
Descrizione: se non c'è connessione a MQTT, questa funzione è
chiamato. Inoltre, l'argomento desiderato viene registrato.
=================================================================
*/
void reconnectMQTT ()
{
while (! mqttClient.connected ())
  {
writeAdvanceDiag ("Accedi al broker MQTT", true);
if (mqttClient.connect (clientID.c_str ()))
    {
Serial.println ("Connesso a MQTT Broker" + String (MQTT_BROKER));
    }
altro
    {
writeAdvanceDiag ("Fallito con rc =" + String (mqttClient.state ()), true);
Serial.println ("Next MQTT-Connect in 3 sec");
ritardo (3000);
    }
  }
}

/*
=================================================================
Funzione: writeAdvanceDiag
Resi: nullo
Descrizione: scrive il messaggio avanzato sul monitor seriale, se
ADVANCEDIAG> = 1
msg: messaggio per il monitor seriale
newLine: messaggio con interruzione di riga (true)
=================================================================
*/
void writeAdvanceDiag (String msg, bool newLine)
{
if (bool (ADVANCEDIAG)) // Controlla se la diag avanzata è abilitata
  {
if (newLine)
Serial.println (msg);
altro
Serial.print (msg);
  }
}

codice 6: Modulo NodeMCU Lua Amica V2

Per aiutarti a comprendere più rapidamente il codice sorgente, sono stati annotati molti commenti e note sulle funzioni.

Il prossimo microcontrollore che deve essere configurato e data la sua funzione qui è il modulo ESP32 NodeMCU WLAN WiFi Development Board. Essendo dotato di due interfacce I2C, riceve due sensori BME / BMP280 e assume la mappatura dei valori del potenziometro analogico. Anche in questo caso, il cablaggio è semplice, vedere la Figura 5.

Figura 5: Cablaggio ESP32 Modulo NodeMCU Scheda di sviluppo WiFi WLAN

Il codice per queste attività, vedere Codice 7, è un po 'più ampio. Innanzitutto, vengono inizializzati la connessione WLAN, la connessione MQTT ei sensori. Nella funzione di callback, il valore del potenziometro analogico appena ricevuto viene mappato su un valore compreso tra 0 e 255 e rinviato al broker. Se uno o entrambi BME / BMP280 hanno nuovi dati di misurazione che si discostano dai valori precedenti, anche questi vengono trasmessi al broker.

Affinché il codice sorgente funzioni con voi, è necessario modificare l'ID WLAN e la password nel codice sorgente.

//-----------------------------------------------------
// Esempio 3 ESP-NodeMCU con due trasferimenti BME in
// broker mqtt e mappatura ingresso analogico
// Autore: Joern Weise
// Licenza: GNU GPl 3.0
// Creato: 20 ottobre 2020
// Aggiornamento: 25 ottobre 2020
//-----------------------------------------------------
#include
#include
#include
#include // Lib per MQTT Pub and Sub

// Definisci le impostazioni WiFi
#ifndef STASSID
#define STASSID "ENTER-WIFI-HERE" // Inserisci il nome Wfi
#define STAPSK "ENTER-PASS-HERE" // Inserisci passkey
#endif

#define ADVANCEDIAG 1

#define I2C_SDA1 21
#define I2C_SCL1 22
#define I2C_SDA2 17
#define I2C_SCL2 16
#define NEXTUPDATE 2000

// Oggetti per I2C e BME
TwoWire I2Cone = TwoWire (0);
TwoWire I2Ctwo = TwoWire (1);
Adafruit_BME280 bmeOne;
Adafruit_BME280 bmeTwo;
lastTime lungo senza segno = 0;

const char * MQTT_BROKER = "raspberrypi"; // Nome del broker mqtt
const char * PubTopicTempOne = "/ Client / ESP32 / TempOne"; // Prima temp
const char * PubTopicTempTwo = "/ Client / ESP32 / TempTwo"; // Seconda temp
const char * PubTopicPresOne = "/ Client / ESP32 / PressOne"; // Argomento prima pressione
const char * PubTopicPresTwo = "/ Client / ESP32 / PressTwo"; // Argomento seconda pressione
const char * PubTopicPotiMap = "/ Client / ESP32 / PotiMapValue"; // Argomento seconda pressione
const char * SUBTOPIC = "/ Client / ESP32 / Poti / Value"; // Sottoscrivi il valore del poti all'argomento
String clientID = "ESP-DevKit_1"; // Nome client per broker MQTT

int iLastTempOne, iLastTempTwo, iLastPressOne, iLastPressTwo;

// Crea oggetti per mqtt
WiFiClient espClient;
PubSubClient mqttClient (espClient);

#define MSG_BUFFER_SIZE (50)
char msg [MSG_BUFFER_SIZE];

void setup () {
// inserisci qui il tuo codice di configurazione, per eseguirlo una volta:
Serial.begin (115200);
Serial.println ("BME280 test");
Serial.println ("Inizializza entrambe le connessioni I2C");
I2Cone.begin (I2C_SDA1, I2C_SCL1, 400000);
I2Ctwo.begin (I2C_SDA2, I2C_SCL2, 400000);
Serial.println ("Fai parlare il primo BME con noi");
bool bStatus;
// Inizializza il primo sensore
bStatus = bmeOne.begin (0x76, & I2Cone);
if (! bStatus)
  {
Serial.println ("Impossibile trovare un sensore BME280 - 1 valido, controllare il cablaggio!");
mentre (1);
  }
altro
Serial.println ("Valid BME280 - 1 sensor!");

// Inizializza il secondo sensore
bStatus = bmeTwo.begin (0x76, & I2Ctwo);
if (! bStatus)
  {
Serial.println ("Impossibile trovare un sensore BME280 - 2 valido, controllare il cablaggio!");
mentre (1);
  }
altro
Serial.println ("Valid BME280 - 2 sensor!");
writeAdvanceDiag ("Init Wifi", true);
setupWifi ();
writeAdvanceDiag ("Init Wifi - DONE", true);
writeAdvanceDiag ("Imposta server MQTT", true);
mqttClient.setServer (MQTT_BROKER, 1883);
writeAdvanceDiag ("Imposta funzione di richiamata", true);
mqttClient.setCallback (callback);
writeAdvanceDiag ("Finish setup () - Function", true);
  }

void loop () {
// inserisci qui il tuo codice principale, da eseguire ripetutamente:
int iTempOne, iTempTwo, iPressOne, iPressTwo;
if (! mqttClient.connected ())
reconnectMQTT ();

mqttClient.loop ();
// Controlla dopo "NEXTUPDATE" se i valori sono cambiati
if (millis () - lastTime> NEXTUPDATE)
    {
iTempOne = int (bmeOne.readTemperature ()); // Ottieni temp uno
iTempTwo = int (bmeTwo.readTemperature ()); // Ottieni temp due
iPressOne = int (bmeOne.readPressure () / 100.0F); // Ottieni premere uno
iPressTwo = int (bmeTwo.readPressure () / 100.0F); // ottieni premere due
if (iTempOne! = iLastTempOne) // Controlla la temp uno cambiato e invia
    {
snprintf (msg, MSG_BUFFER_SIZE, "% 1d", iTempOne); // Converti il ​​messaggio in char
mqttClient.publish (PubTopicTempOne, msg, true); // Invia al broker
writeAdvanceDiag ("Invia Temp uno:" + String (iTempOne), true);
iLastTempOne = iTempOne;
  }
if (iTempTwo! = iLastTempTwo) // Controlla la temp due modificata e invia
    {
snprintf (msg, MSG_BUFFER_SIZE, "% 1d", iTempTwo); // Converti il ​​messaggio in char
mqttClient.publish (PubTopicTempTwo, msg, true); // Invia al broker
writeAdvanceDiag ("Invia Temp due:" + String (iTempTwo), true);
iLastTempTwo = iTempTwo;
    }
if (iPressOne! = iLastPressOne) // Controlla la pressione modificata e invia
    {
snprintf (msg, MSG_BUFFER_SIZE, "% 1d", iPressOne); // Converti il ​​messaggio in char
mqttClient.publish (PubTopicPresOne, msg, true); // Invia al broker
writeAdvanceDiag ("Invia Premere uno:" + Stringa (iPressOne), true);
iLastPressOne = iPressOne;
    }
if (iPressTwo! = iLastPressTwo) // Controlla la pressione due modificata e invia
    {
snprintf (msg, MSG_BUFFER_SIZE, "% 1d", iPressTwo); // Converti il ​​messaggio in char
mqttClient.publish (PubTopicPresTwo, msg, true); // Invia al broker
writeAdvanceDiag ("Invia Premere due:" + Stringa (iPressTwo), true);
iLastPressTwo = iPressTwo;
    }
lastTime = millis ();
  }
}

/*
* =================================================================
* Funzione: richiamata
* Resi: nulli
* Descrizione: verrà chiamato automaticamente, se un argomento sottoscritto
* ha un nuovo messaggio
* topic: restituisce l'argomento da cui proviene un nuovo messaggio
* payload: il messaggio dall'argomento
* length: lunghezza del messaggio, importante per ottenere conntent
* =================================================================
*/
void callback (char * topic, byte * payload, unsigned int length)
{
String stMessage = "";
writeAdvanceDiag ("Messaggio arrivato dall'argomento:" + String (argomento), true);
writeAdvanceDiag ("Lunghezza messaggio:" + Stringa (lunghezza), vero);
for (int i = 0; i stMessage + = String ((char) payload [i]);
writeAdvanceDiag ("Il messaggio è:" + stMessage, true);
// Mappare il valore e inviare il valore mappato al broker mqtt
int iValue, iMapValue;
iValue = stMessage.toInt ();
iMapValue = map (iValue, 0,1024,0,255);
snprintf (msg, MSG_BUFFER_SIZE, "% 1d", iMapValue); // Converti il ​​messaggio in char
writeAdvanceDiag ("Invia PotiValue mappato:" + String (iMapValue), true);
mqttClient.publish (PubTopicPotiMap, msg, true); // Invia al broker
}

/*
* =================================================================
* Funzione: setupWifi
* Resi: nulli
* Descrizione: configurazione wifi per connettersi alla rete
* =================================================================
*/
void setupWifi ()
{
Serial.println ("Connessione a:" + String (STASSID));
WiFi.mode (WIFI_STA);
WiFi.begin (STASSID, STAPSK);
while (WiFi.status ()! = WL_CONNECTED)
  {
ritardo (500);
Serial.print (".");
  }
Serial.println ("");
Serial.println ("WiFi connesso");
Serial.println ("indirizzo IP:");
Serial.println (WiFi.localIP ());
}

/*
* =================================================================
* Funzione: writeAdvanceDiag
* Resi: nulli
* Descrizione: scrive messaggi avanzati sul monitor seriale, se
* ADVANCEDIAG> = 1
* msg: messaggio per il monitor seriale
* newLine: messaggio con interruzione di riga (vero)
* =================================================================
*/
void writeAdvanceDiag (String msg, bool newLine)
{
if (bool (ADVANCEDIAG)) // Controlla se la diag avanzata è abilitata
{
if (newLine)
Serial.println (msg);
altro
Serial.print (msg);
  }
}

/*
* =================================================================
* Funzione: reconnectMQTT
* Resi: nulli
* Descrizione: se non c'è connessione a MQTT, questa funzione è
* chiamato. Inoltre, l'argomento desiderato viene registrato.
* =================================================================
*/
void reconnectMQTT ()
{
while (! mqttClient.connected ())
{
writeAdvanceDiag ("Accedi al broker MQTT", true);
if (mqttClient.connect (clientID.c_str ()))
    {
Serial.println ("Connesso a MQTT Broker" + String (MQTT_BROKER));
writeAdvanceDiag ("Sottoscrivi argomento '" + String (SUBTOPIC) + "'", true);
mqttClient.subscribe (SUBTOPIC, 1); // Sottoscrivi l'argomento "SUBTOPIC"
    }
altro
    {
writeAdvanceDiag ("Fallito con rc =" + String (mqttClient.state ()), true);
Serial.println ("Next MQTT-Connect in 3 sec");
ritardo (3000);
    }
  }
}

 Codice 7: Scheda di sviluppo WiFi WLAN del modulo ESP32 NodeMCU

Nell'ultimo passaggio, dovrebbero essere visualizzati i dati raccolti. Per questo vengono utilizzati Arduino Uno con schermo Ethernet collegato, il display LCD I2C 20x04 e un LED monocromatico.

Puoi vedere il cablaggio esatto Figura 6 vedere. Si noti che il display I2C LCD 20x04 richiede un'alimentazione di 5V.

 

Figura 6: Ethernetshield Arduino Uno per l'output

Non ci sono grandi sorprese durante la programmazione di Arduino Uno. Per prima cosa viene inizializzata la rete e viene verificata la connessione. Nella fase successiva, vengono stabilite la visualizzazione e la connessione al broker MQTT. La funzione callback () è rilevante per l'emissione dei dati, riceve tutti i dati dal broker e mostra le modifiche a uno o più valori sul display o tramite il LED.

//-----------------------------------------------------
// Esempio 3 Arduino Uno Ehternetshiled to receive
// dati dal broker e visualizzati su LCD e LED
// Autore: Joern Weise
// Licenza: GNU GPl 3.0
// Creato: 25 ottobre 2020
// Aggiornamento: 26 ottobre 2020
//-----------------------------------------------------
#include
#include
#include // Lib per MQTT Pub and Sub
#include
#include

#define ADVANCEDIAG 1

LiquidCrystal_I2C lcd (0x27,20,4); // imposta l'indirizzo LCD su 0x27 per un display a 16 caratteri e 2 righe
const int iAnalogOut = 6;
byte mac [] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // Indirizzo MAC per shield
IPAddress ip (192, 168, 178, 177); // Indirizzo IP statico per arduino
IPAddress myDns (192, 168, 178, 1); // Router dell'indirizzo IP
char server [] = "www.google.com"; // Controlla se Arduino è online

String clientID = "Arduino_Uno"; // Nome client per broker MQTT
// Argomenti per la sottoscrizione
const char * MQTT_BROKER = "raspberrypi"; // Nome del broker mqtt
const char * SubTopicTempOne = "/ Client / ESP32 / TempOne"; // Prima temp
const char * SubTopicTempTwo = "/ Client / ESP32 / TempTwo"; // Seconda temp
const char * SubTopicPresOne = "/ Client / ESP32 / PressOne"; // Argomento prima pressione
const char * SubTopicPresTwo = "/ Client / ESP32 / PressTwo"; // Argomento seconda pressione
const char * SubTopicPotiMap = "/ Client / ESP32 / PotiMapValue"; // Potenziometro mappato argomento

// Oggetti per ethernet-com
Client EthernetClient;
PubSubClient mqttClient (client);

// Alcuni vars per l'aggiornamento
bool bUpdateDisplay = false;
bool bUpdatePWM = false;
int iLastTempOne, iLastTempTwo, iLastPressOne, iLastPressTwo, iLastPotiMap;

void setup () {
Serial.begin (115200);
while (! Serial) {
; // attende che la porta seriale si connetta. Necessario solo per la porta USB nativa
  }
Serial.println ("Arduino Uno Monitor");
pinMode (iAnalogOut, OUTPUT);
Ethernet.init (10); // La maggior parte degli shield Arduino utilizza il pin digitale 10
lcd.init (); // Init LCD
lcd.backlight (); // retroilluminazione
lcd.clear (); // Cancella il vecchio contenuto
bUpdateDisplay = true;
Ethernet.begin (mac, ip); // Init ethernet-shield
// Verifica la presenza di hardware Ethernet
if (Ethernet.hardwareStatus () == EthernetNoHardware) {
Serial.println ("Ethernet shield non è stato trovato. Spiacenti, non può essere eseguito senza hardware. :(");
while (true) {
ritardo (1); // non fare nulla, non ha senso eseguire senza hardware Ethernet
    }
  }
// Controlla se c'è com al router
while (Ethernet.linkStatus () == LinkOFF) {
Serial.println ("Il cavo Ethernet non è collegato.");
ritardo (500);
  }

// assegna un secondo allo scudo Ethernet per l'inizializzazione:
ritardo (1000);
Serial.println ("connessione ...");

// Controlla se il sistema è in grado di comunicare
if (client.connect (server, 80)) {
Serial.print ("connesso a");
Serial.println (client.remoteIP ());
// Effettua una richiesta HTTP:
client.println ("GET / cerca? q = arduino HTTP / 1.1");
client.println ("Host: www.google.com");
client.println ("Connessione: chiudi");
client.println ();
} altro {
// se non hai ottenuto una connessione al server:
Serial.println ("connessione non riuscita");
  }
// Init MQTT
writeAdvanceDiag ("Imposta server MQTT", true);
mqttClient.setServer (MQTT_BROKER, 1883);
writeAdvanceDiag ("Imposta funzione di richiamata", true);
mqttClient.setCallback (callback);
writeAdvanceDiag ("Finish setup () - Function", true);
}

void loop () {
// inserisci qui il tuo codice principale, da eseguire ripetutamente:
if (! mqttClient.connected ())
reconnectMQTT ();

mqttClient.loop ();

if (bUpdateDisplay)
  {
UpdateDisplay ();
bUpdateDisplay = false;
  }
if (bUpdatePWM)
  {
analogWrite (iAnalogOut, iLastPotiMap); // Scrive un nuovo valore analogico su LED-Pin
bUpdatePWM = false;
  }
}

/*
* =================================================================
* Funzione: writeAdvanceDiag
* Resi: nulli
* Descrizione: scrive messaggi avanzati sul monitor seriale, se
* ADVANCEDIAG> = 1
* msg: messaggio per il monitor seriale
* newLine: messaggio con interruzione di riga (vero)
* =================================================================
*/
void writeAdvanceDiag (String msg, bool newLine)
{
if (bool (ADVANCEDIAG)) // Controlla se la diag avanzata è abilitata
  {
if (newLine)
Serial.println (msg);
altro
Serial.print (msg);
  }
}

/*
* =================================================================
* Funzione: reconnectMQTT
* Resi: nulli
* Descrizione: se non c'è connessione a MQTT, questa funzione è
* chiamato. Inoltre, l'argomento desiderato viene registrato.
* =================================================================
*/
void reconnectMQTT ()
{
while (! mqttClient.connected ())
  {
writeAdvanceDiag ("Accedi a MQTT-Broker", true);
if (mqttClient.connect (clientID.c_str ()))
    {
Serial.println ("Connesso a MQTT-Broker" + String (MQTT_BROKER));
writeAdvanceDiag ("Sottoscrivi argomento '" + String (SubTopicTempOne) + "'", true);
mqttClient.subscribe (SubTopicTempOne, 1); // Sottoscrivi l'argomento "SubTopicTempOne"
writeAdvanceDiag ("Sottoscrivi argomento '" + String (SubTopicTempTwo) + "'", true);
mqttClient.subscribe (SubTopicTempTwo, 1); // Sottoscrivi l'argomento "SubTopicTempTwo"
writeAdvanceDiag ("Sottoscrivi argomento '" + String (SubTopicPresOne) + "'", true);
mqttClient.subscribe (SubTopicPresOne, 1); // Sottoscrivi l'argomento "SubTopicPresOne"
writeAdvanceDiag ("Sottoscrivi argomento '" + String (SubTopicPresTwo) + "'", true);
mqttClient.subscribe (SubTopicPresTwo, 1); // Sottoscrivi l'argomento "SubTopicPresTwo"
writeAdvanceDiag ("Sottoscrivi argomento '" + String (SubTopicPotiMap) + "'", true);
mqttClient.subscribe (SubTopicPotiMap, 1); // Sottoscrivi l'argomento "SubTopicPotiMap"
    }
altro
    {
writeAdvanceDiag ("Fallito con rc =" + String (mqttClient.state ()), true);
Serial.println ("Next MQTT-Connect in 3 sec");
ritardo (3000);
    }
  }
}

/*
* =================================================================
* Funzione: richiamata
* Resi: nulli
* Descrizione: verrà chiamato automaticamente, se un argomento sottoscritto
* ha un nuovo messaggio
* topic: restituisce l'argomento da cui proviene un nuovo messaggio
* payload: il messaggio dall'argomento
* length: lunghezza del messaggio, importante per ottenere conntent
* =================================================================
*/
void callback (char * topic, byte * payload, unsigned int length)
{
String stMessage = "";
for (int i = 0; i stMessage + = String ((char) payload [i]);

// Controlla se la temp uno è cambiato
if (String (topic) == "/ Client / ESP32 / TempOne")
  {
if (iLastTempOne! = stMessage.toInt ())
    {
iLastTempOne = stMessage.toInt ();
bUpdateDisplay = true;
    }
  }
// Controlla se la temp due è cambiata
if (String (topic) == "/ Client / ESP32 / TempTwo")
  {
if (iLastTempTwo! = stMessage.toInt ())
    {
iLastTempTwo = stMessage.toInt ();
bUpdateDisplay = true;
    }
  }
// Controlla se la pressione uno è cambiata
if (String (topic) == "/ Client / ESP32 / PressOne")
  {
if (iLastPressOne! = stMessage.toInt ())
    {
iLastPressOne = stMessage.toInt ();
bUpdateDisplay = true;
    }
  }
// Controlla se la pressione due è cambiata
if (String (topic) == "/ Client / ESP32 / PressTwo")
  {
if (iLastPressTwo! = stMessage.toInt ())
    {
iLastPressTwo = stMessage.toInt ();
bUpdateDisplay = true;
    }
  }
// Controlla se il valore poti mappato è cambiato
if (String (topic) == "/ Client / ESP32 / PotiMapValue")
  {
if (iLastPotiMap! = stMessage.toInt ())
    {
iLastPotiMap = stMessage.toInt ();
bUpdatePWM = true;
    }
  }
}

/*
* =================================================================
* Funzione: UpdateDisplay
* Resi: nulli
* Descrizione: Visualizza i nuovi valori sul display I2C
* =================================================================
*/
void UpdateDisplay ()
{
lcd.clear ();
lcd.home ();
lcd.print ("Temp uno [C]:");
lcd.print (iLastTempOne);
lcd.setCursor (0,1);
lcd.print ("Temp due [C]:");
lcd.print (iLastTempTwo);
lcd.setCursor (0,2);
lcd.print ("Press one [hPa]:");
lcd.print (iLastPressOne);
lcd.setCursor (0,3);
lcd.print ("Press two [hPa]:");
lcd.print (iLastPressTwo);
}

Codice 8: Arduino Uno zur Anzeige der MQTT-Daten

Ist alles korrekt greenrahtet und der Code auf to MicroController überspielt, sollten Sie schnell ein Ergebnis on dem LCD-Display und der angeschlossenen LED sehen. Beim Drehen vom Potenziometer wird die Helligkeit der LED geändert und die aktuelle Temperatur und Druck beider Sensoren sollten visualisiert werden. Wie das aussehen kann, zeigt Abbildung 7.

Abbildung 7: Ausgabe von Sensordaten und LED-Helligkeit

Wollen Sie alle Daten ihres Brokers sehen, kann ich Ihnen das Tool MQTT.fx empfehlen. Damit können Sie sowohl Daten vom Broker sottoscrive als auch publishen. Probieren Sie gerne auch aus weiterer Hardware and die MicroController anzuschließen und die Daten an den Broker zu senden. Der Arduino Uno kann, über eine Schleife, die Daten abwechselnd anzeigen.

Mit Abschluss dieses Beitrages haben Sie sowohl die Grundlagen, as auch ein komplexeres praktisches Beispiel erhalten. Im nächsten Teil werden die Grundlagen und das praktische Beispiel genutzt, um einen Rollroboter zu steuern.

Dieses und weitere Projekte finden sich auf GitHub unter https://github.com/M3taKn1ght/Blog-Repo

Progetti per principiantiRaspberry pi

3 Kommentare

Jörn Weise

Jörn Weise

Hello jm1704,

thank you for the nice compliment. Of course, as bloggers, we are always interested in writing interesting and knowledgeable posts with az-delivery. Of course, the variety must not be missing and the reference to the products. Especially IoT is an interesting topic, but also holds great dangers if the knowledge is missing.
However, it must not be forgotten at this point that the topic is only dealt with on the surface! The broker is not secured and the Pi itself has no significant protection against manipulation. This makes it easy for criminal bodies to do damage when sensitive systems are controlled and regulated.
As my professor in college used to say, “You’ve now learned the basics, do something with it!”

Greetings Weise
-—-IN GERMAN———

Hallo jm1704,

danke für das nette Kompliment. Natürlich sind wir als Blogger immer daran interessiert mit az-delivery interessante und wissenswerte Beiträge zu schreiben. Natürlich darf die Abwechslung nicht fehlen und der Bezug den den Produkten nicht fehlen. Gerade IoT ist ein interessantes Thema, birgt aber auch große Gefahren, wenn das Wissen fehlt.
Man darf an dieser Stelle aber auch nicht vergessen, dass das Thema nur an der Oberfläche behandelt wird! Der Broker ist nicht gesichert und auch der Pi an sich hat keinen nennenswerten Schutz gegen Manipulation. Das macht es für kriminelle Organe einfach, Schaden anzurichten, wenn sensible Systeme kontrolliert und geregelt werden.
Wie mein Professor an der Uni immer sagte, “Sie haben nun die Grundlagen gelernt, machen Sie was drauß!”

Gruß Weise

Dieter Behm

Dieter Behm

Hallo und einen schönen guten Morgen.
Ich habe den ersten Blog glaube ich verstanden und mein Broker läuft auf dem Raspi. Jetzt mein Problem :
Der Node MCU (allerdings V3) lauft , bekommt nur die Verbindung zur FritzBox , gibt im seriellen Monitor keine Ip aus und folgendes erscheint:
-————-

ets Jan 8 2013,rst cause:2, boot mode:(3,6)

load 0×4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld
SerialMonitor enabled
Connection to: FRITZ!Box 7590 XQ

CUT HERE FOR EXCEPTION DECODER -——————

Exception (3):
epc1=0×40100718 epc2=0×00000000 epc3=0×00000000 excvaddr=0×4006eb39 depc=0×00000000

>>>stack>>>

Warum verbindet er sich nicht mit dem Broker
Ich hoffe Sie können einem Anfänger aufs Fahrrad helfen
Gruß
Dieter

jm1704

jm1704

Jörn,
Very good article on MQTT with explanatory notes and examples.
By this article you show the know how of AZ-Delivery and its team to use products offered for sale and their integrations.
Thanks

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert

Post di blog consigliati

  1. Installa ESP32 ora dal gestore del consiglio di amministrazione
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - Programmazione ESP tramite WLAN