Grafica animada – Datos Serial

El ejemplo usa datos aleatorios para presentar una forma de realizar gráficos en vivo usando la librería matplotlib.

Los datos pueden ser obtenidos de algún experimento que envia datos al computador por el puerto serial, ver ejemplos en la sección Arduino.  Como los datos podrían aumentar en el tiempo, se selecciona un tamaño de ventada de datos a graficar.

El tiempo entre tramas o actualizaciones del gráfico se puede controlar con la variable «retraso» que está dada en milisegundos.

Los valores usados en la gráfica son xi,yi semejantes a lo usado en el curso de análisis Numérico (MATG1013) .

# Grafica "en vivo" para actualizar datos
# recibidos por puerto serial
# Plantilla para proyecto, datos de prueba aleatorios

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random as rnd

# Datos a graficar
xi = []
yi = []

# ventana de datos para gráfico
tamano = 20
# tiempo entre tramas
retraso = 1000

# GRAFICA figura
figura = plt.figure()
grafica = figura.add_subplot(1, 1, 1)

# Nueva Trama
def unatrama(i, xi, yi):

    # Recibe un dato nuevo
    undato = int(rnd.random()*20)+1

    # actualiza cada linea
    yi.append(undato)
    xi.append(len(yi)) # numero del dato ejemplo

    # ventana de datos
    xi = xi[-tamano:]
    yi = yi[-tamano:]

    # limpia y grafica de nuevo
    grafica.clear()
    grafica.plot(xi, yi)

    # Presenta valores en pantalla
    print(yi)
    
    return()

# Animación
ani = animation.FuncAnimation(figura,
                              unatrama,
                              fargs=(xi, yi),
                              interval=retraso)

plt.show()

En la función unatrama(), la variable i en la función es el número de trama. La variable i es un parámetro necesario para la función que se incrementa automáticamente en uno cada vez que se llama a la función unatrama(). Los demás parámetros se adaptan a los datos del problema.

Se pueden añadir otros elementos a la grafica, como títulos, etiquetas, otras líneas, etc. Adicionalmente el procesamiento de los datos se puede incorporar y presentar en la pantalla de texto al final de la función.

Referencia:
https://learn.sparkfun.com/tutorials/graph-sensor-data-with-python-and-matplotlib/update-a-graph-in-real-time

Morse Deco – RX mensaje/Python

Se añade la traducción a texto, letra a letra del alfabeto.

Como referencia se usa la función morsedeco(codigo) descrita en Morse Decodificador, desarrollada en otro curso.

Se añade al ejercicio realizado en Morse Deco – RX mensaje morse/Python

0 31
 --- ...  ... --- .
SOS SO
1015 15
 --- ...  ... --- ..
SOS SO
1 31
 --- ...  ... --- ..
SOS SO
1017 15
 --- ...  ... --- ...
SOS SO
0 128
 --- ...  ... --- ...  
SOS SOS 

Tarea: usar en el transmisor un mensaje diferente, escrito por teclado, revisar para arduino el uso del puerto Serial – Envia y Recibe texto.

Con el uso del teclado para el mensaje, observar cuando se inicia la tx y recepción para codificar en Tx y decodificar en Rx.

# Deco señal a morse, luego a texto
# generados desde arduino
# Continuación de: TxRx Inalambrico 433Mhz ASK/OOK
# http://blog.espol.edu.ec/edelros/2018/04/11/txrx-inalambrico-433mhz-askook/

import numpy as np
import matplotlib.pyplot as plt
import serial, time
def morsedeco(codigo): 
    equivale={ 
        '.-':'A', '-...':'B', '-.-.':'C', 
        '----':'CH', '-..':'D', '.':'E', 
        '..-.':'F', '--.':'G', '....':'H', 
        '..':'I', '.---':'J', '-.-':'K',
        '.-..':'L', '--':'M', '-.':'N', 
        '--.--':'Ñ', '---':'O', '.--.':'P', 
        '--.-':'Q', '.-.':'R', '...':'S', 
        '-':'T', '..-':'U', '...-':'V',
        '.--':'W', '-..-':'X', '-.--':'Y', 
        '--..':'Z',
        '-----':'0', '.----':'1', '..---':'2', 
        '...--':'3', '....-':'4', '.....':'5', 
        '-....':'6', '--...':'7', '---..':'8', 
        '----.':'9', 
        '.-.-.-':'.', '-.-.--':',', '..--..':'?', 
        '.-..-.':'"', '--..--':'!', '   ':' ', 
        ' ':' '}
    caracter=equivale[codigo]
    return(caracter)

# INGRESO
puerto = 'com5'
baudios = 9600
tolera = 100    # rango PIN analógico
ancho = 15      # del mensaje

# PROCEDIMIENTO
arduino = serial.Serial(puerto, baudios)
arduino.setDTR(False)
time.sleep(0.3)

# limpia buffer de datos anteriores
arduino.flushInput()  
arduino.setDTR()  
time.sleep(0.3)
print('\nEstado del puerto: ',arduino.isOpen())
print('Nombre del dispositivo conectado: ', arduino.name)
print('Dump de la configuración:\n ',arduino)
print('\n###############################################\n')


# Lectura de datos
antes = 0
cuenta = 0
simbolo = ''
morse_msg = ''
morse_letra = ''
mensaje = ''

while True:
    # espera hasta recibir un dato
    while (arduino.inWaiting()==0):
        pass
    
    # lee binario del puerto serial
    lectura = arduino.readline()
    # binario a texto, elimina /r/n
    texto = lectura.decode().strip()
    valor = int(texto)
    
    # Busca duración de símbolo
    # valor repetido
    diferencia = np.abs(valor-antes)
    if (diferencia < tolera):
        cuenta = cuenta + 1
    
    else:
        print(antes,cuenta)
        # Revisa espacios
        if (antes<(0+tolera)):
            # Cambio de simbolo
            if (cuenta<(2*ancho+4)):
                simbolo = ''
            else:
                # letra completa
                letra = morsedeco(morse_letra)
                mensaje = mensaje + letra
                morse_letra = ''
                if (cuenta<(4*ancho+5)):
                    simbolo = ' '
                else:
                    # cambio de palabra
                    simbolo = '  '
                    mensaje = mensaje + ' '
        
        # Revisa punto o raya        
        else:
            if (cuenta40:
            morse_msg = ''
            mensaje = ''
            
    antes = valor
    
# Cerrar el puerto serial.
serial.Serial.close

Serial – Lectura datos

Un Arduino puede enviar valores numéricos de un sensor por medio del conector USB en forma Serial (secuencial).

Los datos recibidos por una computadora mediante el puerto USB pueden procesarse usando Python. Para ésto debe conocer el puerto «com» y la velocidad de transmisión en los baudios usada por el arduino.

Ejemplo:

Se muestra una lectura de valores numéricos enteros, a partir del cual se puede modificar otros requerimientos.

El ejemplo usa los resultados de la sección Morse para el receptor: TxRx Inalambrico 433Mhz ASK/OOK

0
0
0
1017
1017
1018
1021
1017
1019
1018
1018
1016
1018
1016
1017
1019
1018
1016
1020
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1017
1017
1016
1017
1016

Instrucciones en Python

# Datos desde puerto Serial
# generados desde arduino

import numpy as np
import matplotlib.pyplot as plt
import serial, time

# INGRESO
puerto = 'com5'
baudios = 9600
ventana = 200 # tamaño ventana datos
datos=[] # vector para graficar

# PROCEDIMIENTO
arduino = serial.Serial(puerto, baudios)
arduino.setDTR(False)
time.sleep(0.3)

# limpia buffer de datos anteriores
arduino.flushInput()  
arduino.setDTR()  
time.sleep(0.3)
print('\nEstado del puerto: ',arduino.isOpen())
print('Nombre del dispositivo conectado: ', arduino.name)
print('Dump de la configuración:\n ',arduino)
print('\n###############################################\n')

# Lectura de datos
while True:
    #esperar hasta recibir un dato
    while (arduino.inWaiting()==0):
        pass 

    # lee linea desde puerto serial
    lectura = arduino.readline()
    # binario a texto, elimina /r/n
    texto = lectura.decode().strip()
    valor = int(texto)
    datos.append(valor)
    
    # mantiene el tamaño "ventana" de datos 
    if (len(datos)>=ventana):
        datos.pop(0)
    print(valor)
    
# Cerrar el puerto serial.
serial.Serial.close