Download diseño y realización de un sistema on board diagnostics (obd-ii)

Document related concepts
no text concepts found
Transcript
DISEÑO Y REALIZACIÓN DE UN SISTEMA
ON BOARD DIAGNOSTICS (OBD-II)
ALUMNO: OSCAR RAYO MANSILLA
DIRECTOR: JORDI SELLARÈS GONZÁLEZ
4 DE JUNIO DE 2009
2
ÍNDICE
1. Introducción
5
1.1.
Justificación del proyecto…………………………………………5
1.2.
Antecedentes…………………………………………………………..6
1.3.
Objetivos………………………………………………………………..10
1.4.
Alcance del proyecto………………………………………………11
1.5.
Descripción general del proyecto……………………………12
1.5.1.
Descripción básica del hardware……………..12
1.5.2.
Descripción básica del software………….…..13
2. Diseños realizados
14
2.1.
Metodología utilizada……………………………………………14
2.2.
Recursos utilizados………………………………………………..16
2.3.
Descripción del diseño del modem interface………….21
2.4.
Descripción del diseño del programador JDM2…......25
2.5.
Modificaciones del diseño del modem…………………..29
2.6.
Diseño de la aplicación de prueba en C++………………37
2.7.
Diseño de la aplicación de prueba en JAVA…………….40
2.8.
Diseño de la aplicación gráfica diseñada en JAVA.....46
3
3. Resultados
52
3.1.
Ámbito de utilización…………………………………………….52
3.2.
Validación de los diseños……………………………………….52
3.3.
Descripción del funcionamiento…………………………….54
3.4.
Aplicaciones del proyecto………………………………………66
4. Comentarios finales
67
4.1. Plan de trabajo……………………………………………………………67
4.2. Lista de materiales………………………………………………………68
4.3. Presupuesto………………………………………………………………..70
4.4. Objetivos logrados………………………………………………………71
4.5. Conclusiones……………………………………………………………….71
4.6. Mejoras futuras…………………………………………………………..72
5. Bibliografía
73
6. Anexo
74
4
1. Introducción
1.1. Justificación del proyecto
La motivación principal de este proyecto es llegar a poder diseñar un sistema
con el que poder diagnosticar las posibles averías de cualquier vehículo sin
tener que recurrir a los costosos servicios oficiales.
Normalmente cuando se nos avería el coche siempre tenemos que acabar
recurriendo a los talleres de reparación de los cuales dispone el fabricante de
nuestro vehículo, y aunque desconocemos cuales son los medios de los que
disponen para diagnosticar la avería, si sabemos que existe un herramienta que
conectándola al vehículo averigua el problema al instante. Esto se debe a que
estas marcas tan famosas equipan nuestros coches con sistemas electrónicos
capaces de gestionar toda la mecánica y electricidad de que dispone, sin más
ayuda que la de un modulo electrónico.
En realidad estos módulos no son más que una pequeña computadora a la cual
si se conoce su funcionamiento se puede acceder aunque su fabricante intente
taparlo, cosa que no les es posible ya que desde hace ya bastantes años están
obligados a implementar un estándar de autodiagnóstico llamado “OBD-II”, que
se hizo público a consecuencia de las grandes emisiones contaminantes a las
que estamos expuestos, implantando así un mecanismo de control de estas.
Estos módulos son el objetivo de este proyecto, ya que en el momento que
podamos comunicarnos con ellos podremos saber que le ocurre a nuestro coche
y por tanto cuando tengamos que acudir al taller nosotros sabremos, en parte,
si nos están estafando, cosa que lamentablemente a veces pasa.
5
1.2. Antecedentes
OBD (On Board Diagnostics) es un sistema de diagnóstico a bordo en vehículos
(coches y camiones). Actualmente se emplea OBD-II (Estados Unidos), EOBD
(Europa), y JOBD (Japón) estándar que aportan un control casi completo del
motor y otros dispositivos del vehículo. OBD II es la abreviatura de On Board
Diagnostics (Diagnóstico de Abordo) II, la segunda generación de los
requerimientos del equipamiento autodiagnosticable de abordo de los Estados
Unidos de América. Las características de autodiagnóstico de a bordo están
incorporadas en el hardware y el software de la computadora de abordo de un
vehículo para monitorear prácticamente todos los componentes que pueden
afectar las emisiones. Cada componente es monitoreado por una rutina de
diagnóstico para verificar si está funcionando perfectamente. Si se detecta un
problema o una falla, el sistema de OBD II ilumina una lámpara de advertencia
en el cuadro de instrumentos para avisarle al conductor.
La lámpara de advertencia normalmente lleva la inscripción "Check Engine" o
"Service Engine Soon". El sistema también guarda informaciones importantes
sobre la falla detectada para que un mecánico pueda encontrar y resolver el
problema. En los Estados Unidos de América, todos los vehículos de pasajeros y
los camiones de gasolina y combustibles alternos a partir de 1996 deben contar
con sistemas de OBD II, al igual que todos los vehículos de pasajeros y camiones
de diesel a partir de 1997, en Europa a partir del año 2001 se obliga implantar el
estándar EOBD. Además, un pequeño número de vehículos de gas fueron
equipados con sistemas de OBD II.
Por tanto la pregunta ahora es, ¿qué fue OBD I?
OBD I fue la primera regulación de OBD que obligaba a los productores a
instalar un sistema de monitoreo de algunos de los componentes controladores
de emisiones en automóviles. Obligatorios en todos los vehículos a partir de
1991, los sistemas de OBD I no eran tan efectivos porque solamente
monitoreaban algunos de los componentes relacionados con las emisiones, y no
eran calibrados para un nivel específico de emisiones.
Y además, ¿qué es EOBD?
EOBD es la abreviatura de European On Board Diagnostics (Diagnóstico de a
Bordo Europeo), la variación europea de OBD II. Una de las diferencias es que
no se monitorean las evaporaciones del depósito. Sin embargo, EOBD es un
sistema mucho más sofisticado que OBD II ya que usa "mapas" de las entradas a
6
los sensores expectadas basados en las condiciones de operación del motor, y
los componentes se adaptan al sistema calibrándose empíricamente. Esto
significa que los repuestos necesitan ser de alta calidad y específicos para el
vehículo y modelo.
Todos los estándares antes mencionados implementan varios modos de trabajo,
es decir, según la parte de información a la que queramos acceder necesitamos
utilizar un modo diferente, dentro de cada uno de ellos podemos usar un
abanico de parámetros muy amplio.
Los modos de trabajo más extendidos son los siguientes:
Modo 01: Se utiliza para determinar qué información del modulo
electrónico (ECU) está a disposición de la herramienta de exploración.
Modo 02: Muestra los llamados en este contexto “Freeze Frame Data”, es
decir, capturas puntuales de información que ha ido almacenado la ECU.
Modo 03: Lista los posibles fallos producidos en la mecánica mediante
códigos de error identificativos (DTC).
Modo 04: Se utiliza para borrar los códigos de error almacenados (DTC) y
los datos “Freeze Frame Data”.
Modo 05: Muestra los valores tomados a los sensores de oxigeno y los
resultados de los test que les ha realizado de forma autónoma la ECU.
Modo 06: Se usa para obtener los resultados de los test realizados por la
ECU al sistema de monitoreo no continuo. Existe normalmente un valor
mínimo, máximo y actual de cada uno de los test.
Modo 07: Se usa para solicitar resultados al sistema de control
permanente. Este modo lo suelen utilizar los técnicos después de una
reparación del vehículo, y después de borrar la información de
diagnóstico para ver los resultados de las pruebas después de un solo
ciclo de conducción, determinando si la reparación ha solucionado el
problema.
Sólo hay tres monitores continuos identificados: combustible, fallo de
encendido, e integridad de los componentes.
En este proyecto solo se va ha hacer uso del modo 01, 03 y 04, aunque teniendo
en cuenta que el modo 01 dispone de más de 60 PID’s diferentes, no es poco el
trabajo a desarrollar.
7
Actualmente ya existen muchas herramientas y software disponible para poder
llevar a cabo la inspección de un vehículo dotado de OBD-II. Existen muchos
tipos de herramientas distintas, pero principalmente la gran diferencia entre
ellas es si pueden o no trabajar de forma autónoma, es decir, si necesitan o no
ser ejecutadas en un ordenador personal bajo un sistema operativo.
Como ejemplo podemos encontrarnos el software llamado ScanMaster, el cual
se puede utilizar de forma completa previo pago de una pequeña cantidad de
dinero:
8
También podemos encontrar el software ScanTool.net, el cual ha sido de mucha
utilidad para este proyecto ya que en una de sus versiones ofrece el código
fuente con el que fue diseñado:
Estos programas están diseñados para trabajar junto con el microcontrolador
ELM327, es decir, necesitan de este elemento intermedio entre el PC y el
vehículo. Existen en el mercado muchos modelos de interface disponibles en el
mercado, pero todas se basan en este micro. A continuación podemos ver
algunos ejemplos:
Interface ELM327
9
Interface ELM327
Interface ELM327 con Bluetooth
En las imágenes vemos que los modelos tienen diferentes formas y diferentes
métodos de conexión, ya que en uno de los casos se realiza por “bluetooth”,
pero su funcionamiento respecto al estándar OBD-II es idéntico.
1.3. Objetivos
Este proyecto abarca una pequeña parte del complejo campo de la
autodiagnosis en la automoción, y por tanto no pretende crear un sistema que
pueda substituir a las avanzadas herramientas de las que dispone cualquier
servicio de manteniendo, ya que el estándar OBD-II, aun siendo de libre acceso,
comprende modos de trabajo de los cuales no se tiene información en este
proyecto. Mucha de la documentación que engloba al OBD-II está disponible
previo pago a las respectivas empresas que lo han diseñado y estandarizado,
como es el caso de la Sociedad Americana de Ingenieros (SAE) o la Organización
Internacional para la Estandarización (ISO). Aun no disponiendo de toda la
información deseada los objetivos de este proyecto son bastante ambiciosos y
se pueden listar como sigue:
Conseguir una comunicación estable con cualquier centralita electrónica
(ECU) de cualquier vehículo equipado con OBD-II.
Conseguir desarrollar una aplicación portable a cualquier sistema
operativo y plataforma utilizando lenguaje JAVA y la estructura de
programación “por capas”.
10
Realizar mejoras en el hardware ya existente en el mercado a partir del
cual se construirá nuestra interface.
Demostrar que con la información disponible en la red, es posible
acceder a los sistemas de control que implementan los fabricantes de
automóviles en sus vehículos.
1.4. Alcance del proyecto
El alcance de este proyecto incluye la creación de un sistema que implementa
una parte de las grandes posibilidades que ofrece el OBD-II, pudiéndose usar
como una herramienta orientativa a la hora de diagnosticar una posible avería.
Este sistema utiliza por un lado un modem interface que adecua las señales
procedentes de la centralita electrónica que se encuentra en el vehículo (ECU), a
las señales que necesita un puerto USB de cualquier ordenador. A partir de aquí,
un software de control gestionara toda la información recibida. Muchos de los
métodos de diagnostico existentes utilizan este planteamiento pero ninguno de
ellos, por lo menos oficialmente, utiliza una aplicación desarrollada en JAVA
que, por lo tanto, permita ejecutarse en la mayoría de los sistemas operativos
existentes, incluyendo el famoso Linux y además en diferentes tipos de
plataformas.
Para desarrollar el hardware se utilizaran diseños de interfaces ya existentes a
partir de los cuales se creará la que se utilizara en este proyecto, es decir, se
recapitularan los esquemas eléctricos de los que se dispongan y sobre el PCB
elegido se añadirán las posibles mejoras que pudieran aportar otros diseños.
Esta parte del trabajo también conlleva la construcción y puesta en marcha de
un programador de microcontroladores, necesario para implementar el
firmware a partir del cual el micro utilizado en la interface funcionará.
Po otro lado el software ha desarrollar tiene un papel igual o más importante,
ya que para conseguir diseñar la aplicación de control sobre el modem
interface, se necesitan realizar los primeros programas de prueba que servirán
para constatar las bases del funcionamiento de la última y definitiva aplicación
que interactuará con el modem. Este último programa constará de diferentes
apartados y opciones en un entorno visual que mostrará los resultados de una
forma fácilmente comprensible dejando así todo el proceso de cálculo en
segundo plano.
11
1.5. Descripción general del proyecto
En este proyecto como se ha ido comentado a lo largo de este documento se
pretende elaborar un sistema capaz de comunicarse con la electrónica que
gestiona cualquiera de los vehículos dotados con el estándar OBD-II, y para
llevarlo acabo ha sido necesario trabajar sobre diferentes aspectos que están
involucrados en el proceso de comunicación. Por tanto principalmente existen
dos partes importantes a diferenciar en el desarrollo de este proyecto:
La parte que engloba el hardware necesario, que nos es más que un
modem interface que hace de intérprete entre la centralita electrónica
del automóvil (ECU), y el puerto USB de un ordenador personal.
La parte que engloba el software, que se refiere a la aplicación que
funcionará en el PC y que gestionará el modem interface a partir de los
datos que se vallan recibiendo y enviando atreves del puerto USB.
1.5.1 Descripción básica del hardware (Modem interface)
Para diseñar el modem interface se recurrió a diseños ya existentes y de libre
disposición en la red, con el fin de conseguir construir una interface que
aportase las mejoras que de forma individual cada diseño implementa.
Esta interface contiene como elemento principal un microcontrolador
(PIC18F2550) que es el encargado de gestionar la comunicación entre los dos
periféricos en cuestión, es decir, recoge la información que obtiene del puerto
USB y la interpreta según el protocolo en que se esté comunicando con la ECU.
Esto se debe a que el estándar OBD-II implementa 4 posibles protocolos en su
capa física, SAEJ1850PWM, ISO 9141/14230, J1850 VPW, ISO 15765 (CAN).
Para que el micro pueda realizar estas funciones se dispone además de un
firmware que implementa las capacidades antes descritas, lo que lleva por tanto
a realizar su grabación en el micro, y además a la construcción de un
programador con el cual realizar este proceso.
Otro aspecto importante a resaltar es la necesidad de construir un cable
específico para realizar la conexión entre la ECU y la interface durante las
primeras pruebas, ya que las centralitas electrónicas disponen de un conector
exclusivo para este uso, y por tanto es muy difícil de encontrar en el mercado
material compatible.
12
1.5.2 Descripción básica del software (Interface Visual)
Para realizar la aplicación que gestionará el modem y todos los datos que serán
enviados y recibidos a través de él, se deben realizar primero unos pasos previos
para poder familiarizarse con las rutinas que deberemos utilizar. Como inicio de
este proceso se debe comenzar por averiguar cuál es el mecanismo que siguen
otras aplicaciones que ya implementan este mecanismo, y para poder hacerlo
existe una aplicación, mencionada anteriormente (ScanTool), que ofrece el
código fuente mediante lenguaje C++. A través de este código es posible extraer
las rutinas básicas con las que se realiza la comunicación con el micro y la ECU,
esto permite que nosotros mismos realicemos un programa de prueba con el
que observar cual es la estructura básica que debemos seguir.
Debido a que el objetivo es realizar el software utilizando JAVA, ya que nos
permitirá hacer portable nuestro trabajo a diferentes plataformas, el programa
anterior no es aun suficiente para poder afrontar la implementación de la
aplicación definitiva, y por tanto es necesario realizar otro programa de prueba
que contenga la misma estructura que el anterior pero con código JAVA.
Para poder llevar a cabo este objetivo es necesario utilizar la librería
“RXTXcomm” como librería nativa para realizar las comunicaciones por los
puertos serie, ya que los medios que ofrece la “API” de Java respecto a este tipo
de comunicaciones están obsoletos.
Una vez sabemos utilizar los recursos existentes de Java, se puede empezar a
desarrollar el software que nos ofrecerá las opciones y características que
queremos implementar en la aplicación definitiva.
El objetivo es que el programa pueda permitirnos, a través de una interface
visual, realizar las siguientes tareas:
Opciones para poder configurar los parámetros del puerto serie según
convenga.
Opciones para poder seleccionar los protocolos de comunicación que sean
necesarios según el vehículo.
Realizar lectura de códigos de error que pueda tener almacenados la
centralita electrónica del automóvil.
Realizar lecturas a tiempo real de los datos que aportan los diferentes
sensores del motor del vehículo, rpm, velocidad, carga del motor, etc.
Disponer de una consola de texto que monitoree el puerto serie refrescando
su contenido según el estado del tráfico de datos entre el PC y el modem
interface.
13
2. Diseños
2.1. Metodología utilizada
Durante el desarrollo de este proyecto se ha seguido en parte la filosofía de la
ingeniería inversa para alcanzar algunos de los objetivos, aunque también se
han seguido las pautas de diseños anteriores de disponibilidad libre que realizan
las mismas funciones, ya que encontrar cual es el camino que se sigue para
realizar los procesos adecuadamente en un sector tan cerrado
tecnológicamente como el del automóvil puede llegar a ser muy desesperante.
Este proyecto consta principalmente de un parte de software y otra de
hardware. En lo que hace referencia a la parte física, es decir, el hardware, se ha
utilizado un diseño de libre uso disponible en la red, a partir del cual se
construye básicamente la interface. Este aparato también se comercializa
actualmente con el nombre de ALLProAdapter por la empresa OBDDiag.net y es
una versión compatible de otra interface llamada ELM327, que originalmente es
utilizada por muchos software disponibles de pago, y del cual también se
disponen de los diseños electrónicos, los cuales también se han aprovechado
para realizar el diseño final de la circuitería del modem interface basado en el
PIC18F2550.
El primer paso ha sido comprobar que los programas que existen como
antecedentes funcionen correctamente sobre el hardware montado. De esta
manera se tiene la garantía de que el hardware (interface con PIC18F2550 con
conexión USB), funciona correctamente y de que los programas en los que nos
basaremos para la realización del proyecto son funcionales. De no ser así,
podríamos basarnos en herramientas que no serian útiles.
Una vez verificados estos puntos, el primer objetivo siempre ha sido conseguir
efectuar algún tipo de comunicación con el dispositivo (PIC18F2550) desde el
PC, ya que uno de los problemas comunes a todos los dispositivos de este tipo
es conocer la forma de comunicarse desde el nivel más básico, es decir,
constatar que el micro controlador reacciona o contesta de alguna manera
delante de un estimulo producido mediante una línea de comunicaciones
digital.
Existe un software para el diagnostico de vehículos llamado ScanTool.net, que
en una de sus versiones ofrece el código fuente, muy útil para el propósito de
este proyecto. Este programa ha sido, para este proyecto, la base para poder
iniciar la búsqueda de los pasos que se siguen a la hora de realizar una
comunicación desde el PC hasta la centralita electrónica del vehículo, atreves
del puerto de comunicaciones serie.
14
Además del software de control y el hardware a controlar hay que tener en
cuenta que los microcontroladores necesitan un “driver” para que el sistema
operativo que lo gestiona pueda controlarlo. Dado que el PIC18F2550 lo fabrica
la compañía Microchip, se pensó en que posiblemente esta proporcionara su
“driver”, y aunque así es, lo proporciona mediante la instalación de un paquete
de herramientas llamado “USB Framework package”, el cual obliga a instalar
además del driver muchas otras utilidades que en principio no son necesarias
para este caso. La empresa que ofrece libremente la información para montar la
interface, OBDDiag.net, también proporciona el driver que se necesita, en forma
de fichero INF, y es suficiente para que Windows XP o Vista la detecte sin
problemas. También se pudo averiguar que en otros sistemas operativos,
como por ejemplo Linux, este microcontrolador está contemplado y en las
mismas distribuciones de Linux ya se incorpora el “driver” necesario.
Por tanto, después de montar la interface y verificar su funcionamiento
mediante el software ya existente, se procedió a intentar una comunicación
utilizando recursos propios, es decir, sin recurrir a la funcionalidad de los
programas anteriores. Utilizando el código fuente antes mencionado, el cual se
basa en C++, se diseño un programa de prueba que conseguía comunicarse de
forma básica con el microcontrolador, pero que aportó mucha información para
realizar el proyecto.
Una vez lograda la comunicación se procedió a intentar obtener el mismo
resultado pero utilizando la plataforma Java. Básicamente el programa de
prueba en este caso tiene la misma estructura que en C++, pero utilizando los
recursos de los que dispone Java. El paso más importante aquí fue encontrar
que métodos utiliza Java para comunicarse con el puerto Serie, y aunque los
que proporciona Sun Microsystems, empresa diseñadora de esta plataforma de
programación, están obsoletos, no fue difícil encontrar otros actualizados y
perfectamente compatibles con su máquina virtual. Esta funcionalidad la
proporciona el paquete RXTXcomm junto con la instalación de la maquina
virtual de Java.
Como último objetivo se planteó realizar un software que ofreciese muchas más
funcionalidades de configuración sobre la interface, utilizando un entorno
grafico y mucho mas intuitivo. Este software engloba toda la capacidad de
comunicación de los programas anteriores pero añadiendo todo el potencial
que ofrece un entorno visual diseñado con java, lo cual dota al programa de
muchas opciones de configuración y operatibilidad sobre la interface y por tanto
sobre la centralita electrónica de cualquier vehículo, que, al fin y al cabo, es lo
que se pretende controlar.
15
2.1 Recursos utilizados
Para realizar este proyecto se han utilizado recursos de diferente tipo según si
nos referimos a la parte de software o a la de hardware, pero siempre
recurriendo como fuente principal de información a la que se dispone en la red.
Para montar la interface se recurrió a la web OBDDiag.net, donde se describen
todos los materiales, software, firmware del micro y diseño del PCB necesarios
para construirla. Paralelamente también se sacó información de la web ELM
Electronics, donde mediante los datasheet que ofrecen (ELM327DS.pdf y
ELM320DS.pdf), describen como fabricar un interface para conectarse a la
centralita electrónica (ECU) de cualquier vehículo utilizando los
microcontroladores que ellos suministran. El datasheet ELM327DS, es el
documento que expone todas las posibles ordenes y respuestas que se reciben
y envían al modem interface ELM327 y por tanto también al microcontrolador
que se utiliza en este proyecto, ya que este incorpora un firmware compatible
que contiene la misma estructura básica que el original, el ELM327.
En el siguiente listado se pueden ver todos los posibles comandos que el
ELM327 implementa, y por tanto, aunque no todos los comandos que utiliza la
interface utilizada en este proyecto:
16
17
A continuación podemos ver uno de los esquemas eléctricos que aporta ELM
Electronics, utilizando su microcontrolador más famoso, el antes mencionado
ELM327, el cual utilizan muchas interfaces del mercado, ya que es capaz de
manejar y gestionar los protocolos de comunicación más utilizados en el
estándar OBD-II:
Detalle del esquema eléctrico de un intérprete de OBD a RS232
18
Para realizar el software de control se utilizo como base de inicio el software
que proporciona la empresa ScanTool.net, la cual ofrece en una de sus
versiones su código fuente. Este código fuente se trató con el tan extendido
programa de desarrollo DEV-C++, y posteriormente también se desarrollaron
con él los primeros diseños de prueba con los se empezó la comunicación con la
interface.
Una vez se empezó a programar utilizando la plataforma JAVA y su máquina
virtual, la cual está disponible en la web de Sun Microsystems y se puede
descargar mediante el paquete JDK 6 Update 13, se pasó a utilizar otra
herramienta para programar con este lenguaje llamada Eclipse en su versión
3.2.2, y fue muy útil para desarrollar el entorno gráfico del que dispone el
software de control que se ha creado en este proyecto.
Un recurso muy importante también fue toda la información que se aporta en
RXTX.org, donde se explica el funcionamiento de la librería RXTXcomm.jar, que
es la que se utiliza en JAVA para manejar los puertos serie. En esta web se
ofrecen claros ejemplos de cómo utilizar y configurar los métodos de los que se
dispone, en especial haciendo hincapié en uno de ellos que será adjuntado en el
anexo del proyecto.
19
Por otro lado para poder entender cómo funcionan los protocolos de
comunicación que utiliza el estándar OBDII (On Borad Diagnostics II), se extrajo
mucha información de la enciclopedia libre Wikipedia, donde en uno de sus
documentos (OBD-II PIDs), explica cuales y como son los formatos de trama de
datos que utiliza este estándar, además de documentos como (ASCII), que
detalla las equivalencias del código ascii entre valores decimales y hexadecimal.
Detalle de equivalencias código ASCII
Detalle de la información aportada en el documento OBD PID’s
20
2.3. Descripción del diseño del modem interface
La primera parte del proyecto que se empezó a diseñar y construir es el modem
interface que se utiliza como aparato para interconectar el PC con la centralita
electrónica del vehículo. Este aparato consta de tres partes a diferenciar, el
cable USB que comunica el PC con el modem, el cable OBD-II que comunica la
centralita electrónica del vehículo con el modem y el modem propiamente
dicho. En los cables no hubo ningún proceso de montaje, se podían comprar ya
hechos, pero si se intento fabricar el del conector OBD-II, ya que es difícil
encontrarlos en los comercios especializados, pero se acabó desechando por su
poca durabilidad ya que después de unas pocas pruebas empezó a deteriorarse.
Cable OBD-II a DB9 hembra
Cable USB tipo A-B
En la siguiente tabla se puede apreciar la correspondencia entre los pines del
conector OBD-II y el DB9:
OBD-II 16 PIN(Macho) DB9 PIN(Hembra)
(J2850 BUS+) 2
7
(Chassis Ground) 4
1+2
(Signal Ground) 5
1+2
(CAN High J-2284) 6
3
(ISO 9141-2 K Line) 7
4
(J2850 BUS- ) 10
6
(CAN Low J-2284) 14
5
(ISO 9141-2 L Line) 15
8
(Battery Power) 16
9
21
Por tanto el trabajo importante aquí estaba en la fabricación del modem. Para
poder construirlo se acudió a una tienda especializada donde disponían de
todos los componentes electrónicos necesarios, los cuales se procedieron a
instalar en el PCB creado a partir del siguiente “layout” de doble cara:
22
Este aparato contempla la posibilidad de utilizar 4 protocolos de comunicación
distintos a nivel de capa física, ya que a lo largo de los años las diferentes
centralitas electrónicas que montan los fabricantes de vehículos así lo han
dispuesto, aunque a partir del año 2004, en Europa, la mayoría de fabricantes
empezaron a implementar solo el protocolo CAN Bus. Cualquiera de los
vehículos fabricados en EE.UU. a partir del 1996, fueron obligados a disponer de
un puerto OBD2, y en Europa a partir del año 2001, también se obligo a
implantar este tipo de conexión. La norma OBD2 comprende cuatro protocolos
de comunicación distintos:
ISO 9141/14230
J1850 PWM
J1850 VPW
ISO 15765 (CAN)
VPW (Variable Pulse Width) fue originalmente introducido por General Motors,
mientras que PWM (Pulse Width Modulation) pertenece al grupo Ford. ISO 9141
y la posterior encarnación ISO 14230 (AKA Keyword 2000) es el que la mayoría
de vehículos europeos y asiáticos utilizaban. Todos los nuevos modelos a partir
2007/2008 sólo pueden implementar el protocolo CAN Bus. La siguiente imagen
es la de un conector típico OBD2 de 16 pines instalado en cualquier vehículo:
Según el protocolo de comunicación que utilice el vehículo los pines habilitados
en el conector serán diferentes.
El protocolo ISO 9141/14230 utiliza los pines 6 y 15, el protocolo J1850 PWM
utiliza el 2 y el 10, el protocolo J1850 VPW utiliza solo el pin 2, y el protocolo ISO
15765 (CAN), el pin 6 y 14. Todos los protocolos utilizan como fuente de
alimentación los pines 4 y 5 (masa chasis y masa señal respectivamente), y el pin
16 (+12V).
23
Para entender el funcionamiento interno del modem habría que empezar por
describir las partes de las que se compone su circuitería. En la siguiente imagen
se puede observar el esquema eléctrico de la interface:
En el esquema se observa que el microcontrolador utilizado es el PIC18F2455,
pero por dificultades a la hora de adquirirlo se optó por el PIC18F2550, que es
perfectamente compatible además de aportar un poco mas de memoria. Este
micro es el encargado de gestionar todo los componentes periféricos del
circuito y de mantener la comunicación entre ellos, es decir, recibe la
información procedente del puerto USB al que está conectado, la transfiere a
los elementos del circuito que proceda y viceversa, ya que la comunicación es
bidireccional.
La parte del circuito que se ocupa de manejar el protocolo CAN BUS, son los
integrados MCP2515 y MCP2551, el integrado MC33290 maneja el protocolo
ISO9141/14230 junto con Q3, J1850 VPW está controlado por MC33390 y el par
de Mosfets (Q2 P-channel y Q1 N-channel) controlan el bus J1850PWM junto
un comparador interno del PIC18F2550 y las resistencias R4 y R5 que crean la
señal diferencial de la entrada del PWM.
24
2.4 Descripción del diseño del programador JDM2
Después de la explicación anterior es obvio deducir que el elemento más
importante aquí es el microcontrolador PIC18F2550, pero por si solo no tiene
ninguna funcionalidad a no ser que se le introduzca el firmware adecuado, por
esta razón se tuvo que construir exclusivamente para este fin un programador
compatible con el protocolo ICSP (In-Circuit Serial Programming). Este tipo de
programador, llamado JDM2, es muy famoso en la red ya que se construye con
pocos componentes e implementa el estándar ICSP que es el que ofrece la
empresa Microchip para poder introducir los firmwares en los
microcontroladores que ellos fabrican. El esquema eléctrico del programador es
de fácil adquisición en cualquier web de electrónica y se representa con el
siguiente esquema:
25
El circuito se montó en una placa de baquelita específica para realizar
prototipos, y se siguió el siguiente “layout”:
Detalle del programador JDM2 en su parte superior
Detalle del programador JDM2 en su parte inferior (lado soldadura)
26
Además del programador necesitamos poder conectarlo a una PC que disponga
de puerto serie, ya que a través de este puerto se comunicará con el software
que enviará el firmware al micro. La aplicación que se utilizó para programar el
microcontrolador fue “PICPgm Develop. Programer” que es un software gratuito
y de fácil manejo; solo hay que seleccionar el archivo que contenga el firmware
y una vez cargado cliquear en la opción de gravado.
Siguiendo el “datasheet” del microcontrolador se conectó al programador según
el siguiente detalle:
Los pines detallados en la imagen son los que utiliza el programador JDM2 y por
tanto el estándar ICSP, para comunicarse con el PIC. Vemos que además de los
pines de comunicación (MCLR, PGC y PGD), también utiliza el puerto serie para
alimentarse mediante los pines 8 y 19 para masa, y el 20 para los +5 V
necesarios. El pin 26 (PGM), no está implementado en el programador ya que
este solo se utiliza en el caso que se realice una programación en modo “LowVoltage ICSP”, y en este caso se realiza en modo “High-Voltage ICSP”.
27
La conexión realizada para proceder a programar el micro fue la siguiente:
En la imagen podemos ver como el cableado procedente del programador está
etiquetado con el nombre de los pines a los cuales debe ser conectado.
Alrededor del micro hay un cable que puentea dos pines, esto se debe a que el
microcontrolador necesita dos puntos de masa. Por otro lado vemos como el
cable procedente del puerto serie está conectado en su el respectivo conector
DB9. También vemos que el programador está dotado de un diodo “led” de
color rojo, el cual es de suma utilidad a la hora de detectar alguna anomalía en
el proceso de gravado.
28
2.5 Modificaciones del diseño del modem
Una vez se había montado la interface y se procedió a comprobar su correcto
funcionamiento con software ya existente, se observó que funcionaba
correctamente en todos los vehículos chequeados los cuales utilizaban
diferentes protocolos de comunicación, exceptuando uno de los casos que no se
obtenía respuesta de su centralita electrónica. Se sospechó que posiblemente la
interface no funcionaba correctamente y se procedió a analizar con un
osciloscopio las señales que producía respecto al protocolo J1850PWM.
Para realizar las mediciones se tuvo recurrir a un osciloscopio digital con una
capacidad de muestro de hasta 1GHz, herramienta que aseguraba el visionado
más que correcto de la señal, ya que además esta era de tipo no periódica y por
tanto con un osciloscopio analógico es prácticamente imposible capturarla.
El resultado fue el siguiente:
Resultado de la trama enviada a través del pin 2 (BUS+) del conector OBD-II
Resultado del trama enviada a través del pin 10 (BUS-) del conector OBD-II
29
Para entender el resultado de estas graficas es preciso hacer una descripción del
comportamiento de la capa física del protocolo j1850PWM. Este protocolo
dispone de dos líneas de comunicación, el BUS+ y BUS-, y se caracteriza por
utilizar la modulación del ancho de pulso (PWM) como mecanismo de
codificación de bits. El periodo de cada bit tiene una duración de 24 µs y su
estado se expresa de la siguiente forma:
Un bit=1, se representa con un estado activo de 8us dentro de un
periodo.
Un bit=0, se representa con un estado activo de 16us dentro de un
periodo.
El BUS+ está activo cuando toma el valor de 5v.
El BUS- está activo cuando toma el valor de 0v.
Por tanto se deduce que en estado de reposo el BUS+ se encuentra a 0 V y el
BUS- a 5 V, a medida que se van enviando los bits los buses van cambiando de
estado quedando siempre entre ellos con tensiones invertidas, lo que se
traduce en un mecanismo de protección contra interferencias exteriores.
Hecha esta explicación podemos darnos cuenta de que la gráfica que representa
el BUS+ desvela un pequeño problema eléctrico, ya que mientras que el BUSreacciona rápidamente colocándose a 0 V, el BUS+ nunca llega a lograr los 5 V,
quedándose siempre en los 4,4 V aproximadamente. Aunque este no sería un
problema para realizar la comunicación satisfactoriamente según las
especificaciones del protocolo SAEJ1850PWM, ya que se encuentra dentro de
los márgenes eléctricos permitidos, se procedió a modificar la electrónica que se
ocupa de implementar esta codificación.
30
En el esquema eléctrico observamos que los encargados de ajustar estas
tensiones son los Mosfets Q1 y Q2 (Q2 P-channel y Q1 N-channel) junto con las
resistencias R7 y R6. Partiendo de otro diseño disponible en la red que
implementa el mismo protocolo, se cambiaron los Mosfets por transistores PNP
y NPN (PNP->2N3906 y NPN->2N3904) y las resistencias R6 y R7 de 22kΩ por
resistencias de 2K7 Ω. Además se incorporaron resistencias de protección a las
bases de los transistores de 1KΩ.
Por tanto la modificación resultaría según el siguiente esquema:
31
Debido a que se constató que el problema no venia causado por el hardware se
empezó a investigar si podía venir dado por errores en las tramas enviadas.
Según el estándar J1850 PWM el formato de trama es el siguiente:
A partir de los documentos que explican las características de este protocolo se
averiguo que las diferentes partes de la trama tienen las siguientes funciones:
SOF: Start of frame
Header Field: Son los encargados de especificar mediante 3 bytes los
siguientes parámetros:
El primer byte especifica el modo en que se van a comunicar la
centralita con la interface, y según el documento SAE J2178 este byte
de cabecera se denomina de tipo mapeado, eso significa que cada bit
tiene un significado. Los 8 bit se identifican así:
BIT
7
6
5
4
3
2
1
0
ID
P
P
P
H
K
Y
Z
Z
Los tres más significativos (7, 6 y 5) indican la prioridad del mensaje y
puede tomar los siguientes valores:
Bit 7
Bit 6
Bit 5
0
0
0
0
0
0
1
1
0
1
0
2
0
1
1
3
1
0
0
4
1
0
1
5
1
1
0
6
1
1
1
7
Prioridad máxima
Prioridad mínima
32
El bit 4 (H) indica si la cabecera es de 3 bytes o uno:
H=0 Tres bytes H=1 Un byte
El bit 3 (K) indica si se utiliza "In-Frame response" ? :
K=0 Requerido K=1 No requerido
El bit 2 (Y) indica si la dirección usada es física o funcional:
Y=0 Funcional Y=1 Física
Los bit 0 y 1 (Z, Z) se usan junto con K e Y para definir el tipo de
mensaje:
Msg.
KKYZ
Respuesta(K)
Dirección(Y)
Tipo de mensaje
0
0000
Requerido
Funcional
“Function”
1
0001
Requerido
Funcional
“Broadcast”
2
0010
Requerido
Funcional
“Function Query”
3
0011
Requerido
Funcional
“Function Read”
4
0100
Requerido
Física
“Nodo a Nodo”
5
0101
Requerido
Física
“Reservado-MFG”
6
0110
Requerido
Física
“Reservado-SAE”
7
0111
No requerido
Física
“Reservado-MFG”
8
1000
No requerido
Funcional
“Function Command/Status”
9
1001
No requerido
Funcional
“Funcion Request/Query”
10
1010
No requerido
Funcional
“FunctionExt.Command/Status”
11
1011
No requerido
Funcional
“Function Ext. Request/Query”
12
1100
No requerido
Física
“Nodo a Nodo”
13
1101
No requerido
Física
“Reservado-MFG”
14
1110
No requerido
Física
“No disponible”
15
1111
No requerido
Física
“Reservado-MFG”
33
El segundo byte representa a la dirección de memoria elegida que
identifica a la centralita (ECU).
El tercer byte representa a la dirección de memoria elegida que
identifica a la interface o herramienta de chequeo.
Data Field: Es la información que se quiere hacer llegar al micro de la
ECU.
CRC: Chequeo de redundancia cíclica de la trama.
Conociendo ya la estructura de este protocolo se pensó que una solución al
problema sería modificar los “Header Field” ya que posiblemente no serian los
adecuados. A partir de aquí se procedió a averiguar cuáles eran los que utilizaba
nuestra interface, y esto se consiguió mediante el comando “ATH1”, el cual le
indica al modem que muestre las cabeceras (Headers) de todas las tramas,
después observando una de las tramas se vio que la cabecera utilizada por
defecto era 6A 61 F1. En el documento antes mencionado (J2178), se indicaba
que esta cabecera es generalmente la más utilizada en muchas de las centralitas
que implementan el protocolo J1850PWM, pero también hacía referencia a otra
posible cabecera a utilizar, que era E4 10 F1.
La cabecera 6A 61 F1 especifica el uso de 0x61 (01100001) como primer byte
que significa prioridad 3, tres bytes de cabecera, tipo de mensaje 2, usando
dirección funcional que es el segundo byte de la cabecera, es decir, 0x6A.
La cabecera E4 10 F1 especifica el uso de 0xE4 (11100100) como primer byte
que indica prioridad 7 (mínima), tres bytes de cabecera, tipo de mensaje 4, con
dirección física y nodo a nodo.
En principio para proceder a cambiar las cabeceras se dispone del comando
“ATSH”, pero por causas aún desconocidas no era reconocido por nuestra
interface, a pesar de que en el firmware del microcontrolador se vio que estaba
implementado, mediante un software para editar ficheros de este tipo.
Utilizando este mismo software (Hex Workshop Hex Editor), se intento
averiguar donde se encontraban los bytes que definían las cabeceras en
cuestión, y después de una búsqueda muy extensa se encontraron y
modificaron con los nuevos valores.
34
En la siguiente captura podemos observar el fragmento de código donde se
encontraban estos datos, fue un tarea laboriosa ya que este fichero solo
contiene tramas hexadecimales, y es el resultado de la compilación de un
código fuente al que no se tenía acceso.
:103C70000350E66EE66A00010028BC6F000E0120CA
:103C8000BD6FBCC0E6FFBDC0E6FF040E0024BE6FE2
:103C9000000E0120BF6FBEC0E6FFBFC0E6FFDDEC37
:103CA0001EF046E90028E96E000E0120EA6E6A0E59
:103CB000EF6E020E0024E96E000E0120EA6E610E26
:103CC000EF6E030E0024E96E000E0120EA6EF10E85
:103CD000EF6E0001030EBC6F00EBE9FF01EBEAFFA2
:103CE000BC51EF2642E9E7CFD9FF1200D9CFE6FF5A
Además de reemplazar estos bytes también se tuvo que recalcular el
“checksum” de cada línea modificada ya que este cambiaba, y el resultado fue
el siguiente:
:103C70000350E66EE66A00010028BC6F000E0120CA
:103C8000BD6FBCC0E6FFBDC0E6FF040E0024BE6FE2
:103C9000000E0120BF6FBEC0E6FFBFC0E6FFDDEC37
:103CA0001EF046E90028E96E000E0120EA6EE40EBA
:103CB000EF6E020E0024E96E000E0120EA6E100E77
:103CC000EF6E030E0024E96E000E0120EA6EF10E85
:103CD000EF6E0001030EBC6F00EBE9FF01EBEAFFA2
:103CE000BC51EF2642E9E7CFD9FF1200D9CFE6FF5A
Con el firmware ya modificado se procedió a volver reescribirlo en el
microcontrolador utilizando el programador antes descrito. Una vez preparada
la interface se volvió a intentar la comunicación con la centralita en cuestión
que nos daba problemas. El resultado fue muy interesante ya que esta vez si nos
contestó pero de la forma no esperada.
La trama enviada fue la siguiente:
E4 10 F1 01 00 0A
Y su respuesta:
C4 F1 10 7F 01 01 00 00 11 41
El dato a resaltar es el 7F 01, que indica respuesta negativa, es decir, según el
documento J2178 una respuesta negativa significa que la centralita electrónica
no dispone de información sobre el modo de trabajo requerido, que es el
“Modo 01”.
35
El estándar OBD-II contempla varios modos de trabajo, entre ellos el modo 01,
modo 03, modo 07, modo 04, modo 09, modo 22 y bastantes más. Cada uno de
ellos se ocupa de una parte de la información que puede aportar la ECU. El
modo más extendido entre todas las centralitas es el modo 01.
Cada modo además especifica sus parámetros PID (Parameter ID), en caso del
modo 01 uno puede ser el parámetro 00, que es el que se utiliza en nuestro
caso. Este parámetro sirve para decirle a la ECU que nos muestre cuales son los
PID que pueden ser utilizados en este modo de entre los PID que se encuentran
numerados del 1 al 20.
Después de consultar nuevamente el documento J2178 se averiguó que cuando
el modo 01 no está disponible en la centralita lo más probable es que se
implementara en su lugar el modo 22. Este fue el final de la investigación ya que
el modo 22 utiliza una longitud de trama más larga que el 01, cosa para la cual
nuestro hardware (el microcontrolador de la interface), no está preparado, ya
que no se implemento en su firmware esta funcionalidad.
36
2.6 Diseño de la aplicación de prueba en C++
Hasta ahora se ha explicado el diseño utilizado para crear la parte de hardware de la
que se compone el proyecto, pero anteriormente se ha hecho referencia también a la
parte de software que es la que tiene más peso y elaboración. El desarrollo del
software se empezó a elaborar a partir del software libre ScanTool.net, que en una de
sus versiones ofrece el código fuente. Utilizando la herramienta Dev-C++ y este
código, el cual se basa en C++, se localizaron los métodos y funciones que se
sospechaban eran los responsables de mantener la comunicación mediante el puerto
serie. El primer paso fue averiguar cuál era la función que realizaba las operaciones
necesarias para realizar las comunicaciones con el PIC. Tras encontrarla y incorporarla
a un programa de prueba, se procedió a compilar la función, tras esto el mismo
compilador mencionaba cuales eran las funciones y variables que llamaba este
método para poder comunicarse, y por lo tanto poder buscarlas en el código anterior
para reunirlas en el programa de prueba. Una vez que se tenían todas las funciones y
variables en el mismo fichero se podía compilar el código sin obtener errores,
averiguando así cómo se comportaba el hilo de ejecución. Después de saber cuál era
la rutina de ejecución, se sacaron todas las órdenes o variables que no son
imprescindibles por realizar una comunicación básica, dejando la clase reducida al
máximo para tener una visión simple del proceso comunicación dejando a la vista
claramente las funciones necesarias. Finalmente el programa de prueba podía
realizar la comunicación enviando órdenes al PIC (atz, 0100, etc...) obteniendo los
mensajes enviados y los recibos con una visualización por consola. A continuación
aparece el código del programa de prueba:
37
38
Este programa utiliza la librería “allegro” como base, un librería muy utilizada
para desarrollar videojuegos, y por tanto era necesario indicarle al compilador
que la cargase con “-lalleg”, aunque también necesita cargar la librería
“iostream” y la “winalleg”, necesaria si se trabaja en Windows. Las funciones
implementadas son:
main(): Arranca el hilo de ejecución.
init(): Carga las librerías y abre el puerto.
deinit(): Descarga las librerías y cierra el puerto.
read_comport(): Lee el puerto serie.
open_comport(): Abre el puerto serie.
39
close_commport(): Cierra el puerto serie.
send_command(): Escribe en el puerto serie.
2.7. Diseño de la aplicación de prueba en JAVA
El segundo diseño se centra en la elaboración de otro programa de prueba a
partir de lenguaje JAVA, ya que era necesario averiguar las capacidades de este
lenguaje a la hora de comunicarse con el puerto serie.
Como primer apunte se ha de decir que se utilizó el IDE para programar en Java
Eclipse. Para poder comunicarse con el puerto serie es necesario incluir las
librerías adecuadas en el paquete de la API de java instalada en el PC, es decir,
en el paquete autoinstalable “JDK-JRE” que ofrece gratuitamente Sun
Microsystems, ya que este no incluye librerías con esta funcionalidad.
Para este fin existe una librería llamada RXTXcomm, disponible en
www.RXTX.org, que mediante métodos nativos dota a Java de la capacidad para
comunicarse con el puerto serie y paralelo, y además puede utilizarse en
cualquier sistema operativo, haciendo hincapié en Windows, ya que aunque Sun
ofrece una API para este fin (Javacomm), no da soporte para este sistema
operativo, quedándose ya esta API obsoleta y aconsejando RXTXcomm.
Descargando y descomprimiendo el “zip” donde se incluyen los ficheros
necesarios de RXTX, debemos de copiar RXTXcomm.jar en la ruta c:\Archivos de
programa\Java\jre\lib\ext, rxtxSerial.dll y rxtxParallel.dll en c:\Archivos de
programa\Java\jre\bin. Si en lugar de Windows nos encontramos en Linux las
rutas donde situar los ficheros es diferente. En Linux debemos de copiar
RXTXcomm.jar en /usr/lib/jvm/jre/lib/ext, los archivos librxtParallel.so y
librxtxSerial.so hay que copiarlos en /usr/lib/jvm/jre/lib/i386 si el sistema es de
32 bits. Con esto el compilador ya tendrá las librerías disponibles y podremos
utilizarla en el código que programemos.
RXTX.org dispone de una web donde se explica el funcionamiento de la librería y
sus métodos, además ofrece ejemplos claros de cómo ponerla en marcha.
40
El programa de prueba que se elaboró en esta fase del proyecto fue el siguiente:
import
import
import
import
import
import
import
import
import
import
gnu.io.CommPortIdentifier;
gnu.io.NoSuchPortException;
gnu.io.PortInUseException;
gnu.io.SerialPort;
gnu.io.UnsupportedCommOperationException;
java.io.IOException;
java.io.InputStream;
java.io.OutputStream;
java.util.Date;
java.util.Enumeration;
public class Principal {
CommPortIdentifier idpuerto;
String NombrePuerto;
String ordre="atz";
String stringRebut;
SerialPort port;
OutputStream DadesEscriu;
InputStream FluxDades;
Date temps,temps2;
StringBuffer respuesta;
public Principal(){}
public void conectar(){
int j=0;
for(Enumeration i=CommPortIdentifier.getPortIdentifiers();i.hasMoreElements();){
idpuerto = (CommPortIdentifier) i.nextElement();
System.out.print(j++ +". " + idpuerto.getName()+"\n");
//Se examinan todos los puertos disponibles
}
try {
idpuerto.getPortIdentifier("COM2");
port = ( SerialPort )idpuerto.open("VisualOBD",2000);
port.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
//Se abre el puerto seleccionado
} catch (PortInUseException e) {
e.printStackTrace();
System.out.println("Puerto en uso.");
} catch (NoSuchPortException e) {
e.printStackTrace();
System.out.println(e);
} catch (UnsupportedCommOperationException e) {
e.printStackTrace();
System.out.println(e);
}
}
41
public void enviar(){
temps=new Date();
int data;
try {
DadesEscriu = port.getOutputStream();
for(int i=0;i<ordre.length();i++){
data= ordre.codePointAt(i);
System.out.println(data);
DadesEscriu.write(data);//Se escribe en el Puerto serie
if((i+1) == ordre.length()){
DadesEscriu.write(13);
//Solamente necessita el retorno de carro,
//sin el salto de linea.
}
}
System.out.println("Enviat atz:");
} catch (IOException e) {
e.printStackTrace();
System.out.println(e);
}
}
public void recibir(){
respuesta=new StringBuffer();
while((timer()-temps.getTime())<3000){}
char z;
int reb=0;
try {
FluxDades = port.getInputStream();
while(reb>-1){
reb=FluxDades.read();//Se lee el Puerto serie
z=(char) reb;
respuesta.append(z);
}
System.out.println(respuesta);//Se imprime la respuesta por consola
port.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println(e);
}
}
public static void main(String[] args) {
Principal prin=new Principal();
prin.conectar();
prin.enviar();
prin.recibir();
}
public long timer(){
temps2 = new Date();
return temps2.getTime();
}
}
42
Estructuralmente el programa se asemeja al diseño en C++, y por tanto
implementa métodos funcionalmente muy parecidos:
public static void main(): Método que inicia la ejecución del programa.
public void Conectar(): Establece la conexión con el puerto serie indicado.
public void Enviar(): Escribe la trama de datos a enviar en el puerto serie.
public void recibir(): Lee la trama de datos recibida del puerto serie.
Public long timer(): Método que realiza la espera necesaria a la respuesta
del puerto.
Tanto en JAVA como en C++, el tratamiento de las tramas digitales recibidas y
enviadas en el puerto serie se traducen en valores decimales según el código
ASCII, a partir de su equivalente en binario y posteriormente en hexadecimal.
Unos ejemplos de trama de datos y su tratamiento sería el siguiente:
Comando a enviar: ”atz”-> equivalencia código ASCII:”97,116,122”
Este comando sirve para hacer un “reset” del micro.
Se le añade a la trama el retorno de carro para indicar fin de trama:
“atz\r”->código ASCII:”97,116,122,13” y el método write() de la clase
SerialPort la envía al puerto serie.
Trama recibida del puerto serie atreves del método read() de la clase
SerialPort:
97,116,122,13,10,69,76,77,51,50,55,32,118,49,46,49,32,99,111,109,112,
97,116,105,98,108,101,13,10,62,-1
Equivalencia de la trama según el código ASCII: atz
ELM327 v1.1 compatible
El último número (-1), indica que no se está recibiendo ningún dato, y
sirve como referencia para saber que la trama ha finalizado, además el
micro marca el fin de la trama con el numero 62 ( equivalente a “>”).
43
Comando a enviar: ”01 0C”-> equivalencia código ASCII:” 48,49,48,67”
Este comando sirve para pedirle a la centralita electrónica del vehículo
(ECU), a cuantas revoluciones por minuto (rpm), está girando el motor.
Se le añade a la trama el retorno de carro para indicar fin de trama:
“01 0C\r”->código ASCII:” 48,49,48,67,13” y el método write() de la clase
SerialPort la envía al puerto serie.
Posteriormente cuando la interface la ha recibido esta la envía a la ECU
según el siguiente formato de trama si el protocolo a utilizar es J1850
PWM:
SOF: Start Of Frame
Header Field: 6A 61 F1
Data Field: 01 0C (Comando que se ha especificado antes)
CRC: 0A
EOF: End Of Frame
La ECU contesta con la siguiente trama y la interface la recoge para
enviarla al puerto serie:
6A F1 61 41 0C 0B 88 0A -> Respuesta ECU
01 0C
-> Respuesta
6A F1 61 41 0C 0B 88 0A
Interface
Se puede observar que la interface le añade a la trama el comando
solicitado
Trama recibida del puerto serie atreves del método read() de la clase
SerialPort:
48,49,48,67,13,10,54,65,70,49,54,49,52,49,48,67,48,66,56,56,48,65,13,1
0,62,-1
44
Por tanto en la respuesta obtenida podemos diferenciar que:
01 0C: Comando requerido
6A F1 61: Cabecera de la trama(Especifica direcciones de memoria,
prioridades, tipo de conexión, etc..)
41 0C: Confirmación de que se ha contestado al comando requerido
sumando 40 a 01, quedando 41 0C.
0B 88: El dato que interesa para calcular las rpm. Según el documento
OBD Pid’s anteriormente mencionado, si pasamos a decimal estos
valores quedando en 11 y 136, y aplicamos esta fórmula
(( A ⋅ 256) + B ) = (11 ⋅ 256) + 136 = 738 , obtenemos las revoluciones por
4
4
minuto del motor a tiempo real.
0A: Chequeo de redundancia cíclica de la trama (CRC).
45
2.5. Diseño de la aplicación grafica diseñada en JAVA
El diseño final y definitivo de este proyecto consistía en realizar un software
multiplataforma diseñado mediante la conocida estructura de programación
“por capas”, para poder unir de forma correcta toda la capacidad de
comunicación que se había conseguido en los programas de prueba anteriores
con la necesidad de ofrecer muchas más opciones, entorno grafico y el potencial
que aporta un entorno visual diseñado con JAVA, lo cual dota al programa de
muchas posibilidades de configuración y operatibilidad sobre la interface y por
tanto sobre la centralita electrónica de cualquier vehículo.
Este software intenta ser compatible con cualquier plataforma que disponga de
una conexión USB o RS-232, de ahí su implementación mediante JAVA, pero
debido a que para realizar las comunicaciones con dichos puertos se ha utilizado
un librería nativa (RXTXcomm.jar), es posible que existan algunas
incompatibilidades de un plataforma a otra, cosa que se debería consultar en la
web de RXTXcomm.
Básicamente el programa ofrece cinco apartados bien diferenciados:
La pantalla principal de inicio: Es la ventana que vemos cuando inicia el
programa, en ella realizamos y vemos las operaciones principales, como
son realizar la conexión/desconexión con la interface y siempre viendo
en una consola de texto los datos que se están enviando y recibiendo a
tiempo real.
La opción de configuración del puerto: En esta sección del programa
podemos configurar todos los parámetros necesarios del puerto serie,
para poder realizar una conexión.
La opción de selección del protocolo de comunicación: Esta funcionalidad
del programa permite que el usuario pueda elegir manualmente el
protocolo con el que se quiere comunicar con la ECU de su vehículo.
La opción de Lectura de códigos de error: Esta opción ofrece la posibilidad
de poder averiguar si nuestro vehículo ha sufrido o sufre algún fallo
técnico, a través de la obtención de un código identificativo que
especifica la avería y que proporciona la ECU.
La opción de mediciones a tiempo real: Esta parte del programa
proporciona información de los diferentes sensores de los que dispone
el motor de nuestro vehículo, mostrando datos como la temperatura,
velocidad, revoluciones por minuto, cantidad de aire absorbido, etc.…
46
Para realizar el software se utilizó la estructura de programación por capas:
capa de datos, capa de dominio y capa de presentación. Cada capa tiene una
función dentro del programa y una serie de clases que cumplen con la función
que se les ha asignado. A continuación se explica la función y clases que
contiene cada capa:
1. Capa de Datos: Es la encargada de gestionar todas las tramas de datos
que se intercambian la computadora y la interface. Su objetivo es
recoger ya sean datos recibidos o enviados, adecuarlos y tratarlos para
poder o bien mandárselos a la interface a través del puerto serie o
recibirlos y mandárselos a las capas superiores. En esta capa podemos
encontrar las siguientes clases:
Clase Conexión: Es la encargada de encapsular todos los atributos
de los que se compone una conexión que se realiza atreves del
puerto serie: velocidad, dataBits, stopBits, paridad,
nombrePuerto, protocolo.
Clase ControladorConexión: Contiene todos los métodos
necesarios para realizar la conexión, contiene mucha de la
estructura conseguida en los programas de prueba.
Clase lecturaTXTErrores: Clase que permite acceder a archivos de
tipo “TXT”, con el objetivo de que el programa disponga de una
memoria permanente. Alguna de las funcionalidades de las que
dispone el software necesita cotejar la información que recibe con
la que dispone para poder reconocerla, como es el caso de la
lectura de los códigos de error.
Clase MuestraIDs: Captura los identificadores de trama del
protocolo CAN Bus.
2. Capa de Dominio: Es la encargada de hacer de intermediario entre la
capa de datos y la inmediatamente superior a la de dominio, que en este
caso es la de presentación. Ofrece la capacidad de trabajo de la capa de
datos, de una forma mucho más accesible para sus capas superiores. En
esta capa encontramos la clase ControladorDominioConexión, la cual
contiene todos los métodos necesarios para manejar todas las clases
que se encuentran en la capa de datos.
47
Capa de Presentación: Esta capa se encarga de gestionar toda la parte
visual del programa y contiene todas las clases y controladores
necesarios para poder llevar a cabo esta tarea. Concretamente estas son
las clases que contiene:
ControladorPrincipal y VistaPrincipal: Gestionan la carga de todas las
demás clases de la capa de presentación y proporcionan las operaciones
básicas del programa, como son poder iniciar o detener un conexión con
la interface y seleccionar las diferentes opciones del programa.
ControladorErrores y VistaCodigosError: Estas clases se ocupan de
gestionar la presentación en pantalla de los códigos de error
proporcionados por la ECU.
ControladorMediciones y VistaMediciones: Se ocupan de gestionar la
presentación en pantalla de los datos referentes a valores que
proporcionan los sensores del vehículo, tales como temperatura,
velocidad, revoluciones por minuto, cantidad de aire absorbido, etc.…
ControladorProtocolo y VistaProtocolo: Gestionan la presentación en
pantalla de las opciones disponibles a la hora de seleccionar un
protocolo de comunicación.
ControladorPSerie y VistaConfiguración: Presentan en pantalla todas las
opciones que requiere el puerto serie para ser configurado. Además
permiten realizar una búsqueda de estos.
Por lo extenso del código de este último programa, se incorporará al final del
proyecto como documento adjunto.
En esta aplicación la clase más importante y difícil de desarrollar es la clase
ControladorConexion, ya que es la que capacita al software de la capacidad de
utilizar varios hilos de ejecución.
Esta clase implementa la interface “Runnable” con su respectivo método
“Run()”, el cual está en permanente escucha a los mensajes que se envían desde
el puerto serie, y por tanto permite liberar al hilo principal para poder realizar
otras funciones simultáneamente.
Otra de las clases que implementa un nuevo hilo de ejecución es la clase
ControladorMediciones, la cual se encarga de mostrar los datos de la lectura a
tiempo real de los diferentes sensores de los que dispone la centralita en el
vehículo.
Por tanto en la aplicación trabajan 3 hilos de ejecución:
Hilo principal: Se mantiene a la espera para realizar las funciones que
reclame el usuario.
Hilo de la clase ControladorConexion: Escucha permanentemente el
puerto serie consiguiendo así no perder ningún posible dato y una
velocidad de respuesta mucho más alta.
Hilo de la clase ControladorMediciones: Refresca constantemente en
pantalla los datos que va recibiendo el método run() de la clase
ControladorConexión.
48
Cuando se procedió a probar el software sobre diferentes sistemas operativos
con la intención de asegurar su funcionalidad, ventaja que tiene JAVA sobre
otros lenguajes ya que utiliza una maquina virtual, se observó que en Windows
funcionaba correctamente ya que sobre este se había realizado la
programación, pero sobre Linux se obtuvo un resultado inesperado.
Se observó que en Linux el programa arrancaba y funcionaba de forma correcta,
pero en el momento que se procedía a desconectarlo del puerto serie el
programa quedaba totalmente bloqueado.
Después de muchas pruebas se averiguó que las librerías nativas
“RXTXcomm.jar” que utiliza esta aplicación se comportaban de diferente forma
según el sistema operativo en el que estuviéramos trabajando. El problema se
encontraba en el método run() de la clase ControladorConexión(), ya que este
utiliza la clase SerialPort constantemente para escuchar el puerto serie.
Observando el siguiente fragmento de código podemos hacernos una idea de la
situación:
public void run(){
boolean datos=false;
String tramaRecibida;
Thread thisThread = Thread.currentThread();
while(hilo == thisThread){
char z;
int longitudTrama=0;
int reb=0;
try {
datosRecibidos = port.getInputStream();
while((reb=datosRecibidos.read())>-1){
z=(char) reb;
if(reb==62){
break;
}
if(reb!=-1){
tramaRecibidaInicial.append(z);
}
}
DestruirHilo=true;
} catch (IOException e1) {
estado("No response.");
}
Vemos que la línea subrayada, “datosRecibidos.read()”, es la orden que se
encarga de acceder al puerto y cuando el hilo de ejecución llega a ella en
Windows la lee una vez y sigue su transcurso dentro del método “run()” hasta el
siguiente ciclo de bucle donde lo volvería a leer, pero en Linux no sucede los
mismo, el hilo de ejecución se detiene en esta línea esperando un nuevo
mensaje del puerto y por tanto bloqueando su posible cierre desde el hilo
principal, es decir, como el hilo que se ejecuta en “run()” nunca libera al objeto
“port”, cuando accedemos al mismo objeto desde el hilo principal de la clase
este provoca un bloqueo de la aplicación ya que nunca tendrá permiso para
cerrarlo. Esto se solucionó enviando un mensaje cualquiera al puerto y
cambiando en el mismo instante la condición del bucle “while”(hilo=null), para
que el hilo de run() saliese de su estado de escucha y acabara extinguiéndose ya
que la condición del bucle ya no se cumplía.
49
Como aporte final a esta aplicación se procedió a empaquetarla en un archivo
“.jar”, lo que facilita mucho su puesta en marcha y portabilidad a cualquier otra
plataforma o sistema operativo. Pero uno de los inconvenientes que presentaba
esta aplicación era que para poder comunicarse con los puertos de
comunicación necesitaba la librería nativa “RXTXcomm”, y por tanto, esta no
viene incluida en las librerías de la maquina virtual que se instala por defecto, lo
que obliga a tener que instalarla manualmente.
Para cualquier persona que esté familiarizada con la programación no resulta
ser un problema, pero si para alguien que solo quiera hacer unas cuantas
pruebas.
La solución fue crear una carpeta donde se introduciría el archivo “JAR”, los
archivos adjuntos necesarios como los “JPG” y “TXT”, y otra carpeta donde
incluiríamos la librería nativa “RXTXcomm”. Además de lo anterior se crearon
dos archivos ejecutables (RunLinux.sh y RunWindows.bat), que se utilizan según
en el sistema operativo en el que estemos.
La carpeta se llama VisualOBDJar y contiene los siguientes archivos:
VisualOBD.jar: Archivo comprimido que contiene todo el código de la
aplicación.
RunLinux.sh: Archivo ejecutable para Linux.
RunWindows.bat: Archivo ejecutable para Windows.
VisualOBD4_1 y AboutVisualOBD: Archivos de tipo “JPG”.
CodigodErrores.txt: Archivo de texto utilizado como base de datos.
Leeme.txt: Archivo de texto que contiene una breve explicación de cómo
arrancar el software.
lib: Carpeta que contiene la librería nativa “RXTXcomm” con los
respectivos archivos “rxtxParallel.dll”, “rxtxSerial.dll”, “librxtxSerial.so”, y
“librxtxParallel.so” necesarios para realizar su carga en el sistema
operativo través de la máquina virtual.
50
Para poder realizar la carga de la librería nativa correctamente se tuvo que
modificar el archivo MANIFEST que contiene el paquete VisualOBD.jar
quedando de la siguiente forma:
Y a los archivos RunWindows.bat y RunLinux.sh se les introdujo los siguientes
comandos:
51
3. Resultados
3.1. Ámbito de utilización
Este proyecto se basa en un sistema para el chequeo del estado técnico de
cualquiera de los vehículos que actualmente se comercializan o se han
comercializado desde 1996 en EEUU y 2001 en Europa, y por tanto su ámbito de
utilización se puede extender bastante, incluso como pequeña herramienta para
los profesionales del sector o para cualquier persona que disponga de un
vehículo dotado con el sistema On Board Diagnostics-II (OBD-II), que tenga
interés en indagar sobre el estado de su automóvil.
Esta herramienta podría ser muy útil, por ejemplo, para un pequeño taller
mecánico donde su presupuesto para adquirir un aparato de diagnostico es
reducido, y utilizando el sistema descrito aquí podría solucionarle muchos
problemas sin tener que hacer un gran desembolso económico.
Actualmente todos los vehículos de cualquiera de los fabricantes, están
obligados por ley a implementar este estándar, como un mecanismo que facilite
a todo el sector del mantenimiento, el rápido diagnostico de las averías, lo que
garantiza que el sistema que se ha desarrollado será útil en un ámbito muy
extenso.
También hay que decir que es necesario que el usuario tenga un mínimo de
conocimientos sobre la materia para comprender los resultados que muestra el
programa de diagnostico durante el chequeo del vehículo, lo que quizás hace
que se reduzca en parte el ámbito de uso.
Por otro lado en este proyecto se profundiza bastante en el tratamiento de las
comunicaciones realizadas a través del puerto serie utilizando los lenguajes C++
y JAVA, información que puede ser muy útil en todo aquel ámbito que necesite
de esta conexión.
3.2. Validación de los diseños
Una vez terminado el proceso de diseño, el siguiente paso ha sido validar el
proyecto realizando pruebas en diferentes vehículos de diferentes marcas,
teniendo la certeza de que estos estaban equipados con estándar OBD-II. Cada
modelo chequeado disponía de un protocolo de comunicación diferente a nivel
de capa física, con lo que se conseguía comprobar que todos los protocolos que
implementa la interface funcionan.
52
Las pruebas realizadas se realizaron con éxito en los siguientes coches:
Citroen C3 1.4 HDI:
Fabricado en 2004
Equipado con OBD-II y implementa el protocolo ISO 14230-4 KWP2000
Seat Toledo 1.9 TDI:
Fabricado en 2001
Equipado con OBD-II y implementa el protocolo ISO 9141-2
VolksWagen Golf 1.9 TDI:
Fabricado en 2002
Equipado con OBD-II y implementa el protocolo ISO 9141-2
Audi A3 1.9 TDI:
Fabricado en 2001
Equipado con OBD-II y implementa el protocolo ISO 9141-2
Toyota Prius (Motor hibrido)
Fabricado en 2006
Equipado con OBD-II y implementa el protocolo ISO 15765-4 CAN BUS
Seat Leon 1.9 TDI:
Fabricado en 2008
Equipado con OBD-II y implementa el protocolo ISO 15765-4 CAN BUS
Ford Focus TDDi:
Fabricado en 2002
Equipado con OBD-II y implementa el protocolo SAE J1850PWM
Opel Astra 1.6i:
Fabricado en 2001
Equipado con OBD-II y implementa el protocolo SAE J1850VPW
Opel Astra 2.0 DTI:
Fabricado en 2003
Equipado con OBD-II y implementa el protocolo ISO 9141-2
Ford Escort 1.8 TD:
Fabricado en 1998, equipado con OBD-II, implementa el protocolo SAE
J1850PWM, pero no es compatible con nuestro trabajo por incorporar un
modo de trabajo (Modo 22) no contemplado en el proyecto por su poco
uso.
53
3.3. Descripción del funcionamiento
A continuación se describen los pasos a seguir para poner en marcha el sistema
a la hora hacer un chequeo sobre un vehículo. El primer paso es localizar en el
coche el conector OBD-II, ya que cada modelo lo puede incorporar en un lugar
diferente.
Una vez localizado debemos conectar nuestro cable OBD-II el cual proviene de
nuestra interface. Disponiendo de un ordenador portátil o de uno de sobremesa
cercano al lugar donde estemos trabajando, conectamos la interface al puerto
USB. El montaje sería el siguiente si se realiza en un Citroen C3 del año 2004, ya
que con respecto a otro modelo puede variar la localización del conector OBD-II.
54
A partir de aquí podemos arrancar nuestro PC, una vez cargado el sistema
operativo entramos dentro de la carpeta que contiene el software del proyecto
llamada VisualOBDJar. En esta carpeta encontramos dos archivos ejecutables, el
RunLinux.sh y RunWindows.bat, los cuales serán utilizamos según en el sistema
operativo en que estemos trabajando.
En este caso arrancamos RunWindows.bat y nos aparecerá el siguiente entorno
visual:
55
El siguiente paso es realizar la conexión, y para ello debemos arrancar el motor
del coche, seleccionar los parámetros de configuración del puerto serie
(Options->Serial Port Configuration):
Cliqueando en “Search for available ports” obtendremos un lista de los puertos
que tenemos disponibles. Posteriormente en la parte superior seleccionaremos
el puerto en el que esté conectada la interface, y modificaremos los demás
parámetros según sea necesario. Después solo queda cliquear en “Apply” para
confirmar los cambios.
56
Ahora debemos seleccionar el protocolo de comunicación (Options>Communication protocol configuration). En el caso de no conocer el protocolo
que se va utilizar, el sistema lo detectará automáticamente:
Vemos que podemos seleccionar el protocolo de comunicación o dejar
seleccionada la opción “Automatic detection of communication protocol”, para
que sea autodetectado. Esta sección también nos proporciona la posibilidad de
modificar las cabeceras de las tramas que se van a enviar. Cada opción (Priority,
ECU Addres, Tool address) se corresponde con un byte dentro de la trama, esto
aumenta las posibilidades de éxito en el momento de conectarse con la ECU, ya
que aunque muchos modelos de centralitas se comunican de la misma forma,
necesitan que se les especifique este parámetro y por tanto modificar el que se
envía por defecto.
57
El siguiente paso es iniciar la conexión cliqueando en “Connect”, si el proceso se ha
realizado con éxito obtendremos la siguiente respuesta:
Observamos que en la consola de texto nos aparecen los comandos
“0100”->”41 00 98 1B 00 11” y “0100”->”86 F1 10 41 00 98 1B 00 11”, lo que
quiere decir que se ha realizado la conexión correctamente y que la ECU
contestó adecuadamente informando de los PID’s (Parameter ID’s) que tiene
disponibles para ser inspeccionados.
58
En caso de que la conexión con la ECU sea fallida este sería el resultado:
Observamos que en la consola de texto se nos comunica que en los comandos
“0100”->”Unable to connect”, no hubo respuesta ya que la captura se trata de
un simple prueba sin conexión a la ECU.
Los demás comandos “AT”, son contestados correctamente porque son datos
procedentes únicamente de la interface, es decir, solo incumben a parámetros
que tienen que ver con el microcontrolador de la interface sin tener en cuenta a
la ECU.
59
Ahora podemos ver un ejemplo de la información que nos daría el programa en
el caso de que el vehículo tuviera almacenados 4 códigos de error indicando así
que se han producido estos fallos técnicos. Para acceder a esta información solo
hay que cliquear en “Read error codes”, estando por supuesto el sistema
correctamente conectado a la ECU:
Este es un ejemplo simulado por eso en la consola de texto seguimos
obteniendo un resultado negativo cuando se envían los comandos
“0100”,”0101” y “03”. El programa nos indica si la luz de chequeo MIL
(Malfunction Indicator Light) situada en el cuadro de mandos, está encendida y
cuantos códigos de error tiene almacenados la ECU. Además se detallan cuales
son los códigos de error y una descripción del significado de estos.
Si además quisiéramos borrar estas fallas almacenadas en la memoria de la
centralita, tendríamos que cliquear en “Clear error codes”, y nos aparecería una
advertencia de seguridad que nos avisaría del paso que vamos a realizar, ya que
si borramos esta información accidentalmente no la podríamos recuperarla.
60
Otra funcionalidad del programa es la lectura de datos a tiempo real de los
sensores que tiene instalados el motor. La cantidad de información que
podemos obtener, depende de la ECU, ya que según el modelo de esta, puede
ofrecer más o menos datos de los sensores que gestiona en la mecánica del
motor. Un ejemplo sería el siguiente:
En la imagen se observan por un lado los datos que se van recibiendo en
formato numérico, es decir, carga del motor, temperatura del refrigerante,
revoluciones por minuto, velocidad actual, temperatura y cantidad de aire
absorbido MAF (Mass Air Flow), y en la consola de texto se observan los mismos
datos pero en formato hexadecimal, que es como la interface los va enviando a
nuestro software. Esta última característica nos permite localizar rápidamente
cualquier incidencia en el proceso de transferencia de datos o en el
procesamiento de la centralita electrónica ya que de no ser así sería mucho más
difícil detectar el problema.
61
En esta captura se observan más datos aportados por la ECU:
Se puede observar que se nos proporciona información sobre la cantidad de
kilómetros que hemos circulado con algún problema técnico indicado con la luz
de chequeo MIL (Malfunction Indicator Lamp) encendida.
Otro dato importante es el de la presión que hay en el circuito de inyección de
combustible en estado de motor a ralentí, proporcionada por la bomba
inyectora a los cilindros. Parece un dato desproporcionado ya que 22070Kpa
equivalen a 220,7 bar de presión, pero teniendo en cuenta que la tecnología hoy
utilizada puede llegar hasta los 2000 bar en el régimen de motor más alto, es
bastante aceptable.
62
En esta otra imagen se observan las mismas lecturas pero realizadas a un
régimen de motor más alto, se ha pasado de estar en 751rpm a 1613.
Observamos que la temperatura de refrigerante es menor que en la captura
anterior, esto se debe a que se tomaron los datos anteriormente. Lo importante
a señalar es que además de ver cambios en la rpm, también los hay en “MAF
Air Flow Rate” ya que el motor necesita absorber más aire. En “Calculated
engine load value” los datos también varían, este dato nos informa sobre la
carga a la que está sometido el motor en ese preciso momento con respecto a la
carga total que podría soportar, y aunque lo lógico sería que aumentase a mas
revoluciones el resultado es todo lo contrario, disminuye. Esto se debe a que
aunque el motor gira a más vueltas, este no debe ejercer ningún esfuerzo ya
que se encuentra parado y por tanto no encuentra ninguna fuerza contraria al
sentido de giro.
63
Una imagen muy determinante para constatar que las lecturas son correctas es
la siguiente:
Observamos que el cuenta revoluciones del panel de instrumentos del vehículo,
está marcando alrededor de las 1500 rpm, dato que se confirma observando la
pantalla del ordenador portátil donde aparece una lectura de 1510 rpm. Se
observa también que hay coincidencia en la velocidad, que es de 0 km/h ya que
nos encontrábamos parados.
64
Hasta ahora el software se ha presentado funcionando bajo sistema operativo
Windows XP, pero también es capaz de funcionar en otros sistemas operativos,
como por ejemplo Linux. En la siguiente imagen podemos apreciarlo:
En la imagen vemos funcionar el software diseñado en este proyecto bajo
sistema operativo Linux, concretamente en la distribución Ubuntu en su versión
8.04, con la maquina virtual de JAVA instalada.
Respecto a Linux hay que hacer una pequeña aclaración sobre la detección de
los puertos serie. En este sistema operativo los puertos serie se suelen
identificar con nombres como “ttyS0”, “ttyACM0” o “ttyUSB0”, a diferencia de
los COM1, COM2, COM3, etc., de Windows y además se ubican en un carpeta
llamada “/dev”. Por tanto cuando arrancamos el programa en Linux
seleccionamos una de estas opciones y no tendremos ningún problema si
nuestra interface se conecta directamente al puerto RS-232, ya que la detectará
como /dev/ttySO, que es la referencia de dispositivo que siempre es detectada
de forma correcta.
65
Muchas de las interface compatibles utilizan el puerto USB, como es nuestro
caso, y en Windows las detecta también como puerto COM y no encontramos
problemas, pero en Linux estas interface son detectadas como /dev/ttyACM0, y
aquí es donde podemos tener impedimentos, porque este error viene causado
por la librería nativa RXTXcomm, la cual no contempla este tipo de puertos.
Para poder solucionarlo podemos ejecutar la siguiente línea de comando en un
terminal de Linux, con la intención de hacer un linkado simbólico de la interface
“/dev/ttyACM0” con una referencia que si reconozca la librería, por ejemplo
“/dev/ttyS0”:
>ln -sf /dev/ttyS0 /dev/ttyACM0
Después de ejecutar este comando podremos seleccionar el dispositivo “ttyS0”
como si se tratase de “ttyACM0”, y la comunicación se realizará sin ningún tipo
de problema.
3.4. Aplicaciones del proyecto
Como se ha ido viendo durante todo el desarrollo de la memoria, las
aplicaciones de este sistema de diagnosis son bastante obvias. El sistema
diseñado es aplicable al chequeo del estado técnico de cualquiera de los
vehículos que actualmente se comercializan o se han comercializado desde el
año 1996 en EEUU y 2001 en Europa. Es a partir de estas fechas cuando se
obligó a los fabricantes a implantar el estándar OBD-II, y aunque anteriormente
los vehículos también estaban equipados con un sistema de este tipo
precisamente llamado OBD, es decir, el mismo sistema pero en su primera
versión, este no estaba estandarizado entre todos los fabricantes y por tanto
cada uno de ellos implementaba sus propios mecanismos para realizar la auto
diagnosis de sus modelos, lo que lleva a descartar este proyecto en aplicaciones
referentes a este tipo de vehículos.
Por tanto como ejemplo este sistema se puede aplicar en las labores de
manteniendo de cualquier profesional del sector que se encuentre con uno de
los vehículos mencionados anteriormente averiado y que después de su
reparación verifique con esta herramienta si el problema se ha subsanado
correctamente asegurándose de que la ECU no devuelve ningún código de error
o de que el sensor en cuestión ofrece unas lecturas correctas según
especificaciones del fabricante.
66
Otro ejemplo podría ser el que se da normalmente cuando cualquier poseedor
de un vehículo con OBD-II observa que en el cuadro de instrumentos se le ha
encendido una luz llamada “Check Engine” y se pregunta el porqué de este fallo.
En lugar de recurrir al servicio de mantenimiento inmediatamente podemos
proceder a realizar una lectura de “Codigos de Error” obteniendo el posible
código que nos describirá brevemente a que se debe el problema.
Otra de las facetas en las que se puede incluir este sistema es entre aquellas
personas que por puro placer o interés quieren conectarse con su automóvil
para observar los datos que la centralita electrónica les puede ofrecer, con fines
de simple curiosidad.
Como vemos esta herramienta, aunque no está dotada de todo el potencial
posible que ofrece el OBD-II, si aporta una funcionalidad muy útil entre los
posibles usuarios interesados por la mecánica.
4. Comentarios finales
4.1 Plan de trabajo
El plan de trabajo de este proyecto se ha ido desarrollando según los siguientes
puntos:
1. Conseguir todos los componentes y materiales electrónicos necesarios
para construir el modem interface y el programador de PICs.
2. Montar la interface y el programador según el PCB y esquemas eléctricos
especificados en el proyecto.
3. Montar un cable OBD-II para ser utilizado provisionalmente durante las
primeras pruebas.
4. Comprobar el correcto funcionamiento de la interface y familiarizarse
con los comandos “AT” que permiten configurar el microcontrolador
PIC18F2550.
5. Instalar en un ordenador portátil los sistemas operativos WindowsXP y
Linux Ubuntu 8.04 con la respectiva maquina virtual de JAVA.
6. Instalar software compatible con la interface para comprobar su correcto
funcionamiento.
67
7. Conectar la interface a diferentes vehículos para asegurar su
funcionalidad.
8. Programar aplicaciones de prueba en C++ y Java.
9. Programar aplicación utilizando JAVA con un entorno visual lo
suficientemente potente que permita gobernar la interface y la
centralita electrónica de forma estable.
10. Verificar el correcto funcionamiento de la aplicación sobre la interface
mediante pruebas.
11. Verificar el correcto funcionamiento de la aplicación sobre la centralita
electrónica de los vehículos mediante pruebas.
12. Verificar el correcto funcionamiento de la aplicación en diferentes
sistemas operativos, Windows y Linux.
4.2 Listado de materiales
Listado de los materiales para montar el modem interface:
J1
Conector USB tipo B
J2
Conector DB-9 Macho
Q1,Q3
Transistor 2N7000
Q2
Transistor BS250/VP2106
IC1
PIC18F2455
IC2
MC33290
IC3
MC33390/MC33990
IC4
MCP2551/PCA82C250
IC5
MCP2515
X1
Cristal, 16.000Mhz
X2
Cristal, 20.000Mhz
D1
LED verde 5 mm
D2
LED Amarillo 5mm
68
D3
LED rojo 5mm
D4,D5
Diodo 1N4148
R1,R4,R5,R8
10K Ohm
R2,R3
330 Ohm
R6,R7
22K Ohm
R9,R10
510 Ohm
R11,R12
100 Ohm
C1,C2,C4,C5
15pF
C3,C8,C9
0.1uF
C6
0.47uF
C10,C11
560pF
C7
10uF 16V
IC Socket
Socket para PIC18F2550 28 pin
Listado de materiales para montar el programador:
J1
Conector DB9 Hembra
D1, D2, D6, D7
Diodo 1N4149
D4
Diodo Zener 6.2 V
D5
Diodo Zener 5.1 V
D3
LED Rojo 5 mm
Q1, Q2
Transistor 2N3904
C1, C4
33pF
C2
100µF 16V
C3
22µF 6.3V
R3
100Ω
R1
1.5KΩ
R2
10KΩ
69
Listado se software y hardware utilizado durante el proyecto:
Bloodshed Dev-C++: Programa utilizado para desarrollo de software en
C++.
Eclipse 3.2: Programa utilizado principalmente para desarrollo de
software en JAVA.
ScanTool: Programa de diagnostico OBD-II basado en microcontrolador
ELM327.
Hex Workshop: Programa para la edición de archivos en formato
hexadecimal.
PICPgm Programer: Utilizado para el gravado del firmware en el
PIC18F2550.
GerbMagic: Programa utilizado para la edición y diseño del circuito
electrónico del modem interface.
JDK 6 Update 13: Paquete instalador de la máquina virtual de JAVA.
PC de sobremesa con WindowsXP Home Edition y Linux Ubuntu 8.04
instalados para realizar la programación.
Ordenador portátil con WindowsXP Home Edition Y Linux Ubuntu 8.04
instalados para realizar las pruebas en los vehículos.
4.3 Presupuesto
La tabla siguiente especifica el presupuesto detallado en euros:
Referencia
Cantidad
Precio unitario
Precio total
Material montaje interface
1
20
20
Material montaje programador
1
5
5
Cable OBD-II a DB9 hembra
1
5
5
Cable USB tipo A-B
1
2
2
Hora trabajo
35
30
1050
Total
1082
70
4.4 Objetivos logrados
Durante todo el proyecto se han ido consiguiendo diferentes objetivos que en
conjunto han hecho que el resultado final haya sido satisfactorio. A
continuación se detallan por puntos:
Conseguir que el montaje de la interface funcione correctamente.
Lograr que el cable OBD-II utilizado previamente para hacer pruebas sea
fiable.
Poder acceder a las centralitas electrónicas (ECU), según el estándar
OBD-II.
Consolidar la comunicación con el modem a través del puerto serie
mediante aplicaciones de software de propio desarrollo en C++ y JAVA.
Conseguir descifrar las tramas digitales para obtener una información
fácilmente comprensible en pantalla de los datos enviados por la ECU.
Finalizar el desarrollo de la aplicación visual en JAVA con todas las
opciones previstas.
Estabilizar la aplicación visual en JAVA sin que se produzca ningún error
ya sea de comunicación con la interface o de manejo respecto al usuario.
Conseguir que la aplicación visual en JAVA funcione correctamente tanto
en Windows como en Linux.
4.5 Conclusiones
El lenguaje de programación JAVA es una herramienta muy potente, ya
que permite que una misma aplicación pueda funcionar de igual forma
en diferentes sistemas operativos y plataformas.
Es posible acceder a la centralita electrónica de un vehículo utilizando
montajes sencillos y ordenadores personales. En realidad está al alcance
de cualquier usuario particular.
71
La ingeniería inversa sobre un “firmware” (desensamblado), tiene
limitaciones y para realizar cambios significativos es necesario disponer
del código fuente, sino estamos limitados a pequeñas modificaciones.
Los fabricantes de automóviles han implementado el estándar OBD-II
obligados por EE.UU. i U.E de una forma bastante compatible como lo
demuestra el que un pequeño dispositivo genérico como el que se ha
realizado, funcione en un amplio rango de vehículos.
El hecho de disponer de un microcontrolador programable disminuye la
dependencia en la plataforma, ya que solo es necesario que disponga de
conexión USB, y a partir de aquí el papel de las plataformas es de
gestionar una conexión serie. El procesado de los protocolos los realiza
el micro.
4.6. Mejoras futuras
Internacionalizar el software de control con la intención de que pueda
mostrar la información en varios idiomas ya que en esta primera versión
solo se muestran en ingles.
Implementar todos los modos de trabajo del estándar OBD-II en el
software de control.
Dotar a la interface de una botonera y un pequeño “display” para poder
realizar las funciones más simples de forma autónoma, como por
ejemplo la lectura y borrado de los códigos de error DTC.
Implementar en el software de control una opción de autoayuda para
poder entender y manejar el sistema de forma más rápida. Esta mejora
sería muy útil porque los datos que se manejan son bastante abstractos.
Crear un paquete instalador que automáticamente sitúe los ficheros
necesarios del software para acelerar su puesta en marcha.
72
Bibliografía
[1] OBD2 ELM327 compatible AllPro adapter with USB, www.obddiag.net
[2] OBD-II PID’s, Wikipedia-The Free Encyclopedia.
[3] ASCII, Wikipedia-The Free Encyclopedia.
[4] OBD-II Trouble Codes Home, OBD-Codes.com
[5] Scanner OBD2, www.gncusers.com.ar
[6] ELM327DS.pdf, www.elmelectronics.com
[7] ELM320DS.pdf, www.elmelectronics.com
[8] 18F2455_2550.pdf, www.microchip.com
[9]Librería nativa “RXTXcomm”, www.rxtx.org
73
Anexo
Código ejemplo para el manejo de la librería “RXTXcomm” en lenguaje Java,
disponible en www.rxtx.org:
import
import
import
import
import
import
import
gnu.io.CommPort;
gnu.io.CommPortIdentifier;
gnu.io.SerialPort;
java.io.FileDescriptor;
java.io.IOException;
java.io.InputStream;
java.io.OutputStream;
public class TwoWaySerialComm
{
public TwoWaySerialComm()
{
super();
}
void connect ( String portName ) throws Exception
{
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if ( portIdentifier.isCurrentlyOwned() )
{
System.out.println("Error: Port is currently in use");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
if ( commPort instanceof SerialPort )
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(57600,SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
(new Thread(new SerialReader(in))).start();
(new Thread(new SerialWriter(out))).start();
}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}
74
public static class SerialReader implements Runnable
{
InputStream in;
public SerialReader ( InputStream in )
{
this.in = in;
}
public void run ()
{
byte[] buffer = new byte[1024];
int len = -1;
try
{
while ( ( len = this.in.read(buffer)) > -1 )
{
System.out.print(new String(buffer,0,len));
}
}
catch ( IOException e )
{
e.printStackTrace();
}
}
}
public static class SerialWriter implements Runnable
{
OutputStream out;
public SerialWriter ( OutputStream out )
{
this.out = out;
}
public void run ()
{
try
{
int c = 0;
while ( ( c = System.in.read()) > -1 )
{
this.out.write(c);
}
}
catch ( IOException e )
{
e.printStackTrace();
}
}
}
public static void main ( String[] args )
{
try
{
(new TwoWaySerialComm()).connect("COM3");
}
catch ( Exception e )
{
e.printStackTrace();
}
}
}
75
Código fuente del software de control desarrollado en el proyecto:
Capa de Datos:
Clase Conexión:
package Datos;
public class Conexion {
int velocidad;
int dataBits;
int stopBits;
int paridad;
String nombrePuerto;
String protocolo;
public Conexion(int velocidad, int dataBits, int stopBits, int
paridad, String nombrePuerto, String protocolo) {
super();
this.velocidad = velocidad;
this.dataBits = dataBits;
this.stopBits = stopBits;
this.paridad = paridad;
this.nombrePuerto = nombrePuerto;
this.protocolo = protocolo;
}
public int getDataBits() {
return dataBits;
}
public int getStopBits() {
return stopBits;
}
public String getNombrePuerto() {
return nombrePuerto;
}
public int getParidad() {
return paridad;
}
public int getVelocidad() {
return velocidad;
}
public String getProtocolo(){
return protocolo;
}
}
76
Clase ControladorConexión:
package Datos;
import
import
import
import
import
import
import
import
import
import
import
import
java.io.IOException;
java.io.InputStream;
java.io.OutputStream;
java.util.Date;
java.util.Enumeration;
java.util.Vector;
javax.swing.JTextArea;
gnu.io.CommPortIdentifier;
gnu.io.NoSuchPortException;
gnu.io.PortInUseException;
gnu.io.SerialPort;
gnu.io.UnsupportedCommOperationException;
public class ControladorConexion implements Runnable{
SerialPort port;
CommPortIdentifier idpuerto;
OutputStream datosEnviados;
InputStream datosRecibidos;
String estado;
StringBuffer tramaEnviada;
StringBuffer tramaRecibidaInicial;
StringBuffer tramaDatos;
StringBuffer tramaDatosCan;
StringBuffer tramaMediciones;
StringBuffer pids_disponibles;
JTextArea respuestaTexto;
String strDatos;
lecturaTXTErrores lecErr;
boolean conexionCOM=false;
boolean listo=false;
boolean procesaDatos=false;
boolean permisoEnvioManual=false;
boolean DestruirHilo=false;
private volatile Thread hilo;
Date temps,temps2;
String numeroProtocolo;
Vector<String> ids;
String ID;
MuestraIDs MIDs;
Conexion con;
public ControladorConexion(JTextArea respuestaTexto) {
this.respuestaTexto=respuestaTexto;
lecErr = new lecturaTXTErrores();
MIDs = new MuestraIDs();
}
public void establecerConexion(Conexion con){
this.con=con;
this.tramaEnviada=new StringBuffer();
this.tramaRecibidaInicial=new StringBuffer();
this.tramaDatos=new StringBuffer();
this.tramaDatosCan=new StringBuffer();
this.tramaMediciones=new StringBuffer();
this.pids_disponibles=new StringBuffer();
this.ID="";
this.numeroProtocolo="0";
77
if(conexionCOM==false){
try {
idpuerto =
CommPortIdentifier.getPortIdentifier(con.getNombrePuerto());
} catch (NoSuchPortException e) {
estado("Port "+con.getNombrePuerto()+" not available.");
}
try {
port = ( SerialPort )idpuerto.open("VisualOBD",2000);
} catch (PortInUseException e) {
estado("Port "+con.getNombrePuerto()+" in use.");
}
try {
port.setSerialPortParams(con.getVelocidad(),
con.getDataBits(),
con.getStopBits(),
con.getParidad());
} catch (UnsupportedCommOperationException e) {
estado("Operation not supported.");
}
hilo=new Thread(this);
hilo.start();
hilo.setPriority(Thread.MIN_PRIORITY);
conexionCOM=true;
}
estado("Connected "+con.getNombrePuerto()+".");
enviar("atz");
enviar(con.getProtocolo());
enviar("0100");
enviar("atdp");
enviar("atdpn");
enviar("ath1");
enviar("0100");
timer();
}
public void desconectar(){
if(conexionCOM==true){
enviar("atws");//En linux el hilo del run, se para en el
datosRecibidos.read(), por tanto necessiatmos mandar algo
DestruirHilo=false;//para que se mueva de ahi, atws esta bien porque resetea
//la interface al desconectar.
while(DestruirHilo==false){//Espera a que se reciba la ultima trama en run()
//para poder despues destruir el hilo y cerrar los
//puertos.
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
hilo = null;//Obliga a desacer el bucle del hilo para asi pararlo de forma
//segura.
conexionCOM=false;//Cuando el hilo ya ha recibido la informacion (en linux),
//sigue el camino muriendo, ya que hilo=null
try {
datosEnviados.close();
} catch (IOException e) {
estado("Failed to close communication");
}
try {
78
datosRecibidos.close();
} catch (IOException e) {
estado("Failed to close communication.");
}
try{
port.disableReceiveFraming();//Meramente formal
port.close();
estado("Offline.");
} catch (Exception e){
estado("Failed to close port");
}
}else{
estado("You are not connected.");
}
}
public void enviar(String trama){
int longitudTramaEnv=0;
int data;
listo=false;
if(conexionCOM==true){
this.tramaEnviada.append(trama+"\r");//Solamente necessita el retorno de
//carro, sin el salto de linea.
try {
datosEnviados = port.getOutputStream();
for(int i=0;i<tramaEnviada.length();i++){
data= tramaEnviada.codePointAt(i);
datosEnviados.write(data);
}
longitudTramaEnv=tramaEnviada.length();
tramaEnviada.delete(0, longitudTramaEnv);
} catch (IOException e) {
estado("Unable to send "+tramaEnviada+".");
}
}else{
estado("You are not connected to any port.");
}
}
public void run(){
boolean datos=false;
String tramaRecibida;
Thread thisThread = Thread.currentThread();
while(hilo == thisThread){
char z;
int longitudTrama=0;
int reb=0;
try {
datosRecibidos = port.getInputStream();
while((reb=datosRecibidos.read())>-1){
z=(char) reb;
if(reb==62){ //Cuando se recibe 62 = >, se sale del bucle
//para separar los mensajes.
//Se hace break en run
break;
}
if(reb!=-1){
tramaRecibidaInicial.append(z);
}
}
DestruirHilo=true;//Esto da permiso al metodo desconectar() para
//poner el hilo=null.
79
} catch (IOException e1) {
estado("No response.");
}
if(reb==62){
try {
tramaRecibidaInicial.deleteCharAt(tramaRecibidaInicial.length()-1);
//Se borra el último
//salto de linea
} catch (RuntimeException e2) {estado("No response.");}
estado("Sent "+tramaRecibidaInicial.toString());
tramaRecibida=tramaRecibidaInicial.toString();
longitudTrama=tramaRecibidaInicial.length();
tramaRecibidaInicial.delete(0, longitudTrama);
if(permisoEnvioManual==false){
for(int x=0;x<tramaRecibida.length();x++){
if(tramaRecibida.codePointAt(x)==10){
datos=true;
}
if(datos==true){
tramaDatos.append(tramaRecibida.charAt(x));
}
}
datos=false;
try {
if(tramaRecibida.codePointAt(0)==97 ||
tramaRecibida.codePointAt(0)==65){
procesaDatos=false;
}else{
procesaDatos=true;
}
} catch (RuntimeException e2) {estado("No response.");}
try {
if(tramaRecibida.substring(0,
5).toString().compareTo("atdpn")==0){
if(tramaDatos.codePointAt(1)==65){
numeroProtocolo=tramaDatos.substring(2,3);
}else{
numeroProtocolo=tramaDatos.substring(1,2);
}
estado("Protocol number: "+numeroProtocolo);
}
} catch (RuntimeException e1) {estado("No response.");}
if(procesaDatos==true){
if(Integer.parseInt(numeroProtocolo)>=6){
try{
if(tramaDatos.codePointAt(8)==52){
80
//El siguiente metodo diferencia las cabeceras CAN.
if(ID.compareTo("")==0){
ids=new Vector<String>();
for(int f=0;f<tramaDatos.length();f++){
if(tramaDatos.codePointAt(f)==10){
ids.add(tramaDatos.substring(f+1, f+4));//Delemito los IDs,
//hay que almacenarlos.
}
}
mostrarIDS(ids);
}
for(int f=0;f<tramaDatos.length();f++){
if(tramaDatos.codePointAt(f)==10){
if(ID.compareTo(tramaDatos.substring(f+1, f+4))==0){
int longitud=0;
try{
for(int g=f+8;tramaDatos.codePointAt(g)!=10;g++){
longitud=g;
}
}catch(Exception e){
longitud=longitud+1;
System.out.println(e);
}
tramaDatosCan.append("\n"+tramaDatos.substring(f+8,longitud));
//No hacemos break para que asi coja todas las lineas con la misma cabecera.
}
}
}
strDatos=tramaDatosCan.toString();
longitudTrama=tramaDatosCan.length();
tramaDatosCan.delete(0, longitudTrama);
if(ID==""){
strDatos="N";//Para que los demas metodos sepan que no se han
//asignado los ids CAN.
}
}else if(tramaDatos.codePointAt(10)==55){
strDatos="Neg";//Para que se sepa que hay respuesta negativa.
}else{
strDatos="N";//Para que los demas metodos sepan que no a llegado
//informacion
}
}catch(Exception e){
//System.out.println(e);
strDatos="N";
}
}else{
try{
if(tramaDatos.codePointAt(10)==52){
for(int f=0;f<tramaDatos.length();f++){
if(tramaDatos.codePointAt(f)==10){
tramaDatos.delete(f+1, f+10);
}
}
strDatos=tramaDatos.toString();
}else if(tramaDatos.codePointAt(10)==55){
strDatos="Neg";//Para que se sepa que hay respuesta negativa.
}else{
strDatos="N";//Para que los demas metodos sepan que no a llegado informacion
}
81
}catch(Exception e){
//System.out.println(e);
strDatos="N";
}
}
}
listo=true;
longitudTrama=tramaDatos.length();
tramaDatos.delete(0, longitudTrama);
}
permisoEnvioManual=false;
}
}
}
public Vector puertosdisponibles(){
int j=1;
Vector <String> listapuertos = new Vector<String>();
for (Enumeration i = CommPortIdentifier.getPortIdentifiers() ; i.hasMoreElements() ;) {
CommPortIdentifier idpuerto = (CommPortIdentifier) i.nextElement();
listapuertos.add(j++ +". "
}
return listapuertos;
+ idpuerto.getName()+"\n");
}
public void estado(String estado){
respuestaTexto.append(">"+estado+"\n\n");
respuestaTexto.setCaretPosition( respuestaTexto.getText().length() );
}
public String devuelve_cantidad_errores(){
if(conexionCOM==true){
//esperando cantidad de errores
timer();
//strDatos="\n41 01 84 4B A5 F1 0A\r";
//asignando cantidad de errores
if(strDatos.compareTo("N")==0){
return "ECU does not respond.";
}else if(strDatos.compareTo("Neg")==0){
return "ECU responded negatively.";
}else if(strDatos.compareTo("NElm")==0){
return "ELM does not respond.";
}else{
return lecErr.descifraTramaHex(strDatos);
}
}else{
return "Without connection port.";
}
}
public String devuelve_descripcion_errores(){//Este metodo coje 2 o mas lineas de errores
if(conexionCOM==true){
//Al devolver 2 lineas, entre lineas no hay el
//simbolo ">", esto puede ser bueno.
//esperando descripcion de errores
timer();
//strDatos="\n43 01 33 02 45 61 21 0A\r\n43 01 33 02 45 61 21 0A\r";
//asignando cantidad de errores
if(strDatos.compareTo("N")==0){
return "Not received information about errors.";
}else if(strDatos.compareTo("Neg")==0){
82
return "ECU responded negatively.";
}else if(strDatos.compareTo("NElm")==0){
return "ELM does not respond.";
}else{
return lecErr.descifraTramaHexDescripcionErrores(strDatos+"\n");
}
}else{
return "First you must connect to the COM port.";
}
}
public String borrado_de_errores(){
if(conexionCOM==true){
timer();
//strDatos="\n44 0A\r";
if(strDatos.compareTo("N")==0){
return "ECU does not respond.";
}else if(strDatos.compareTo("Neg")==0){
return "ECU responded negatively.";
}else if(strDatos.compareTo("NElm")==0){
return "ELM does not respond.";
}else{
return "Removed errors stored in the ECU..";
}
}else{
return "Without connection port.";
}
}
public String devuelve_pid(){
timer();
//strDatos="\n41 0C 04 88 8F B0\r";
if(strDatos.compareTo("N")==0){
strDatos="\n41 0C 00 00 00 00\r";//Para que no pete el hilo de mediciones si llega
//un NO DATA o algo inadecuado.
estado("ECU does not respond");
return strDatos;
}else if(strDatos.compareTo("Neg")==0){
strDatos="\n41 0C 00 00 00 00\r";
estado("ECU responded negatively");
return strDatos;
}else if(strDatos.compareTo("NElm")==0){
strDatos="\n41 0C 00 00 00 00\r";
estado("ELM does not respond");
return strDatos;
}else{
return strDatos;
}
}
public boolean estado_conexion(){
return conexionCOM;
}
public void borrar_pids_establecidos(){
int longitudTrama;
longitudTrama=pids_disponibles.length();
pids_disponibles.delete(0, longitudTrama);
}
public void establece_pids(){
if(conexionCOM==true){
//esperando pids
83
timer();
//asignando pids
String pids_binario;
//strDatos="\n41 00 FF FF FF FF 0A\r";
int pids_decimal;
int longitud_trama;
int t=7;
if(strDatos.compareTo("N")==0){
pids_disponibles.append("N00000000000000000000000000000000");
estado("ECU does not respond");
}else if(strDatos.compareTo("Neg")==0){
pids_disponibles.append("N00000000000000000000000000000000");
estado("ECU responded negatively");
}else if(strDatos.compareTo("NElm")==0){
pids_disponibles.append("N00000000000000000000000000000000");
estado("ELM does not respond");
}else{
for(int q=0;q<4;q++){ //Da 4 pasadas para lo 4 bytes de datos
for(int r=t;r<(t+2);r++){ //coje los bytes, en grupos de 2 chars
tramaMediciones.append(strDatos.charAt(r));
}
t=t+3;
pids_decimal=Integer.parseInt(tramaMediciones.toString(), 16);
//pasa de hex a int
pids_binario=Integer.toString(pids_decimal, 2);//pasa de int a bin
longitud_trama=tramaMediciones.length();
tramaMediciones.delete(0, longitud_trama);
for(int f=0;f<(8-pids_binario.length());f++){//introduce un 0 al
//principio de las tramas de menos de 8 bits
pids_disponibles.append("0");
}
pids_disponibles.append(pids_binario);
}
}
}
}
public String cojer_pids(){
if(conexionCOM==true){
if(pids_disponibles.codePointAt(0)!=78){//Si los datos que llegan empiezan por N
return pids_disponibles.toString();
}else{
estado("No data available pids");
return "N";
}
}else{
estado("Without connection port.");
return "N";
}
}
public void mostrarIDS(Vector vect){
MIDs.getJListIDs().setListData(vect);
MIDs.getJListIDs().setSelectedIndex(0);
MIDs.setVisible(true);
MIDs.getJButtonIDsAceptar().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
asignaIDCanBus();
MIDs.setVisible(false);
}
});
}
84
public void asignaIDCanBus(){
ID=MIDs.getJListIDs().getSelectedValue().toString();
}
public void timer(){
temps=new Date();
while(agafatemps()-temps.getTime()<5000){//Espera 5 segundos la respuesta del puerto
procedente de la interface ELM.
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(listo==true){
break;
}
}
if(listo==false){
estado("Without connection to the interface ELM.");
strDatos="NElm";
listo=true;
}
}
public void permiteEnvioManual(boolean permiso){
permisoEnvioManual=permiso;//Avilita el envio manual de ordenes a la interface ELM.
}
public long agafatemps(){//Metodo que utiliza el timer().
temps2 = new Date();
return temps2.getTime();
}
}
Clase lecturaTXTErrores:
package Datos;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class lecturaTXTErrores {
FileReader fr;
BufferedReader bf;
int longitudTrama;
int numeroErrores;
StringBuffer valorHex;
public lecturaTXTErrores(){}
85
public String descifraTramaHex(String error){
String estadoErrores;
int valorDec;
valorDec=Integer.parseInt(error.substring(7, 9), 16);
if(valorDec<128){
estadoErrores= "The check engine light (MIL) is OFF, and the ECU doesn't have any
error code stored";
}else{
numeroErrores=valorDec-128;
estadoErrores= "The check engine light (MIL) is ON, and the ECU has
"+numeroErrores+" error code/s stored";
}
return estadoErrores;
}
public String descifraTramaHexDescripcionErrores(String error){
valorHex = new StringBuffer();
StringBuffer codigoError=new StringBuffer();
int incremento=4;
for(int s=0;s<numeroErrores;s++){
boolean codigo_encontrado=false;
if(error.codePointAt(incremento)==48){
valorHex.append("P0");
}else if(error.codePointAt(incremento)==49){
valorHex.append("P1");
}else if(error.codePointAt(incremento)==50){
valorHex.append("P2");
}else if(error.codePointAt(incremento)==51){
valorHex.append("P3");
}else if(error.codePointAt(incremento)==52){
valorHex.append("C0");
}else if(error.codePointAt(incremento)==53){
valorHex.append("C1");
}else if(error.codePointAt(incremento)==54){
valorHex.append("C2");
}else if(error.codePointAt(incremento)==55){
valorHex.append("C3");
}else if(error.codePointAt(incremento)==56){
valorHex.append("B0");
}else if(error.codePointAt(incremento)==57){
valorHex.append("B1");
}else if(error.codePointAt(incremento)==65){
valorHex.append("B2");
}else if(error.codePointAt(incremento)==66){
valorHex.append("B3");
}else if(error.codePointAt(incremento)==67){
valorHex.append("U0");
}else if(error.codePointAt(incremento)==68){
valorHex.append("U1");
}else if(error.codePointAt(incremento)==69){
valorHex.append("U2");
}else if(error.codePointAt(incremento)==70){
valorHex.append("U3");
}
for(int p=incremento+1;p<(incremento+5);p++){//Introduce el resto de
//numeros del error
if(error.codePointAt(p)!=32){
valorHex.append(error.charAt(p));
}
86
}
incremento=incremento+6;//Coloca la posicion en la trama para el siguiente
//error
if(error.codePointAt(incremento+3)==10){//Si detecta salto de linea se
//prepara la posicion para el siguiente error en la siguiente linea
incremento=incremento+7;
}
String codError=valorHex.toString();
String sCadena;
try {
fr = new FileReader("CodigosErrores.txt");
bf = new BufferedReader(fr);
while ((sCadena = bf.readLine())!=null) {
if(codError.compareTo(sCadena.substring(0, 5))==0){//se compara
//el error leido con cada linea del fichero, si lo encuentra se sale del bucle
codigoError.append(sCadena+"\n\n");
codigo_encontrado=true;
break;
}
}
if(codigo_encontrado==false){
codigoError.append("Unknown "+codError+" error\n\n");
}
} catch (IOException e) {
codigoError.append("Database error codes inaccessible");
}
longitudTrama=valorHex.length();//Se deja vacio el buffer que contiene el
//código procedente de la ECU
valorHex.delete(0, longitudTrama);
}
return codigoError.toString();
}
}
87
Clase MuestraIDs:
package Datos;
import
import
import
import
import
import
javax.swing.JPanel;
javax.swing.JFrame;
javax.swing.JList;
java.awt.Rectangle;
javax.swing.JButton;
javax.swing.JScrollPane;
public class MuestraIDs extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private JList jListIDs = null;
private JButton jButtonIDsAceptar = null;
private JScrollPane jScrollPaneListaIDs = null;
public MuestraIDs() {
super();
initialize();
}
private void initialize() {
this.setSize(300, 200);
this.setLocation(500, 200);
this.setContentPane(getJContentPane());
this.setTitle("CAN Bus IDs");
}
private JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.add(getJButtonIDsAceptar(), null);
jContentPane.add(getJScrollPaneListaIDs(), null);
}
return jContentPane;
}
public JList getJListIDs() {
if (jListIDs == null) {
jListIDs = new JList();
}
return jListIDs;
}
public JButton getJButtonIDsAceptar() {
if (jButtonIDsAceptar == null) {
jButtonIDsAceptar = new JButton();
jButtonIDsAceptar.setBounds(new Rectangle(200, 133, 82, 22));
jButtonIDsAceptar.setText("OK");
}
return jButtonIDsAceptar;
}
88
private JScrollPane getJScrollPaneListaIDs() {
if (jScrollPaneListaIDs == null) {
jScrollPaneListaIDs = new JScrollPane();
jScrollPaneListaIDs.setBounds(new Rectangle(10, 10, 273, 115));
jScrollPaneListaIDs.setViewportView(getJListIDs());
}
return jScrollPaneListaIDs;
}
}
Capa de Dominio:
Clase ControladorDominioConexión:
package Dominio;
import
import
import
import
java.util.Vector;
javax.swing.JTextArea;
Datos.Conexion;
Datos.ControladorConexion;
public class ControladorDominioConexion{
Conexion con;
ControladorConexion contCon;
public ControladorDominioConexion(JTextArea respuestaTexto) {
contCon = new ControladorConexion(respuestaTexto);
}
public void establecerConexion(int velocidad,int dataBits,int stopBits,int
paridad,String nombrePuerto,String protocolo){
con = new Conexion(velocidad,dataBits,stopBits,paridad,nombrePuerto,protocolo);
contCon.establecerConexion(con);
}
public void enviar(String tramaEnviada){
contCon.enviar(tramaEnviada);
}
public void desconectar(){
contCon.desconectar();
}
public Vector puertosdisponibles(){
return contCon.puertosdisponibles();
}
public String devuelve_cantidad_errores(){
return contCon.devuelve_cantidad_errores();
}
public String devuelve_descripcion_errores(){
return contCon.devuelve_descripcion_errores();
}
public boolean estado_conexion(){
return contCon.estado_conexion();
}
89
public String cojer_pids(){
return contCon.cojer_pids();
}
public String devuelvePid(){
return contCon.devuelve_pid();
}
public void establece_pids(){
contCon.establece_pids();
}
public String borrado_de_errores(){
return contCon.borrado_de_errores();
}
public void borrar_pids_establecidos(){
contCon.borrar_pids_establecidos();
}
public void permiteEnvioManual(boolean permiso){
contCon.permiteEnvioManual(permiso);
}
}
Capa de Presentación:
Clase ConfirmaciónBorradoErrores:
package Presentacion;
import
import
import
import
import
javax.swing.JPanel;
javax.swing.JFrame;
javax.swing.JLabel;
java.awt.Rectangle;
javax.swing.JButton;
public class ConfirmacionBorradoErrores extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private JLabel jLabelConfirmaErrores = null;
private JButton jButtonOK = null;
private JLabel jLabelConfirmarBorradoErrores = null;
private JButton jButtonCancel = null;
public ConfirmacionBorradoErrores() {
super();
initialize();
}
private void initialize() {
this.setSize(330, 200);
this.setLocation(500,200);
this.setContentPane(getJContentPane());
90
this.setTitle("Confirm erasing error codes");
}
private JPanel getJContentPane() {
if (jContentPane == null) {
jLabelConfirmarBorradoErrores = new JLabel();
jLabelConfirmarBorradoErrores.setBounds(new Rectangle(10, 41, 206, 20));
jLabelConfirmarBorradoErrores.setText("Do you really want to continue?");
jLabelConfirmaErrores = new JLabel();
jLabelConfirmaErrores.setBounds(new Rectangle(10, 20, 308, 20));
jLabelConfirmaErrores.setText("You will erase all error codes stored in
the ECU.");
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.add(jLabelConfirmaErrores, null);
jContentPane.add(getJButtonOK(), null);
jContentPane.add(jLabelConfirmarBorradoErrores, null);
jContentPane.add(getJButtonCancel(), null);
}
return jContentPane;
}
public JButton getJButtonOK() {
if (jButtonOK == null) {
jButtonOK = new JButton();
jButtonOK.setBounds(new Rectangle(161, 135, 75, 20));
jButtonOK.setText("OK");
}
return jButtonOK;
}
public JButton getJButtonCancel() {
if (jButtonCancel == null) {
jButtonCancel = new JButton();
jButtonCancel.setBounds(new Rectangle(235, 135, 75, 20));
jButtonCancel.setText("Cancel");
}
return jButtonCancel;
}
}
91
Clase ControladorErrores:
package Presentacion;
import javax.swing.JPanel;
import Dominio.ControladorDominioConexion;
public class ControladorErrores {
VistaCodigosError VCE;
ControladorDominioConexion contDom;
ControladorMediciones contMed;
ConfirmacionBorradoErrores confErr;
boolean ventanaConfirmaErrores;
public ControladorErrores(ControladorDominioConexion contDom,ControladorMediciones contMed){
this.contMed=contMed;
VCE = new VistaCodigosError();
this.contDom = contDom;
ventanaConfirmaErrores=false;
eventos();
}
public void eventos(){
VCE.getJButtonErrores().addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
if(contMed.lectura==true){
contMed.pararHilo=true;
contMed.inicializacion=true;
contMed.lectura=false;
while(contMed.indica_hilo_destruido==false){
try {
Thread.sleep(10);
} catch (InterruptedException error) {
error.printStackTrace();
}
}
}
consulta_errores();
}
});
VCE.getJButtonBorrarErrores().addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
if(ventanaConfirmaErrores==false){
confirmaErrores();
ventanaConfirmaErrores=true;//Esta variable evita que podamos
//abrir varias ventanas.
}
}
});
}
public void consulta_errores(){
contDom.enviar("0101");
VCE.getJTextAreaErrores().append(contDom.devuelve_cantidad_errores()+"\n\n");
contDom.enviar("03");
VCE.getJTextAreaErrores().append(contDom.devuelve_descripcion_errores()+"\n\n");
}
public JPanel devuelve_panel(){
return this.VCE;
}
92
public void confirmaErrores(){
confErr=new ConfirmacionBorradoErrores();
confErr.setVisible(true);
confErr.getJButtonOK().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
contDom.enviar("04");
VCE.getJTextAreaErrores().append(contDom.borrado_de_errores()+"\n\n");
confErr.setVisible(false);
ventanaConfirmaErrores=false;
}
});
confErr.getJButtonCancel().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
confErr.setVisible(false);
ventanaConfirmaErrores=false;
}
});
confErr.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
confErr.setVisible(false);
ventanaConfirmaErrores=false;
}
});
}
}
Clase ControladorMediciones:
package Presentacion;
import java.text.DecimalFormat;
import javax.swing.JPanel;
import Dominio.ControladorDominioConexion;
public class ControladorMediciones implements Runnable{
VistaMediciones VMed;
ControladorDominioConexion contDom;
String pids_disponibles;
DecimalFormat df;
boolean lectura=false;
boolean pararHilo=false;
boolean inicializacion=false;
boolean indica_hilo_destruido;
boolean conectado=false;
Thread hilo;
public ControladorMediciones(ControladorDominioConexion contDom){
VMed = new VistaMediciones();
this.contDom = contDom;
df = new DecimalFormat("0.0");//Especifica los decimales mostrados en las TextField.
eventos();
}
93
public void eventos(){
VMed.getJButtonLeer().addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
if(lectura==false){
if(conectado==true){
if(inicializacion==true){
hilo = new Thread(ControladorMediciones.this);
inicializacion=false;
indica_hilo_destruido=false;
}
contDom.borrar_pids_establecidos();
contDom.enviar("0100");
contDom.establece_pids();
contDom.enviar("0120");
contDom.establece_pids();
contDom.enviar("0140");
contDom.establece_pids();
pids_disponibles=contDom.cojer_pids();
if(pids_disponibles.codePointAt(0)==78){
lectura=false;
}else{
pararHilo=false;
lectura=true;
hilo.start();
}
}else{
contDom.enviar("0100");
}
}
}
});
VMed.getJButtonDetener().addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
if(conectado==true){
pararHilo=true;
lectura=false;
inicializacion=true;
}else{
contDom.enviar("0100");
}
}
});
}
public JPanel devuelve_panel(){
return this.VMed;
}
public void run(){
while(true){
if(pids_disponibles.codePointAt(3)==49){
contDom.enviar("0104");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField04().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(4)==49){
contDom.enviar("0105");
94
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField05().setText(Integer.toString(valorDec-40)+"ºC");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(5)==49){
contDom.enviar("0106");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField06().setText(df.format(((valorDec128)*100)/128)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(6)==49){
contDom.enviar("0107");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField07().setText(df.format(((valorDec128)*100)/128)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(7)==49){
contDom.enviar("0108");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField08().setText(df.format(((valorDec128)*100)/128)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(8)==49){
contDom.enviar("0109");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField09().setText(df.format(((valorDec128)*100)/128)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(9)==49){
contDom.enviar("010A");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField0A().setText(Integer.toString(valorDec*3)+"kPa");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(10)==49){
contDom.enviar("010B");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField0B().setText(Integer.toString(valorDec)+"kPa");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
95
}
}
if(pids_disponibles.codePointAt(11)==49){
contDom.enviar("010C");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField0C().setText(Integer.toString(((a*256)+b)/4)+"rpm");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(12)==49){
contDom.enviar("010D");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField0D().setText(Integer.toString(valorDec)+"km/h");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(13)==49){
contDom.enviar("010E");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField0E().setText(df.format((valorDec/2)-64)+"º");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(14)==49){
contDom.enviar("010F");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField0F().setText(Integer.toString(valorDec-40)+"ºC");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(15)==49){
contDom.enviar("0110");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField10().setText(df.format(((a*256)+b)/100)+"g/s");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(16)==49){
contDom.enviar("0111");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField11().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(17)==49){
contDom.enviar("0112");
StringBuffer trama_binaria=new StringBuffer();
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
String pids_binario=Integer.toString(valorDec, 2);
96
for(int f=0;f<(8-pids_binario.length());f++){//introduce un 0 al principio
//de las tramas de menos de 8 bits
trama_binaria.append("0");
}
trama_binaria.append(pids_binario);
if(trama_binaria.codePointAt(7)==49){
VMed.getJTextField12().setText("Upstream of catalytic converter");
}else if(trama_binaria.codePointAt(6)==49){
VMed.getJTextField12().setText("Downstream of catalytic converter");
}else if(trama_binaria.codePointAt(5)==49){
VMed.getJTextField12().setText("From the outside atmosphere or
off");
}else{
VMed.getJTextField12().setText("OK");
}
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(19)==49){
contDom.enviar("0114");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField14().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(20)==49){
contDom.enviar("0115");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField15().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(21)==49){
contDom.enviar("0116");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField16().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(22)==49){
contDom.enviar("0117");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField17().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
97
}
}
if(pids_disponibles.codePointAt(23)==49){
contDom.enviar("0118");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField18().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(24)==49){
contDom.enviar("0119");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField19().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(25)==49){
contDom.enviar("011A");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField1A().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(26)==49){
contDom.enviar("011B");
int voltios=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int porcentaje=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField1B().setText(df.format(voltios*(0.005))+"V
"+df.format((porcentaje-128)*(100/128))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(27)==49){
contDom.enviar("011C");
String valorHex=contDom.devuelvePid().substring(7,9);
if(valorHex.compareTo("01")==0){
VMed.getJTextField1C().setText("OBD-II as defined by the CARB");
}else if(valorHex.compareTo("02")==0){
VMed.getJTextField1C().setText("OBD as defined by the EPA");
}else if(valorHex.compareTo("03")==0){
VMed.getJTextField1C().setText("OBD ''and'' OBD-II");
}else if(valorHex.compareTo("04")==0){
VMed.getJTextField1C().setText("OBD-I");
}else if(valorHex.compareTo("05")==0){
VMed.getJTextField1C().setText("Not meant to comply with any OBD
standard");
}else if(valorHex.compareTo("06")==0){
VMed.getJTextField1C().setText("EOBD");
98
}else{
VMed.getJTextField1C().setText("Unknown");
}
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(29)==49){
contDom.enviar("011E");
StringBuffer trama_binaria=new StringBuffer();
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
String pids_binario=Integer.toString(valorDec, 2);
for(int f=0;f<(8-pids_binario.length());f++){//introduce un 0 al principio
//de las tramas de menos de 8 bits
trama_binaria.append("0");
}
trama_binaria.append(pids_binario);
if(trama_binaria.codePointAt(7)==49){
VMed.getJTextField1E().setText("Active");
}else{
VMed.getJTextField1E().setText("No active");
}
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(30)==49){
contDom.enviar("011F");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField1F().setText(df.format((a*256)+b)+"segs");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(31)==49){
if(pids_disponibles.codePointAt(32)==49){
contDom.enviar("0121");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField21().setText(Integer.toString((a*256)+b)+"km");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(33)==49){
contDom.enviar("0122");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField22().setText(df.format(((a*256)+b)*(0.079))+"kPa");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(34)==49){
contDom.enviar("0123");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
99
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField23().setText(Integer.toString(((a*256)+b)*10)+"kPa");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(35)==49){
contDom.enviar("0124");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField24().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(36)==49){
contDom.enviar("0125");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField25().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(37)==49){
contDom.enviar("0126");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField26().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(38)==49){
contDom.enviar("0127");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField27().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(29)==49){
contDom.enviar("0128");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField28().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(40)==49){
contDom.enviar("0129");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField29().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
100
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(41)==49){
contDom.enviar("012A");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField2A().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(42)==49){
contDom.enviar("012B");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField2B().setText(df.format(((c*256)+d)*(0.000122))+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(43)==49){
contDom.enviar("012C");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField2C().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(44)==49){
contDom.enviar("012D");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField2D().setText(df.format((valorDec*(0.78125))-100)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(45)==49){
contDom.enviar("012E");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField2E().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(46)==49){
contDom.enviar("012F");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField2F().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
101
if(pids_disponibles.codePointAt(48)==49){
contDom.enviar("0131");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField31().setText(Integer.toString((a*256)+b)+"km");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(49)==49){
contDom.enviar("0132");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField32().setText(df.format((((a*256)+b)/4)-(8.192))+"Pa");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(50)==49){
contDom.enviar("0133");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField33().setText(Integer.toString(valorDec)+"kPa");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(51)==49){
contDom.enviar("0134");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField34().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(52)==49){
contDom.enviar("0135");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField35().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(53)==49){
contDom.enviar("0136");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField36().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(54)==49){
contDom.enviar("0137");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
102
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField37().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(55)==49){
contDom.enviar("0138");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField38().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(56)==49){
contDom.enviar("0139");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField39().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(57)==49){
contDom.enviar("013A");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField3A().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(58)==49){
contDom.enviar("013B");
int c=Integer.parseInt(contDom.devuelvePid().substring(13,15), 16);
int d=Integer.parseInt(contDom.devuelvePid().substring(16,18), 16);
VMed.getJTextField3B().setText(df.format(((c*256)+d)*(0.00390625)-128)+"mA");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(59)==49){
contDom.enviar("013C");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField3C().setText(df.format((((a*256)+b)/10)-40)+"ºC");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(60)==49){
contDom.enviar("013D");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField3D().setText(df.format((((a*256)+b)/10)-40)+"ºC");
if(pararHilo==true){
103
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(61)==49){
contDom.enviar("013E");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField3E().setText(df.format((((a*256)+b)/10)-40)+"ºC");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(62)==49){
contDom.enviar("013F");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField3F().setText(df.format((((a*256)+b)/10)-40)+"ºC");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(63)==49){
if(pids_disponibles.codePointAt(65)==49){
contDom.enviar("0142");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField42().setText(df.format(((a*256)+b)/1000)+"V");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(66)==49){
contDom.enviar("0143");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField43().setText(df.format(((a*256)+b)*(100/255))+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(67)==49){
contDom.enviar("0144");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField44().setText(df.format(((a*256)+b)*(0.0000305)));
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(68)==49){
contDom.enviar("0145");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField45().setText(df.format((valorDec*100)/255)+"%");
104
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(69)==49){
contDom.enviar("0146");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField46().setText(Integer.toString(valorDec-40)+"ºC");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(70)==49){
contDom.enviar("0147");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9),
16);
VMed.getJTextField47().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(71)==49){
contDom.enviar("0148");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField48().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(72)==49){
contDom.enviar("0149");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField49().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(73)==49){
contDom.enviar("014A");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField4A().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(74)==49){
105
contDom.enviar("014B");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField4B().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(75)==49){
contDom.enviar("014C");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField4C().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(76)==49){
contDom.enviar("014D");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField4D().setText(Integer.toString((a*256)+b)+"min");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(77)==49){
contDom.enviar("014E");
int a=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
int b=Integer.parseInt(contDom.devuelvePid().substring(10,12), 16);
VMed.getJTextField4E().setText(Integer.toString((a*256)+b)+"min");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(80)==49){
contDom.enviar("0151");
if(contDom.devuelvePid().substring(7,9).compareTo("01")==0){
VMed.getJTextField51().setText("Gasoline");
}else if(contDom.devuelvePid().substring(7,9).compareTo("02")==0){
VMed.getJTextField51().setText("Methanol");
}else if(contDom.devuelvePid().substring(7,9).compareTo("03")==0){
VMed.getJTextField51().setText("Ethanol");
}else if(contDom.devuelvePid().substring(7,9).compareTo("04")==0){
VMed.getJTextField51().setText("Diesel");
}else if(contDom.devuelvePid().substring(7,9).compareTo("05")==0){
VMed.getJTextField51().setText("LPG");
}else if(contDom.devuelvePid().substring(7,9).compareTo("06")==0){
VMed.getJTextField51().setText("CNG");
}else if(contDom.devuelvePid().substring(7,9).compareTo("07")==0){
VMed.getJTextField51().setText("Propane");
}else if(contDom.devuelvePid().substring(7,9).compareTo("08")==0){
VMed.getJTextField51().setText("Electric");
}else if(contDom.devuelvePid().substring(7,9).compareTo("09")==0){
VMed.getJTextField51().setText("Bifuel running Gasoline");
}else if(contDom.devuelvePid().substring(7,9).compareTo("0A")==0){
VMed.getJTextField51().setText("Bifuel running Methanol");
106
}else if(contDom.devuelvePid().substring(7,9).compareTo("0B")==0){
VMed.getJTextField51().setText("Bifuel running Ethanol");
}else if(contDom.devuelvePid().substring(7,9).compareTo("0C")==0){
VMed.getJTextField51().setText("Bifuel running LPG");
}else if(contDom.devuelvePid().substring(7,9).compareTo("0D")==0){
VMed.getJTextField51().setText("Bifuel running CNG");
}else if(contDom.devuelvePid().substring(7,9).compareTo("0E")==0){
VMed.getJTextField51().setText("Bifuel running Propane");
}else if(contDom.devuelvePid().substring(7,9).compareTo("0F")==0){
VMed.getJTextField51().setText("Bifuel running Electricity");
}else if(contDom.devuelvePid().substring(7,9).compareTo("10")==0){
VMed.getJTextField51().setText("Bifuel mixed gas/electric");
}else if(contDom.devuelvePid().substring(7,9).compareTo("11")==0){
VMed.getJTextField51().setText("Hybrid gasoline");
}else if(contDom.devuelvePid().substring(7,9).compareTo("12")==0){
VMed.getJTextField51().setText("Hybrid Ethanol");
}else if(contDom.devuelvePid().substring(7,9).compareTo("13")==0){
VMed.getJTextField51().setText("Hybrid Diesel");
}else if(contDom.devuelvePid().substring(7,9).compareTo("14")==0){
VMed.getJTextField51().setText("Hybrid Electric");
}else if(contDom.devuelvePid().substring(7,9).compareTo("15")==0){
VMed.getJTextField51().setText("Hybrid Mixed fuel");
}else if(contDom.devuelvePid().substring(7,9).compareTo("16")==0){
VMed.getJTextField51().setText("Hybrid Regenerative");
}
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
if(pids_disponibles.codePointAt(81)==49){
contDom.enviar("0152");
int valorDec=Integer.parseInt(contDom.devuelvePid().substring(7,9), 16);
VMed.getJTextField52().setText(df.format((valorDec*100)/255)+"%");
if(pararHilo==true){
indica_hilo_destruido=true;
break;
}
}
}
}
}
}
}
Clase ControladorPrincipal:
package Presentacion;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import Dominio.ControladorDominioConexion;
public class ControladorPrincipal{
VistaPrincipal VP;
ControladorDominioConexion contDomCon;
ControladorPSerie cP;
ControladorProtocolo cProt;
107
ControladorMediciones cMed;
ControladorErrores cErr;
JPanel panel;
JLabel labelImagen;
boolean existe_panel=false;
boolean existe_label=true;
public ControladorPrincipal(){
VP = new VistaPrincipal();
contDomCon = new ControladorDominioConexion(VP.getJTextArea());
cP = new ControladorPSerie(contDomCon);
cProt = new ControladorProtocolo(contDomCon);
cMed = new ControladorMediciones(contDomCon);
cErr = new ControladorErrores(contDomCon,cMed);
labelImagen = new JLabel();
labelImagen.setSize(791, 677);
labelImagen.setIcon (new ImageIcon("VisualOBD4_1.jpg"));
VP.getJContentPane().add(labelImagen, null);
VP.initialize();
}
public void inicializar(){
VP.getJButtonConectar().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
contDomCon.establecerConexion(cP.cojerDatosConexion().getVelocidad(),
cP.cojerDatosConexion().getDataBits(), cP.cojerDatosConexion().getStopBits(),
cP.cojerDatosConexion().getParidad(), cP.cojerDatosConexion().getNombrePuerto(),
cProt.fijar_protocolo());
cMed.pararHilo=false;
cMed.inicializacion=true;
cMed.conectado=true;
}
});
VP.getJButtonDesconectar().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
cMed.pararHilo=true;
cMed.conectado=false;
if(cMed.lectura==true){
while(cMed.indica_hilo_destruido==false){
try {
Thread.sleep(10);
} catch (InterruptedException des) {
des.printStackTrace();
}
}
contDomCon.desconectar();
}else{
contDomCon.desconectar();
}
cMed.lectura=false;
}
});
VP.getJMenuItemPSerie().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(existe_panel==true){
VP.getJContentPane().remove(panel);
}
if(existe_label==true){
VP.getJContentPane().remove(labelImagen);
}
108
panel = cP.retornaPanel();
VP.getJContentPane().add(panel, null);
existe_panel=true;
VP.initialize();
}
});
VP.getJMenuItemProtocolo().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(existe_panel==true){
VP.getJContentPane().remove(panel);
}if(existe_label==true){
VP.getJContentPane().remove(labelImagen);
}
panel = cProt.devuelve_panel();
VP.getJContentPane().add(panel, null);
existe_panel=true;
VP.initialize();
}
});
VP.getJMenuItemErrores().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(existe_panel==true){
VP.getJContentPane().remove(panel);
}if(existe_label==true){
VP.getJContentPane().remove(labelImagen);
}
panel = cErr.devuelve_panel();
VP.getJContentPane().add(panel, null);
existe_panel=true;
VP.initialize();
}
});
VP.getJMenuItemLectura().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(existe_panel==true){
VP.getJContentPane().remove(panel);
}if(existe_label==true){
VP.getJContentPane().remove(labelImagen);
}
panel = cMed.devuelve_panel();
VP.getJContentPane().add(panel, null);
existe_panel=true;
VP.initialize();
}
});
VP.getJMenuItemPresentacion().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(existe_panel==true){
VP.getJContentPane().remove(panel);
}if(existe_label==true){
VP.getJContentPane().remove(labelImagen);
}
labelImagen.setSize(791, 677);
labelImagen.setIcon (new ImageIcon("VisualOBD4_1.jpg"));
VP.getJContentPane().add(labelImagen, null);
existe_label=true;
VP.initialize();
}
});
109
VP.getJMenuItemExit().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
System.exit(0);
}
});
VP.getJButtonEnvioManual().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
contDomCon.permiteEnvioManual(true);
contDomCon.enviar(VP.getJTextFieldEnvioManual().getText());
VP.getJTextFieldEnvioManual().setText("");
}
});
VP.getJTextFieldEnvioManual().addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent e) {
if(e.getKeyCode()==10){
VP.getJButtonEnvioManual().doClick();
}
}
});
VP.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
VP.getJMenuItemAbout().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if(existe_panel==true){
VP.getJContentPane().remove(panel);
}if(existe_label==true){
VP.getJContentPane().remove(labelImagen);
}
labelImagen.setSize(791, 677);
labelImagen.setIcon (new ImageIcon("AboutVisualOBD.jpg"));
VP.getJContentPane().add(labelImagen, null);
existe_label=true;
VP.initialize();
}
});
}
public static void main (String args[]){
ControladorPrincipal conPrin = new ControladorPrincipal();
conPrin.inicializar();
}
}
Clase ControladorProtocolo:
package Presentacion;
import javax.swing.JPanel;
import Dominio.ControladorDominioConexion;
110
public class ControladorProtocolo {
VistaProtocolo VProt;
String protocolo;
ControladorDominioConexion contDom;
public ControladorProtocolo(ControladorDominioConexion contDom){
VProt = new VistaProtocolo();
this.contDom = contDom;
eventos();
}
public String fijar_protocolo(){
if(VProt.getJRadioButtonAutomatico().isSelected()==true){
protocolo="atsp0";
}
if(VProt.getJRadioButtonPWM().isSelected()==true){
protocolo="atsp1";
}
if(VProt.getJRadioButtonVPW().isSelected()==true){
protocolo="atsp2";
}
if(VProt.getJRadioButtonISO().isSelected()==true){
protocolo="atsp3";
}
if(VProt.getJRadioButtonKWP1().isSelected()==true){
protocolo="atsp4";
}
if(VProt.getJRadioButtonKWP2().isSelected()==true){
protocolo="atsp5";
}
if(VProt.getJRadioButtonCAN1().isSelected()==true){
protocolo="atsp6";
}
if(VProt.getJRadioButtonCAN2().isSelected()==true){
protocolo="atsp7";
}
if(VProt.getJRadioButtonCAN3().isSelected()==true){
protocolo="atsp8";
}
if(VProt.getJRadioButtonCAN4().isSelected()==true){
protocolo="atsp9";
}
return protocolo;
}
public JPanel devuelve_panel(){
return this.VProt;
}
public void eventos(){
VProt.getJComboBoxPrio1().setEnabled(false);
VProt.getJComboBoxPrio2().setEnabled(false);
VProt.getJComboBoxRec1().setEnabled(false);
VProt.getJComboBoxRec2().setEnabled(false);
VProt.getJComboBoxTran1().setEnabled(false);
VProt.getJComboBoxTran2().setEnabled(false);
VProt.getJButtonAplByHead().setVisible(false);
VProt.getJButtonAplByHead().addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent e) {
111
contDom.enviar("atsh
"+VProt.getJComboBoxPrio1().getSelectedItem()+VProt.getJComboBoxPrio2().getSelectedItem()+"
"+VProt.getJComboBoxRec1().getSelectedItem()+VProt.getJComboBoxRec2().getSelectedItem()+"
"+VProt.getJComboBoxTran1().getSelectedItem()+VProt.getJComboBoxTran2().getSelectedItem());
}
});
VProt.getJCheckBoxIntroHead().addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
if(VProt.getJCheckBoxIntroHead().isSelected()==true){
VProt.getJComboBoxPrio1().setEnabled(true);
VProt.getJComboBoxPrio2().setEnabled(true);
VProt.getJComboBoxRec1().setEnabled(true);
VProt.getJComboBoxRec2().setEnabled(true);
VProt.getJComboBoxTran1().setEnabled(true);
VProt.getJComboBoxTran2().setEnabled(true);
VProt.getJButtonAplByHead().setVisible(true);
}else{
VProt.getJComboBoxPrio1().setEnabled(false);
VProt.getJComboBoxPrio2().setEnabled(false);
VProt.getJComboBoxRec1().setEnabled(false);
VProt.getJComboBoxRec2().setEnabled(false);
VProt.getJComboBoxTran1().setEnabled(false);
VProt.getJComboBoxTran2().setEnabled(false);
VProt.getJButtonAplByHead().setVisible(false);
}
}
});
}
}
112
Clase ControladorPSerie:
package Presentacion;
import javax.swing.JPanel;
import Datos.Conexion;
import Dominio.ControladorDominioConexion;
public class ControladorPSerie {
VistaConfiguracio VC;
Conexion con;
ControladorDominioConexion contDom;
public ControladorPSerie(ControladorDominioConexion contDom){
VC = new VistaConfiguracio();
this.contDom = contDom;
eventos();
datosconexion();
}
public void eventos(){
VC.getJButtonIdentificarPuertos().addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
puertosDisponibles();
}
});
VC.getJButtonAplicar().addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
try{
if(contDom.estado_conexion()==true){
contDom.desconectar();
}
datosconexion();
}catch(Exception err){
}
}
});
}
public JPanel retornaPanel(){
return this.VC;
}
public void puertosDisponibles(){
VC.getJListListaPuertos().setListData(contDom.puertosdisponibles());
}
public Conexion cojerDatosConexion(){
return con;
}
public void datosconexion(){
con = new
Conexion(Integer.parseInt((String)VC.getJComboBoxVelocidad().getSelectedItem()),Integer.pars
eInt((String)VC.getJComboBoxDataBits().getSelectedItem()),(VC.getJComboBoxStopBits().getSele
ctedIndex())+1,VC.getJComboBoxParidad().getSelectedIndex(),VC.getJComboBoxNombrePort().getSe
lectedItem().toString(),"0100");
}
}
113
Clase VistaCodigosError:
package Presentacion;
import
import
import
import
import
import
import
java.awt.Dimension;
java.awt.Font;
javax.swing.JPanel;
javax.swing.JTextArea;
java.awt.Rectangle;
javax.swing.JButton;
javax.swing.JScrollPane;
public class VistaCodigosError extends JPanel {
private
private
private
private
private
static final long serialVersionUID = 1L;
JTextArea jTextAreaErrores = null;
JButton jButtonErrores = null;
JScrollPane jScrollPaneErrores = null;
JButton jButtonBorrarErrores = null;
public VistaCodigosError() {
super();
initialize();
}
private void initialize() {
this.setSize(new Dimension(800, 677));
this.setLayout(null);
this.add(getJTextAreaErrores(), null);
this.add(getJButtonErrores(), null);
this.add(getJScrollPaneErrores(), null);
this.add(getJButtonBorrarErrores(), null);
}
public JTextArea getJTextAreaErrores() {
if (jTextAreaErrores == null) {
jTextAreaErrores = new JTextArea();
jTextAreaErrores.setBounds(new Rectangle(77, 88, 182, 155));
jTextAreaErrores.setFont(new Font("Dialog", Font.BOLD, 19));
jTextAreaErrores.setEditable(false);
}
return jTextAreaErrores;
}
public JButton getJButtonErrores() {
if (jButtonErrores == null) {
jButtonErrores = new JButton();
jButtonErrores.setBounds(new Rectangle(7, 650, 177, 20));
jButtonErrores.setText("Read error codes");
}
return jButtonErrores;
}
private JScrollPane getJScrollPaneErrores() {
if (jScrollPaneErrores == null) {
jScrollPaneErrores = new
JScrollPane(getJTextAreaErrores(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONT
AL_SCROLLBAR_ALWAYS);
jScrollPaneErrores.setBounds(new Rectangle(7, 7, 784, 637));
}
return jScrollPaneErrores;
}
114
public JButton getJButtonBorrarErrores() {
if (jButtonBorrarErrores == null) {
jButtonBorrarErrores = new JButton();
jButtonBorrarErrores.setBounds(new Rectangle(183, 650, 183, 20));
jButtonBorrarErrores.setText("Clear error codes");
}
return jButtonBorrarErrores;
}
}
Clase VistaConfiguracion:
package Presentacion;
import
import
import
import
import
import
import
import
import
import
import
javax.swing.JPanel;
java.awt.Dimension;
javax.swing.JComboBox;
java.awt.Rectangle;
java.awt.Color;
java.awt.Point;
javax.swing.JLabel;
java.awt.Font;
javax.swing.JButton;
javax.swing.JList;
javax.swing.JScrollPane;
public class VistaConfiguracion extends JPanel {
private static final long serialVersionUID = 1L;
private JComboBox jComboBoxNombrePort = null;
private JComboBox jComboBoxDataBits = null;
private JComboBox jComboBoxStopBits = null;
private JComboBox jComboBoxParidad = null;
private JComboBox jComboBoxVelocidad = null;
private JLabel jLabelTituloPserie = null;
private JLabel jLabelVelocidad = null;
private JLabel jLabelNombrePuerto = null;
private JLabel jLabelBitsDatos = null;
private JLabel jLabelBitsStop = null;
private JLabel jLabelParidad = null;
private JButton jButtonAplicar = null;
private JButton jButtonIdentificarPuertos = null;
String [] puertos
={"COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","COM10","COM11","COM12","/d
ev/ttyS0","/dev/ttyS1","/dev/ttyACM0","/dev/ttyACM1","/dev/ttyUSB0","/dev/ttyUSB1"};
String [] velocidad
={"75","110","134","150","300","600","1200","1800","2400","4800","7200","9600","14400","1920
0","38400","57600","115200","128000"};
String [] bitsDatos ={"4","5","6","7","8"};
String [] paridad ={"Ninguno","Impar","Par","Marca","Espacio"};
String [] bitsParada ={"1","2","1,5"};
private JList jListListaPuertos = null;
private JScrollPane jScrollPaneListaPuertos = null;
public VistaConfiguracion() {
super();
initialize();
}
115
private void initialize() {
jLabelParidad = new JLabel();
jLabelParidad.setBounds(new Rectangle(30, 385, 68, 17));
jLabelParidad.setText("Parity:");
jLabelParidad.setFont(new Font("Dialog", Font.BOLD, 14));
jLabelBitsStop = new JLabel();
jLabelBitsStop.setBounds(new Rectangle(30, 310, 90, 17));
jLabelBitsStop.setText("Stop bits:");
jLabelBitsStop.setFont(new Font("Dialog", Font.BOLD, 14));
jLabelBitsDatos = new JLabel();
jLabelBitsDatos.setBounds(new Rectangle(30, 235, 88, 17));
jLabelBitsDatos.setText("Data bits:");
jLabelBitsDatos.setFont(new Font("Dialog", Font.BOLD, 14));
jLabelNombrePuerto = new JLabel();
jLabelNombrePuerto.setBounds(new Rectangle(30, 85, 122, 17));
jLabelNombrePuerto.setText("Port Identifier:");
jLabelNombrePuerto.setFont(new Font("Dialog", Font.BOLD, 14));
jLabelVelocidad = new JLabel();
jLabelVelocidad.setBounds(new Rectangle(30, 160, 79, 17));
jLabelVelocidad.setText("Bit rate:");
jLabelVelocidad.setFont(new Font("Dialog", Font.BOLD, 14));
jLabelTituloPserie = new JLabel();
jLabelTituloPserie.setBounds(new Rectangle(30, 25, 257, 26));
jLabelTituloPserie.setFont(new Font("Dialog", Font.BOLD, 18));
jLabelTituloPserie.setText("Serial port configuration");
this.setLayout(null);
this.setBackground(new Color(238, 238, 238));
this.setLocation(new Point(0, 0));
this.setSize(new Dimension(800, 675));
this.add(getJComboBoxNombrePort(), null);
this.add(getJComboBoxDataBits(), null);
this.add(getJComboBoxStopBits(), null);
this.add(getJComboBoxParidad(), null);
this.add(getJComboBoxVelocidad(), null);
this.add(jLabelTituloPserie, null);
this.add(jLabelVelocidad, null);
this.add(jLabelNombrePuerto, null);
this.add(jLabelBitsDatos, null);
this.add(jLabelBitsStop, null);
this.add(jLabelParidad, null);
this.add(getJButtonAplicar(), null);
this.add(getJButtonIdentificarPuertos(), null);
this.add(getJScrollPaneListaPuertos(), null);
}
public JComboBox getJComboBoxNombrePort() {
if (jComboBoxNombrePort == null) {
jComboBoxNombrePort = new JComboBox(puertos);
jComboBoxNombrePort.setBounds(new Rectangle(30, 105, 135, 25));
jComboBoxNombrePort.setSelectedIndex(0);
}
return jComboBoxNombrePort;
}
public JComboBox getJComboBoxDataBits() {
if (jComboBoxDataBits == null) {
jComboBoxDataBits = new JComboBox(bitsDatos);
jComboBoxDataBits.setBounds(new Rectangle(30, 255, 135, 25));
jComboBoxDataBits.setSelectedIndex(4);
}
return jComboBoxDataBits;
}
116
public JComboBox getJComboBoxStopBits() {
if (jComboBoxStopBits == null) {
jComboBoxStopBits = new JComboBox(bitsParada);
jComboBoxStopBits.setBounds(new Rectangle(30, 330, 135, 25));
jComboBoxStopBits.setSelectedIndex(0);
}
return jComboBoxStopBits;
}
public JComboBox getJComboBoxParidad() {
if (jComboBoxParidad == null) {
jComboBoxParidad = new JComboBox(paridad);
jComboBoxParidad.setBounds(new Rectangle(30, 405, 135, 25));
jComboBoxParidad.setSelectedIndex(0);
}
return jComboBoxParidad;
}
public JComboBox getJComboBoxVelocidad() {
if (jComboBoxVelocidad == null) {
jComboBoxVelocidad = new JComboBox(velocidad);
jComboBoxVelocidad.setBounds(new Rectangle(30, 180, 135, 25));
jComboBoxVelocidad.setSelectedIndex(14);
}
return jComboBoxVelocidad;
}
public JButton getJButtonAplicar() {
if (jButtonAplicar == null) {
jButtonAplicar = new JButton();
jButtonAplicar.setBounds(new Rectangle(30, 648, 115, 20));
jButtonAplicar.setText("Apply");
}
return jButtonAplicar;
}
public JButton getJButtonIdentificarPuertos() {
if (jButtonIdentificarPuertos == null) {
jButtonIdentificarPuertos = new JButton();
jButtonIdentificarPuertos.setBounds(new Rectangle(30, 520, 209, 19));
jButtonIdentificarPuertos.setText("Search for available ports");
}
return jButtonIdentificarPuertos;
}
public JList getJListListaPuertos() {
if (jListListaPuertos == null) {
jListListaPuertos = new JList();
jListListaPuertos.setEnabled(false);
jListListaPuertos.setFont(new Font("Dialog", Font.BOLD, 12));
}
return jListListaPuertos;
}
private JScrollPane getJScrollPaneListaPuertos() {
if (jScrollPaneListaPuertos == null) {
jScrollPaneListaPuertos = new JScrollPane();
jScrollPaneListaPuertos.setBounds(new Rectangle(30, 540, 209, 58));
jScrollPaneListaPuertos.setViewportView(getJListListaPuertos());
}
return jScrollPaneListaPuertos;
}
}
117
Clase VistaMediciones:
package Presentacion;
import
import
import
import
import
import
import
import
java.awt.Color;
java.awt.Font;
javax.swing.JPanel;
javax.swing.JTabbedPane;
java.awt.Rectangle;
javax.swing.JTextField;
javax.swing.JLabel;
javax.swing.JButton;
public class VistaMediciones extends JPanel {
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
static final long serialVersionUID = 1L;
JTabbedPane jTabbedPane = null;
JPanel jPanel4_19 = null;
JPanel jPanel21_40 = null;
JPanel jPanel41_60 = null;
JTextField jTextField04 = null;
JTextField jTextField05 = null;
JTextField jTextField06 = null;
JTextField jTextField07 = null;
JTextField jTextField08 = null;
JTextField jTextField09 = null;
JTextField jTextField0A = null;
JTextField jTextField0B = null;
JTextField jTextField0C = null;
JTextField jTextField0D = null;
JTextField jTextField0E = null;
JTextField jTextField0F = null;
JTextField jTextField10 = null;
JTextField jTextField11 = null;
JTextField jTextField12 = null;
JTextField jTextField14 = null;
JTextField jTextField15 = null;
JTextField jTextField16 = null;
JTextField jTextField17 = null;
JTextField jTextField18 = null;
JTextField jTextField19 = null;
JTextField jTextField1A = null;
JTextField jTextField1B = null;
JTextField jTextField1E = null;
JTextField jTextField1F = null;
JTextField jTextField24 = null;
JTextField jTextField25 = null;
JTextField jTextField26 = null;
JTextField jTextField27 = null;
JTextField jTextField28 = null;
JTextField jTextField29 = null;
JTextField jTextField2A = null;
JTextField jTextField2B = null;
JTextField jTextField2C = null;
JTextField jTextField2D = null;
JTextField jTextField2E = null;
JTextField jTextField2F = null;
JTextField jTextField33 = null;
JTextField jTextField31 = null;
JTextField jTextField32 = null;
JTextField jTextField34 = null;
JTextField jTextField35 = null;
JTextField jTextField36 = null;
118
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
JTextField jTextField37 = null;
JTextField jTextField38 = null;
JTextField jTextField39 = null;
JTextField jTextField3A = null;
JTextField jTextField3B = null;
JTextField jTextField3E = null;
JTextField jTextField3F = null;
JLabel jLabel04 = null;
JLabel jLabel05 = null;
JLabel jLabel06 = null;
JLabel jLabel07 = null;
JLabel jLabel08 = null;
JLabel jLabel09 = null;
JLabel jLabel0A = null;
JLabel jLabel0B = null;
JLabel jLabel0C = null;
JLabel jLabel0D = null;
JLabel jLabel0E = null;
JLabel jLabel0F = null;
JLabel jLabel10 = null;
JLabel jLabel11 = null;
JLabel jLabel12 = null;
JLabel jLabel14 = null;
JLabel jLabel15 = null;
JLabel jLabel16 = null;
JLabel jLabel18 = null;
JLabel jLabel19 = null;
JLabel jLabel17 = null;
JLabel jLabel1A = null;
JLabel jLabel1E = null;
JLabel jLabel1B = null;
JLabel jLabel1F = null;
JLabel jLabel24 = null;
JLabel jLabel25 = null;
JLabel jLabel26 = null;
JLabel jLabel27 = null;
JLabel jLabel28 = null;
JLabel jLabel29 = null;
JLabel jLabel2A = null;
JLabel jLabel2B = null;
JLabel jLabel2C = null;
JLabel jLabel2D = null;
JLabel jLabel2E = null;
JLabel jLabel2F = null;
JLabel jLabel33 = null;
JLabel jLabel31 = null;
JLabel jLabel32 = null;
JLabel jLabel34 = null;
JLabel jLabel35 = null;
JLabel jLabel36 = null;
JLabel jLabel38 = null;
JLabel jLabel39 = null;
JLabel jLabel37 = null;
JLabel jLabel3A = null;
JLabel jLabel3E = null;
JLabel jLabel3B = null;
JLabel jLabel3F = null;
JLabel jLabel12_1 = null;
JLabel jLabel12_2 = null;
JLabel jLabelSensores = null;
JTextField jTextField21 = null;
JTextField jTextField22 = null;
JTextField jTextField23 = null;
119
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
JLabel jLabel21 = null;
JLabel jLabel22 = null;
JLabel jLabel23 = null;
JLabel jLabel21_1 = null;
JTextField jTextField3C = null;
JTextField jTextField3D = null;
JLabel jLabel3C = null;
JLabel jLabel3D = null;
JButton jButtonLeer = null;
JButton jButtonDetener = null;
JTextField jTextField42 = null;
JTextField jTextField43 = null;
JTextField jTextField44 = null;
JTextField jTextField45 = null;
JTextField jTextField46 = null;
JTextField jTextField47 = null;
JTextField jTextField48 = null;
JTextField jTextField49 = null;
JTextField jTextField4A = null;
JTextField jTextField4B = null;
JTextField jTextField4C = null;
JTextField jTextField4D = null;
JTextField jTextField4E = null;
JLabel jLabel42 = null;
JLabel jLabel43 = null;
JLabel jLabel44 = null;
JLabel jLabel45 = null;
JLabel jLabel46 = null;
JLabel jLabel47 = null;
JLabel jLabel48 = null;
JLabel jLabel49 = null;
JLabel jLabel4A = null;
JLabel jLabel4B = null;
JLabel jLabel4C = null;
JLabel jLabel4D = null;
JLabel jLabel4E = null;
JTextField jTextField51 = null;
JLabel jLabel51 = null;
JLabel jLabel52 = null;
JTextField jTextField52 = null;
JTextField jTextField1C = null;
JLabel jLabel1C = null;
public VistaMediciones() {
super();
initialize();
}
private void initialize() {
this.setSize(803, 676);
this.setLayout(null);
this.add(getJTabbedPane(), null);
this.add(getJButtonLeer(), null);
this.add(getJButtonDetener(), null);
}
private JTabbedPane getJTabbedPane() {
if (jTabbedPane == null) {
jTabbedPane = new JTabbedPane();
jTabbedPane.setBounds(new Rectangle(6, 6, 788, 638));
jTabbedPane.addTab("
PID's 4-19
getJPanel4_19(), null);
", null,
120
jTabbedPane.addTab("
getJPanel21_40(), null);
jTabbedPane.addTab("
getJPanel41_60(), null);
}
return jTabbedPane;
}
PID's 21-40
", null,
PID's 41-60
", null,
private JPanel getJPanel4_19() {
if (jPanel4_19 == null) {
jLabel1C = new JLabel();
jLabel1C.setBounds(new Rectangle(5, 505, 287, 16));
jLabel1C.setFont(new Font("Dialog", Font.BOLD, 14));
jLabel1C.setText("This vehicle conforms the standards:");
jLabelSensores = new JLabel();
jLabelSensores.setBounds(new Rectangle(380, 145, 335, 17));
jLabelSensores.setText("Oxygen sensor voltage, Short term fuel trim");
jLabelSensores.setFont(new Font("Dialog", Font.BOLD, 14));
jLabel12_2 = new JLabel();
jLabel12_2.setBounds(new Rectangle(675, 121, 78, 17));
jLabel12_2.setText("air status");
jLabel12_2.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel12_1 = new JLabel();
jLabel12_1.setBounds(new Rectangle(675, 103, 85, 17));
jLabel12_1.setText("secondary");
jLabel12_1.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel1F = new JLabel();
jLabel1F.setBounds(new Rectangle(525, 525, 198, 17));
jLabel1F.setText("Run time since engine start");
jLabel1F.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel1B = new JLabel();
jLabel1B.setBounds(new Rectangle(525, 445, 138, 17));
jLabel1B.setText("Bank 2, Sensor 4");
jLabel1B.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel1E = new JLabel();
jLabel1E.setBounds(new Rectangle(525, 485, 152, 17));
jLabel1E.setText("Auxiliary input status");
jLabel1E.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel1A = new JLabel();
jLabel1A.setBounds(new Rectangle(525, 405, 138, 17));
jLabel1A.setText("Bank 2, Sensor 3");
jLabel1A.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel17 = new JLabel();
jLabel17.setBounds(new Rectangle(525, 285, 136, 17));
jLabel17.setText("Bank 1, Sensor 4");
jLabel17.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel19 = new JLabel();
jLabel19.setBounds(new Rectangle(525, 365, 138, 17));
jLabel19.setText("Bank 2, Sensor 2");
jLabel19.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel18 = new JLabel();
jLabel18.setBounds(new Rectangle(525, 325, 136, 17));
jLabel18.setText("Bank 2, Sensor 1");
jLabel18.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel16 = new JLabel();
jLabel16.setBounds(new Rectangle(525, 245, 136, 17));
jLabel16.setText("Bank 1, Sensor 3");
jLabel16.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel15 = new JLabel();
jLabel15.setBounds(new Rectangle(525, 205, 134, 17));
jLabel15.setText("Bank 1, Sensor 2");
jLabel15.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel14 = new JLabel();
121
jLabel14.setBounds(new Rectangle(525, 165, 133, 17));
jLabel14.setText("Bank 1, Sensor 1");
jLabel14.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel12 = new JLabel();
jLabel12.setBounds(new Rectangle(675, 85, 99, 17));
jLabel12.setText("Commanded ");
jLabel12.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel11 = new JLabel();
jLabel11.setBounds(new Rectangle(525, 45, 132, 17));
jLabel11.setText("Throttle position");
jLabel11.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel10 = new JLabel();
jLabel10.setBounds(new Rectangle(525, 5, 132, 17));
jLabel10.setText("MAF air flow rate");
jLabel10.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel0F = new JLabel();
jLabel0F.setBounds(new Rectangle(150, 445, 167, 17));
jLabel0F.setText("Intake air temperature");
jLabel0F.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel0E = new JLabel();
jLabel0E.setBounds(new Rectangle(150, 405, 133, 17));
jLabel0E.setText("Timing advance");
jLabel0E.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel0D = new JLabel();
jLabel0D.setBounds(new Rectangle(150, 365, 120, 17));
jLabel0D.setText("Vehicle speed");
jLabel0D.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel0C = new JLabel();
jLabel0C.setBounds(new Rectangle(150, 325, 104, 17));
jLabel0C.setText("Engine RPM");
jLabel0C.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel0B = new JLabel();
jLabel0B.setBounds(new Rectangle(150, 285, 186, 17));
jLabel0B.setText("Intake manifold pressure");
jLabel0B.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel0A = new JLabel();
jLabel0A.setBounds(new Rectangle(150, 245, 118, 17));
jLabel0A.setText("Fuel pressure");
jLabel0A.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel09 = new JLabel();
jLabel09.setBounds(new Rectangle(150, 205, 225, 17));
jLabel09.setText("Long term fuel % trim_Bank 2");
jLabel09.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel08 = new JLabel();
jLabel08.setBounds(new Rectangle(150, 165, 226, 17));
jLabel08.setText("Short term fuel % trim_Bank 2");
jLabel08.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel07 = new JLabel();
jLabel07.setBounds(new Rectangle(150, 125, 225, 17));
jLabel07.setText("Long term fuel % trim_Bank 1");
jLabel07.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel06 = new JLabel();
jLabel06.setBounds(new Rectangle(150, 85, 224, 17));
jLabel06.setText("Short term fuel % trim_Bank 1");
jLabel06.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel05 = new JLabel();
jLabel05.setBounds(new Rectangle(150, 45, 207, 17));
jLabel05.setText("Engine coolant temperature");
jLabel05.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel04 = new JLabel();
jLabel04.setBounds(new Rectangle(150, 5, 206, 17));
jLabel04.setText("Calculated engine load value");
jLabel04.setFont(new Font("Dialog", Font.PLAIN, 14));
122
jPanel4_19 = new JPanel();
jPanel4_19.setLayout(null);
jPanel4_19.add(getJTextField04(), null);
jPanel4_19.add(getJTextField05(), null);
jPanel4_19.add(getJTextField06(), null);
jPanel4_19.add(getJTextField07(), null);
jPanel4_19.add(getJTextField08(), null);
jPanel4_19.add(getJTextField09(), null);
jPanel4_19.add(getJTextField0A(), null);
jPanel4_19.add(getJTextField0B(), null);
jPanel4_19.add(getJTextField0C(), null);
jPanel4_19.add(getJTextField0D(), null);
jPanel4_19.add(getJTextField0E(), null);
jPanel4_19.add(getJTextField0F(), null);
jPanel4_19.add(getJTextField10(), null);
jPanel4_19.add(getJTextField11(), null);
jPanel4_19.add(getJTextField12(), null);
jPanel4_19.add(getJTextField14(), null);
jPanel4_19.add(getJTextField15(), null);
jPanel4_19.add(getJTextField16(), null);
jPanel4_19.add(getJTextField17(), null);
jPanel4_19.add(getJTextField18(), null);
jPanel4_19.add(getJTextField19(), null);
jPanel4_19.add(getJTextField1A(), null);
jPanel4_19.add(getJTextField1B(), null);
jPanel4_19.add(getJTextField1E(), null);
jPanel4_19.add(getJTextField1F(), null);
jPanel4_19.add(jLabel04, null);
jPanel4_19.add(jLabel05, null);
jPanel4_19.add(jLabel06, null);
jPanel4_19.add(jLabel07, null);
jPanel4_19.add(jLabel08, null);
jPanel4_19.add(jLabel09, null);
jPanel4_19.add(jLabel0A, null);
jPanel4_19.add(jLabel0B, null);
jPanel4_19.add(jLabel0C, null);
jPanel4_19.add(jLabel0D, null);
jPanel4_19.add(jLabel0E, null);
jPanel4_19.add(jLabel0F, null);
jPanel4_19.add(jLabel10, null);
jPanel4_19.add(jLabel11, null);
jPanel4_19.add(jLabel12, null);
jPanel4_19.add(jLabel14, null);
jPanel4_19.add(jLabel15, null);
jPanel4_19.add(jLabel16, null);
jPanel4_19.add(jLabel18, null);
jPanel4_19.add(jLabel19, null);
jPanel4_19.add(jLabel17, null);
jPanel4_19.add(jLabel1A, null);
jPanel4_19.add(jLabel1E, null);
jPanel4_19.add(jLabel1B, null);
jPanel4_19.add(jLabel1F, null);
jPanel4_19.add(jLabel12_1, null);
jPanel4_19.add(jLabel12_2, null);
jPanel4_19.add(jLabelSensores, null);
jPanel4_19.add(getJTextField1C(), null);
jPanel4_19.add(jLabel1C, null);
}
return jPanel4_19;
}
123
private JPanel getJPanel21_40() {
if (jPanel21_40 == null) {
jLabel3D = new JLabel();
jLabel3D.setBounds(new Rectangle(525, 485, 258, 16));
jLabel3D.setText("Catalyst Temperature Bank2, Sensor1");
jLabel3D.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel3C = new JLabel();
jLabel3C.setBounds(new Rectangle(525, 445, 258, 16));
jLabel3C.setText("Catalyst Temperature Bank1, Sensor1");
jLabel3C.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel21_1 = new JLabel();
jLabel21_1.setBounds(new Rectangle(145, 23, 166, 17));
jLabel21_1.setText("indicator lamp (MIL) on");
jLabel21_1.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel23 = new JLabel();
jLabel23.setBounds(new Rectangle(150, 85, 192, 16));
jLabel23.setText("Fuel Rail Pressure (diesel)");
jLabel23.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel22 = new JLabel();
jLabel22.setBounds(new Rectangle(150, 45, 170, 17));
jLabel22.setText("Fuel Rail Pressure");
jLabel22.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel21 = new JLabel();
jLabel21.setBounds(new Rectangle(145, 5, 243, 17));
jLabel21.setText("Distance traveled with malfunction");
jLabel21.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel3F = new JLabel();
jLabel3F.setBounds(new Rectangle(525, 565, 258, 17));
jLabel3F.setText("Catalyst Temperature Bank2, Sensor2");
jLabel3F.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel3B = new JLabel();
jLabel3B.setBounds(new Rectangle(525, 405, 221, 17));
jLabel3B.setText("O2S8_WR_lambda(1): Current");
jLabel3B.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel3E = new JLabel();
jLabel3E.setBounds(new Rectangle(525, 525, 258, 17));
jLabel3E.setText("Catalyst Temperature Bank1, Sensor2");
jLabel3E.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel3A = new JLabel();
jLabel3A.setBounds(new Rectangle(525, 365, 223, 17));
jLabel3A.setText("O2S7_WR_lambda(1): Current");
jLabel3A.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel37 = new JLabel();
jLabel37.setBounds(new Rectangle(525, 245, 220, 17));
jLabel37.setText("O2S4_WR_lambda(1): Current");
jLabel37.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel39 = new JLabel();
jLabel39.setBounds(new Rectangle(525, 325, 222, 17));
jLabel39.setText("O2S6_WR_lambda(1): Current");
jLabel39.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel38 = new JLabel();
jLabel38.setBounds(new Rectangle(525, 285, 220, 17));
jLabel38.setText("O2S5_WR_lambda(1): Current");
jLabel38.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel36 = new JLabel();
jLabel36.setBounds(new Rectangle(525, 205, 221, 17));
jLabel36.setText("O2S3_WR_lambda(1): Current");
jLabel36.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel35 = new JLabel();
jLabel35.setBounds(new Rectangle(525, 165, 222, 17));
jLabel35.setText("O2S2_WR_lambda(1): Current");
jLabel35.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel34 = new JLabel();
124
jLabel34.setBounds(new Rectangle(525, 125, 223, 17));
jLabel34.setText("O2S1_WR_lambda(1): Current");
jLabel34.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel32 = new JLabel();
jLabel32.setBounds(new Rectangle(525, 45, 216, 17));
jLabel32.setText("Evap. System Vapor Pressure");
jLabel32.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel31 = new JLabel();
jLabel31.setBounds(new Rectangle(525, 5, 257, 17));
jLabel31.setText("Distance traveled since codes cleared");
jLabel31.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel33 = new JLabel();
jLabel33.setBounds(new Rectangle(525, 85, 159, 17));
jLabel33.setText("Barometric pressure");
jLabel33.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel2F = new JLabel();
jLabel2F.setBounds(new Rectangle(150, 565, 127, 17));
jLabel2F.setText("Fuel Level Input");
jLabel2F.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel2E = new JLabel();
jLabel2E.setBounds(new Rectangle(150, 525, 224, 17));
jLabel2E.setText("Commanded evaporative purge");
jLabel2E.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel2D = new JLabel();
jLabel2D.setBounds(new Rectangle(150, 485, 89, 17));
jLabel2D.setText("EGR Error");
jLabel2D.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel2C = new JLabel();
jLabel2C.setBounds(new Rectangle(150, 445, 153, 17));
jLabel2C.setText("Commanded EGR");
jLabel2C.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel2B = new JLabel();
jLabel2B.setBounds(new Rectangle(150, 405, 224, 17));
jLabel2B.setText("O2S8_WR_lambda(1): Voltage");
jLabel2B.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel2A = new JLabel();
jLabel2A.setBounds(new Rectangle(150, 365, 225, 17));
jLabel2A.setText("O2S7_WR_lambda(1): Voltage");
jLabel2A.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel29 = new JLabel();
jLabel29.setBounds(new Rectangle(150, 325, 226, 17));
jLabel29.setText("O2S6_WR_lambda(1): Voltage");
jLabel29.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel28 = new JLabel();
jLabel28.setBounds(new Rectangle(150, 285, 225, 17));
jLabel28.setText("O2S5_WR_lambda(1): Voltage");
jLabel28.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel27 = new JLabel();
jLabel27.setBounds(new Rectangle(150, 245, 225, 17));
jLabel27.setText("O2S4_WR_lambda(1): Voltage");
jLabel27.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel26 = new JLabel();
jLabel26.setBounds(new Rectangle(150, 205, 227, 17));
jLabel26.setText("O2S3_WR_lambda(1): Voltage");
jLabel26.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel25 = new JLabel();
jLabel25.setBounds(new Rectangle(150, 165, 225, 17));
jLabel25.setText("O2S2_WR_lambda(1): Voltage");
jLabel25.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel24 = new JLabel();
jLabel24.setBounds(new Rectangle(150, 125, 227, 17));
jLabel24.setText("O2S1_WR_lambda(1): Voltage");
jLabel24.setFont(new Font("Dialog", Font.PLAIN, 14));
125
jPanel21_40 = new JPanel();
jPanel21_40.setLayout(null);
jPanel21_40.add(getJTextField24(),
jPanel21_40.add(getJTextField25(),
jPanel21_40.add(getJTextField26(),
jPanel21_40.add(getJTextField27(),
jPanel21_40.add(getJTextField28(),
jPanel21_40.add(getJTextField29(),
jPanel21_40.add(getJTextField2A(),
jPanel21_40.add(getJTextField2B(),
jPanel21_40.add(getJTextField2C(),
jPanel21_40.add(getJTextField2D(),
jPanel21_40.add(getJTextField2E(),
jPanel21_40.add(getJTextField2F(),
jPanel21_40.add(getJTextField33(),
jPanel21_40.add(getJTextField31(),
jPanel21_40.add(getJTextField32(),
jPanel21_40.add(getJTextField34(),
jPanel21_40.add(getJTextField35(),
jPanel21_40.add(getJTextField36(),
jPanel21_40.add(getJTextField37(),
jPanel21_40.add(getJTextField38(),
jPanel21_40.add(getJTextField39(),
jPanel21_40.add(getJTextField3A(),
jPanel21_40.add(getJTextField3B(),
jPanel21_40.add(getJTextField3E(),
jPanel21_40.add(getJTextField3F(),
jPanel21_40.add(jLabel24, null);
jPanel21_40.add(jLabel25, null);
jPanel21_40.add(jLabel26, null);
jPanel21_40.add(jLabel27, null);
jPanel21_40.add(jLabel28, null);
jPanel21_40.add(jLabel29, null);
jPanel21_40.add(jLabel2A, null);
jPanel21_40.add(jLabel2B, null);
jPanel21_40.add(jLabel2C, null);
jPanel21_40.add(jLabel2D, null);
jPanel21_40.add(jLabel2E, null);
jPanel21_40.add(jLabel2F, null);
jPanel21_40.add(jLabel33, null);
jPanel21_40.add(jLabel31, null);
jPanel21_40.add(jLabel32, null);
jPanel21_40.add(jLabel34, null);
jPanel21_40.add(jLabel35, null);
jPanel21_40.add(jLabel36, null);
jPanel21_40.add(jLabel38, null);
jPanel21_40.add(jLabel39, null);
jPanel21_40.add(jLabel37, null);
jPanel21_40.add(jLabel3A, null);
jPanel21_40.add(jLabel3E, null);
jPanel21_40.add(jLabel3B, null);
jPanel21_40.add(jLabel3F, null);
jPanel21_40.add(getJTextField21(),
jPanel21_40.add(getJTextField22(),
jPanel21_40.add(getJTextField23(),
jPanel21_40.add(jLabel21, null);
jPanel21_40.add(jLabel22, null);
jPanel21_40.add(jLabel23, null);
jPanel21_40.add(jLabel21_1, null);
jPanel21_40.add(getJTextField3C(),
jPanel21_40.add(getJTextField3D(),
jPanel21_40.add(jLabel3C, null);
jPanel21_40.add(jLabel3D, null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
null);
126
}
return jPanel21_40;
}
private JPanel getJPanel41_60() {
if (jPanel41_60 == null) {
jLabel52 = new JLabel();
jLabel52.setBounds(new Rectangle(525, 85, 123, 19));
jLabel52.setText("\tEthanol fuel %");
jLabel52.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel51 = new JLabel();
jLabel51.setBounds(new Rectangle(380, 5, 99, 19));
jLabel51.setText("Fuel Type:");
jLabel51.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel4E = new JLabel();
jLabel4E.setBounds(new Rectangle(150, 485, 239, 19));
jLabel4E.setText("Time since trouble codes cleared");
jLabel4E.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel4D = new JLabel();
jLabel4D.setBounds(new Rectangle(150, 445, 163, 19));
jLabel4D.setText("Time run with MIL on");
jLabel4D.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel4C = new JLabel();
jLabel4C.setBounds(new Rectangle(150, 405, 216, 19));
jLabel4C.setText("Commanded throttle actuator");
jLabel4C.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel4B = new JLabel();
jLabel4B.setBounds(new Rectangle(150, 365, 209, 19));
jLabel4B.setText("Accelerator pedal position F");
jLabel4B.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel4A = new JLabel();
jLabel4A.setBounds(new Rectangle(150, 325, 209, 19));
jLabel4A.setText("Accelerator pedal position E");
jLabel4A.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel49 = new JLabel();
jLabel49.setBounds(new Rectangle(150, 285, 211, 19));
jLabel49.setText("Accelerator pedal position D");
jLabel49.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel48 = new JLabel();
jLabel48.setBounds(new Rectangle(150, 245, 194, 19));
jLabel48.setText("Absolute throttle position C");
jLabel48.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel47 = new JLabel();
jLabel47.setBounds(new Rectangle(150, 205, 194, 19));
jLabel47.setText("Absolute throttle position B");
jLabel47.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel46 = new JLabel();
jLabel46.setBounds(new Rectangle(150, 165, 182, 19));
jLabel46.setText("Ambient air temperature");
jLabel46.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel45 = new JLabel();
jLabel45.setBounds(new Rectangle(150, 125, 179, 19));
jLabel45.setText("Relative throttle position");
jLabel45.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel44 = new JLabel();
jLabel44.setBounds(new Rectangle(150, 85, 201, 19));
jLabel44.setText("Command equivalence ratio");
jLabel44.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel43 = new JLabel();
jLabel43.setBounds(new Rectangle(150, 45, 147, 19));
jLabel43.setText("Absolute load value");
jLabel43.setFont(new Font("Dialog", Font.PLAIN, 14));
jLabel42 = new JLabel();
127
jLabel42.setBounds(new Rectangle(150, 5, 176, 19));
jLabel42.setText("Control module voltage");
jLabel42.setFont(new Font("Dialog", Font.PLAIN, 14));
jPanel41_60 = new JPanel();
jPanel41_60.setLayout(null);
jPanel41_60.add(getJTextField42(), null);
jPanel41_60.add(getJTextField43(), null);
jPanel41_60.add(getJTextField44(), null);
jPanel41_60.add(getJTextField45(), null);
jPanel41_60.add(getJTextField46(), null);
jPanel41_60.add(getJTextField47(), null);
jPanel41_60.add(getJTextField48(), null);
jPanel41_60.add(getJTextField49(), null);
jPanel41_60.add(getJTextField4A(), null);
jPanel41_60.add(getJTextField4B(), null);
jPanel41_60.add(getJTextField4C(), null);
jPanel41_60.add(getJTextField4D(), null);
jPanel41_60.add(getJTextField4E(), null);
jPanel41_60.add(jLabel42, null);
jPanel41_60.add(jLabel43, null);
jPanel41_60.add(jLabel44, null);
jPanel41_60.add(jLabel45, null);
jPanel41_60.add(jLabel46, null);
jPanel41_60.add(jLabel47, null);
jPanel41_60.add(jLabel48, null);
jPanel41_60.add(jLabel49, null);
jPanel41_60.add(jLabel4A, null);
jPanel41_60.add(jLabel4B, null);
jPanel41_60.add(jLabel4C, null);
jPanel41_60.add(jLabel4D, null);
jPanel41_60.add(jLabel4E, null);
jPanel41_60.add(getJTextField51(), null);
jPanel41_60.add(jLabel51, null);
jPanel41_60.add(jLabel52, null);
jPanel41_60.add(getJTextField52(), null);
}
return jPanel41_60;
}
public JTextField getJTextField04() {
if (jTextField04 == null) {
jTextField04 = new JTextField();
jTextField04.setBounds(new Rectangle(5, 5, 140, 40));
jTextField04.setHorizontalAlignment(JTextField.CENTER);
jTextField04.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField04.setEditable(false);
jTextField04.setBackground(Color.white);
}
return jTextField04;
}
public JTextField getJTextField05() {
if (jTextField05 == null) {
jTextField05 = new JTextField();
jTextField05.setBounds(new Rectangle(5, 45, 140, 40));
jTextField05.setHorizontalAlignment(JTextField.CENTER);
jTextField05.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField05.setEditable(false);
jTextField05.setBackground(Color.white);
}
return jTextField05;
}
128
public JTextField getJTextField06() {
if (jTextField06 == null) {
jTextField06 = new JTextField();
jTextField06.setBounds(new Rectangle(5, 85, 140, 40));
jTextField06.setHorizontalAlignment(JTextField.CENTER);
jTextField06.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField06.setEditable(false);
jTextField06.setBackground(Color.white);
}
return jTextField06;
}
public JTextField getJTextField07() {
if (jTextField07 == null) {
jTextField07 = new JTextField();
jTextField07.setBounds(new Rectangle(5, 125, 140, 40));
jTextField07.setHorizontalAlignment(JTextField.CENTER);
jTextField07.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField07.setEditable(false);
jTextField07.setBackground(Color.white);
}
return jTextField07;
}
public JTextField getJTextField08() {
if (jTextField08 == null) {
jTextField08 = new JTextField();
jTextField08.setBounds(new Rectangle(5, 165, 140, 40));
jTextField08.setHorizontalAlignment(JTextField.CENTER);
jTextField08.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField08.setEditable(false);
jTextField08.setBackground(Color.white);
}
return jTextField08;
}
public JTextField getJTextField09() {
if (jTextField09 == null) {
jTextField09 = new JTextField();
jTextField09.setBounds(new Rectangle(5, 205, 140, 40));
jTextField09.setHorizontalAlignment(JTextField.CENTER);
jTextField09.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField09.setEditable(false);
jTextField09.setBackground(Color.white);
}
return jTextField09;
}
public JTextField getJTextField0A() {
if (jTextField0A == null) {
jTextField0A = new JTextField();
jTextField0A.setBounds(new Rectangle(5, 245, 140, 40));
jTextField0A.setHorizontalAlignment(JTextField.CENTER);
jTextField0A.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField0A.setEditable(false);
jTextField0A.setBackground(Color.white);
}
return jTextField0A;
}
public JTextField getJTextField0B() {
if (jTextField0B == null) {
jTextField0B = new JTextField();
129
jTextField0B.setBounds(new Rectangle(5, 285, 140, 40));
jTextField0B.setHorizontalAlignment(JTextField.CENTER);
jTextField0B.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField0B.setEditable(false);
jTextField0B.setBackground(Color.white);
}
return jTextField0B;
}
public JTextField getJTextField0C() {
if (jTextField0C == null) {
jTextField0C = new JTextField();
jTextField0C.setBounds(new Rectangle(5, 325, 140, 40));
jTextField0C.setHorizontalAlignment(JTextField.CENTER);
jTextField0C.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField0C.setEditable(false);
jTextField0C.setBackground(Color.white);
}
return jTextField0C;
}
public JTextField getJTextField0D() {
if (jTextField0D == null) {
jTextField0D = new JTextField();
jTextField0D.setBounds(new Rectangle(5, 365, 140, 40));
jTextField0D.setHorizontalAlignment(JTextField.CENTER);
jTextField0D.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField0D.setEditable(false);
jTextField0D.setBackground(Color.white);
}
return jTextField0D;
}
public JTextField getJTextField0E() {
if (jTextField0E == null) {
jTextField0E = new JTextField();
jTextField0E.setBounds(new Rectangle(5, 405, 140, 40));
jTextField0E.setHorizontalAlignment(JTextField.CENTER);
jTextField0E.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField0E.setEditable(false);
jTextField0E.setBackground(Color.white);
}
return jTextField0E;
}
public JTextField getJTextField0F() {
if (jTextField0F == null) {
jTextField0F = new JTextField();
jTextField0F.setBounds(new Rectangle(5, 445, 140, 40));
jTextField0F.setHorizontalAlignment(JTextField.CENTER);
jTextField0F.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField0F.setEditable(false);
jTextField0F.setBackground(Color.white);
}
return jTextField0F;
}
public JTextField getJTextField10() {
if (jTextField10 == null) {
jTextField10 = new JTextField();
jTextField10.setBounds(new Rectangle(380, 5, 140, 40));
jTextField10.setHorizontalAlignment(JTextField.CENTER);
jTextField10.setFont(new Font("Dialog", Font.BOLD, 22));
130
jTextField10.setEditable(false);
jTextField10.setBackground(Color.white);
}
return jTextField10;
}
public JTextField getJTextField11() {
if (jTextField11 == null) {
jTextField11 = new JTextField();
jTextField11.setBounds(new Rectangle(380, 45, 140, 40));
jTextField11.setHorizontalAlignment(JTextField.CENTER);
jTextField11.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField11.setEditable(false);
jTextField11.setBackground(Color.white);
}
return jTextField11;
}
public JTextField getJTextField12() {
if (jTextField12 == null) {
jTextField12 = new JTextField();
jTextField12.setBounds(new Rectangle(380, 85, 291, 53));
jTextField12.setHorizontalAlignment(JTextField.CENTER);
jTextField12.setFont(new Font("Dialog", Font.PLAIN, 17));
jTextField12.setEditable(false);
jTextField12.setBackground(Color.white);
}
return jTextField12;
}
public JTextField getJTextField14() {
if (jTextField14 == null) {
jTextField14 = new JTextField();
jTextField14.setBounds(new Rectangle(380, 165, 140, 40));
jTextField14.setHorizontalAlignment(JTextField.CENTER);
jTextField14.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField14.setEditable(false);
jTextField14.setBackground(Color.white);
}
return jTextField14;
}
public JTextField getJTextField15() {
if (jTextField15 == null) {
jTextField15 = new JTextField();
jTextField15.setBounds(new Rectangle(380, 205, 140, 40));
jTextField15.setHorizontalAlignment(JTextField.CENTER);
jTextField15.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField15.setEditable(false);
jTextField15.setBackground(Color.white);
}
return jTextField15;
}
public JTextField getJTextField16() {
if (jTextField16 == null) {
jTextField16 = new JTextField();
jTextField16.setBounds(new Rectangle(380, 245, 140, 40));
jTextField16.setHorizontalAlignment(JTextField.CENTER);
jTextField16.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField16.setEditable(false);
jTextField16.setBackground(Color.white);
}
131
return jTextField16;
}
public JTextField getJTextField17() {
if (jTextField17 == null) {
jTextField17 = new JTextField();
jTextField17.setBounds(new Rectangle(380, 285, 140, 40));
jTextField17.setHorizontalAlignment(JTextField.CENTER);
jTextField17.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField17.setEditable(false);
jTextField17.setBackground(Color.white);
}
return jTextField17;
}
public JTextField getJTextField18() {
if (jTextField18 == null) {
jTextField18 = new JTextField();
jTextField18.setBounds(new Rectangle(380, 325, 140, 40));
jTextField18.setHorizontalAlignment(JTextField.CENTER);
jTextField18.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField18.setEditable(false);
jTextField18.setBackground(Color.white);
}
return jTextField18;
}
public JTextField getJTextField19() {
if (jTextField19 == null) {
jTextField19 = new JTextField();
jTextField19.setBounds(new Rectangle(380, 365, 140, 40));
jTextField19.setHorizontalAlignment(JTextField.CENTER);
jTextField19.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField19.setEditable(false);
jTextField19.setBackground(Color.white);
}
return jTextField19;
}
public JTextField getJTextField1A() {
if (jTextField1A == null) {
jTextField1A = new JTextField();
jTextField1A.setBounds(new Rectangle(380, 405, 140, 40));
jTextField1A.setHorizontalAlignment(JTextField.CENTER);
jTextField1A.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField1A.setEditable(false);
jTextField1A.setBackground(Color.white);
}
return jTextField1A;
}
public JTextField getJTextField1B() {
if (jTextField1B == null) {
jTextField1B = new JTextField();
jTextField1B.setBounds(new Rectangle(380, 445, 140, 40));
jTextField1B.setHorizontalAlignment(JTextField.CENTER);
jTextField1B.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField1B.setEditable(false);
jTextField1B.setBackground(Color.white);
}
return jTextField1B;
}
public JTextField getJTextField1E() {
132
if (jTextField1E == null) {
jTextField1E = new JTextField();
jTextField1E.setBounds(new Rectangle(380, 485, 140, 40));
jTextField1E.setHorizontalAlignment(JTextField.CENTER);
jTextField1E.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField1E.setEditable(false);
jTextField1E.setBackground(Color.white);
}
return jTextField1E;
}
public JTextField getJTextField1F() {
if (jTextField1F == null) {
jTextField1F = new JTextField();
jTextField1F.setBounds(new Rectangle(380, 525, 140, 40));
jTextField1F.setHorizontalAlignment(JTextField.CENTER);
jTextField1F.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField1F.setEditable(false);
jTextField1F.setBackground(Color.white);
}
return jTextField1F;
}
public JTextField getJTextField24() {
if (jTextField24 == null) {
jTextField24 = new JTextField();
jTextField24.setBounds(new Rectangle(5, 125, 140, 40));
jTextField24.setHorizontalAlignment(JTextField.CENTER);
jTextField24.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField24.setEditable(false);
jTextField24.setBackground(Color.white);
}
return jTextField24;
}
public JTextField getJTextField25() {
if (jTextField25 == null) {
jTextField25 = new JTextField();
jTextField25.setBounds(new Rectangle(5, 165, 140, 40));
jTextField25.setHorizontalAlignment(JTextField.CENTER);
jTextField25.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField25.setEditable(false);
jTextField25.setBackground(Color.white);
}
return jTextField25;
}
public JTextField getJTextField26() {
if (jTextField26 == null) {
jTextField26 = new JTextField();
jTextField26.setBounds(new Rectangle(5, 205, 140, 40));
jTextField26.setHorizontalAlignment(JTextField.CENTER);
jTextField26.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField26.setEditable(false);
jTextField26.setBackground(Color.white);
}
return jTextField26;
}
public JTextField getJTextField27() {
if (jTextField27 == null) {
jTextField27 = new JTextField();
jTextField27.setBounds(new Rectangle(5, 245, 140, 40));
133
jTextField27.setHorizontalAlignment(JTextField.CENTER);
jTextField27.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField27.setEditable(false);
jTextField27.setBackground(Color.white);
}
return jTextField27;
}
public JTextField getJTextField28() {
if (jTextField28 == null) {
jTextField28 = new JTextField();
jTextField28.setBounds(new Rectangle(5, 285, 140, 40));
jTextField28.setHorizontalAlignment(JTextField.CENTER);
jTextField28.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField28.setEditable(false);
jTextField28.setBackground(Color.white);
}
return jTextField28;
}
public JTextField getJTextField29() {
if (jTextField29 == null) {
jTextField29 = new JTextField();
jTextField29.setBounds(new Rectangle(5, 325, 140, 40));
jTextField29.setHorizontalAlignment(JTextField.CENTER);
jTextField29.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField29.setEditable(false);
jTextField29.setBackground(Color.white);
}
return jTextField29;
}
public JTextField getJTextField2A() {
if (jTextField2A == null) {
jTextField2A = new JTextField();
jTextField2A.setBounds(new Rectangle(5, 365, 140, 40));
jTextField2A.setHorizontalAlignment(JTextField.CENTER);
jTextField2A.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField2A.setEditable(false);
jTextField2A.setBackground(Color.white);
}
return jTextField2A;
}
public JTextField getJTextField2B() {
if (jTextField2B == null) {
jTextField2B = new JTextField();
jTextField2B.setBounds(new Rectangle(5, 405, 140, 40));
jTextField2B.setHorizontalAlignment(JTextField.CENTER);
jTextField2B.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField2B.setEditable(false);
jTextField2B.setBackground(Color.white);
}
return jTextField2B;
}
public JTextField getJTextField2C() {
if (jTextField2C == null) {
jTextField2C = new JTextField();
jTextField2C.setBounds(new Rectangle(5, 445, 140, 40));
jTextField2C.setHorizontalAlignment(JTextField.CENTER);
jTextField2C.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField2C.setEditable(false);
134
jTextField2C.setBackground(Color.white);
}
return jTextField2C;
}
public JTextField getJTextField2D() {
if (jTextField2D == null) {
jTextField2D = new JTextField();
jTextField2D.setBounds(new Rectangle(5, 485, 140, 40));
jTextField2D.setHorizontalAlignment(JTextField.CENTER);
jTextField2D.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField2D.setEditable(false);
jTextField2D.setBackground(Color.white);
}
return jTextField2D;
}
public JTextField getJTextField2E() {
if (jTextField2E == null) {
jTextField2E = new JTextField();
jTextField2E.setBounds(new Rectangle(5, 525, 140, 40));
jTextField2E.setHorizontalAlignment(JTextField.CENTER);
jTextField2E.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField2E.setEditable(false);
jTextField2E.setBackground(Color.white);
}
return jTextField2E;
}
public JTextField getJTextField2F() {
if (jTextField2F == null) {
jTextField2F = new JTextField();
jTextField2F.setBounds(new Rectangle(5, 565, 140, 40));
jTextField2F.setHorizontalAlignment(JTextField.CENTER);
jTextField2F.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField2F.setEditable(false);
jTextField2F.setBackground(Color.white);
}
return jTextField2F;
}
public JTextField getJTextField33() {
if (jTextField33 == null) {
jTextField33 = new JTextField();
jTextField33.setBounds(new Rectangle(380, 85, 140, 40));
jTextField33.setHorizontalAlignment(JTextField.CENTER);
jTextField33.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField33.setEditable(false);
jTextField33.setBackground(Color.white);
}
return jTextField33;
}
public JTextField getJTextField31() {
if (jTextField31 == null) {
jTextField31 = new JTextField();
jTextField31.setBounds(new Rectangle(380, 5, 140, 40));
jTextField31.setHorizontalAlignment(JTextField.CENTER);
jTextField31.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField31.setEditable(false);
jTextField31.setBackground(Color.white);
}
return jTextField31;
135
}
public JTextField getJTextField32() {
if (jTextField32 == null) {
jTextField32 = new JTextField();
jTextField32.setBounds(new Rectangle(380, 45, 140, 40));
jTextField32.setHorizontalAlignment(JTextField.CENTER);
jTextField32.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField32.setEditable(false);
jTextField32.setBackground(Color.white);
}
return jTextField32;
}
public JTextField getJTextField34() {
if (jTextField34 == null) {
jTextField34 = new JTextField();
jTextField34.setBounds(new Rectangle(380, 125, 140, 40));
jTextField34.setHorizontalAlignment(JTextField.CENTER);
jTextField34.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField34.setEditable(false);
jTextField34.setBackground(Color.white);
}
return jTextField34;
}
public JTextField getJTextField35() {
if (jTextField35 == null) {
jTextField35 = new JTextField();
jTextField35.setBounds(new Rectangle(380, 165, 140, 40));
jTextField35.setHorizontalAlignment(JTextField.CENTER);
jTextField35.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField35.setEditable(false);
jTextField35.setBackground(Color.white);
}
return jTextField35;
}
public JTextField getJTextField36() {
if (jTextField36 == null) {
jTextField36 = new JTextField();
jTextField36.setBounds(new Rectangle(380, 205, 140, 40));
jTextField36.setHorizontalAlignment(JTextField.CENTER);
jTextField36.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField36.setEditable(false);
jTextField36.setBackground(Color.white);
}
return jTextField36;
}
public JTextField getJTextField37() {
if (jTextField37 == null) {
jTextField37 = new JTextField();
jTextField37.setBounds(new Rectangle(380, 245, 140, 40));
jTextField37.setHorizontalAlignment(JTextField.CENTER);
jTextField37.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField37.setEditable(false);
jTextField37.setBackground(Color.white);
}
return jTextField37;
}
public JTextField getJTextField38() {
136
if (jTextField38 == null) {
jTextField38 = new JTextField();
jTextField38.setBounds(new Rectangle(380, 285, 140, 40));
jTextField38.setHorizontalAlignment(JTextField.CENTER);
jTextField38.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField38.setEditable(false);
jTextField38.setBackground(Color.white);
}
return jTextField38;
}
public JTextField getJTextField39() {
if (jTextField39 == null) {
jTextField39 = new JTextField();
jTextField39.setBounds(new Rectangle(380, 325, 140, 40));
jTextField39.setHorizontalAlignment(JTextField.CENTER);
jTextField39.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField39.setEditable(false);
jTextField39.setBackground(Color.white);
}
return jTextField39;
}
public JTextField getJTextField3A() {
if (jTextField3A == null) {
jTextField3A = new JTextField();
jTextField3A.setBounds(new Rectangle(380, 365, 140, 40));
jTextField3A.setHorizontalAlignment(JTextField.CENTER);
jTextField3A.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField3A.setEditable(false);
jTextField3A.setBackground(Color.white);
}
return jTextField3A;
}
public JTextField getJTextField3B() {
if (jTextField3B == null) {
jTextField3B = new JTextField();
jTextField3B.setBounds(new Rectangle(380, 405, 140, 40));
jTextField3B.setHorizontalAlignment(JTextField.CENTER);
jTextField3B.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField3B.setEditable(false);
jTextField3B.setBackground(Color.white);
}
return jTextField3B;
}
public JTextField getJTextField3E() {
if (jTextField3E == null) {
jTextField3E = new JTextField();
jTextField3E.setBounds(new Rectangle(380, 525, 140, 40));
jTextField3E.setHorizontalAlignment(JTextField.CENTER);
jTextField3E.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField3E.setEditable(false);
jTextField3E.setBackground(Color.white);
}
return jTextField3E;
}
public JTextField getJTextField3F() {
if (jTextField3F == null) {
jTextField3F = new JTextField();
jTextField3F.setBounds(new Rectangle(380, 565, 140, 40));
137
jTextField3F.setHorizontalAlignment(JTextField.CENTER);
jTextField3F.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField3F.setEditable(false);
jTextField3F.setBackground(Color.white);
}
return jTextField3F;
}
public JTextField getJTextField21() {
if (jTextField21 == null) {
jTextField21 = new JTextField();
jTextField21.setBounds(new Rectangle(5, 5, 140, 40));
jTextField21.setHorizontalAlignment(JTextField.CENTER);
jTextField21.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField21.setEditable(false);
jTextField21.setBackground(Color.white);
}
return jTextField21;
}
public JTextField getJTextField22() {
if (jTextField22 == null) {
jTextField22 = new JTextField();
jTextField22.setBounds(new Rectangle(5, 45, 140, 40));
jTextField22.setHorizontalAlignment(JTextField.CENTER);
jTextField22.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField22.setEditable(false);
jTextField22.setBackground(Color.white);
}
return jTextField22;
}
public JTextField getJTextField23() {
if (jTextField23 == null) {
jTextField23 = new JTextField();
jTextField23.setBounds(new Rectangle(5, 85, 140, 40));
jTextField23.setHorizontalAlignment(JTextField.CENTER);
jTextField23.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField23.setEditable(false);
jTextField23.setBackground(Color.white);
}
return jTextField23;
}
public JTextField getJTextField3C() {
if (jTextField3C == null) {
jTextField3C = new JTextField();
jTextField3C.setBounds(new Rectangle(380, 445, 140, 40));
jTextField3C.setHorizontalAlignment(JTextField.CENTER);
jTextField3C.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField3C.setEditable(false);
jTextField3C.setBackground(Color.white);
}
return jTextField3C;
}
public JTextField getJTextField3D() {
if (jTextField3D == null) {
jTextField3D = new JTextField();
jTextField3D.setBounds(new Rectangle(380, 485, 140, 40));
jTextField3D.setHorizontalAlignment(JTextField.CENTER);
jTextField3D.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField3D.setEditable(false);
138
jTextField3D.setBackground(Color.white);
}
return jTextField3D;
}
public JButton getJButtonLeer() {
if (jButtonLeer == null) {
jButtonLeer = new JButton();
jButtonLeer.setBounds(new Rectangle(6, 650, 130, 20));
jButtonLeer.setText("Start reading");
}
return jButtonLeer;
}
public JButton getJButtonDetener() {
if (jButtonDetener == null) {
jButtonDetener = new JButton();
jButtonDetener.setBounds(new Rectangle(135, 650, 130, 20));
jButtonDetener.setText("Stop");
}
return jButtonDetener;
}
public JTextField getJTextField42() {
if (jTextField42 == null) {
jTextField42 = new JTextField();
jTextField42.setBounds(new Rectangle(5, 5, 140, 40));
jTextField42.setHorizontalAlignment(JTextField.CENTER);
jTextField42.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField42.setEditable(false);
jTextField42.setBackground(Color.white);
}
return jTextField42;
}
public JTextField getJTextField43() {
if (jTextField43 == null) {
jTextField43 = new JTextField();
jTextField43.setBounds(new Rectangle(5, 45, 140, 40));
jTextField43.setHorizontalAlignment(JTextField.CENTER);
jTextField43.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField43.setEditable(false);
jTextField43.setBackground(Color.white);
}
return jTextField43;
}
public JTextField getJTextField44() {
if (jTextField44 == null) {
jTextField44 = new JTextField();
jTextField44.setBounds(new Rectangle(5, 85, 140, 40));
jTextField44.setHorizontalAlignment(JTextField.CENTER);
jTextField44.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField44.setEditable(false);
jTextField44.setBackground(Color.white);
}
return jTextField44;
}
public JTextField getJTextField45() {
if (jTextField45 == null) {
139
jTextField45 = new JTextField();
jTextField45.setBounds(new Rectangle(5, 125, 140, 40));
jTextField45.setHorizontalAlignment(JTextField.CENTER);
jTextField45.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField45.setEditable(false);
jTextField45.setBackground(Color.white);
}
return jTextField45;
}
public JTextField getJTextField46() {
if (jTextField46 == null) {
jTextField46 = new JTextField();
jTextField46.setBounds(new Rectangle(5, 165, 140, 40));
jTextField46.setHorizontalAlignment(JTextField.CENTER);
jTextField46.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField46.setEditable(false);
jTextField46.setBackground(Color.white);
}
return jTextField46;
}
public JTextField getJTextField47() {
if (jTextField47 == null) {
jTextField47 = new JTextField();
jTextField47.setBounds(new Rectangle(5, 205, 140, 40));
jTextField47.setHorizontalAlignment(JTextField.CENTER);
jTextField47.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField47.setEditable(false);
jTextField47.setBackground(Color.white);
}
return jTextField47;
}
public JTextField getJTextField48() {
if (jTextField48 == null) {
jTextField48 = new JTextField();
jTextField48.setBounds(new Rectangle(5, 245, 140, 40));
jTextField48.setHorizontalAlignment(JTextField.CENTER);
jTextField48.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField48.setEditable(false);
jTextField48.setBackground(Color.white);
}
return jTextField48;
}
public JTextField getJTextField49() {
if (jTextField49 == null) {
jTextField49 = new JTextField();
jTextField49.setBounds(new Rectangle(5, 285, 140, 40));
jTextField49.setHorizontalAlignment(JTextField.CENTER);
jTextField49.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField49.setEditable(false);
jTextField49.setBackground(Color.white);
}
return jTextField49;
}
public JTextField getJTextField4A() {
if (jTextField4A == null) {
jTextField4A = new JTextField();
jTextField4A.setBounds(new Rectangle(5, 325, 140, 40));
jTextField4A.setHorizontalAlignment(JTextField.CENTER);
140
jTextField4A.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField4A.setEditable(false);
jTextField4A.setBackground(Color.white);
}
return jTextField4A;
}
public JTextField getJTextField4B() {
if (jTextField4B == null) {
jTextField4B = new JTextField();
jTextField4B.setBounds(new Rectangle(5, 365, 140, 40));
jTextField4B.setHorizontalAlignment(JTextField.CENTER);
jTextField4B.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField4B.setEditable(false);
jTextField4B.setBackground(Color.white);
}
return jTextField4B;
}
public JTextField getJTextField4C() {
if (jTextField4C == null) {
jTextField4C = new JTextField();
jTextField4C.setBounds(new Rectangle(5, 405, 140, 40));
jTextField4C.setHorizontalAlignment(JTextField.CENTER);
jTextField4C.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField4C.setEditable(false);
jTextField4C.setBackground(Color.white);
}
return jTextField4C;
}
public JTextField getJTextField4D() {
if (jTextField4D == null) {
jTextField4D = new JTextField();
jTextField4D.setBounds(new Rectangle(5, 445, 140, 40));
jTextField4D.setHorizontalAlignment(JTextField.CENTER);
jTextField4D.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField4D.setEditable(false);
jTextField4D.setBackground(Color.white);
}
return jTextField4D;
}
public JTextField getJTextField4E() {
if (jTextField4E == null) {
jTextField4E = new JTextField();
jTextField4E.setBounds(new Rectangle(5, 485, 140, 40));
jTextField4E.setHorizontalAlignment(JTextField.CENTER);
jTextField4E.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField4E.setEditable(false);
jTextField4E.setBackground(Color.white);
}
return jTextField4E;
}
public JTextField getJTextField51() {
if (jTextField51 == null) {
jTextField51 = new JTextField();
jTextField51.setBounds(new Rectangle(380, 25, 336, 59));
jTextField51.setHorizontalAlignment(JTextField.CENTER);
jTextField51.setFont(new Font("Dialog", Font.PLAIN, 17));
jTextField51.setEditable(false);
jTextField51.setBackground(Color.white);
141
}
return jTextField51;
}
public JTextField getJTextField52() {
if (jTextField52 == null) {
jTextField52 = new JTextField();
jTextField52.setBounds(new Rectangle(380, 85, 140, 40));
jTextField52.setHorizontalAlignment(JTextField.CENTER);
jTextField52.setFont(new Font("Dialog", Font.BOLD, 22));
jTextField52.setEditable(false);
jTextField52.setBackground(Color.white);
}
return jTextField52;
}
public JTextField getJTextField1C() {
if (jTextField1C == null) {
jTextField1C = new JTextField();
jTextField1C.setBounds(new Rectangle(5, 525, 300, 40));
jTextField1C.setFont(new Font("Dialog", Font.PLAIN, 17));
jTextField1C.setEditable(false);
jTextField1C.setBackground(Color.white);
}
return jTextField1C;
}
}
Clase VistaPrincipal:
package Presentacion;
import
import
import
import
import
import
import
import
import
import
import
javax.swing.JPanel;
javax.swing.JFrame;
javax.swing.JMenuBar;
javax.swing.JMenu;
javax.swing.JMenuItem;
java.awt.Rectangle;
javax.swing.JButton;
javax.swing.JTextArea;
java.awt.Point;
javax.swing.JScrollPane;
javax.swing.JTextField;
public class VistaPrincipal extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private JMenuBar jJMenuBar = null;
private JMenu jMenuInicio = null;
private JMenuItem jMenuItemErrores = null;
private JMenuItem jMenuItemLectura = null;
private JPanel jPanel = null;
private JButton jButtonConectar = null;
142
private JButton jButtonDesconectar = null;
private JTextArea jTextArea = null;
private JMenu jMenuOpciones = null;
private JMenu jMenuAyuda = null;
private JMenuItem jMenuItemPSerie = null;
private JMenuItem jMenuItemProtocolo = null;
private JScrollPane jScrollPane = null;
private JButton jButtonEnvioManual = null;
private JTextField jTextFieldEnvioManual = null;
private JMenuItem jMenuItemPresentacion = null;
private JMenuItem jMenuItemAbout = null;
private JMenuItem jMenuItemExit = null;
public VistaPrincipal() {
super();
this.setLocation(new Point(100, 25));
initialize();
}
public void initialize() {
this.setSize(1050, 734);
this.setContentPane(getJContentPane());
this.setJMenuBar(getJJMenuBar());
this.setTitle("VisualOBD");
this.setVisible(true);
}
public JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.add(getJPanel(), null);
}
return jContentPane;
}
private JMenuBar getJJMenuBar() {
if (jJMenuBar == null) {
jJMenuBar = new JMenuBar();
jJMenuBar.add(getJMenuInicio());
jJMenuBar.add(getJMenuOpciones());
jJMenuBar.add(getJMenuAyuda());
}
return jJMenuBar;
}
private JMenu getJMenuInicio() {
if (jMenuInicio == null) {
jMenuInicio = new JMenu();
jMenuInicio.setText("
Start
");
jMenuInicio.add(getJMenuItemPresentacion());
jMenuInicio.add(getJMenuItemErrores());
143
jMenuInicio.add(getJMenuItemLectura());
jMenuInicio.add(getJMenuItemExit());
}
return jMenuInicio;
}
public JMenuItem getJMenuItemErrores() {
if (jMenuItemErrores == null) {
jMenuItemErrores = new JMenuItem();
jMenuItemErrores.setText("Reading errors");
}
return jMenuItemErrores;
}
public JMenuItem getJMenuItemLectura() {
if (jMenuItemLectura == null) {
jMenuItemLectura = new JMenuItem();
jMenuItemLectura.setText("Real-time measurements");
}
return jMenuItemLectura;
}
private JPanel getJPanel() {
if (jPanel == null) {
jPanel = new JPanel();
jPanel.setLayout(null);
jPanel.setBounds(new Rectangle(795, 2, 250, 675));
jPanel.add(getJButtonConectar(), null);
jPanel.add(getJButtonDesconectar(), null);
jPanel.add(getJScrollPane(), null);
jPanel.add(getJButtonEnvioManual(), null);
jPanel.add(getJTextFieldEnvioManual(), null);
}
return jPanel;
}
public JButton getJButtonConectar() {
if (jButtonConectar == null) {
jButtonConectar = new JButton();
jButtonConectar.setBounds(new Rectangle(5, 647, 115, 20));
jButtonConectar.setText("Connect");
}
return jButtonConectar;
}
public JButton getJButtonDesconectar() {
if (jButtonDesconectar == null) {
jButtonDesconectar = new JButton();
jButtonDesconectar.setBounds(new Rectangle(120, 647, 119, 20));
jButtonDesconectar.setText("Disconnect");
}
return jButtonDesconectar;
}
public JTextArea getJTextArea() {
if (jTextArea == null) {
jTextArea = new JTextArea();
jTextArea.setEditable(false);
}
return jTextArea;
}
144
private JMenu getJMenuOpciones() {
if (jMenuOpciones == null) {
jMenuOpciones = new JMenu();
jMenuOpciones.setText("
Options
");
jMenuOpciones.add(getJMenuItemPSerie());
jMenuOpciones.add(getJMenuItemProtocolo());
}
return jMenuOpciones;
}
private JMenu getJMenuAyuda() {
if (jMenuAyuda == null) {
jMenuAyuda = new JMenu();
jMenuAyuda.setText("
Help
");
jMenuAyuda.add(getJMenuItemAbout());
}
return jMenuAyuda;
}
public JMenuItem getJMenuItemPSerie() {
if (jMenuItemPSerie == null) {
jMenuItemPSerie = new JMenuItem();
jMenuItemPSerie.setText("Serial Port configuration");
}
return jMenuItemPSerie;
}
public JMenuItem getJMenuItemProtocolo() {
if (jMenuItemProtocolo == null) {
jMenuItemProtocolo = new JMenuItem();
jMenuItemProtocolo.setText("Communication protocol configuration");
}
return jMenuItemProtocolo;
}
private JScrollPane getJScrollPane() {
if (jScrollPane == null) {
jScrollPane = new
JScrollPane(getJTextArea(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCRO
LLBAR_ALWAYS);
jScrollPane.setBounds(new Rectangle(5, 26, 235, 616));
jScrollPane.setViewportView(getJTextArea());
jScrollPane.setWheelScrollingEnabled(true);
}
return jScrollPane;
}
public JButton getJButtonEnvioManual() {
if (jButtonEnvioManual == null) {
jButtonEnvioManual = new JButton();
jButtonEnvioManual.setBounds(new Rectangle(163, 5, 77, 19));
jButtonEnvioManual.setText("Send");
}
return jButtonEnvioManual;
}
public JTextField getJTextFieldEnvioManual() {
if (jTextFieldEnvioManual == null) {
jTextFieldEnvioManual = new JTextField();
jTextFieldEnvioManual.setBounds(new Rectangle(5, 5, 159, 20));
145
}
return jTextFieldEnvioManual;
}
public JMenuItem getJMenuItemPresentacion() {
if (jMenuItemPresentacion == null) {
jMenuItemPresentacion = new JMenuItem();
jMenuItemPresentacion.setText("Initial presentation");
}
return jMenuItemPresentacion;
}
public JMenuItem getJMenuItemAbout() {
if (jMenuItemAbout == null) {
jMenuItemAbout = new JMenuItem();
jMenuItemAbout.setText("About VisualOBD");
}
return jMenuItemAbout;
}
public JMenuItem getJMenuItemExit() {
if (jMenuItemExit == null) {
jMenuItemExit = new JMenuItem();
jMenuItemExit.setText("Exit");
}
return jMenuItemExit;
}
}
Clase VistaProtocolo:
package Presentacion;
import
import
import
import
import
import
import
import
import
import
java.awt.Dimension;
javax.swing.ButtonGroup;
javax.swing.JPanel;
javax.swing.JRadioButton;
java.awt.Rectangle;
javax.swing.JLabel;
java.awt.Font;
javax.swing.JCheckBox;
javax.swing.JComboBox;
javax.swing.JButton;
public class VistaProtocolo extends JPanel {
private
private
private
private
private
private
private
private
private
private
private
private
private
private
static final long serialVersionUID = 1L;
JRadioButton jRadioButtonAutomatico = null;
JRadioButton jRadioButtonPWM = null;
JRadioButton jRadioButtonVPW = null;
JRadioButton jRadioButtonISO = null;
JRadioButton jRadioButtonKWP1 = null;
JRadioButton jRadioButtonKWP2 = null;
JRadioButton jRadioButtonCAN1 = null;
JRadioButton jRadioButtonCAN2 = null;
JRadioButton jRadioButtonCAN3 = null;
JRadioButton jRadioButtonCAN4 = null;
ButtonGroup grupoBotones;
JLabel jLabelProtocolo = null;
JCheckBox jCheckBoxIntroHead = null;
146
private
private
private
private
private
private
private
private
private
private
private
JComboBox jComboBoxPrio1 = null;
JComboBox jComboBoxPrio2 = null;
JComboBox jComboBoxRec1 = null;
JComboBox jComboBoxRec2 = null;
JComboBox jComboBoxTran1 = null;
JComboBox jComboBoxTran2 = null;
JLabel jLabelPrio = null;
JLabel jLabelRec = null;
JLabel jLabelTran = null;
JButton jButtonAplByHead = null;
String [] hexa={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
public VistaProtocolo() {
super();
initialize();
}
private void initialize() {
jLabelTran = new JLabel();
jLabelTran.setBounds(new Rectangle(690, 120, 86, 16));
jLabelTran.setFont(new Font("Dialog", Font.PLAIN, 12));
jLabelTran.setText("Tool address");
jLabelRec = new JLabel();
jLabelRec.setBounds(new Rectangle(575, 120, 91, 16));
jLabelRec.setFont(new Font("Dialog", Font.PLAIN, 12));
jLabelRec.setText("ECU address");
jLabelPrio = new JLabel();
jLabelPrio.setBounds(new Rectangle(445, 120, 53, 16));
jLabelPrio.setFont(new Font("Dialog", Font.PLAIN, 12));
jLabelPrio.setText("Priority");
jLabelProtocolo = new JLabel();
jLabelProtocolo.setBounds(new Rectangle(10, 10, 375, 28));
jLabelProtocolo.setFont(new Font("Dialog", Font.BOLD, 18));
jLabelProtocolo.setText("Selecting the communication protocol");
this.setSize(new Dimension(775, 712));
this.setLayout(null);
this.add(getJRadioButtonAutomatico(), null);
this.add(getJRadioButtonPWM(), null);
this.add(getJRadioButtonVPW(), null);
this.add(getJRadioButtonISO(), null);
this.add(getJRadioButtonKWP1(), null);
this.add(getJRadioButtonKWP2(), null);
this.add(getJRadioButtonCAN1(), null);
this.add(getJRadioButtonCAN2(), null);
this.add(getJRadioButtonCAN3(), null);
this.add(getJRadioButtonCAN4(), null);
this.add(jLabelProtocolo, null);
this.add(getJCheckBoxIntroHead(), null);
this.add(getJComboBoxPrio1(), null);
this.add(getJComboBoxPrio2(), null);
this.add(getJComboBoxRec1(), null);
this.add(getJComboBoxRec2(), null);
this.add(getJComboBoxTran1(), null);
this.add(getJComboBoxTran2(), null);
this.add(jLabelPrio, null);
this.add(jLabelRec, null);
this.add(jLabelTran, null);
this.add(getJButtonAplByHead(), null);
grupoBotones = new ButtonGroup();
grupoBotones.add(getJRadioButtonAutomatico());
grupoBotones.add(getJRadioButtonPWM());
grupoBotones.add(getJRadioButtonVPW());
grupoBotones.add(getJRadioButtonISO());
147
grupoBotones.add(getJRadioButtonKWP1());
grupoBotones.add(getJRadioButtonKWP2());
grupoBotones.add(getJRadioButtonCAN1());
grupoBotones.add(getJRadioButtonCAN2());
grupoBotones.add(getJRadioButtonCAN3());
grupoBotones.add(getJRadioButtonCAN4());
getJRadioButtonAutomatico().setSelected(true);
}
public JRadioButton getJRadioButtonAutomatico() {
if (jRadioButtonAutomatico == null) {
jRadioButtonAutomatico = new JRadioButton();
jRadioButtonAutomatico.setBounds(new Rectangle(10, 70, 328, 21));
jRadioButtonAutomatico.setText("Automatic detection of communication protocol");
}
return jRadioButtonAutomatico;
}
public JRadioButton getJRadioButtonPWM() {
if (jRadioButtonPWM == null) {
jRadioButtonPWM = new JRadioButton();
jRadioButtonPWM.setBounds(new Rectangle(10, 120, 219, 21));
jRadioButtonPWM.setText("SAE J1850 PWM (41.6 kBit/s)");
}
return jRadioButtonPWM;
}
public JRadioButton getJRadioButtonVPW() {
if (jRadioButtonVPW == null) {
jRadioButtonVPW = new JRadioButton();
jRadioButtonVPW.setBounds(new Rectangle(10, 170, 219, 21));
jRadioButtonVPW.setText("SAE J1850 VPW (10.4 kBit/s)");
}
return jRadioButtonVPW;
}
public JRadioButton getJRadioButtonISO() {
if (jRadioButtonISO == null) {
jRadioButtonISO = new JRadioButton();
jRadioButtonISO.setBounds(new Rectangle(10, 220, 114, 21));
jRadioButtonISO.setText("ISO 9141-2");
}
return jRadioButtonISO;
}
public JRadioButton getJRadioButtonKWP1() {
if (jRadioButtonKWP1 == null) {
jRadioButtonKWP1 = new JRadioButton();
jRadioButtonKWP1.setBounds(new Rectangle(10, 270, 256, 21));
jRadioButtonKWP1.setText("ISO 14230-4 KWP2000 (5-baud init)");
}
return jRadioButtonKWP1;
}
public JRadioButton getJRadioButtonKWP2() {
if (jRadioButtonKWP2 == null) {
jRadioButtonKWP2 = new JRadioButton();
jRadioButtonKWP2.setBounds(new Rectangle(10, 320, 243, 21));
jRadioButtonKWP2.setText("ISO 14230-4 KWP2000 (fast init)");
}
return jRadioButtonKWP2;
}
148
public JRadioButton getJRadioButtonCAN1() {
if (jRadioButtonCAN1 == null) {
jRadioButtonCAN1 = new JRadioButton();
jRadioButtonCAN1.setBounds(new Rectangle(10, 370, 300, 21));
jRadioButtonCAN1.setText("ISO 15765-4 CAN (11-bit ID, 500 kBit/s)");
}
return jRadioButtonCAN1;
}
public JRadioButton getJRadioButtonCAN2() {
if (jRadioButtonCAN2 == null) {
jRadioButtonCAN2 = new JRadioButton();
jRadioButtonCAN2.setBounds(new Rectangle(10, 420, 300, 21));
jRadioButtonCAN2.setText("ISO 15765-4 CAN (29-bit ID, 500 kBit/s)");
}
return jRadioButtonCAN2;
}
public JRadioButton getJRadioButtonCAN3() {
if (jRadioButtonCAN3 == null) {
jRadioButtonCAN3 = new JRadioButton();
jRadioButtonCAN3.setBounds(new Rectangle(10, 470, 300, 21));
jRadioButtonCAN3.setText("ISO 15765-4 CAN (11-bit ID, 250 kBit/s)");
}
return jRadioButtonCAN3;
}
public JRadioButton getJRadioButtonCAN4() {
if (jRadioButtonCAN4 == null) {
jRadioButtonCAN4 = new JRadioButton();
jRadioButtonCAN4.setBounds(new Rectangle(10, 520, 300, 21));
jRadioButtonCAN4.setText("ISO 15765-4 CAN (29-bit ID, 250 kBit/s)");
}
return jRadioButtonCAN4;
}
public JCheckBox getJCheckBoxIntroHead() {
if (jCheckBoxIntroHead == null) {
jCheckBoxIntroHead = new JCheckBox();
jCheckBoxIntroHead.setBounds(new Rectangle(425, 70, 254, 21));
jCheckBoxIntroHead.setFont(new Font("Dialog", Font.BOLD, 14));
jCheckBoxIntroHead.setText("Enter specific header bytes");
}
return jCheckBoxIntroHead;
}
public JComboBox getJComboBoxPrio1() {
if (jComboBoxPrio1 == null) {
jComboBoxPrio1 = new JComboBox(hexa);
jComboBoxPrio1.setBounds(new Rectangle(445, 135, 40, 20));
}
return jComboBoxPrio1;
}
public JComboBox getJComboBoxPrio2() {
if (jComboBoxPrio2 == null) {
jComboBoxPrio2 = new JComboBox(hexa);
jComboBoxPrio2.setBounds(new Rectangle(484, 135, 40, 20));
}
return jComboBoxPrio2;
}
public JComboBox getJComboBoxRec1() {
149
if (jComboBoxRec1 == null) {
jComboBoxRec1 = new JComboBox(hexa);
jComboBoxRec1.setBounds(new Rectangle(575, 135, 40, 20));
}
return jComboBoxRec1;
}
public JComboBox getJComboBoxRec2() {
if (jComboBoxRec2 == null) {
jComboBoxRec2 = new JComboBox(hexa);
jComboBoxRec2.setBounds(new Rectangle(614, 135, 40, 20));
}
return jComboBoxRec2;
}
public JComboBox getJComboBoxTran1() {
if (jComboBoxTran1 == null) {
jComboBoxTran1 = new JComboBox(hexa);
jComboBoxTran1.setBounds(new Rectangle(690, 135, 40, 20));
}
return jComboBoxTran1;
}
public JComboBox getJComboBoxTran2() {
if (jComboBoxTran2 == null) {
jComboBoxTran2 = new JComboBox(hexa);
jComboBoxTran2.setBounds(new Rectangle(729, 135, 40, 20));
}
return jComboBoxTran2;
}
public JButton getJButtonAplByHead() {
if (jButtonAplByHead == null) {
jButtonAplByHead = new JButton();
jButtonAplByHead.setBounds(new Rectangle(445, 180, 81, 18));
jButtonAplByHead.setText("Apply");
}
return jButtonAplByHead;
}
}
150