Proyecto aTIC (VI) - Sensor OBD

 Sensor OBD. 

Con este post finalizamos la serie de publicaciones relacionadas con el proyecto desarrollado. El sensor empleado para las lecturas es un dispositivo OBD: un sistema de diagnóstico de a bordo de vehículos. Este sistema permite monitorizar y controlar el motor y otros dispositivos del vehículo. En la siguiente imagen se puede ver al aspecto que tienen este tipo de sensores.

Con este dispositvo conectado al vehículo (y con el vehícuo en marcha), es posible concetarse a él por bluetooth y solicitar información de variables: velocidad, posición del acelerador, temperatura del motor, tensión de la batería, rpms del motor... Además, permite recoger los códigos de fallo de los posibles errores que se estén dando en el vehículo.

En el caso del proyecto realizado, la conexión bluetooth se ha realizado entre el dispositivo y un ordenador portátil mediante un script de Python. En ese script se hace uso de la librería propia de Python llamada "obd", que permite: establecer la conexion bluetooth con el dispositivo, enviar/recibir comandos específicos del dispositivo y traducir las respuesta del dispositivo.

Este script mencionado se puede consultar a continuación.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
import serial
import time
from MQTTpublisher import *


def connecttoOBD():
    ser = serial.Serial('COM5', 9600, timeout=1)
    print("Port opened!")

    print("Default settings")
    ser.write("ATD".encode())
    time.sleep(2)
    print(ser.readline().decode().split()[1])

    print("Reseting...")
    ser.write("ATZ".encode())
    time.sleep(2)
    print(ser.readline().decode().split()[1])

    ser.write("ATE0".encode())
    print("ATE0: Echo off")
    time.sleep(1)
    print(ser.readline().decode().split()[1])

    print("ATL0: Line feed off")
    ser.write("ATL0\r".encode())
    time.sleep(1)
    print(ser.readline().decode().split()[0][1:3])

    print("ATH0: Headers off")
    ser.write("ATH0\r".encode())
    time.sleep(1)
    print(ser.readline().decode().split()[0])

    print("ATSP00: Set Protocol to Auto")
    ser.write("ATSP0\r".encode())
    time.sleep(1)
    print(ser.readline().decode().split()[0])

    return ser

def waitnsec(n):
    for i in range(1,n+1):
        print(f"{i}...")
        time.sleep(1)

def getBattery(ser):
    # Bateria
    ser.write("ATRV\r".encode())
    time.sleep(1)
    battery_lvl_raw = ser.readline()
    # print(battery_lvl_raw)
    battery_lvl = float(battery_lvl_raw.decode().split()[0][0:4])
    print(f"\nBattery lvl: {battery_lvl}V")
    return battery_lvl

def getVelocidad(ser):
    # Velocidad
    ser.readline()
    ser.write("01 0D\r".encode())
    time.sleep(5)
    vel_raw = ser.readline().split()
    print(vel_raw)
    ind = 3
    if len(vel_raw) == 5:
        ind = 3
    else:
        ind = 2

    vel = int(vel_raw[ind].decode(), 16)
    print(f"Velocity: {vel}km\h")
    return vel

def getRPM(ser):
    # RPM
    ser.write("01 0C\r".encode())
    time.sleep(5)
    rpm_raw = ser.readline().split()
    print(rpm_raw)
    A = int(rpm_raw[2].decode(), 16)
    B = int(rpm_raw[3].decode(), 16)
    rpm = int((256*A+B)/4)
    print(f"RPM: {rpm}rpm")
    return rpm

def closeOBD(ser):
    print("Clossing port...")
    ser.flushInput()
    ser.flushOutput()
    ser.close()

if __name__ == "__main__":

    OBD = connecttoOBD()
    waitnsec(10)
    while True:
        bat = getBattery(OBD)
        sendValue('battery_lvl',bat)
        # waitnsec(5)
        vel = getVelocidad(OBD)
        sendValue('velocity',vel)
        # waitnsec(5)
        rpm = getRPM(OBD)
        sendValue('rpm', rpm)
        # waitnsec(5)

Como se ve en el script, esta aplicación recoge los valores de velocidad, nivel de batería y rpms del motor del dispositivo y los publica en el tipoc "Datos OBD" del broker MQTT de la RPI2. Esta aplicación se puede resumir en los siguientes pasos:

- Inicialización de la comunicación: Se conecta el ordenador al dispositivo y se deja preparado para la comunicación.

- Obtención del nivel de batería (tensión de la batería): Se envía el comando corespondiente al nivel de la batería (ATRV), se recoge la respuesta del dispositivo y se pubica el valor recogido al topic MQTT.

- Obtención de la velocidad: Se envía el comando corespondiente a la veelocidad (010D), se recoge la respuesta del dispositivo y se pubica el valor recogido al topic MQTT.

- Obtención de rpms del motor: Se envía el comando corespondiente a las rpms del motor (010C), se recoge la respuesta del dispositivo y se pubica el valor recogido al topic MQTT.

Es de mencionar que las lecturas se realizan cada 15s, desfasadas 5s entre sí, de manera que cada 5s se realiza una lectura y se publica individualmente en el topic MQTT.



Comentarios

Entradas populares de este blog

Proyecto aTIC (I) - Introducción

Proyecto aTIC (V) - Grafana

Proyecto aTIC (IV) - Bridge MQTT/InfluxDB