Tabla de contenido:

IoT hecho fácil: ESP-MicroPython-MQTT-ThingSpeak: 12 pasos
IoT hecho fácil: ESP-MicroPython-MQTT-ThingSpeak: 12 pasos

Video: IoT hecho fácil: ESP-MicroPython-MQTT-ThingSpeak: 12 pasos

Video: IoT hecho fácil: ESP-MicroPython-MQTT-ThingSpeak: 12 pasos
Video: ESP8266 con DHT22 mediante WiFi, Broker MQTT en Raspberry Pi y visualización en Node-RED 2024, Mes de julio
Anonim
IoT hecho fácil: ESP-MicroPython-MQTT-ThingSpeak
IoT hecho fácil: ESP-MicroPython-MQTT-ThingSpeak

En mi tutorial anterior, MicroPython en ESP usando Jupyter, aprendimos cómo instalar y ejecutar MicroPython en un dispositivo ESP. Utilizando Jupyter Notebook como nuestro entorno de desarrollo, también aprendimos a leer de sensores (Temperatura, Humedad y Luminosidad), utilizamos varios protocolos y métodos de comunicación, Analógico, Digital, 1-Wire e I2C, este último para mostrar nuestros capturados datos en una pantalla OLED.

Ahora, en este tutorial usando un protocolo MQTT, obtendremos todos los datos capturados, enviándolos a un servicio de IoT, ThingSpeak.com y a una aplicación móvil (Thingsview), donde podemos registrar y jugar con los datos.

Aquí, el diagrama de bloques de nuestro proyecto:

Imagen
Imagen

Paso 1: BoM - Lista de materiales

  1. NodeMCU - US $ 8,39
  2. Sensor de temperatura y humedad relativa DHT22 - USD 9,95
  3. Sensor de temperatura impermeable DS18B20 - USD 5,95
  4. Pantalla OLED SSD1366- USD 8,99 (opcional)
  5. LDR (1x)
  6. LED (1x) (opcional)
  7. Botón pulsador (1x)
  8. Resistencia 4K7 ohmios (2x)
  9. Resistencia 10K ohmios (1x)
  10. Resistencia 220 ohmios (1x)

Paso 2: El Hw

El Hw
El Hw

El Hw que usaremos aquí básicamente es el mismo que se usó en el tutorial: Micropython en ESP usando Jupyter. Consúltelo para todas las conexiones HW.

La excepción es el Servo, que no se utilizará en este proyecto.

Arriba puede ver el HW completo. Conecte los dispositivos como se muestra allí.

Paso 3: Micropython, REPL, Jupyter

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

Debe tener un intérprete de Micropython cargado en su dispositivo ESP. Una vez cargado, debe programar su ESP usando cualquiera de las formas disponibles / IDE disponibles, como:

  • REPL
  • Cuaderno Jupyter
  • Mu
  • ESPCut (solo Windows)
  • … Etc

En mi tutorial, Micropython en ESP usando Jupyter, detallé cómo descargar e instalar el intérprete de MicroPython, ESPTool para administrar dispositivos ESP y cómo usar Jupyter Notebook como entorno de desarrollo. Siéntase libre de usar lo que le resulte más cómodo.

Por lo general, hago todo el desarrollo en Jupyter Notebook, y una vez que obtengo el código final, lo copio en Geany y lo cargo en mi ESP usando Ampy.

Paso 4: Sensores

Sensores
Sensores

Instalemos las bibliotecas, definamos GPIO, creemos objetos, funciones para todos los sensores individualmente:

A. DHT (temperatura y humedad)

Instalemos la biblioteca DHT y creemos un objeto:

desde dht import DHT22

desde la importación de la máquina Pin dht22 = DHT22 (Pin (12))

Ahora, cree una función para leer el sensor DHT:

def readDht ():

dht22.measure () devuelve dht22.temperature (), dht22.humidity () Prueba de la función DHT

imprimir (readDht ())

El resultado debería ser, por ejemplo:

(17.7, 43.4)

B. DS18B20 (temperatura externa)

Instalemos las bibliotecas y creemos un objeto:

importar onewire, ds18x20

tiempo de importación # Definir qué pin se conectará el dispositivo de 1 cable ==> pin 2 (D4) dat = Pin (2) # crear el objeto onewire ds = ds18x20. DS18X20 (onewire. OneWire (dat)) Busque dispositivos en el bu

