Ingeniería inversa de un LCD con I2C integrado

Subforo dedicado exclusivamente a la electrónica y a la robótica, incluyendo la programación orientada a la robótica en sí.
Robots con patas, ruedas, orugas, humanoides, insectoides, ... ¡Sed todos bienvenidos!

Moderador: nake

Avatar de Usuario
nake
管理者 (Admin)
Mensajes: 1994
Registrado: Vie Jun 04, 2010 4:10 pm
Ubicación: (sin(3t), 0, 0, t+10)
Contactar:

Ingeniería inversa de un LCD con I2C integrado

Mensajepor nake » Mar Abr 15, 2014 5:48 pm

¡Muy buenas a todos! Esto está un poco dejado últimamente así que voy a postear lo último en lo que he estado trabajando.

Soul666 me dejó un LCD de esos de 16x2 de toda la vida que se pueden usar en Arduino porque venía con un chip metido para ser usado por I2C y no lo conseguía hacer funcionar. (A cambio le dejé yo el mío, como podéis ver en un post que hizo hace poco).

El cacharro venía sin documentación, y las entradas son solo 4 pines que al menos tienen nombre como podéis ver en la siguiente imagen.
CAM00761.jpg


Por desgracia venía todo soldado (y la gracia está en hacerlo sin desoldar cosas), y no se puede ver todo el circuitado del breakout extra.

La alimentación era fácil de asumir: si los LCD normales van a 5V, aunque tenga un chip extra integrado, la alimentación será la misma. Ya tenemos 2 de los pines (VCC a +5V y GND a tierra).
Ahora bien, los divertidos son los otros dos pines. Observamos que uno es SCL y otro SDA, y además solo están esos dos así que se trata de un protocolo de comunicación serie con dos líneas, una que seguramente se llame Serial CLock, y otra que sea Seria DAta... Todo apunta a que se trate de I2C, pero vamos a confirmarlo:
El único integrado que se ve en el breakout es uno cuyo identificador es PCF8574T. La primera entrada en DuckDuckGo es el propio datasheet de un tal Remote 8-bit I/O expander for I2 C-bus. Así que vamos bien.

El chip ese se encarga de pasar un mensaje de 8 bits enviado por I2C (serie) a 8 pines (paralelo), así que es relativamente sencillo cómo hacerlo funcionar y no necesitamos el datasheet.
Ah, pero no es directo el pasar los datos al LCD... Veamos, el LCD trabaja de normal con 3 bits de control, 1 analógico de contraste, una retroiluminación con un led, y 4 u 8 bits de datos de transmisión de datos. En total son 16 pines de entrada.

Tras investigar podemos ver que el potenciómetro controla el contraste, el jumper que tiene controla la retroiluminación, pero el resto de líneas no se sabe cómo están conectadas. Tenemos 11 bits a controlar en teoría y solo podemos mandar 8 bits...

En este punto se me ocurrieron dos posibles soluciones, una que el sistema funcionase con varias direcciones I2C a las que poder escribir (una de control y otra de datos), que estuviese multiplexada de alguna forma, o (lo más probable) que estuviese en modo 4bits y los otros 4 bits sean los de control.

Antes de empezar a jugar con esto hace falta saber la dirección I2C del aparato. En mi caso tuve la suerte de que Soul666 ya la había encontrado mediante un ataque fuerza bruta (intentar acceder dirección a dirección hasta que el dispositivo contesta). Así que en mi caso solo tuve que, usando un Arduino y la librería Wire (para I2C) ir mandando datos y mirando qué pines se ponen a nivel alto o bajo en cada situación.

La conexión con la librería Wire es muy sencilla, SDA se conecta al puerto 4 de los pines analógicos, y SCL se conecta al analógico 5. Luego basta con inicializar el puerto e ir escribiendo.
Para hacer las pruebas me monté un pequeño programa al que le mandaba un string por el puerto de serie (USB) que significaba un byte en hexadecimal y el arduino lo traducía a un byte real y lo enviaba por el puerto I2C.

CAM00755.jpg

CAM00754.jpg


Como está todo soldado y no tengo 16 osciloscopios/multímetros para ver cómo varían las líneas, me monté un pequeño hack con conectores PCB, leds y resistencias para ver cómo va encendiéndose y apagándose los pines del LCD.
Observé, como esperaba, que mandase el byte que mandase los 4 bits de menor peso del LCD nunca cambiaban, y que el nibble alto del byte controla los 4 bits de mayor peso del LCD.

CAM00760.jpg


Realmente tuve unos pocos problemas respecto a enviar datos al azar ya que algunos mensajes apagaban por completo el LCD y no tenía claro el por qué. Luego descubrí que de los 4 bits de control, 3 son para las líneas de control como tal del LCD y el último es para activar/desactivar el LCD.

CAM00757.jpg


Finalmente quedó algo así:

Código: [Seleccionar todo] [Download] GeSHi © Codebox Plus

Los pines del LCD son: RS RW E B0 .. B7
0xX0 -> b000****XXXX
X es un valor arbitrario, * es indefinido (a mi me salía como un 1 lógico, pero a saber).
 

Los bits RS, RW y E están ordenados de la siguiente manera:
RS bit 0 (menor peso), RW bit 1, y E bit 2. El bit 3 es el que se usa para encender/apagar el LCD.
Así que los mensajes a enviar son (en binario):

Código: [Seleccionar todo] [Download] GeSHi © Codebox Plus

Mayor peso <--> Menor peso
B7 B6 B5 B4 On E RW RS
 


Así que me puse a construirme un pequeño código para mandar los comandos adecuadamente, y finalmente obtuve lo siguiente :D :
CAM00759.jpg



Estoy montando ahora una pequeña librería de Arduino para hacer su uso más fácil, cuando la tenga la postearé aquí.

El código que he usado para hacer funcionar el cacharro este es el siguiente: OJO, está sin comentar ni optimizar en tiempos, pero funciona.

Código: [Seleccionar todo] [Expand] [Download] GeSHi © Codebox Plus

Mi clave pública de correo electrónico: http://www.nakerium.com/nakerium.gpg (Si no sabes lo que es lee este artículo)
Click aquí para ver mi email.


Programo aplicaciones a la carta (con soporte de por vida, para ingeniería o informática) y doy asesoramiento en seguridad informática. Si quieres más información mándame un email o un mensaje privado.
Avatar de Usuario
nake
管理者 (Admin)
Mensajes: 1994
Registrado: Vie Jun 04, 2010 4:10 pm
Ubicación: (sin(3t), 0, 0, t+10)
Contactar:

Re: Ingeniería inversa de un LCD con I2C integrado

Mensajepor nake » Mié Abr 16, 2014 4:07 pm

Ya tengo la librería hecha. La podéis descargar de aquí.

Es un fork de la librería LiquidCrystal estándar de Arduino adaptada para funcionar con este LCD concreto (aunque debería de funcionar con cualquier LCD por I2C si se conecta igual).


Para hacerla funcionar basta con conectar los cables de la línea I2C como se indica en la página de arduino (es decir, A4 (SDA), A5 (SCL) para un Arduino Uno), alimentar a +5V y ejecutar el programa de una forma similar a como se hace con la librería LiquidCrystal.

Código: [Seleccionar todo] [Expand] [Download] GeSHi © Codebox Plus



Una nota importante es que ahora es obligatorio llamar a la función begin antes de ejecutar nada. No se por qué pero no me funcionaba si la auto llamaba en el constructor.
También es obligatorio ahora añadir la librería Wire, ya que internamente la utiliza el sistema para la comunicación I2C.

No he probado todas las funciones, pero deberían de funcionar todas sin problemas.
También he visto que por la red hay versiones de librerías similares, pero todas las que he visto son muy viejas y ya no funcionan con las nuevas versiones de Arduino.

Si alguien encuentra algún bug, o quiere mejorar algo que lo diga en este mismo hilo.
¡Espero sea de ayuda!
Mi clave pública de correo electrónico: http://www.nakerium.com/nakerium.gpg (Si no sabes lo que es lee este artículo)
Click aquí para ver mi email.


Programo aplicaciones a la carta (con soporte de por vida, para ingeniería o informática) y doy asesoramiento en seguridad informática. Si quieres más información mándame un email o un mensaje privado.
soul666
Programador en BASIC (48-64)
Mensajes: 53
Registrado: Jue Sep 30, 2010 3:25 pm

Re: Ingeniería inversa de un LCD con I2C integrado

Mensajepor soul666 » Dom May 04, 2014 6:17 pm

Good job nake. No creo que yo lo hubiera conseguido... XD
Hoygan! que les convierto en rana!

Volver a “Robótica y electrónica”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado