Obteniendo el valor del par motor de las ECUs del Toyobaru

Desde que empecé a cacharrear con los datos que circulan por el bus CAN del coche, uno de los parámetros que busqué con especial interés fue el par motor.

Después de múltiples observaciones, tengo la certeza de que está -implícita o explícitamente- en los datos que transportan el CAN ID 0x141 o el 0x142. Pero nunca he tenido forma de corroborarlo y mucho menos de escalarlo. Sólo es una sospecha que espero poder aclarar algún día.

Pero cuando hace unos meses accedí a los datos del coche a través de TechStream, me encontré con una agradable sorpresa.

Al solicitar la ‘lista de datos’ a la ECU 0x7B0 (responsable del ABS y del control de tracción) aparecía el dato ‘Real Engine Torque’ … y ya en Nm.

Valores ofrecidos por la ECU 0x780 (ABS/VSC/TRC)

Si podía capturar el tráfico que mandaba TechStream al coche, podría ver como estaba obteniendo esos datos y obtener por fin un dato contrastado del par motor.

Para ello, me hice con un conector OBDII que me permitía obtener más de una salida del bus del coche

Duplicador OBDII

Y así poder conectar más de un equipo al coche de forma simultánea. Ahora mis pruebas se realizan, en muchas ocasiones, con un portátil con Windows ejecutando el TechStream y otro portátil (con Linux en este caso) capturando los datos que se transmiten por el bus. Luego, en casa, puedo analizar y reproducir los datos capturados tranquilamente.

Cuando empecé a perseguir al dato del par motor, esperaba encontrar un protocolo del tipo pregunta-respuesta. Es decir, el TechStream solicitando el dato y la ECU respondiendo (tal como hace Torque App para obtener un dato).

Así que, con todos los equipos instalados, seleccioné de la lista de datos que ofrece la ECU 0x7B0 únicamente el valor del par motor, y le pedí a TechStream que lo enviara.

Par motor ofrecido por la ECU 0x780 (ABS/VSC/TRC)

Capturé los datos en el portátil con Linux, y al analizarlo me encontré con esto (represento con fondo gris las tramas que manda TechStream y con fondo blanco las que manda la ECU):

Datos CAN capturados

Analicemos lo que pasa. Para una mejor comprensión, he marcado en negro los bytes de protocolo; en rojo las longitudes, en azul los identificadores de servicio UDS, en verde los datos y en gris las tramas de relleno.

Solicitud Servicio UDS 0x10 (DiagnosticSessionControl)

En la primera trama que envía TechStream, el primer byte especifica que solo va a mandar una trama con una longitud de datos de 2 bytes.

El siguiente dato (0x10) es el identificador del servicio UDS 0x10 DiagnosticSessionControl, acorde con la norma ISO 14.229. Dicho servicio, requiere un parámetro (0x5F) que identifica el tipo de la sesión de diagnóstico que se va a iniciar.

Según la norma, el rango de valores comprendidos entre 0x40 y 0x5F son sesiones específicas del fabricante, así que Denso (fabricante tanto de las ECUs del toyobaru como autor de TechStream) tendrá más datos sobre el tipo de sesión. La norma no dice nada al respecto y por tanto no podemos saber más.

El resto de valores de la trama son ceros de relleno.

En la segunda trama podemos ver como la ECU responde afirmativamente.

El primer byte de la trama que envía recoge la longitud de datos (2), el siguiente es una respuesta al servicio afirmativa (que coincide con la operación lógica AND del valor 0x40 con el identificador de servicio. En este caso: 0x10 & 0x40 = 0x50) a la que acompaña el valor 0x01, que como estamos ante una sesión propietaria no sabemos que significa.

El resto de valores de la trama son ceros de relleno.

En definitiva, TechStream solicita una sesión de diagnóstico de tipo 0x5F y la ECU le dice que OK.

El análisis de la siguiente secuencia de tramas me sorprendió:

Solicitud Servicio UDS 0xA1 (específico del fabricante)

Aquí TechStream le dice a la ECU que va a mandar más de una trama (0x10) pues la longitud que quiere enviar (0x09) no le cabe en una sola trama. A continuación, manda el identificador del servicio 0xA1 y empieza a mandar los datos 0x0605020B0C.

El identificador 0xA1 es irregular, pues está reservado por protocolo.

La ECU contesta (según norma ISO 15.765) con la trama de control de flujo (0x30) donde indica que no va a mandar ninguna más (0x00) para los 9 bytes que le han dicho que van a llegar y que espera recibirlas con una separación de 0x02 milisegundos (algo innecesario, pues no va a haber más tramas).

Y TechStream manda los datos que faltan (0xE10101) con una trama consecutiva (0x21).

Así que lo que manda TechStream es la solicitud del servicio 0xA1 con 8 bytes de datos 0x0605020B0CE10101.

Y de nuevo nos encontramos un servicio no recogido por las normas. Si tratamos de aplicar ISO 14.229, nos dice que este servicio está reservado por la norma y no se puede usar. Si aplicamos ISO 14.230, nos indica que ese servicio está definido por el fabricante.

Así que Denso parece estar aplicando esta última norma para definir este servicio. Pero por ser un servicio propio del fabricante no tenemos ayuda para tratar de entender que significan los datos 0x0605020B0CE10101.

A continuación, la ECU contesta:

Respuesta Servicio UDS 0xA1 (específico del fabricante)

La respuesta es idéntica a la solicitud, con la salvedad de que el identificador de servicio es ahora 0xE1 = 0x40 & 0xA1, es decir, la ECU acepta la solicitud y la confirma con un AND 0x40.

Lo siguiente que ocurre es:

Solicitud Servicio UDS 0xA2 (específico del fabricante)

Es decir, TechStream manda 0x02 datos, el identificador de servicio 0xA2 y el parámetro 0x06. Y la ECU empieza a transmitir tramas con 0x05 bytes de datos, la respuesta afirmativa al servicio 0xA2 (0xE2 = 0x40 & 0xA2), el parámetro 0x06 que había enviado TechStream y que parece actuar como identificador (0x06) y 3 bytes de datos: 0x07E003.

La transmisión de tramas a partir de ese momento por parte de la ECU es automática, pero al llegar a la trama 79 (0x4F), TechStream ‘refresca’ la solicitud:

Refresco de la solicitud del Servicio UDS 0xA2 (específico del fabricante)

Y así sucesivamente. Cada 79 tramas enviadas por la ECU, TechStream refresca la petición. Sorprende la frecuencia con la que la ECU envía las tramas de respuesta: 25 veces por segundo.

Y si en estas condiciones se acciona el acelerador y se modifica el régimen del motor, los dos primeros bytes (tras el 0x06) cambian (si bien el segundo byte siempre termina con 0) y TechStream muestra el correspondiente valor del par motor. El valor 0x03 final permanece inalterable durante la prueba.

Cuando abandono la pantalla de TechStream ocurre lo siguiente:

Respuesta Servicio UDS 0xA3 (específico del fabricante)

Es decir, TechStream manda 1 byte, el identificador de servicio 0xA3 y la ECU responde mandando otro byte, 0xE3, la respuesta positiva a la solicitud 0xA3. Y deja de enviar tramas.

En resumen, parece que TechStream usa tres servicios propietarios de Denso (0xA1, 0xA2 y 0xA3) para obtener el valor del par motor.

Con el servicio 0xA1 parece ‘programar’ la solicitud del valor deseado, con el servicio 0xA2 solicita el envío periódico de tramas con esos datos (en grupos de 79 y refrescando la solicitud al recibir ese número de tramas) y con el servicio 0xA3 finaliza la transmisión del envío periódico.

Perfecto. Ya tenía un método para obtener el par motor que tanto había buscado. Pero estaba un tanto desconcertado. No era lo que esperaba obtener y me obligaba a escribir un software adhoc para soportar esta nueva casuística. Además, con este método, tampoco podía usar Torque App ni ninguna otra aplicación basada en el método pregunta-respuesta.

La parte positiva es que parecía que la conversión parecía sencilla. Si 0x7E0 se correspondía con 63 Nm., parecía claro que bastaba con dividir por 32 (0x20) el valor transmitido en los dos primeros bytes de datos.

Para tratar de seguir avanzando en el entendimiento de estos servicios (0xA1, 0xA2 y 0xA3), amplié la solicitud de datos con las revoluciones del motor. Este es un dato que tengo identificado y que puedo obtener de varios modos, así que me sería relativamente sencillo identificarlo en los datos de las tramas que recibiera.

Par motor y RPM ofrecidos por la ECU 0x780 (ABS/VSC/TRC)

Al solicitar los nuevos datos, la programación que hizo TechStream fue:

Nueva solicitud Servicio UDS 0xA1 (específico del fabricante)

Donde vemos que ahora, en vez de 9 bytes transmite 11 (0x0B) y que los datos iniciales: 0x0605020B0CE10101 han pasado a ser 0x06050403040B0CE10101. Por otro lado, al invocar al servicio 0xA2, se recibía:

Nueva solicitud Servicio UDS 0xA2 (específico del fabricante)

Al poner el coche en marcha es fácil comprobar que los dos primeros bytes tras el 06 muestran las revoluciones, los dos siguientes bytes mandan el valor del par motor que teníamos identificado y finalmente llega el inalterable 03 que no se muy bien que es.

Concluí la prueba y el servicio 0xA3 hizo acto de presencia para finalizar la transmisión de datos.

Empecé a darle vueltas a la transformación que se había producido entre 0x09A10605020B0CE10101 y 0x0BA106050403040B0CE10101.

No sé muy bien como fue. Pero el hecho de que pudiera obtener las revoluciones mediante consulta a la ECU 0x7B0 con el servicio 0x21 y el PID 0x05 (devuelve 7 bytes de datos donde se pueden encontrar las revoluciones del motor, que es algo fácilmente identificable, por que normalmente es un valor entero sin factor de conversión y que está presente en el mensaje CAN ID 0x140) y que he trabajado muchos años con protocolos de comunicaciones de lo más variopintos, me hizo encontrar un cierto sentido a estas tramas.

Trama solicitud Servicio UDS 0xA1 (específico del fabricante)

El primer byte en rojo es la longitud total de la trama. Eso lo sabemos por protocolo.

El segundo byte (0xA1) es el identificador de servicio. También lo sabemos por protocolo. Pero como el servicio 0xA1 no está normalizado no sabemos el resto.

El tercer byte (0x06) parece comportarse como el identificador de la programación de datos.

El cuarto byte (0x05) parece actuar como un identificador, del cual se desean el número de datos que se indican a continuación (0x02, como es una longitud también la pongo en rojo).

Luego vienen dos bytes que indican algo sobre lo que se quiere obtener. Entiendo que 0x0B0C identifica de alguna forma al par motor.

El octavo byte (0xE1) es otro identificador, del cual se desean (noveno byte) un único dato, que se identifica por 0x01.

Si aplicamos lo mismo a la segunda trama, tenemos:

Nueva trama solicitud Servicio UDS 0xA1 (específico del fabricante)

El primer byte en rojo es la longitud total de la trama

El segundo byte (0xA1) es el identificador de servicio.

El tercer byte (0x06) es el identificador de la programación de datos.

El cuarto byte (0x05) identificador, del cual se desean el número de datos que se indican a continuación (0x04). Luego vienen cuatro bytes que indican lo que se quiere obtener. 0x0304 identifica a las revoluciones y 0x0B0C identifica -como vimos- al par motor.

Y como antes, el siguiente byte (0xE1) es otro identificador, del cual se desea (0x01) un único dato, que se identifica por 0x01.

Parece cuadrar.

¿ Podemos entonces deducir que el 0x05 que aparece en la solicitud del servicio 0xA1 es el mismo identificador que se usa para consultar con el servicio 0x21 a la ECU ?

Bastaba hacer unas pruebas. Conecté el portátil al coche y provoqué una serie de consultas periódicas a la ECU 0x7B0, servicio 0x21, PID 0x05 mientras recorría unos metros, para luego analizar los datos obtenidos.

Solicitud Servicio UDS 0x21 (ReadDataByLocalIdentifier)

De los 7 bytes que enviaba la respuesta (en el ejemplo ABCDEFG=818002BD0000E0), es fácil comprobar que el tercer y cuarto byte por la izquierda (CD=02BD en el ejemplo) eran las revoluciones del motor. El análisis del quinto byte (E=00 en el ejemplo) rápidamente se comprobó que se correspondía con el sensor del acelerador (bastaba pisar el pedal para verlo cambiar) y, finalmente, el sexto y séptimo byte (FG=00E0, en el ejemplo) tenía todas las papeletas para ser el par motor.

Como en el volcado del TechStream con el servicio 0xA2, su último byte era siempre 0, por lo que al dividir el número por 32 daba unos valores razonables en Nm. Además, cuando con el coche en marcha no se pisaba el acelerador el valor era negativo o cero, como ocurre con el par motor.

Nota: No puedo comprobarlo conectando de forma simultánea TechStream y otro programa mandando el servicio 0x21 (por ejemplo, Torque App) y ver que se obtiene lo mismo, porque al no tener el protocolo control de sesión, las sesiones se mezclan y los dos programas encuentran resultados inesperados y fallan.

En cualquier caso, no parecía haber duda. Todas las pruebas que realicé indicaban que con el PID 0x05 y el servicio 0x21 obtenía el par motor en modo pregunta-respuesta interrogando a la ECU 0x7B0.

Además, como la respuesta al servicio 0x05 también se encuentran las revoluciones del motor, además del par, es posible obtener de forma sencilla la potencia que está entregando el motor.

Así, podemos obtener el par motor como C*256+B en revoluciones por minuto. Para obtener las revoluciones por segundo basta con dividir por 60: (C*256+B)/60

Y el par motor se obtiene como (SIGNED(F)*256+G)/32.

Para obtener la potencia entregada por el motor basta multiplicar las revoluciones por el par, por tanto: (C*256+B)*(SIGNED(F)*256+G)/1920, obteniendo la potencia en vatios.

Si queremos la potencia en kw, habrá que dividir por 1.920.000 en vez de 1.920 y si preferimos la información en CV, dividiremos por 1.412.158

Añadir un comentario

El código HTML se muestra como texto y las direcciones web se transforman automáticamente.

Page top