Serial a SQL

En un articulo anterior había comentado como logré tomar los datos que transmite un Arduino (provenientes de un sensor) y guardarlos en una hoja de calculo. En esta oportunidad quiero comentarles algo que esta en la misma dirección, en lugar de guardar en una hoja de calculo, llevarlos a una base de datos.

Para cumplir esto desarrolle una sencilla herramienta de terminal, que la pueden encontrar:

https://github.com/gsampallo/serial2sql

Luego de descargar la herramienta, el primer punto es tener acceso a un motor de base de datos; en mi caso utilice MySQL, puesto que es la más común y fácil de implementar. Debemos tener disponible los datos de las credenciales y permisos sobre una base de datos, luego el script se ocupara de crear una tabla e insertar en ella los datos. También existe la opción de no guardar los datos en la base al momento de recibirlos sino guardarlos en un archivo sql para luego insertarlos donde necesitemos. Está en las necesidades puntuales de cada uno ver cual es el uso optimo para cada aplicación.

Sera necesario proveerle un mínimo de información al script para que este realizar las acciones, para ello se utiliza una archivo config.json con la siguiente estructura:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
    "port":"/dev/ttyUSB0",
    "baudrate": 115200,
    "credentials" : {
    "host":"host",
    "database":"databaseName",
    "user":"userName",
    "password":"password",
    "raise_on_warnings": "True"
    },
    "tableName": "tableName",
    "fields": [
        { "name":"indice","type":"INT(10)" },
        { "name":"valor","type":"INT(10)" }
    ]
}

Se debe editar el archivo para que sea congruente con los datos de nuestra instalación.

Basicamente contiene la información de los datos de conexion del puerto serie: puerto y velocidad que se van a emplear para conectarse. Asi como tambien el nombre de la tabla (tableName) que utilizara para almacenar los datos, a continuación tenemos fields, que es una lista que contiene el nombre de cada campo junto con el tipo de dato que almacenara.

Un punto a tener en cuenta, es que el tipo de datos empleado es SQL, por lo que es sencillo definirlo; en este caso utilizamos los tipos de MySQL. En el json de ejemplo solo empleamos dos campos indice y valor, ambos enteros; pero esto podemos establecerlo según las necesidades puntuales. Siempre sabiendo de antemano cuales serán los datos que Arduino transmitirá por el puerto serie.

Si por ejemplo Arduino transmitiera cuatro campos: A,B,C,D donde A,B y C son enteros y D es una cadena de texto, deberíamos especificar el segmento fields de la siguiente manera:


1
2
3
4
5
6
    "fields": [
        { "name":"A","type":"INT(10)" },
        { "name":"B","type":"INT(10)" },
        { "name":"C","type":"INT(10)" },
        { "name":"D","type":"VARCHAR(80)" }
    ]

La longitud dependerá de lo que almacenemos.

Luego de establecido el archivo config.json simplemente basta ejecutarlo de la siguiente manera:

python serial2sql.py

Si estuviéramos en linux debemos anteponer el comando sudo para tener permisos sobre el puerto.

Adicionalmente también existe la posibilidad de guardar los datos a un archivo sql, de forma de poder insertarlos luego, para hacerlo basta especificar el parametro -o y el nombre del archivo:

python serial2sql.py -o output.sql

Otra variante interesante es utilizar la extensión csv en lugar sql, los datos de serán almacenados en formato csv:

python serial2sql.py -o output.csv

Especificando estas dos opciones no se guardara en la base de datos, ni se creara la tabla, solo se guardara el archivo.

Hojas de cálculo y Arduino

Al trabajar con arduino y los sensores una de la tareas mas recurrentes es poder registrar los valores que se registran para luego hacer algún tipo de análisis con ellos.

Esto resulta extremadamente sencillo si utilizamos un dispositivo que se conecte a la nube, como ESP8266 o el NodeMCU, puesto que con plataformas como thingspeak, es muy fácil, basta agregar algunas lineas de código a nuestro programa y todos los datos que se registren van a la base de datos de thingspeak y luego la podes descargar para analizarlo. Esto lo veremos más adelante en otro articulo.

La cosa cambia si estamos utilizando alguna versión mas modesta de Arduino (en nuestro caso utilizaremos un Arduno Nano) puesto que solo tenemos la salida por puerto serie y de alguna forma tenemos que capturar estos datos.

Para ello hacemos uso de un sencillo programa en Python, que abre el puerto serie, reconoce las columnas y guarda registro a registro en una planilla de calculo.

Puede descargar desde aquí:
https://github.com/gsampallo/serialToExcel

En el arduino tenemos un sencillo programa, que su única tarea es leer el valor del puerto analógico A0 e imprimirlo en el puerto serie. Es el siguiente:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int sensorPin = A0;
int sensorValue = 0;

void setup() {
  Serial.begin(115200);
}

int i = 0;
void loop() {
  sensorValue = analogRead(sensorPin);
  Serial.print(i);
  Serial.print(",");
  Serial.print(sensorValue);
  Serial.println(";");
  i = i + 1;

  delay(10);
}

Se puede encontrar el archivo aquí, como ven es una modificación del ejemplo de Arduino para leer datos analógicos. Lo que se debe tener en cuenta es la forma en la que se envían los campos en el puerto serie, utilizar algún carácter para separar los campos, en el ejemplo utilizamos la coma.

Dentro del repositorio podemos encontrar un archivo llamado example.py que contiene un sencillo ejemplo de como utilizar la clase para guardar en un excel:


1
2
3
4
5
6
7
8
9
10
from serialToExcel import SerialToExcel

serialToExcel = SerialToExcel("COM36",115200)
serialToExcel.setColumns(["Nro Lectura","Valor"])
serialToExcel.setRecordsNumber(10)


serialToExcel.readPort()

serialToExcel.writeFile("archivo1.xls")

Como se puede ver es bastante sencillo, podemos dividirlo en tres etapas que se producen luego de importar la libreria:

  1. Se instancia la clase SerialToExcel, pasando como parámetros el puerto y la velocidad. También indicamos cuales son los nombres de las columnas y la cantidad de registros que deseamos guardar.
  2. readPort() comienza la lectura de datos desde el dispositivo. Hay que tener en cuenta que el proceso puede demorar, dependiendo de cada cuanto tiempo el dispositivo envie datos y la cantidad de registros que deseamos guardar.
  3. writeFile() guarda la planilla de calculo en el archivo cuyo nombre pasamos como argumento a la función.

El programa aún tiene mucho por mejorar, pero para realizar registros de datos es totalmente funcional.