top of page

MY RESEARCH BLOG

Buscar

Sensor Dashboard para Raspberry Pi usando MySQL, PHP y Highcharts.

Este tutorial lo guiará a través del proceso de obtención de datos del sensor de temperatura, presión y humedad BME280 para mostrarlos en un servidor web local. Registraremos los datos con una Raspberry Pi, los guardaremos en una base de datos MYSQL y los enviaremos a Highcharts usando PHP.


Al final, obtendrá un gráfico maravilloso incrustado en una página web como esta:


Lo que necesitarás:

  • Raspberry Pi (utilicé un Pi4)

  • Tarjeta SD con la última distribución

  • Sensor BME280 / Sensor BME180

  • Cables puente (hembra a hembra)


El conexionado GPIO del BMP180 sería muy sencillo, con la Raspberry Pi obviamente apagada, conectamos del BMP180 la conexión VCC al Pin 1 (3.3v), GND a un puerto de tierra de la Raspberry Pi, el SCL al Pin 5 (GPIO03) o SCL1; y por último la conexión SDA irá al Pin 3 (GPIO02) o SDA1 de la Pi.

Conecte el sensor:


apt-get install build-essential python-pip python-dev python-smbus git

git clone https://github.com/adafruit/Adafruit_Python_GPIO.git

sudo python setup.py install


o puedes utilizar la siguiente linea de comandos:


sudo apt-get update

sudo apt-get install build-essential python-pip python-dev python-smbus git

git clone https://github.com/adafruit/Adafruit_Python_GPIO.git

cd Adafruit_Python_GPIO

sudo python setup.py install


En la carpeta que se acaba de crear



Todo está cargado ahora. Desde la carpeta Adafruit_Python_BME280, ejecute el archivo de ejemplo.

python ./Adafruit_BME280_Example.py


Aqui ya devemos ver la temperatura, la presión y la humedad.


NOTA: Esto funciona con BME280 o BMP280. La principal diferencia es la lectura de humedad y altitud respectivamente.

El sensor de presión barométrica BMP180 está diseñado para leer la presión atmosférica y de esta forma estimar indirectamente la Altura sobre el nivel del mar. La presión atmosférica es la fuerza que ejerce el aire (atmósfera) sobre la superficie de la tierra.



Ahora que puede ver que puede obtener lecturas del sensor, queremos obtenerlas cada 10 minutos y almacenarlas en algún lugar. Las almacenaremos en una base de datos MySQL.


También necesitará otra biblioteca que le permita interactuar con MySQL a través de Python, por lo que deberá instalarla.

sudo apt-get install python-mysqldb



Nota: Recordemos reniciar despues de cada instalación:

sudo reboot

Reiniamos la base de datos:

sudo mysql -u root -p

Te pedirá tu contraseña. Una vez ingresado, obtendrá otra interfaz de línea de comando.



Vamos a crear una base de datos, y en esa base de datos vamos a crear una tabla. Llamaremos a la base de datos sensor y a la tabla la llamaremos bmesensor/ nombre que prefieran.


CREATE DATABASE sensor;


Esto hace una base de datos llamada sensor. Sólo necesitas hacer esto una vez. Todos los comandos en MYSQL terminan con un ';'.


USE sensor;


Esto lo lleva a la base de datos de sensores. En esta base de datos crearemos una tabla llamada bmesensor.


CREATE TABLE bmesensor(datetime BIGINT NOT NULL, temperature FLOAT (6,3) NOT NULL, pressure FLOAT (8,3) NOT NULL, humidity FLOAT (6,3) NOT NULL);


Esta es una expresión larga, así que separémosla. Todo lo que está entre paréntesis después de bmesensor son los encabezados de la tabla bmesensor que estamos creando. Estamos haciendo cuatro columnas.


  1. datetime: será un número entero que debe tener muchos dígitos. Podríamos haber usado INTEGER pero está limitado a 11 dígitos, así que usamos BIGINT en su lugar. Esta columna contendrá una marca de tiempo UNIX en milisegundos.

  2. temperatura: será un punto decimal flotante con un total de 6 dígitos, tres de los cuales podrían estar después del punto decimal. Puede cambiar cualquiera de esos números si necesita un rango diferente.

  3. presión: de nuevo, un punto decimal flotante. El sensor nos lo da en pascales, así que aumenté el número total de dígitos. (101325 pascales es 1,0 atm, y eso es aproximadamente la presión que estaríamos midiendo).

  4. humedad – Nuestro decimal de punto flotante final.

  5. NOT NULL aparece después de cada uno. Eso significa que estas columnas deben contener cada una un valor. Completaremos esta tabla ejecutando un programa de python, que nos dará un valor o nos dará un rastreo.

DESCRIBE bmesensor;


Para salir de MYSQL presione "Control Z".


Otros comandos que encontré útiles:


TRUNCATE TABLE: eso eliminará los datos de su tabla, pero mantendrá las filas.

DROP TABLE: eso eliminará la tabla y sus datos.


Ahora necesitamos hacer un programa que obtenga los datos que necesitamos con nuestro sensor. Cambie los directorios para que esté en la carpeta del sensor de Adafruit.


cd

cd Adafruit_Python_GPIO/Adafruit_Python_BME280/


En esta carpeta harás un programa llamado sensor.

nano sensor.py


Este es el programa que vamos a utilizar:


#!/usr/bin/env python


import os

import time

import datetime

import glob

import MySQLdb

from time import strftime

from Adafruit_BME280 import *


sensor = BME280(t_mode=BME280_OSAMPLE_8, p_mode=BME280_OSAMPLE_8, h_mode=BME280_OSAMPLE_8)


#Variables for MySQL

db = MySQLdb.connect(host="localhost", user="root", passwd="password", db="sensor") # replace password with your password

cur = db.cursor()


def dateTime(): #get UNIX time

secs = float(time.time())

secs = secs*1000

return secs


def tempRead(): #read temperature, return float with 3 decimal places

degrees = float('{0:.3f}'.format(sensor.read_temperature()))

return degrees


def pressRead():#read pressure, return float with 3 decimal places

pascals = float('{0:.3f}'.format(sensor.read_pressure()/100))

return pascals


def humidityRead(): #read humidity, return float with 3 decimal places

humidity = float('{0:.3f}'.format(sensor.read_humidity()))

return humidity


secs = dateTime()

temperature = tempRead()

pressure = pressRead()

humidity = humidityRead()


sql = ("""INSERT INTO bmesensor (datetime,temperature,pressure,humidity) VALUES (%s,%s,%s,%s)""", (secs, temperature, pressure, humidity))


try:

print "Writing to the database..."

cur.execute(*sql)

db.commit()

print "Write complete"


except:

db.rollback()

print "We have a problem"


cur.close()

db.close()


print secs

print temperature

print pressure

print humidity



Hay mucho en este programa, pero podemos descomprimirlo bastante fácilmente.


  • La parte superior tiene todas las bibliotecas que deben importarse para que se ejecute el programa.

  • Las variables db y cur están ahí para abrir su base de datos MYSQL.

Entonces tenemos algunos métodos para definir:

  • datetime(): Esto obtendrá la marca de tiempo de UNIX y la convertirá en milisegundos. Esto es necesario porque eso es lo que usa Highcharts para las marcas de tiempo.

  • tempRead(): Esto nos da un punto decimal flotante con tres lugares decimales que indican la temperatura en grados Celsius.

  • pressRead(): Esto nos da un punto decimal flotante con tres lugares decimales que indican la presión en pascales.

  • humidityRead(): Esto nos da un punto decimal flotante con tres lugares decimales que indican la humedad relativa en porcentaje.


Después de eso, llamamos a cada método y almacenamos el resultado en una variable.

  • La línea sql=”” es un comando MYSQL que insertará cada una de esas cuatro variables en su tabla bmesensor.

  • Usamos try y except para hacer la escritura real, e incluí algunas declaraciones de impresión solo para asegurarme de que todo funcionaba.

  • Luego cerramos la conexión a la base de datos.

  • Finalmente, imprimo las variables.

Para hacer el programa ejecutable:

sudo chmod +x sensor.py


Pruébelo desde la misma carpeta, y debería ver las variables impresas.

./sensor.py


Por último, la haremos un trabajo programado.

sudo crontab -e


En la parte inferior de este archivo, agregará

*/10 * * * * /home/pi/Adafruit_Python_GPIO/Adafruit_Python_BME280/sensor.py


Esto significa que cada 10 minutos se ejecutará el programa. Si cambia el 10 por un 5, se ejecutará cada cinco minutos.


Listas para un descanso ...... te lo mereces.



Ya tenemos creado nuestro servidor Web


Vayamos codigo fuente esta pagina: para encontrar la carpeta /var/www/html/. Así que vayamos allí y hagamos un nuevo archivo llamado index.php.

cd /var/www/html

nano index.php


Eliminaremos el archivo index.html que se encuentra allí.

rm index.html


Pon tus datos en la página web


En el archivo index.php que acaba de crear, deberá tener al menos tres partes diferentes.


  • Una sección de php que obtiene información de su tabla de datos MYSQL.

  • Una sección html que un navegador puede leer

  • Una porción de javascript que usa Highcharts

Vamos a revisarlo individualmente:


En el archivo index.php, copia el siguiente código.



<?php


$username="root";

$password="password";//use your password

$database="sensor";


mysql_connect(localhost,$username,$password);

@mysql_select_db($database) or die ( "Unable to make it happen Cap'n");


$query = "SELECT datetime, temperature FROM bmesensor";

$result = mysql_query($query);

$dateTemp = array();

$index = 0;

while ($row = mysql_fetch_array($result, MYSQL_NUM))

{

$dateTemp[$index]=$row;

$index++;

}


//echo json_encode($dateTemp, JSON_NUMERIC_CHECK);


mysql_close();


?>

La magia está en la parte de consulta (líneas 10-18). Aquí configuramos un bucle while. Recorre la tabla bmesensor y selecciona los valores de fecha, hora y temperatura. Esos se colocan en una matriz llamada dateTemp. Pasé por varias iteraciones antes de finalmente hacerlo bien. La línea 20 tiene algo que está comentado, pero útil. Si lo descomentas, esos pares [x,y] se imprimirán para que sepas que estás en el camino correcto. La parte json_encode elimina las comillas, lo que facilita la colocación de elementos en Highcharts.


La sección html:


Aquí hay más de lo que debe haber. Terminé extrayendo de varias fuentes, y probablemente debería limpiarlo un poco.

Hay algunas cosas a las que prestar atención en las líneas 4-8. Estas son varias fuentes de secuencias de comandos que se necesitan para ejecutar Highcharts.

Las líneas 7 y 8 le dan al eje x la zona horaria correcta, ya que nuestro tiempo se mide en milisegundos a partir de la época. La línea 22 crea un contenedor para el gráfico Highcharts



​<?php


$username="root";

$password="password";//use your password

$database="sensor";


mysql_connect(localhost,$username,$password);

@mysql_select_db($database) or die ( "Unable to make it happen Cap'n");


$query = "SELECT datetime, temperature FROM bmesensor";

$result = mysql_query($query);

$dateTemp = array();

$index = 0;

while ($row = mysql_fetch_array($result, MYSQL_NUM))

{

$dateTemp[$index]=$row;

$index++;

}


//echo json_encode($dateTemp, JSON_NUMERIC_CHECK);


mysql_close();


?>


<!DOCTYPE html>

<html>

<head>

<title>HighChart</title>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>

<script src="https://code.highcharts.com/highcharts.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js"></script>


</head>

<body>


<script type="text/javascript">

$(function () {


$('#container').highcharts({

chart: {

type: 'line'

},

time: {

timezone: 'America/New_York'

},

title: {

text: 'Temperature vs Time'

},

xAxis: {

title: {

text: 'Time'

},

type: 'datetime',

},

yAxis: {

title: {

text: 'Temperature'

}

},

series: [{

name: 'Celcius',

data: <?php echo json_encode($dateTemp, JSON_NUMERIC_CHECK);?>

}]

});

});


</script>

<script src="charts/js/highcharts.js"></script>

<script src="charts/js/modules/exporting.js"></script>


<div class="container">

<br/>

<h2 class="text-center">Living Room Sensor - Temp vs. Time</h2>

<div class="row">

<div class="col-md-10 col-md-offset-1">

<div class="panel panel-default">

<div class="panel-heading">Dashboard</div>

<div class="panel-body">

<div id="container"></div>

</div>

</div>

</div>

</div>

</div>


</body>

</html>


https://www.youtube.com/watch?v=DVGMDYpk5Ds

750 visualizaciones1 comentario

Entradas Recientes

Ver todo

1 Comment


Luis Anco Alderete
Luis Anco Alderete
Jan 09, 2023

Excelente trabajo, voy a iniciar este proyecto, rápidamente, me ayudan si tengo algún inconveniente.

Like
bottom of page