sensores = ds.scan ()

print ('dispositivos encontrados:', sensores)

El resultado impreso no es realmente importante, lo que necesitaremos es el primer sensor detectado: sensores [0]. Y ahora, podemos crear una función para leer los datos del sensor:

def readDs ():

ds.convert_temp () time.sleep_ms (750) devuelve ds.read_temp (sensores [0])

Siempre es importante probar el sensor usando la función creada

imprimir (readDs ()) Si obtiene un valor de temperatura, su código es correcto

17.5

C. LDR (luminosidad)

El LDR usará el pin analógico de nuestro ESP (es solo uno en el caso del ESP8266 y varios para el ESP32).

Consulte mi tutorial de ESP32 para obtener más detalles.

Igual que antes:

# importar biblioteca

desde la importación de la máquina ADC # Definir objeto adc = ADC (0) Se puede usar una función simple: adc.read () para leer el valor de ADC. Pero recuerde que el ADC interno convertirá voltajes entre 0 y 3.3V en valores digitales correspondientes, variando de 0 a 1023. Una vez que estemos interesados en "Luminosidad", consideraremos la luz máxima como el valor máximo capturado del sensor (en mi caso 900) y luz mínima que en mi caso es 40. Teniendo esos valores podemos "mapear" el valor de 40 a 900 en 0 a 100% de luminosidad. Para eso, crearemos una nueva función

def readLdr ():

lumPerct = (adc.read () - 40) * (10/86) # convertir en porcentaje ("mapa") return round (lumPerct)

Debe probar la función usando print (readLDR ()). El resultado debe ser un número entero entre o y 100.

D. Botón pulsador (entrada digital)

Aquí estamos usando un pulsador como sensor digital, pero podría ser un "eco" de un actuador (una bomba que se enciende / apaga, por ejemplo).

# defina el pin 13 como una entrada y active una resistencia Pull-up interna:

button = Pin (13, Pin. IN, Pin. PULL_UP) # Función para leer el estado del botón: def readBut (): return button.value ()

Puede probar el botón leyendo la función print (readBut ()). Sin presionar, el resultado debe ser "1". Al presionar el botón, el resultado debe ser "0"

Paso 5: captura y visualización local de todos los datos del sensor

Captura y visualización local de todos los datos del sensor
Captura y visualización local de todos los datos del sensor

Ahora que hemos creado una función para cada sensor, creemos la última que los leerá todos al mismo tiempo:

def colectData ():

temp, hum, = readDht () extTemp = readDs () lum = readLdr () butSts = readBut () return temp, hum, extTemp, lum, butSts Ahora si usas

imprimir (colectData ())

Dará como resultado una tupla que incluye todos los datos capturados de los sensores:

(17.4, 45.2, 17.3125, 103, 1)

También podemos, opcionalmente, mostrar esos datos en una pantalla local:

# importar biblioteca y crear objeto i2c

desde la importación de la máquina I2C i2c = I2C (scl = Pin (5), sda = Pin (4)) # importar biblioteca y crear objeto oled import ssd1306 i2c = I2C (scl = Pin (5), sda = Pin (4)) oled = ssd1306. SSD1306_I2C (128, 64, i2c, 0x3c) # crear una función: 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 ("Botón:" + str (butSts), 0, 57) oled.show () # mostrar datos usando la función displayData (temp, hum, extTemp, lum, butSts)

Como opción, también incluiré el LED para que se encienda cuando comencemos a leer los sensores, y se apagará después de que se muestren esos datos. Hacer esto ayudará a confirmar que el programa está funcionando cuando tengamos el ESP desconectado de la PC y ejecutándose automáticamente.

Entonces, la función principal sería:

# Función principal para leer todos los sensores

def main (): # mostrar datos con una función led.on () temp, hum, extTemp, lum, butSts = colectData () displayData (temp, hum, extTemp, lum, butSts) led.off ()

Entonces, ejecutando main (), obtendremos los datos del sensor que se muestran en OLED como se muestra en la imagen.

Paso 6: Ejecución del código de la estación local en el inicio del ESP

Ejecución del código de la estación local en el inicio del ESP
Ejecución del código de la estación local en el inicio del ESP

Podemos tener todo lo desarrollado hasta ahora en un solo archivo para ser ejecutado por nuestro ESP.

Abramos cualquier editor de texto y peguemos todo el código:

# importar bibliotecas generales

desde la importación de la máquina Tiempo de importación de PIN # definir el pin 0 como led de salida = Pin (0, Pin. OUT) # DHT de dht import DHT22 dht22 = DHT22 (Pin (12)) # Función para leer DHT def readDht (): dht22.measure () return dht22.temperature (), dht22.humidity () # DS18B20 import onewire, ds18x20 # Define qué pin se conectará el dispositivo de 1 cable ==> pin 2 (D4) dat = Pin (2) # Crea el onewire object ds = ds18x20. DS18X20 (onewire. OneWire (dat)) # escaneo de dispositivos en el bus sensores = ds.scan () # función para leer DS18B20 def readDs (): ds.convert_temp () time.sleep_ms (750) return round (ds.read_temp (sensores [0]), 1) # LDR de la máquina import ADC # Definir objeto adc = ADC (0) # función para leer la luminosidad def readLdr (): lumPerct = (adc.read () - 40) * (10/86) # convertir en porcentaje ("mapa") return round (lumPerct) # definir el pin 13 como una entrada y activar una resistencia interna de pull-up: button = Pin (13, Pin. IN, Pin. PULL_UP) # Función para leer el estado del botón: def readBut (): return button.value () # Función para leer todos los datos: def cole ctData (): temp, hum, = readDht () extTemp = readDs () lum = readLdr () butSts = readBut () return temp, hum, extTemp, lum, butSts # importar biblioteca y crear objeto i2c desde máquina import I2C i2c = I2C (scl = Pin (5), sda = Pin (4)) # importar biblioteca y crear objeto oled import ssd1306 i2c = I2C (scl = Pin (5), sda = Pin (4)) oled = ssd1306. SSD1306_I2C (128, 64, i2c, 0x3c) # crear una función: 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 ("Botón:" + str (butSts), 0, 57) oled.show () # Función principal para leer todos los sensores def main (): # mostrar datos con una función led.on () temp, hum, extTemp, lum, butSts = colectData () displayData (temp, hum, extTemp, lum, butSts) led.off () '' '- ----- ejecutar la función principal -------- '' 'main ()

Guárdelo, por ejemplo, como localData.py.

Para ejecutar este código directamente en su terminal, necesitará Ampy.

Primero, en la Terminal, informemos a Ampy nuestro puerto serie:

exportar AMPY_PORT = / dev / tty. SLAB_USBtoUART

Ahora, podemos ver los archivos que están dentro de nuestro directorio raíz de ESP:

ampy ls

Como respuesta, obtendremos boot.py, que es el primer archivo que se ejecutará en el sistema.

Ahora, usemos Ampy para cargar nuestro script Python LocalData.py como /main.py, por lo que el script se ejecutará justo después del arranque:

ampy poner localData.py / main / py

Si usamos el comando amp ls ahora, verá 2 archivos dentro del ESP.: boot.py y main.py

Restablecer su ESP, hará que el programa localData.py se ejecute automáticamente, mostrando los datos del sensor en la pantalla.

La pantalla de impresión de Terminal anterior muestra lo que hemos hecho.

Con el código anterior, la pantalla se mostrará solo una vez, pero podemos definir un bucle en la función main (), que mostrará datos en cada intervalo de tiempo definido (PUB_TIME_SEC), y por ejemplo, hasta que presionemos el botón:

# bucle obteniendo datos hasta que se presione el botón

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 variable PUB_TIME_SEC debe declararse en el momento en que desee sus muestras.

Para potenciar más nuestro código, sería bueno informar que saldremos del bucle, para eso definiremos 2 nuevas funciones generales, una para borrar la pantalla y otra para hacer parpadear el LED en un número determinado de veces.

# Pantalla clara:

def displayClear (): oled.fill (0) oled.show () # crea una función de parpadeo def blinkLed (num): para i en el rango (0, num): led.on () sleep (0.5) led.off () dormir (0.5)

Entonces, ahora podemos reescribir nuestra función main ():

while 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 ()

El código final se puede descargar de mi GitHub: localData.py y también del Jupyter Notebook usado para el desarrollo del código completo: Jupyter Local Data Development.

Paso 7: Conexión del ESP a WiFi local

Conexión del ESP a WiFi local
Conexión del ESP a WiFi local

El módulo de red se utiliza para configurar la conexión WiFi. Hay dos interfaces WiFi, una para la estación (cuando el ESP8266 se conecta a un enrutador) y otra para el punto de acceso (para que otros dispositivos se conecten al ESP8266). Aquí, nuestro ESP estará conectado a la red local. Llamemos a la biblioteca y definamos nuestras credenciales de red:

importar red

WiFi_SSID = "SU SSID" WiFi_PASS = "SU CONTRASEÑA"

La siguiente función se puede utilizar para conectar el ESP a su red local:

def do_connect ():

wlan = network. WLAN (network. STA_IF) wlan.active (True) si no wlan.isconnected (): print ('conectando a la red …') wlan.connect (WiFi_SSID, WiFi_SSID) mientras no wlan.isconnected (): pass print ('configuración de red:', wlan.ifconfig ())

Al ejecutar la función, puede obtener como resultado la dirección IP:

do_connect ()

El resultado será:

configuración de red: ('10.0.1.2 ',' 255.255.255.0 ', '10.0.1.1', '10.0.1.1 ')

Fueron, en mi caso, 10.0.1.2, es la dirección IP de ESP.

Paso 8: The ThingSpeak

The ThingSpeak
The ThingSpeak

En este punto, aprendimos cómo capturar datos de todos los sensores, mostrándolos en nuestro OLED. Ahora es el momento de ver cómo enviar esos datos a una plataforma de IoT, ThingSpeak.

¡Vamos a empezar!

Primero, debe tener una cuenta en ThinkSpeak.com. A continuación, siga las instrucciones para crear un canal y tome nota de su ID de canal y escriba la clave API.

Arriba puede ver los 5 campos que se utilizarán en nuestro Canal.

Paso 9: Protocolo MQTT y conexión ThingSpeak

Protocolo MQTT y conexión ThingSpeak
Protocolo MQTT y conexión ThingSpeak

MQTT es una arquitectura de publicación / suscripción que se desarrolló principalmente para conectar dispositivos con ancho de banda y con limitaciones de energía a través de redes inalámbricas. Es un protocolo simple y liviano que se ejecuta sobre sockets TCP / IP o WebSockets. MQTT sobre WebSockets se puede proteger con SSL. La arquitectura de publicación / suscripción permite que los mensajes se envíen a los dispositivos del cliente sin que el dispositivo tenga que sondear continuamente el servidor.

El corredor MQTT es el punto central de comunicación y está a cargo de enviar todos los mensajes entre los remitentes y los destinatarios legítimos. Un cliente es cualquier dispositivo que se conecta al corredor y puede publicar o suscribirse a temas para acceder a la información. Un tema contiene la información de enrutamiento del intermediario. Cada cliente que quiere enviar mensajes los publica en un tema determinado, y cada cliente que quiere recibir mensajes se suscribe a un tema determinado. El corredor entrega todos los mensajes con el tema correspondiente a los clientes apropiados.

ThingSpeak ™ tiene un intermediario MQTT en la URL mqtt.thingspeak.com y el puerto 1883. El intermediario ThingSpeak admite tanto la publicación MQTT como la suscripción MQTT.

En nuestro caso usaremos: MQTT Publish

Imagen
Imagen

La figura describe la estructura del tema. La clave de API de escritura es necesaria para publicar. El corredor reconoce una solicitud CONNECT correcta con CONNACK.

El protocolo MQTT es compatible con una biblioteca incorporada en los archivos binarios de Micropython; este protocolo se puede usar para enviar datos desde su ESP8266, a través de WIFI, a una base de datos en la nube gratuita.

Usemos la biblioteca umqtt.simple:

desde umqtt.simple import MQTTClient

Y conociendo nuestro SERVER ID, es posible crear nuestro objeto cliente MQTT:

SERVIDOR = "mqtt.thingspeak.com"

cliente = MQTTClient ("umqtt_client", SERVIDOR)

Ahora, teniendo sus credenciales de ThingSpeak a mano:

CHANNEL_ID = "SU ID DE CANAL"

WRITE_API_KEY = "TU LLAVE AQUÍ"

Creemos nuestro "Tema" MQTT:

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

Hagamos que nuestros datos sean enviados al ThingSpeak IoT Service, usando la función creada y asociemos su respuesta a variables de datos específicas:

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

Con esas variables actualizadas, podemos crear nuestra "Carga MQTT":

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

¡Y eso es! Estamos listos para enviar datos a ThinsSpeak, simplemente usando las 3 líneas de código a continuación:

client.connect ()

client.publish (tema, carga útil) client.disconnect ()

Ahora, si vas a la página de tu canal (como la mía arriba) verás que cada uno de los 5 campos tendrá datos relacionados con tus sensores.

Paso 10: Registrador de datos del sensor

Registrador de datos del sensor
Registrador de datos del sensor

Ahora que sabemos que con solo unas pocas líneas de código es posible subir datos a un servicio de IoT, creemos una función de bucle para hacerlo automáticamente en un intervalo de tiempo regular (similar a lo que hemos hecho con "Datos locales ").

Usando la misma variable (PUB_TIME_SEC), declarada anteriormente, una función principal simple para capturar datos de forma continua, lográndolos en nuestro canal sería:

mientras que es cierto:

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 (tema, carga útil) client.disconnect () time.sleep (PUB_TIME_SEC)

Tenga en cuenta que solo se debe actualizar la "carga útil", una vez que el "tema" esté relacionado con la credencial de nuestro canal y no cambiará.

Al buscar la página de su canal de ThingSpeak, observará que los datos se cargarán continuamente en cada campo. Puede cubrir el LDR, poner la mano en los sensores de temperatura / zumbido, presionar el botón, etc. y ver cómo el canal automáticamente "registrará" esos datos para análisis futuros.

Por lo general, para el registro de datos, deberíamos intentar usar la menor cantidad de energía posible, por lo que no usaríamos el LED o la pantalla localmente. Además, es común con los dispositivos ESP ponerlos en "sueño profundo", donde el microprocesador estará en su estado de mínima energía hasta que llegue el momento de capturar datos y enviarlos a la plataforma IoT.

Pero, una vez aquí, la idea está aprendiendo, incluyamos también la pantalla y el LED como lo hicimos antes. Haciendo eso, nuestra función de "registrador" será:

while 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) cliente.connect () client.publish (tema, carga útil) client.disconnect () time.sleep (PUB_TIME_SEC) blinkLed (3) displayClear ()

El script microPython completo se puede encontrar aquí: dataLoggerTS_EXT.py y el cuaderno Jupyter que se usó para el desarrollo también se puede encontrar aquí: IoT ThingSpeak Data Logger EXT.ipynb.

Para cargar el script en ESP, en su terminal use el comando:

ampy put dataLoggerTS.py /main.py

Y presione el botón ESP - reiniciar. Tendrá el ESP capturando datos y registrándolos en ThingSpeak.com hasta que se mantenga presionada la parte inferior (espere a que el LED parpadee 3 veces y el OLED se apague).

Paso 11: la aplicación ThingView

La aplicación ThingView
La aplicación ThingView

Los datos registrados se pueden ver directamente en el sitio ThingSpeak.com o mediante una aplicación, por ejemplo, ThingsView!

ThingView es una APLICACIÓN desarrollada por CINETICA, que le permite visualizar sus canales ThingSpeak de una manera fácil, solo ingrese el ID del canal y estará listo para comenzar.

Para los canales públicos, la aplicación respetará la configuración de Windows: color, escala de tiempo, tipo de gráfico y número de resultados. La versión actual admite gráficos de líneas y columnas, los gráficos de spline se muestran como gráficos de líneas.

Para los canales privados, los datos se mostrarán usando la configuración predeterminada, ya que no hay forma de leer la configuración de Windows privada solo con la clave API.

La APLICACIÓN ThingView se puede descargar para ANDROID e IPHONE.

Paso 12: Conclusión

Conclusión
Conclusión

Como siempre, espero que este proyecto pueda ayudar a otros a encontrar su camino hacia el apasionante mundo de la electrónica.

Para obtener detalles y el código final, visite mi depósito de GitHub: IoT_TS_MQTT

Para más proyectos, visite mi blog: MJRoBot.org

¡Saludos desde el sur del mundo!

¡Nos vemos en mi próximo instructable!

Gracias, Marcelo

Recomendado: