Sommario:

IoT semplificato: ESP-MicroPython-MQTT-ThingSpeak: 12 passaggi
IoT semplificato: ESP-MicroPython-MQTT-ThingSpeak: 12 passaggi

Video: IoT semplificato: ESP-MicroPython-MQTT-ThingSpeak: 12 passaggi

Video: IoT semplificato: ESP-MicroPython-MQTT-ThingSpeak: 12 passaggi
Video: Menu Semplificato (IT) - Tutorial 2024, Dicembre
Anonim
IoT semplificato: ESP-MicroPython-MQTT-ThingSpeak
IoT semplificato: ESP-MicroPython-MQTT-ThingSpeak

Nel mio tutorial precedente, MicroPython su ESP utilizzando Jupyter, abbiamo imparato come installare ed eseguire MicroPython su un dispositivo ESP. Utilizzando Jupyter Notebook come nostro ambiente di sviluppo, abbiamo anche imparato a leggere dai sensori (Temperatura, Umidità e Luminosità), Utilizziamo diversi protocolli e metodi di comunicazione, Analogico, Digitale, 1-Wire e I2C, quest'ultimo per visualizzare i nostri dati su un display OLED.

Ora, in questo tutorial utilizzando un protocollo MQTT, otterremo tutti i dati acquisiti, inviandoli a un servizio IoT, ThingSpeak.com e a un'app mobile (Thingsview), dove possiamo accedere e giocare con i dati.

Qui, lo schema a blocchi del nostro progetto:

Immagine
Immagine

Passaggio 1: Distinta base - Distinta base

  1. NodoMCU - US$ 8.39
  2. Sensore di temperatura e umidità relativa DHT22 - USD 9.95
  3. Sensore di temperatura impermeabile DS18B20 - 5,95 USD
  4. Display OLED SSD1366 - 8,99 USD (opzionale)
  5. LDR (1x)
  6. LED (1x) (opzionale)
  7. Pulsante (1x)
  8. Resistenza 4K7 ohm (2x)
  9. Resistenza 10K ohm (1x)
  10. Resistenza 220 ohm (1x)

Passaggio 2: l'Hw

Il Hw
Il Hw

L'Hw che useremo qui fondamentalmente è lo stesso usato nel tutorial: Micropython su ESP Using Jupyter. Fare riferimento ad esso per tutte le connessioni HW.

L'eccezione è il Servo, che non verrà utilizzato in questo progetto.

Sopra puoi vedere l'HW completo. Collegare i dispositivi come mostrato lì.

Passaggio 3: Micropython, REPL, Jupyter

Micropython, REPL, Jupyter
Micropython, REPL, Jupyter
Micropython, REPL, Jupyter
Micropython, REPL, Jupyter

Devi avere un interprete Micropython caricato sul tuo dispositivo ESP. Una volta caricato, dovresti programmare il tuo ESP utilizzando uno dei modi/IDE disponibili, come:

  • REPL
  • Taccuino Jupyter
  • Mu
  • ESPCut (solo Windows)
  • … eccetera

Nel mio tutorial, Micropython su ESP Using Jupyter, ho descritto in dettaglio come scaricare e installare l'interprete MicroPython, ESPTool per gestire i dispositivi ESP e come utilizzare Jupyter Notebook come ambiente di sviluppo. Sentiti libero di usare ciò che è più comodo per te.

Di solito faccio tutto lo sviluppo su Jupyter Notebook e, una volta ottenuto il codice finale, lo copio su Geany e lo carico sul mio ESP usando Ampy.

Passaggio 4: sensori

Sensori
Sensori

Installiamo le librerie, definiamo GPIO, creiamo oggetti, funzioni per tutti i sensori singolarmente:

A. DHT (temperatura e umidità)

Installiamo la libreria DHT e creiamo un oggetto:

da dht import DHT22

da importazione macchina Pin dht22 = DHT22(Pin(12))

Ora, crea una funzione per leggere il sensore DHT:

def readDht():

dht22.measure() restituisce dht22.temperature(), dht22.humidity() Prova la funzione DHT

stampa (leggiDht())

Il risultato dovrebbe essere ad esempio:

(17.7, 43.4)

B. DS18B20 (temperatura esterna)

Installiamo le librerie e creiamo un oggetto:

importare un filo, ds18x20

import time # Definisce a quale pin verrà connesso il dispositivo 1-wire ==> pin 2 (D4) dat = Pin(2) # crea l'oggetto onewire ds = ds18x20. DS18X20(onewire. OneWire(dat)) Cerca dispositivi sul bu

sensori = ds.scan()

print('dispositivi trovati:', sensori)

Il risultato stampato non è molto importante, ciò di cui avremo bisogno è il primo sensore rilevato: i sensori[0]. E ora, possiamo costruire una funzione per leggere i dati del sensore:

def readDs():

ds.convert_temp() time.sleep_ms(750) return ds.read_temp(sensors[0])

È sempre importante testare il sensore utilizzando la funzione creata

print(readDs()) Se ottieni un valore di temperatura, il tuo codice è corretto

17.5

C. LDR (luminosità)

L'LDR utilizzerà il pin analogico del nostro ESP (è solo uno nel caso di ESP8266 e diversi per ESP32).

Fare riferimento al mio tutorial ESP32 per i dettagli.

Come fatto prima:

# importa la libreria

from machine import ADC # Definisci oggetto adc = ADC(0) Una semplice funzione: adc.read() può essere utilizzata per leggere il valore ADC. Ma ricorda che l'ADC interno convertirà le tensioni comprese tra 0 e 3,3V in corrispondenti valori digitali, variabili da 0 a 1023. Una volta interessati alla "Luminosità", considereremo la luce Max come il valore massimo catturato dal sensore (nel mio case 900) e luce minima che nel mio caso è 40. Avendo quei valori possiamo "mappare" il valore da 40 a 900 in 0 al 100% di luminosità. Per questo, creeremo una nuova funzione

def readLdr():

lumPerct = (adc.read()-40)*(10/86) # convert in percentuale ("map") return round(lumPerct)

Dovresti testare la funzione usando print (readLDR()). Il risultato dovrebbe essere un numero intero compreso tra o e 100.

D. Pulsante (ingresso digitale)

Qui stiamo usando un pulsante come sensore digitale, ma potrebbe essere un "eco" di un attuatore (una pompa che è stata accesa/spenta, per esempio).

# definire il pin 13 come ingresso e attivare un resistore di pull-up interno:

button = Pin(13, Pin. IN, Pin. PULL_UP) # Funzione per leggere lo stato del pulsante: def readBut(): return button.value()

Puoi testare il pulsante leggendo la funzione print(readBut()). Senza premere il risultato dovrebbe essere "1". Premendo il pulsante, il risultato dovrebbe essere "0"

Passaggio 5: acquisizione e visualizzazione locale di tutti i dati del sensore

Acquisizione e visualizzazione locale di tutti i dati del sensore
Acquisizione e visualizzazione locale di tutti i dati del sensore

Ora che abbiamo creato una funzione per ogni sensore, creiamo l'ultima che li leggerà tutti contemporaneamente:

def colectData():

temp, hum, = readDht() extTemp = readDs() lum = readLdr() butSts = readBut() return temp, hum, extTemp, lum, butSts Ora se usi

print(colectData())

Risulterà in una tupla che include tutti i dati acquisiti dai sensori:

(17.4, 45.2, 17.3125, 103, 1)

Possiamo anche, facoltativamente, mostrare quei dati su un display locale:

# importa libreria e crea oggetto i2c

from machine import I2C i2c = I2C(scl=Pin(5), sda=Pin(4)) # importa libreria e crea oggetto oled import ssd1306 i2c = I2C(scl=Pin(5), sda=Pin(4)) oled = ssd1306. SSD1306_I2C(128, 64, i2c, 0x3c) # crea una funzione: def displayData(temp, hum, extTemp, lum, butSts): oled.fill(0) oled.text("Temp: " + str(temp)) + "oC", 0, 4) oled.text("Hum: " + str(hum) + "%", 0, 16) oled.text("ExtTemp: " + str(extTemp) + "oC", 0, 29) oled.text("Lumin: " + str(lum) + "%", 0, 43) oled.text("Button: " + str(butSts), 0, 57) oled.show() # visualizzare i dati utilizzando la funzione displayData(temp, hum, extTemp, lum, butSts)

Come opzione, includerò anche il LED per essere acceso quando iniziamo a leggere i sensori, spegnendosi dopo che i dati sono stati visualizzati. Ciò contribuirà a confermare che il programma funziona quando l'ESP è disconnesso dal PC e viene eseguito automaticamente.

Quindi, la funzione principale sarebbe:

# Funzione principale per leggere tutti i sensori

def main(): # visualizza i dati con una funzione led.on() temp, hum, extTemp, lum, butSts = colectData() displayData(temp, hum, extTemp, lum, butSts) led.off()

Quindi, eseguendo main(), otterremo i dati del sensore visualizzati su OLED come mostrato nell'immagine.

Passaggio 6: esecuzione del codice della stazione locale all'avvio dell'ESP

Esecuzione del codice della stazione locale all'avvio dell'ESP
Esecuzione del codice della stazione locale all'avvio dell'ESP

Possiamo avere tutto ciò che è stato sviluppato finora su un singolo file da eseguire dal nostro ESP.

Apriamo qualsiasi editor di testo e incolliamo tutto il codice:

# importa librerie generali

from machine import Pin import time # definisce il pin 0 come output led = Pin(0, Pin. OUT) # DHT from dht import DHT22 dht22 = DHT22(Pin(12)) # Funzione per leggere DHT def readDht(): dht22.measure () return dht22.temperature(), dht22.humidity() # DS18B20 import onewire, ds18x20 # Definisce a quale pin verrà collegato il dispositivo 1-wire ==> pin 2 (D4) dat = Pin(2) # Crea il onewire oggetto ds = ds18x20. DS18X20(onewire. OneWire(dat)) # ricerca dispositivi sul bus sensori = ds.scan() # funzione per leggere DS18B20 def readDs(): ds.convert_temp() time.sleep_ms(750) return round(ds.read_temp(sensors[0]), 1) # LDR from machine import ADC # Define object adc = ADC(0) #function to read luminosity def readLdr(): lumPerct = (adc.read()-40) *(10/86) # convert in percentuale ("map") return round(lumPerct) # definisce il pin 13 come input e attiva un resistore di pull-up interno: button = Pin(13, Pin. IN, Pin. PULL_UP) # Funzione per leggere lo stato del pulsante: def readBut(): return button.value() # Funzione per leggere tutti i dati: def cole ctData(): temp, hum, = readDht() extTemp = readDs() lum = readLdr() butSts = readBut() return temp, hum, extTemp, lum, butSts # importa la libreria e crea l'oggetto i2c dalla macchina import I2C i2c = I2C(scl=Pin(5), sda=Pin(4)) # importa libreria e crea oggetto oled import ssd1306 i2c = I2C(scl=Pin(5), sda=Pin(4)) oled = ssd1306. SSD1306_I2C(128, 64, i2c, 0x3c) # crea una funzione: def displayData(temp, hum, extTemp, lum, butSts): oled.fill(0) oled.text("Temp: " + str(temp) + "oC", 0, 4) oled.text("Hum: " + str(hum) + "%", 0, 16) oled.text("ExtTemp: " + str(extTemp) + "oC", 0, 29) oled. text("Lumin: " + str(lum) + "%", 0, 43) oled.text("Button: " + str(butSts), 0, 57) oled.show() # Funzione principale per leggere tutti i sensori def main(): # visualizza i dati con una funzione led.on() temp, hum, extTemp, lum, butSts = colectData() displayData(temp, hum, extTemp, lum, butSts) led.off() '''- ----- esegui la funzione principale --------''' main()

Salvalo, ad esempio come localData.py.

Per eseguire questo codice direttamente sul tuo terminale avrai bisogno di Ampy.

Per prima cosa, su Terminale informiamo Ampy della nostra porta seriale:

export AMPY_PORT=/dev/tty. SLAB_USBtoUART

Ora possiamo vedere i file che si trovano all'interno della nostra directory radice ESP:

ampio ls

Come risposta, otterremo boot.py, che è il primo file che verrà eseguito nel sistema.

Ora, usiamo Ampy per caricare il nostro script Python LocalData.py come /main.py, quindi lo script verrà eseguito subito dopo l'avvio:

ampy put localData.py /main/py

Se usiamo il comando amp ls ora, vedrai 2 file all'interno dell'ESP.: boot.py e main.py

Ripristinando il tuo ESP, il programma localData.py verrà eseguito automaticamente, visualizzando i dati del sensore sul display.

La schermata di stampa del terminale sopra mostra cosa abbiamo fatto.

Con il codice sopra, il display verrà mostrato solo una volta, ma possiamo definire un ciclo sulla funzione main(), che mostrerà i dati su ogni intervallo di tempo definito (PUB_TIME_SEC), e per esempio, finché non premiamo il pulsante:

# loop per ottenere i dati fino a quando non viene premuto il pulsante

while button.value(): led.on() temp, hum, extTemp, lum, butSts = colectData() displayData(temp, hum, extTemp, lum, butSts) led.off() time.sleep(PUB_TIME_SEC)

La variabile PUB_TIME_SEC deve essere dichiarata entro l'ora in cui desideri i tuoi campioni.

Per migliorare ulteriormente il nostro codice, sarebbe bene informare che usciremo dal loop, per questo definiremo 2 nuove funzioni generali, una per cancellare il display e un'altra per far lampeggiare il LED un certo numero di volte.

# Display chiaro:

def displayClear(): oled.fill(0) oled.show() # crea una funzione di lampeggio def blinkLed(num): for i in range(0, num): led.on() sleep(0.5) led.off() dormire(0,5)

Quindi, ora possiamo riscrivere la nostra funzione main():

mentre button.value():

led.on() temp, hum, extTemp, lum, butSts = colectData() displayData(temp, hum, extTemp, lum, butSts) led.off() time.sleep(PUB_TIME_SEC) blinkLed(3) displayClear()

Il codice finale può essere scaricato dal mio GitHub: localData.py e anche dal Jupyter Notebook utilizzato per lo sviluppo del codice completo: Jupyter Local Data Development.

Passaggio 7: collegamento dell'ESP al WiFi locale

Collegamento dell'ESP al WiFi locale
Collegamento dell'ESP al WiFi locale

Il modulo di rete viene utilizzato per configurare la connessione WiFi. Esistono due interfacce WiFi, una per la stazione (quando ESP8266 si connette a un router) e una per l'access point (per la connessione di altri dispositivi a ESP8266). Qui, il nostro ESP sarà connesso alla rete locale. Chiamiamo la biblioteca e definiamo le nostre credenziali di rete:

importare rete

WiFi_SSID = "IL TUO SSID" WiFi_PASS = "LA TUA PASSWORD"

La funzione seguente può essere utilizzata per connettere l'ESP alla rete locale:

def do_connect():

wlan = network. WLAN(network. STA_IF) wlan.active(True) if not wlan.isconnected(): print('connessione alla rete…') wlan.connect(WiFi_SSID, WiFi_SSID) mentre non wlan.isconnected(): pass print('configurazione rete:', wlan.ifconfig())

Eseguendo la funzione, è possibile ottenere come risultato l'indirizzo IP:

do_connect()

Il risultato sarà:

configurazione di rete: ('10.0.1.2', '255.255.255.0', '10.0.1.1', '10.0.1.1')

Erano, nel mio caso, 10.0.1.2, è l'indirizzo IP ESP.

Passaggio 8: la cosa parla

La cosa parla
La cosa parla

A questo punto abbiamo imparato a catturare i dati da tutti i sensori, visualizzandoli sul nostro OLED. Ora è il momento di vedere come inviare quei dati a una piattaforma IoT, ThingSpeak.

Cominciamo!

Innanzitutto, devi avere un account su ThinkSpeak.com. Successivamente, segui le istruzioni per creare un canale e prendi nota del tuo ID canale e della chiave API di scrittura.

Sopra puoi vedere i 5 campi che verranno utilizzati sul nostro Canale.

Passaggio 9: protocollo MQTT e connessione ThingSpeak

Protocollo MQTT e connessione ThingSpeak
Protocollo MQTT e connessione ThingSpeak

MQTT è un'architettura di pubblicazione/sottoscrizione sviluppata principalmente per connettere dispositivi con limitazioni di larghezza di banda e alimentazione su reti wireless. È un protocollo semplice e leggero che funziona su socket TCP/IP o WebSocket. MQTT su WebSocket può essere protetto con SSL. L'architettura di pubblicazione/sottoscrizione consente di inviare messaggi ai dispositivi client senza che il dispositivo debba eseguire continuamente il polling del server.

Il broker MQTT è il punto centrale di comunicazione ed è incaricato di inviare tutti i messaggi tra i mittenti e i legittimi destinatari. Un client è qualsiasi dispositivo che si connette al broker e può pubblicare o sottoscrivere argomenti per accedere alle informazioni. Un argomento contiene le informazioni di instradamento per il broker. Ogni client che desidera inviare messaggi li pubblica su un determinato argomento e ogni client che desidera ricevere messaggi si iscrive a un determinato argomento. Il broker consegna tutti i messaggi con l'argomento corrispondente ai client appropriati.

ThingSpeak™ ha un broker MQTT all'URL mqtt.thingspeak.com e alla porta 1883. Il broker ThingSpeak supporta sia la pubblicazione MQTT che la sottoscrizione MQTT.

Nel nostro caso, useremo: MQTT Publish

Immagine
Immagine

La figura descrive la struttura dell'argomento. La chiave API di scrittura è necessaria per la pubblicazione. Il broker riconosce una richiesta CONNECT corretta con CONNACK.

Il protocollo MQTT è supportato in una libreria integrata nei binari Micropython: questo protocollo può essere utilizzato per inviare dati dal tuo ESP8266, tramite WIFI, a un database cloud gratuito.

Usiamo la libreria umqtt.simple:

da umqtt.simple import MQTTClient

E conoscendo il nostro ID SERVER, è possibile creare il nostro oggetto client MQTT:

SERVER = "mqtt.thingspeak.com"

client = MQTTClient("umqtt_client", SERVER)

Ora, avendo a portata di mano le tue credenziali di ThingSpeak:

CHANNEL_ID = "ID DEL TUO CANALE"

WRITE_API_KEY = "LA TUA CHIAVE QUI"

Creiamo il nostro "Topic" MQTT:

topic = "channels/" + CHANNEL_ID + "/publish/" + WRITE_API_KEY

Otteniamo i nostri dati da inviare a ThingSpeak IoT Service, utilizzando la funzione creata e associamo la sua risposta a specifiche variabili di dati:

temp, hum, extTemp, lum, butSts = colectData()

Con queste variabili aggiornate, possiamo creare il nostro "MQTT Payload":

payload = "field1="+str(temp)+"&field2="+str(hum)+"&field3="+str(extTemp)+"&field4="+str(lum)+"&field5="+str(butSts))

E questo è tutto! Siamo pronti per inviare dati a ThinsSpeak, semplicemente utilizzando le 3 righe di codice sottostanti:

client.connect()

client.publish(argomento, carico utile) client.disconnect()

Ora, se vai alla tua pagina canale (come la mia sopra) vedrai che ognuno dei 5 campi avrà dati relativi ai tuoi sensori.

Passaggio 10: registratore di dati del sensore

Registratore di dati del sensore
Registratore di dati del sensore

Ora che sappiamo che con poche righe di codice è possibile caricare dati su un servizio IoT, creiamo una funzione loop per farlo automaticamente a intervalli di tempo regolari (simile a quello che abbiamo fatto con "Dati locali ").

Utilizzando la stessa variabile (PUB_TIME_SEC), dichiarata prima, una semplice funzione principale per acquisire continuamente dati, registrandoli sul nostro canale sarebbe:

mentre vero:

temp, hum, extTemp, lum, butSts = colectData() payload = "field1="+str(temp)+"&field2="+str(hum)+"&field3="+str(extTemp)+"&field4="+ str(lum)+"&field5="+str(butSts) client.connect() client.publish(topic, payload) client.disconnect() time.sleep(PUB_TIME_SEC)

Tieni presente che solo il "payload" deve essere aggiornato, una volta che "topic" è correlato alle credenziali del nostro canale e non cambierà.

Cercando la tua pagina canale ThingSpeak, osserverai che i dati verranno caricati continuamente in ogni campo. Puoi coprire l'LDR, mettere la mano sui sensori di temperatura/ronzio, premere il pulsante, ecc. e vedere come il canale "registrerà" automaticamente quei dati per analisi future.

Di solito, per la registrazione dei dati, dovremmo cercare di utilizzare meno energia possibile, quindi non utilizzeremmo il LED o il display localmente. Inoltre, è comune con i dispositivi ESP, metterli in "sonno profondo", dove il microprocessore sarà nel suo stato di minima energia fino a quando non sarà il momento di acquisire i dati e inviarli alla piattaforma IoT.

Ma, una volta che l'idea sta imparando, includiamo anche il display e il LED come abbiamo fatto prima. Così facendo, la nostra funzione "logger" sarà:

mentre button.value():

led.on() temp, hum, extTemp, lum, butSts = colectData() displayData(temp, hum, extTemp, lum, butSts) led.off() temp, hum, extTemp, lum, butSts = colectData() payload = "field1="+str(temp)+"&field2="+str(hum)+"&field3="+str(extTemp)+"&field4="+str(lum)+"&field5="+str(butSts) client.connect() client.publish(topic, payload) client.disconnect() time.sleep(PUB_TIME_SEC) blinkLed(3) displayClear()

Lo script microPython completo è disponibile qui: dataLoggerTS_EXT.py e il notebook Jupyter utilizzato per lo sviluppo è disponibile anche qui: IoT ThingSpeak Data Logger EXT.ipynb.

Per caricare lo script su ESP, sul tuo terminale usa il comando:

ampy put dataLoggerTS.py /main.py

E premi il pulsante ESP - reset. Avrai l'ESP che catturerà i dati e li registrerà su ThingSpeak.com fino a quando non si terrà premuto il fondo (attendere che il LED lampeggi 3 volte e che l'OLED si spenga).

Passaggio 11: l'app ThingView

L'app ThingView
L'app ThingView

I dati registrati possono essere visualizzati direttamente sul sito ThingSpeak.com o tramite APP, ad esempio ThingsView!

ThingView è un'APP sviluppata da CINETICA, che ti consente di visualizzare i tuoi canali ThingSpeak in modo semplice, basta inserire l'ID del canale e sei pronto per partire.

Per i canali pubblici, l'applicazione rispetterà le impostazioni di Windows: colore, scala temporale, tipo di grafico e numero di risultati. La versione corrente supporta grafici a linee ea colonne, i grafici spline vengono visualizzati come grafici a linee.

Per i canali privati, i dati verranno visualizzati utilizzando le impostazioni predefinite, poiché non è possibile leggere le impostazioni delle finestre private solo con la chiave API.

L'APP ThingView può essere scaricata per ANDROID e IPHONE.

Passaggio 12: Conclusione

Conclusione
Conclusione

Come sempre, spero che questo progetto possa aiutare gli altri a trovare la loro strada nell'eccitante mondo dell'elettronica!

Per i dettagli e il codice finale, visita il mio deposito GitHub: IoT_TS_MQTT

Per altri progetti, visita il mio blog: MJRoBot.org

Saludos dal sud del mondo!

Ci vediamo nel mio prossimo istruibile!

Grazie, Marcelo

Consigliato: