Advertisement
  1. Computer Skills
  2. Electronics

Construye un sensor de humedad para monitorear tus plantas con Raspberry Pi

Scroll to top
Read Time: 23 min

Spanish (Español) translation by Juliana Carvajal (you can also view the original English article)

En este tutorial, aprovecharé la genialidad de Raspberry Pi para construir un sensor de humedad para una maceta. Podrás monitorear el sensor localmente en la pantalla LCD o de forma remota, a través de ControlMyPi.com, y recibir correos electrónicos diarios si la humedad cae por debajo de un nivel específico.

Durante el camino haremos:

  • Conectar y leer un valor de un sensor analógico sobre SPI usando una placa de pruebas.
  • Formatear bien la lectura del sensor en la consola.
  • Mostrar la lectura del sensor en una pantalla LCD RGB.
  • Hacer que la Raspberry Pi envíe un correo electrónico con la lectura del sensor.
  • Monitorear fácilmente el sensor y tener algunas lecturas históricas en la web.
Raspberry Pi Moisture SensorRaspberry Pi Moisture SensorRaspberry Pi Moisture Sensor
Esto es lo que estamos creando en este tutorial.

Suministros de hardware

Para aprovechar al máximo este tutorial, te recomiendo adquirir lo siguiente:

The ComponentsThe ComponentsThe Components
Los componentes

Algunos componentes alternativos

  • En lugar del sensor de humedad del suelo, puedes usar cualquier tipo de sensor analógico de voltaje variable o incluso solo una resistencia variable para realizar pruebas.
  • Puedes usar un MCP3004 más pequeño (ADC SPI de 4 canales) si lo deseas, pero el cableado será diferente.
  • Puedes omitir la pantalla LCD RGB o reemplazarla con una pantalla alternativa. Tendrás que eliminar o cambiar algunas líneas en el script final si lo haces.

El costo

Después de agregar unos pocos dólares para los cables de puente, el costo total del proyecto es de aproximadamente $55 sin la pantalla LCD y con la pantalla $82. Sin embargo, recuerda que estás almacenando tu kit de electrónica; todas estas piezas se pueden usar nuevamente para otros proyectos.


1. Cableado

Si estás utilizando la pantalla LCD con el cabezal de apilamiento, conéctala a la Raspberry Pi ahora. Las dos primeras etapas del software no utilizan la pantalla LCD, pero te ahorrarán tiempo de recableado más adelante si la conectas ahora.

Advertencia: un cableado incorrecto podría dañar tu Raspberry Pi. Asegúrate de verificar cuidadosamente todas tus conexiones antes de encender.

Paso 1: rieles eléctricos y de tierra

Power and Ground RailsPower and Ground RailsPower and Ground Rails
Rieles eléctricos y de tierra

A la izquierda de la foto, puedes ver los puentes rojos y negros que van a los rieles + y - en la placa de pruebas. Para ayudar a describir las conexiones desde el encabezado, consulta esta tabla de colores de cables. Cada celda de la tabla se refiere a un pin en el encabezado de Raspberry Pi. El color de la celda corresponde al color del cable de puente como se ve en la foto:

Wiring ChartWiring ChartWiring Chart
Tabla de cableado

Conecta el pin 1 al riel positivo y el pin 6 al riel de tierra.

Paso 2: MCP3008

Importante: El chip debe estar ubicado sobre el valle en el tablero con el indicador de pin 1, la muesca, arriba a la derecha como en la foto.

MCP3008MCP3008MCP3008
MCP3008

Consulta esta tabla de colores de cables y la hoja de datos cuando conectes este chip:

Wire colour tableWire colour tableWire colour table
Tabla de colores de alambre

Todas las conexiones de los rieles y el cabezal al chip MCP3008 van ordenadamente a lo largo de la fila inferior del chip en esta orientación. Primero conecta la alimentación y la tierra como se muestra en la foto de arriba:

  • Carril de tierra a DGND
  • Carril de tierra a AGND
  • Línea de alimentación a VREF
  • Línea de alimentación a VDD

A continuación, conecta los pines del encabezado SPI de Raspberry Pi al chip:

  • Encabezado 26 a CS
  • Cabecera 19 según DIN
  • Encabezado 21 a DOUT
  • Encabezado 23 a CLK
MCP3008 Wired upMCP3008 Wired upMCP3008 Wired up
MCP3008 cableado

Paso 3: sensor

Wiring up the moisture sensorWiring up the moisture sensorWiring up the moisture sensor
Cableado del sensor de humedad

El cableado del sensor es simple; hay tres conexiones para hacer:

  • Sensor amarillo a CH5
  • Sensor rojo al riel de alimentación
  • Sensor negro a riel de tierra
Consejo: Si tienes algunos pines de cabezal de repuesto en tu caja de herramientas, puedes insertarlos en el enchufe hembra del sensor Octopus para formar un enchufe de tres pines. Esto hace que sea fácil de insertar en la placa de pruebas. Alternativamente, el cable de puente se puede usar directamente en el enchufe.
Sensor wiringSensor wiringSensor wiring
Cableado del sensor

Finalmente, si tienes tu maceta a mano, puedes insertar la sonda en el suelo ahora. Asegúrate de no empujarlo demasiado profundo, solo cubre las puntas:

The moisture sensorThe moisture sensorThe moisture sensor
El sensor de humedad

2. Preparación del entorno del software

Paso 1: sistema operativo

Este proyecto fue construido usando Occidentalis v0.2 de Adafruit, que viene con el controlador SPI de hardware listo para funcionar. Sigue las instrucciones en el sitio de Adafruit para instalarlo en tu Raspberry Pi.

Consejo: si utilizas la descarga de Wheezy desde el sitio de Raspberry Pi, deberás buscar y seguir algunos pasos para habilitar el controlador SPI tú mismo.

Paso 2: utilidades necesarias

git - ya deberías tener esto (intenta escribir git) si no, instálalo con: sudo apt-get install git pip - instala esto con: sudo apt-get install python-pip

Paso 3: envoltorio de Python SPI

Todo el código de este proyecto está escrito en Python. Necesitamos una envoltura de Python para el controlador SPI para que podamos leer los valores del sensor sobre SPI:

1
cd ~
2
git clone git://github.com/doceme/py-spidev
3
cd py-spidev/
4
sudo python setup.py install

Paso 4: biblioteca de Adafruit Python

Ya habrás instalado la biblioteca Adafruit al ensamblar y probar tu LCD. Asegúrate de conocer la ubicación de la biblioteca, ya que el código del proyecto la necesitará.

Paso 5: biblioteca ControlMyPi

ControlMyPi es un servicio para crear de forma rápida y sencilla paneles de control en Internet desde tus scripts de Raspberry Pi Python. Usa pip para instalarlo:

1
sudo pip install controlmypi

Paso 6: código del proyecto

Todo el código de este tutorial se puede descargar así:

1
cd ~
2
mkdir py
3
cd py
4
git clone git://github.com/jerbly/tutorials

Deberás editar algunos de estos archivos para proporcionar nombres de usuario, contraseñas y rutas de archivo. Esto se explica a medida que avanzamos.


3. Lee un valor del sensor

El MCP3008 convierte el voltaje de entrada a un número de 0 a 1023 (10 bits). Luego puedes leer este valor sobre SPI (las conexiones verde y blanca al encabezado en el Pi). El paquete py-spidev nos permite hacer esto desde Python.

Existe una complicación sutil al leer un número de 10 bits en un sistema de 8 bits. El controlador SPI devolverá dos palabras de 8 bits y estamos interesados ​​en los últimos 2 bits de la primera palabra seguidos de los 8 bits de la siguiente palabra. Para convertir esto en un número con el que podamos trabajar, necesitamos enmascarar y luego desplazar a la izquierda en 8 los 2 bits de la primera palabra antes de agregar la segunda palabra.

Sin embargo, no necesitas preocuparte por codificar esto, ya que en la descarga he incluido el módulo mcp3008.py para encargarte de ello. Puedes usar una cascara de Python interactivo para probar tu configuración de SPI y tu cableado de esta manera:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python
2
Python 2.7.3 (default, Jan 13 2013, 11:20:46)
3
[GCC 4.6.3] on linux2
4
Type "help", "copyright", "credits" or "license" for more information.
5
>>> import mcp3008
6
>>> mcp3008.readadc(5)
7
444

Importante: debes ejecutar Python con sudo para poder acceder al controlador de dispositivo SPI.

Si tienes problemas, primero revisa tu cableado. Luego, verifica los pasos de instalación del software anteriores. Si estás utilizando el sensor de humedad Octopus, sostén las puntas para hacer una conexión con tu mano. De lo contrario, probablemente leerás cero.

Puedes sacar el sensor de la ecuación aquí conectando un puente desde la línea de alimentación a, digamos, CH1 y luego usando readadc(1). Esto debería devolver 1023 (o cerca de él). Del mismo modo, una conexión desde el riel de tierra debe devolver 0.


Programas

Programa 1: monitoreo en la consola

El primer programa simplemente extiende lo que practicamos en la consola interactiva para incluir un bucle de modo que el valor del sensor se imprima continuamente:

1
from time import sleep
2
import mcp3008
3
4
while True:
5
    m = mcp3008.readadc(5)
6
    print "Moisture level: {:>5} ".format(m)
7
    sleep(.5)

Observa que hay medio segundo de suspensión en el bucle. Esto es así que el programa cede; da paso a otros procesos. De lo contrario, consumiría mucho tiempo de CPU y otros procesos que está ejecutando no funcionarían tan bien. Una lectura dos veces por segundo probablemente sea demasiado de todos modos, ciertamente para un sensor de humedad.

La salida debería ser así:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python moist_cmd.py
2
Moisture level:   452
3
Moisture level:   486
4
Moisture level:   485
5
Moisture level:   483
6
Moisture level:   489
7
Moisture level:   491
8
Moisture level:   490
9
^CTraceback (most recent call last):
10
    File "moist_cmd.py", line 7, in <module>
11
            sleep(.5)
12
KeyboardInterrupt
13
pi@raspberrypi ~/py/tutorials/moisture $

Simplemente presiona Control-C cuando hayas terminado y el programa saldrá como se indica arriba.

Programa 2: mejor supervisión de la consola

Este programa mejora la visualización de la consola. En lugar de imprimir el valor en la pantalla en una ventana de desplazamiento, este script creará un efecto de tablero. Cada lectura del sensor se escribe encima de la última para que la ventana no se desplace.

También se utilizan fondos rojos, amarillos y verdes como luces de semáforo. Cuando el suelo esté bien regado, el fondo será verde. Cuando esté demasiado seco, se verá rojo.

Para lograr este color, se utilizan códigos de escape ANSI especiales para enviar comandos a la consola. Cada secuencia de código de escape comienza con \x1b[ seguido de los códigos de comando para producir un efecto.

1
from time import sleep
2
import mcp3008
3
4
# ANSI escape codes
5
PREVIOUS_LINE="\x1b[1F"
6
RED_BACK="\x1b[41;37m"
7
GREEN_BACK="\x1b[42;30m"
8
YELLOW_BACK="\x1b[43;30m"
9
RESET="\x1b[0m"
10
11
# Clear the screen and put the cursor at the top
12
print '\x1b[2J\x1b[H'
13
print 'Moisture sensor'
14
print '===============\n'
15
16
while True:
17
    m = mcp3008.readadc(5)
18
    if m < 150:
19
        background = RED_BACK
20
     elif m < 500:
21
        background = YELLOW_BACK
22
     else:
23
        background = GREEN_BACK
24
     print PREVIOUS_LINE + background + "Moisture level: {:>5} ".format(m) + RESET
25
     sleep(.5)

El programa borra la pantalla y muestra un título. Luego entra nuevamente en el bucle perpetuo, pero esta vez usa umbrales para determinar el color de fondo. Finalmente, se imprimen las secuencias de escape y el texto seguido de una secuencia de RESET para desactivar el color. El código de escape PREVIOUS_LINE se usa para mover el cursor hacia atrás una línea para que escribamos sobre la parte superior del valor anterior cada vez.

Ejecuta este ejemplo así:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python moist_ansi.py

La salida debería ser algo como esto:

OutputOutputOutput
Producción

Programa 3: monitoreo LCD

Ahora vamos a alejarnos de la consola y mostrar los datos del sensor en la pantalla LCD. Antes de continuar con este tutorial, asegúrate de haber construido tu pantalla LCD Adafruit con el encabezado de apilamiento y de haberlo probado siguiendo el tutorial de Adafruit.

Nuestro programa utilizará la biblioteca Adafruit, por lo que necesitamos conocer la ruta completa al directorio Adafruit_CharLCDPlate. Simplemente creo un directorio py en la casa del usuario pi para mantener todo el código Python en un solo lugar, por lo que en mi Raspberry Pi la ruta es:

1
/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate

Es posible que debas ajustar el siguiente script si tu ruta es diferente.

1
import sys
2
sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate')
3
4
from time import sleep
5
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
6
import mcp3008
7
8
lcd = Adafruit_CharLCDPlate()
9
10
while True:
11
    m = mcp3008.readadc(5)
12
    try:
13
        lcd.home()
14
        lcd.message("Moisture level:\n%d    " % m)
15
        if m < 150:
16
            lcd.backlight(lcd.RED)
17
        elif m < 500:
18
            lcd.backlight(lcd.YELLOW)
19
        else:
20
            lcd.backlight(lcd.GREEN)
21
        except IOError as e:
22
            print e
23
        sleep(.5)

Ejecuta el programa así:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python moist_lcd.py

Deberías ver la versión LCD del programa de la consola de color. Esta vez, los indicadores de umbral rojo, amarillo y verde utilizan la luz de fondo RGB.

Liquid Crystal Display (LCD)Liquid Crystal Display (LCD)Liquid Crystal Display (LCD)
Pantalla de cristal líquida (LCD)

Programa 4: monitoreo remoto con ControlMyPi

En esta sección vamos a hacer uso de ControlMyPi para producir un tablero en Internet. Así es como se describe el servicio en las preguntas frecuentes:

ControlMyPi proporciona un servicio basado en web que permite controlar scripts simples de Python desde un panel a través de internet. Tu secuencia de comandos de Python define un diseño de widget de etiquetas, botones, indicadores de estado y más para que ControlMyPi lo muestre. Cuando haces clic en un botón, tu secuencia de comandos recibirá un mensaje. Si tienes algún estado para informar, tu secuencia de comandos puedes enviarlo a ControlMyPi en cualquier momento y se enviará a tu navegador web.

Si aún no has instalado el paquete de Python, hazlo ahora. También necesitarás una cuenta XMPP. Recomendaría una cuenta de Gmail de Google, ya que funciona bien y también se utilizará más adelante cuando queramos que nuestro script envíe un correo electrónico. Sigue las instrucciones en el sitio web de ControlMyPi para comenzar y probar tu conexión.

La primera iteración del tablero simplemente mostrará un solo indicador con la lectura del sensor. Subiremos una nueva lectura a ControlMyPi cada 30 segundos para producir esto:

Moisture monitorMoisture monitorMoisture monitor
Monitor de humedad

El script para producir esto sigue siendo relativamente sencillo:

1
from time import sleep
2
import mcp3008
3
from controlmypi import ControlMyPi
4
import logging
5
6
def on_msg(conn, key, value):
7
    pass
8
9
logging.basicConfig(level=logging.INFO)
10
11
p = [ 
12
    [ ['G','moist','level',0,0,1023] ], 
13
    ]
14
15
conn = ControlMyPi('you@gmail.com', 'password', 'moisture', 'Moisture monitor', p, on_msg)
16
if conn.start_control():
17
        try:
18
            while True:
19
                    m = mcp3008.readadc(5)
20
                    conn.update_status({'moist':m})
21
                    sleep(30)
22
    finally:
23
conn.stop_control()

En la parte superior, ahora estamos importando la clase ControlMyPi y el módulo de registro. Si necesitas depurar cualquier problema de conexión XMPP, cambia el nivel de registro a DEBUG.

La on_msg function es lo que se llamaría si definiéramos botones u otras entradas en el diseño de nuestro widget. Como solo tenemos un medidor, no hay entrada y, por lo tanto, esta función no hace nada.

La lista, p, es donde se define el diseño del widget. Cada entrada de la lista define una fila de widgets que se mostrarán en el tablero. Tenemos una sola fila con un solo widget, el indicador. Moist es el nombre del widget, nivel es la etiqueta que aparecerá en el indicador, 0 es el nivel inicial, 0 es el nivel mínimo y 1023 es el máximo.

Luego, el script crea un objeto ControlMyPi y se inicia. Aquí deberás proporcionar tu propia dirección y contraseña de Gmail.

Sugerencia: esta es una conexión segura a los servidores de Google; la contraseña no se comparte con ningún otro servicio. Si estás preocupado, simplemente configura otra cuenta. De hecho, una cuenta separada es bastante útil, especialmente cuando deseas que se envíen correos electrónicos automatizados desde tu Raspberry Pi.

Finalmente, el bucle principal toma la lectura del sensor como de costumbre, pero en lugar de imprimirla en la consola o en la pantalla LCD, envía el nuevo valor a ControlMyPi. Las actualizaciones se envían en un mapa de widget name / value.

Ejecuta el script usando sudo como de costumbre:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python moist_cmp.py

Parte de la información de conexión se imprimirá en la consola seguida de "Registrado con controlmypi". Ahora ve a ControlMyPi.com e ingresa tu dirección de Gmail en el formulario:

Control my PiControl my PiControl my Pi
Controla mi Pi

Haz clic en buscar paneles para mostrar una lista de paneles de control asociados con tu dirección de Gmail. Debería haber uno en la lista, monitor de humedad. Haz clic aquí para iniciar tu panel y ver los datos en vivo enviados desde tu Raspberry Pi.

Cada 30 segundos, cuando se toma una nueva lectura del sensor, este valor se envía a través de la conexión XMPP a ControlMyPi. Luego envía estos datos a todos los espectadores de tu panel (solo a ti en este momento). ¡Verás moverse el indicador ante tus ojos! Si lo deseas, puedes copiar/pegar la URL larga y enviársela a un amigo para mostrar tu monitor de humedad. Ahora las actualizaciones se enviarán a tu amigo y a ti.

Programa 5: agrega un gráfico de líneas

ControlMyPi tiene un número de widgets disponibles para que los uses en tu tablero. Uno de los más útiles para visualizar datos es el gráfico de líneas. El programa en esta sección agrega un gráfico de líneas simple para trazar los cambios en el nivel de humedad a lo largo del tiempo. Para comenzar, simplemente trazaremos un nuevo punto en el gráfico cada treinta segundos cuando tomamos una lectura.

1
from time import sleep
2
import mcp3008
3
from controlmypi import ControlMyPi
4
import logging
5
import datetime
6
7
def on_msg(conn, key, value):
8
    pass
9
10
def append_chart_point(chart, point):
11
    if len(chart) >= 10:
12
        del chart[0]
13
    chart.append(point)
14
    return chart
15
16
logging.basicConfig(level=logging.INFO)
17
18
p = [ 
19
    [ ['G','moist','% level',0,0,100], ['LC','chart1','Time','Value',0,100] ], 
20
    ]
21
22
c1 = []
23
24
conn = ControlMyPi('you@gmail.com', 'password', 'moistcmp2', 'Moisture monitor 2', p, on_msg)
25
if conn.start_control():
26
    try:
27
        while True:
28
            dt = datetime.datetime.now().strftime('%H:%M:%S')
29
            m = mcp3008.read_pct(5)                
30
            c1 = append_chart_point(c1, [dt, m])
31
            conn.update_status({'moist':m,'chart1':c1})
32
            sleep(30)
33
    finally:
34
        conn.stop_control()

En el diseño del widget, p, puedes ver la definición del widget de gráfico de líneas después del indicador. El nombre del widget es chart1, el x axis es tiempo, el y axis es valor y los valores max y min se establecen en 0 y 100.

Consejo: he cambiado la escala del rango del sensor sin formato (0 a 1023) a un valor porcentual más significativo. El módulo mcp3008 proporciona una función read_pct () para devolver un punto porcentual entero en lugar del valor bruto.

Para actualizar el gráfico en el tablero, simplemente envía una lista de puntos de datos a ControlMyPi. Los puntos de datos se guardan en la lista c1 del programa y cada punto consta de un tiempo y un valor. La función append_chart_point() se utiliza para mantener una lista continua de los últimos diez puntos, de modo que a medida que llega un nuevo valor, se elimina el más antiguo. Sin esto, la tabla crecería para siempre.

Ejecuta el script usando sudo como de costumbre:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python moist_cmp2.py
Moisture monitor with widgetMoisture monitor with widgetMoisture monitor with widget
Monitor de humedad con widget

Programa 6: mejora del gráfico de líneas

Este script mejora la versión anterior por:

  • Reintroduciendo la pantalla LCD para que tengamos monitoreo local y en línea.
  • Registro de puntos de datos en el gráfico de líneas durante 24 horas.
  • Suavizando las fluctuaciones en el gráfico tomando un promedio.
  • Guarda los datos del gráfico en un archivo para que no los perdamos si necesitamos reiniciar el programa.
1
import sys
2
sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate')
3
4
from time import sleep
5
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
6
import mcp3008
7
from controlmypi import ControlMyPi
8
import logging
9
import datetime
10
import pickle
11
from genericpath import exists
12
13
lcd = Adafruit_CharLCDPlate()
14
15
PICKLE_FILE = '/home/pi/py/moisture/moist.pkl'
16
17
def on_msg(conn, key, value):
18
    pass
19
20
def append_chart_point(chart, point):
21
    if len(chart) >= 48:
22
        del chart[0]
23
    chart.append(point)
24
    return chart
25
26
def save(data):
27
    output = open(PICKLE_FILE, 'wb')
28
    pickle.dump(data, output)
29
    output.close()
30
31
def load(default):
32
    if not exists(PICKLE_FILE):
33
        return default
34
    pkl_file = open(PICKLE_FILE, 'rb')
35
    data = pickle.load(pkl_file)
36
    pkl_file.close()
37
    return data
38
39
def update_lcd(m):
40
    try:
41
        lcd.home()
42
        lcd.message("Moisture level:\n%d%%   " % m)
43
        if m < 15:
44
            lcd.backlight(lcd.RED)
45
        elif m < 50:
46
            lcd.backlight(lcd.YELLOW)
47
        else:
48
            lcd.backlight(lcd.GREEN)
49
    except IOError as e:
50
        print e
51
52
logging.basicConfig(level=logging.INFO)
53
54
p = [ 
55
    [ ['G','moist','% level',0,0,100], ['LC','chart1','Time','Value',0,100] ], 
56
    ]
57
58
c1 = load([])
59
60
readings = []
61
62
conn = ControlMyPi('you@gmail.com', 'password', 'moisture3', 'Moisture monitor 3', p, on_msg)
63
64
delta = datetime.timedelta(minutes=30)
65
next_time = datetime.datetime.now()
66
67
if conn.start_control():
68
    try:
69
        while True:
70
            dt = datetime.datetime.now()
71
            m = mcp3008.read_pct(5)
72
            readings.append(m)
73
            update_lcd(m)
74
            to_update = {'moist':m}
75
            if dt > next_time:       
76
                # Take the average from the readings list to smooth the graph a little
77
                avg = int(round(sum(readings)/len(readings)))             
78
                readings = []   
79
                c1 = append_chart_point(c1, [dt.strftime('%H:%M'), avg])                         
80
                save(c1)
81
                next_time = dt + delta
82
                to_update['chart1'] = c1
83
            conn.update_status(to_update)
84
            sleep(30)
85
    finally:
86
        conn.stop_control()

Deberías reconocer el contenido de la función update_lcd() del programa anterior. Esta función ahora se llama desde el bucle principal para actualizar la pantalla LCD en cada iteración.

Sugerencia: si no tienes la pantalla LCD, simplemente elimina esta función y la línea que la llama. También elimina la ruta e importa desde la parte superior y la línea lcd = Adafruit_CharLCDPlate().

Grabando datos

Para registrar 24 horas de datos en el gráfico de líneas, tomaremos una lectura cada 30 minutos y mostraremos 48 puntos en el gráfico. La función append_chart_point() se ha actualizado para mantener 48 puntos de datos. En el ciclo principal ahora tenemos un tiempo de 30 minutos en el futuro en la variable next_time.

En cada bucle, comparamos la hora actual con la next_time. Si pasamos next_time, se agrega un punto de datos al gráfico y next_time avanza 30 minutos nuevamente. Usar el reloj es una forma ordenada de realizar acciones en diferentes granularidades de tiempo sin tener varios medidores contando bucles, etc. Usaremos esta técnica nuevamente en el programa final para enviar un correo electrónico diario.

Como habrás notado, la lectura del sensor fluctúa bastante. Otros tipos de sensores no necesariamente harán esto, pero este sí. Entonces, en lugar de tomar una sola lectura y graficarla en el esquema cada media hora, vamos a graficar el promedio de todas las lecturas tomadas en la última media hora. La lista de lecturas se usa para guardar todas las lecturas, int(round(sum(readings)/len(readings)))  calcula el promedio al número entero más cercano. Esto luego se traza en el gráfico.

El módulo pickle de Python se usa para guardar y cargar los datos del gráfico en un archivo. Esto simplemente almacena la lista c1 en caso de que tengamos que detener el programa e iniciarlo de nuevo. Un reinicio para un cambio de batería, por ejemplo. La función save() se llama cada vez que actualizamos el gráfico y la función load() se llama cada vez que se inicia el programa.

Ejecuta el script usando sudo como de costumbre:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python moist_cmp3_lcd.py

La captura de pantalla muestra ahora un gráfico mucho más fluido:

Moisture monitor chartMoisture monitor chartMoisture monitor chart
Gráfico del monitor de humedad

El programa final

Para finalizar este proyecto, agregaremos un último paso: correo electrónico. Podemos monitorear el sensor desde la pantalla LCD y mirar la lectura actual y el historial en la web, pero es posible que nos olvidemos de verificarlo después de un tiempo. Para cubrir esto, vamos a conseguir que el programa envíe un correo electrónico una vez al día siempre que la lectura del sensor esté por debajo de un valor especificado.

1
import sys
2
sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate')
3
4
from time import sleep
5
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
6
import mcp3008
7
from controlmypi import ControlMyPi
8
import logging
9
import datetime
10
import pickle
11
from genericpath import exists
12
import smtplib
13
14
lcd = Adafruit_CharLCDPlate()
15
16
PICKLE_FILE = '/home/pi/py/moisture/moist.pkl'
17
18
def on_msg(conn, key, value):
19
    pass
20
21
def append_chart_point(chart, point):
22
    if len(chart) >= 48:
23
        del chart[0]
24
    chart.append(point)
25
    return chart
26
27
def save(data):
28
    output = open(PICKLE_FILE, 'wb')
29
    pickle.dump(data, output)
30
    output.close()
31
32
def load(default):
33
    if not exists(PICKLE_FILE):
34
        return default
35
    pkl_file = open(PICKLE_FILE, 'rb')
36
    data = pickle.load(pkl_file)
37
    pkl_file.close()
38
    return data
39
40
def update_lcd(m):
41
    try:
42
        lcd.home()
43
        lcd.message("Moisture level:\n%d%%   " % m)
44
        if m < 15:
45
            lcd.backlight(lcd.RED)
46
        elif m < 50:
47
            lcd.backlight(lcd.YELLOW)
48
        else:
49
            lcd.backlight(lcd.GREEN)
50
    except IOError as e:
51
        print e
52
53
def send_gmail(from_name, sender, password, recipient, subject, body):
54
    '''Send an email using a GMail account.'''
55
    senddate=datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d')
56
    msg="Date: %s\r\nFrom: %s <%s>\r\nTo: %s\r\nSubject: %s\r\nX-Mailer: My-Mail\r\n\r\n" % (senddate, from_name, sender, recipient, subject)
57
    server = smtplib.SMTP('smtp.gmail.com:587')
58
    server.starttls()
59
    server.login(sender, password)
60
    server.sendmail(sender, recipient, msg+body)
61
    server.quit()
62
63
logging.basicConfig(level=logging.INFO)
64
65
p = [ 
66
    [ ['G','moist','level',0,0,100], ['LC','chart1','Time','Value',0,100] ], 
67
    ]
68
69
c1 = load([])
70
71
readings = []
72
73
conn = ControlMyPi('you@gmail.com', 'password', 'moisture', 'Moisture monitor', p, on_msg)
74
75
delta = datetime.timedelta(minutes=30)
76
next_time = datetime.datetime.now()
77
78
delta_email = datetime.timedelta(days=1)
79
next_email_time = datetime.datetime.now()
80
81
if conn.start_control():
82
    try:
83
        while True:
84
            dt = datetime.datetime.now()
85
            m = mcp3008.read_pct(5)
86
            readings.append(m)
87
            update_lcd(m)
88
            to_update = {'moist':m}
89
90
            # Update the chart?
91
            if dt > next_time:
92
                # Take the average from the readings list to smooth the graph a little
93
                avg = int(round(sum(readings)/len(readings)))             
94
                readings = []   
95
                c1 = append_chart_point(c1, [dt.strftime('%H:%M'), avg])
96
                save(c1)
97
                next_time = dt + delta
98
                to_update['chart1'] = c1
99
            conn.update_status(to_update)
100
101
            #Send an email?
102
            if dt > next_email_time:
103
                next_email_time = dt + delta_email
104
                if m < 40:
105
                    send_gmail('Your Name', 'you@gmail.com', 'password', 'recipient@email.com', 'Moisture sensor level', 'The level is now: %s' % m)
106
107
            sleep(30)
108
    finally:
109
        conn.stop_control()

La función send_gmail() se encarga de enviar el correo electrónico. En el ciclo principal, usamos la técnica de verificación del reloj para determinar si ha pasado un día desde la última vez que enviamos un correo electrónico. Si es así, aumentamos este tiempo con un día para la siguiente verificación. A continuación, si el valor de humedad es inferior a 40, enviamos el correo electrónico.

¡Ese es el programa completo! Ejecútalo usando sudo como de costumbre:

1
pi@raspberrypi ~/py/tutorials/moisture $ sudo python moist_final.py

Hay una última cosa que hacer: ejecuta automáticamente el programa al iniciarse. Esto te permitirá ejecutar tu Raspberry Pi sin cabeza. Para hacer esto, edita el archivo /etc/rc.local/ como este:

1
pi@raspberrypi ~ $ sudo pico /etc/rc.local

Agrega esta línea al archivo y guárdalo:

1
python /home/pi/py/tutorials/moisture/moist_final.py &amp;

Ahora puedes apagar tu Raspberry Pi, moverla a la planta que está monitoreando, encenderla y el programa comenzará por ti.


Conclusión

En este tutorial, aprendiste cómo configurar y usar SPI en tu Raspberry Pi para usar con un convertidor de analógico al digital. Luego usaste un sensor para monitorear el nivel de humedad del suelo en una maceta. El software nos permite ver la lectura de este sensor en la consola, en una pantalla LCD, en un medidor y gráfico a través de Internet y a través de un correo electrónico diario.

Había mucho que aprender, pero ahora puedes usar estas técnicas para todo tipo de sensores diferentes para medir la temperatura, la humedad, la intensidad de la luz, etc. También puedes conectarlo a un acelerómetro o sensor de distancia por infrarrojos. ¡Diviértete!

The finished projectThe finished projectThe finished project
El proyecto terminado
Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Computer Skills tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.