Teclado de matriz 4×4 analógico para arduino

Aunque ya hay teclados de matriz analógicos comerciales y librerías para arduino (este, por ejemplo: https://www.sparkfun.com/products/12080) es interesante convertir los teclados de matriz que ya tenemos por casa a analógico.
Las placas Arduino tienen entradas analógicas de 10 bit y solemos tener alguna sin usar…
Siguiendo esta idea: http://www.technoblogy.com/show?NGM puede hacerse con 7 restencias normales del 5% de tolerancia con este esquema:

Código:

/*
* AnalogKeyPad: Teclado de matriz para lectura analógica
* segun esquema:  http://www.technoblogy.com/show?NGM
*
* (c) Heli Tejedor, https://heli.xbot.es, Octubre 2017
*
* Este Software se distribuye bajo licencia
*
* Creative Commons 3.0 Reconocimiento, No Comercial, Compartir Igual (CC BY-NC-SA 3.0)
* http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es_ES
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*
*/

// Configuracion del teclado
#define nKeys 16

#define NO_KEY 0
#define KEYPAD_PIN A0

// Tecla de la matriz 4x4: NINGUNA S1 S5 S9 S13 S2 S3 S4 S6 S7 S8 S10 S11 S14 S12 S15 S16
const int KeyVals[nKeys+1] = { 693, 665, 624, 573, 544, 491, 463, 432, 393, 353, 308, 249, 188, 157, 117, 79, 0};
const char Keys[nKeys+1] = {NO_KEY, '7', '4', '1', 'A', '8', '9', 'F', '5', '6', 'E', '2', '3', '0', 'T', 'C', 'P'};

// ===============================================================================
// Retorna caracter de la matriz
// ===============================================================================
char GetKey (int Val)
{
char i=0;
for (; i < nKeys; i++) if (Val >= KeyVals[i]) break;
return Keys[i];
}

// ===============================================================================
// Lee el teclado, retorna caracter de la matriz o NO_KEY
// ===============================================================================
char ReadKeyPad()
{
static char OldKey = NO_KEY;
char KeyPressed;
char FirstKey = GetKey (analogRead(KEYPAD_PIN));

// Necesita 10 lecturas validas seguidas durante 10ms
for (char i=0; i<10; i++)
{
KeyPressed = GetKey (analogRead(KEYPAD_PIN));
if (KeyPressed != FirstKey) return NO_KEY;
delay (1);
}
if (KeyPressed == OldKey) return NO_KEY;
OldKey = KeyPressed;
return KeyPressed;
}

// ===============================================================================
void setup(void)
{
Serial.begin (115200);
Serial.println ("Testing AnalogKeyPad");
}

// ===============================================================================
void loop(void)
{
char b = ReadKeyPad();
if (b != NO_KEY)
{
Serial.print ("Pulsado "); Serial.println (b);
}
delay(100);
}

Todos los ficheros del proyecto estan aqui:
https://heli.xbot.es/wp-content/uploads/2017/11/AnalogKeyPad.zip
junto con una tabla de excell para calcular los valores analógicos en función de las resistencias elegidas.

Actualización 2/11/2017: Una mejora que puede hacerse es montar la resisitencia de pullup de 15K Ohmios directamente en la entrada analógica, junto al arduino. De esta forma se evita que un mal conexionado del teclado provoque pulsaciones fantasma de las teclas. Además se elimina un cable del conexionado del teclado: ahora es solo de dos hilos!

Usando viejos displays LED 7 segmentos con SDA2131 desde arduino

Tengo una caja llena de viejos display de 7 segmentos LED, muchos de máquinas pimball, otros de básculas industriales…
Todos tienen más de 25 años y usan para controlar los displays chips Siemens SDA2131. Hoja de datos del SDA2131.

Cada uno de estos chips SDA2131 puede manejar 16 segmentos LED directamente, sin resistencias limitadoras, y la información se carga usando un bus serie síncrono. No es muy dificil escribir un programa que pueda manejarlos.
Usando partes de otro programa para LED de 7 segmentos (YL-3) https://heli.xbot.es/?p=151 que ya había escrito antes he escrito un pequeño programa para Arduino uno que controla estos displays: SDA2131 con Arduino

Usando un display de matriz LED indocumentado CDM102

Haciendo limpieza he desmontado y tirado una docena de viejos switches ethernet 10baseT de Nortel Networks «Baystack 102». Specs Baystack 102

A parte de mucho hierro tienen unas fuentes de alimentación fabricadas por Delta SMP43ep-5 muy interesantes.
https://www.usbid.com/assets/datasheets/C5/smp43ep.pdf
Proporcionan 5V hasta 11A, 12V 3A y -12V 0,5A aunque la potencia total es de 43W.

También son muy interesantes los displays de matriz de 12 * 5 LED bicolores. La pega es que no hay mucha información acerca de su funcionamiento. Llevan impreso el código «CDM102», pero parecen ser diseñados a medida y no existe información pública sobre ellos.

En google he encontrado algo de información, que coincide con mis primeros análisis: http://home.earthlink.net/~drbarrall/CDM102.html

El interface es série síncrono al estilo del SPI. El uso de cada uno de los 6 pines es el siguiente:

1: LOAD Load data (Active low)
2: V+ 5V
3: SDCLK Data Clock (Active high)
4: Ground
5: SDDATA Data
6: Reset (Active low)

Despues de probar los comandos publicados por DrBarral he llegado a la conclusión de que este display es un diseño a medida para Nortel, fabricado por Siemens – Infineon – OSRAM y derivado de los displays estándar SCDQ554x http://www.osram-os.com/Graphics/XPic1/00052446_0.pdf o SCD551x http://www.osram-os.com/Graphics/XPic4/00045726_0.pdf.
CDM102 podría ser Custom Display Module 102.
La principal diferencia es que se trata de una matriz doble de 6 x 5 mientras que los displays citados son de matriz de 5 x 5.

El juego de comandos es bastante sencillo, basado en una única palabra de 8 bits:
00 – 7F: 5 bits de datos para las columnas, bit 0 es el LED de mas arriba. Se incrementa el puntero automaticamente.
Hay 6 columnas
80 – 9F: Nop
A0 – A5: Selecciona bloque de columnas. Hay 2 bloques de 6 columnas. Bloque par color ROJO, impar color VERDE.
El bit 4 no importa. El primer bloque es el de la izquierda.
A6 – AF: Select none
B0 – B5: Selecciona bloque de columnas. Hay 2 bloques de 6 columnas. Bloque par color ROJO, impar color VERDE.
El bit 4 no importa. El primer bloque es el de la izquierda.
B6 – BF: Seleccionar NADA
C0 – DF: Test: rellena filas con rojo+verde: bit 0 = primera columna, bit 1 = segunda etc
E0 – EF: Ajustar brillo en 8 steps, el bit 3 no importa
F0 – FF: Ajustar brillo en 8 steps, el bit 3 no importa

He escrito un software de prueba que permite escribir caracteres en un número arbitrario de displays puestos lado con lado, bien de forma vertical como horizontal. Tembién contiene un ejemplo para usarlo como barra gráfica de 12 barras berticales x 5 LED o 5 barras horizontales de 12 LED.
He aprovechado los bitmap que ya tenía escritos hace años para los SCDQ554x, sirven igual pero solo son de 5 x 5 pixel, dejo sin uso una línea de LED en este display de 6 x 5.
Prueba para CDM102 con Arduino/Teensy

El montaje de pruebas ha quedado así:

Las funciones que he incluido dentro del programa de pruebas son las mismas que ya usé en el display YL-3: https://heli.xbot.es/wp-admin/post.php?post=151
Aunque he añadido un par de comandos para cambiar la orientación del texto y el color «ºh , ºv, «ºr y ºg.

Mini algoritmo de cifrado XXTEA para arduino

Estoy metido en tres fregados simultáneos de IOT (ahora se llama así, antes solo eran redes de sensores distribuidos) y estaba buscando un algoritmo de encriptación aceptable para dispositivos embebidos (no hay que perder de vista la seguridad de la IOT, que luego vienen los disgustos..)
De momento estoy usando Arduino Uno (Atmega328) y había reciclado un DES que usé en otro proyecto (librería de arduino http://spaniakos.github.io/ArduinoDES) pero como voy justo de memoria y tiempo de ciclo pensé en mejorarlo.

Valoré un AES del que también tengo librería para arduino https://github.com/DavyLandman/AESLib pero ocupaba demasiado espacio en flash.

Entonces me encuentro la sorpresa, viendo avr-crypto-lib un listado de algoritmos para micros AVR de atmel, veo que existe uno llamado XTEA muy sencillo de implementar y pensado para dispositivos embebidos. Desgraciadamente la implementación de avr-crypto-lib es muy básica y no es la versión mejorada XXTEA
Buscando por la red he encontrado algunas librerías de XXTEA para Arduino, pero son un calco de la publicación original y no aportan mejoras.

Después de un cortapega de la wikipedia y de machacar el teclado un rato he dejado el algorítmo bastante óptimo para Arduino.

En los test que he realizado, un arduino Uno a 16Mhz tarda en cifrar y descifra un bloque de 64 bytes:
Con DES en modo CBC tarda 284568us y ocupa 2572 bytes de flash
Con XTEA en modo CBC tarda 11008us y ocupa 916 bytes de flash
Con XXTEA tarda 4168us y ocupa 1086 bytes de flash
O sea que es rapidísimo y pequeñito…

La KEY es de 128 bits (mejor que el DES que solo es de 56) aceptable para mi aplicación. Se conocen ataques pero se basan en usar mas de 2^59 «textos planos escogidos», también aceptable!!

El código es extremadamente sencillo, la única desventaja es que sobreescribe los datos planos con los datos encriptados, aunque he preparado una versión con un simple memcpy que soluciona este problema con unas decenas de microsegundos de trabajo extra.

El código fuente con DES, XTEA y XXTEA y algunas pruebas: XxteaTest

Mini programa para iniciar la EEprom del ATmega328 del Arduino UNO

Llevo bastante tiempo liado desarrollando aplicaciones para Arduino…
En algunos proyectos me encuentro que es dificil inicalizar la EEprom del Arduino (ATmega328). El IDE arduino (la version actual es 1.8.2) no genera los ficheros .eep que necesita avrdude para grabar el atmega, entonces declarar variables con EEMEM e inicializarlas en el IDE no sirve para nada.

Para solucionar este problema he escrito un pequeño programa que se carga en el arduino UNO (valdría para otros modelos con algunas modificaciones) y mediante comandos por el puerto serie permite leer o escribir la EEprom y dejarla ya inicializada. Luego se carga el programa que se necesite y se encuentra las EEprom inicada con los valores adecuados.

El proceso es el siguiente:
Se carga este programa en el Arduino UNO (renombrarlo a .ino):

SetEEprom.ino

A continuación se abre el monitor serie y se configura a 115200 baudios y enviar CR LF.
En el monitor serie se pueden escribir los comandos adecuados para ir iniciando la EEprom a los valores deseados. Lo mejor es prepararlo en un archivo de texto y hacer corta-pega sobre el monitor serie.
Estos son los comandos disponibles en el programa:

SetEEprom.txt

Por ejemplo se puede borrar toda ea EEprom (ponerla a 0xFF) con:
Write Init EEprom

Y luego iniciar una cadena de 10 caracteres en la dirección 0 con el valor «hola mundo»
Write String 0 10 Hola Mundo

y un bloque de 10 datos en la dirección 20:
Write EEprom 20 10 0F0302B1421CA7485823

Una vez iniciada la EEprom se carga el programa que necesitamos en el Arduino UNO y cuando arranque se encontrará la EEprom ya iniciada con los valores que introdujimos.

Solucion al crash en mame4all 0.37b5 para raspberry pi con 6 joysticks

Intentando configurar MAME en mi consola con RPI2 y retropie ( esta: https://heli.xbot.es/?p=365 ) con los joysticks /dev/input/js4 y /dev/input/js5 que son tipo PSX, veo que hay algún error en la distribución actual de mame 0.37b5.
Mame4all «casca» con «fallo de segmentación» (técnicamente es un «crash» con «segmentation fault») cuando activo alguno de los botones de los joysticks, incluso aunque no estén configurados en el mame. Basta con tenerlos conectados y usarlos.

Gracias a que el software es de fuente abierta he podido analizar el código (es c y c++) y usando mis superpoderes de programador he conseguido encontrar el error y crear un parche que soluciona el problema.

En primer lugar es necesario descargar los sources actuales de mame4all para RPI.

Esta versión que distribuyen con retropie: https://github.com/RetroPie/mame4all-pi
Esta versión es un poco mas moderna, aunque solo tiene cambios precisamente en la gestión de joysticks de PSX, pero no solucionan mi problema:
https://sourceforge.net/p/mame4allpi/code/ci/master/tree/src/

Desde la RPI con conexión a internet hacer, como usuario pi desde su directorio personal:
git clone git://git.code.sf.net/p/mame4allpi/code mame4allpi-code

Esto creará un directorio «~/mame4allpi-code» con los fuentes actuales V0.37b5 a fecha de hoy (Octubre de 2016).
En «~/mame4allpi-code/src/rpi» se encuentran los dos ficheros que hay que modificar.
El problema se presenta porque se crea un array de 4 elementos para almacenar los datos de 4 joysticks. Un comentario en el código indica que solo se trabajará con 4 joysticks. Pero en una función posterior existe un bucle que rellena los arrays de datos de los joysticks. El buche tiene tantas interaciones como joysticks tenga el sistema (detectado mediante una llamada a la API). Entonces si esa llamada devuelve mas de 4 la función acaba escribiendo datos fuera del los arrays declarados.

En el fichero «minimal.cpp», en la línea 140 se encuentra la función «int init_SDL(void)»
Voy a comentar los cambios necesarios y los problemas que problema el código original de «minimal.cpp»:
//SDL_Joystick* myjoy[4]; // Original: solo soporta 4 joysticks
SDL_Joystick* myjoy[6]; // Nuevo: Ahora tiene cabida para 6 joysticks

int init_SDL(void)
{
myjoy[0]=0;
myjoy[1]=0;
myjoy[2]=0;
myjoy[3]=0;
myjoy[4]=0; // Nuevo: Inicializar los nuevos elementos
myjoy[5]=0; // Nuevo: Inicializar los nuevos elementos

if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
return(0);
}
sdlscreen = SDL_SetVideoMode(0,0, 16, SDL_SWSURFACE);

//We handle up to four joysticks
if(SDL_NumJoysticks)
{
int i;
SDL_JoystickEventState(SDL_ENABLE);

for(i=0;i<SDL_NumJoysticks;i++) { // Aqui estaba el problema, SDL_NumJoysticks() puede devolver mas de 4
myjoy[i]=SDL_JoystickOpen(i); // Pero solo habia mjoy[] para 4, si SDL_NumJoysticks() devuelve > 4 se escribe fuera del array!

Esto NO SOLUCIONA TODO EL PROBLEMA porque si el sistema tiene configurados mas de 6 joysticks estamos igual. Solo hemos actualizado el mame para que soporte 6 joysticks, pero cascará igual si hay mas.
La solución definitiva sería modifica la función «int init_SDL(void)» en minimal.cpp de forma que solo procese 6 joysticks independientemente del número de ellos que devuelva la llamada al sistema, así:
//We handle up to SIX joysticks
int NumJoysticks = SDL_NumJoysticks();

if (NumJoysticks > 6) NumJoysticks=6; // Ignoramos los demas joysticks
if(NumJoysticks)
{
int i;
SDL_JoystickEventState(SDL_ENABLE);
{
for(i=0;i<NumJoysticks;i++) { // Aqui estaba el problema,
myjoy[i]=SDL_JoystickOpen(i); // Ya no puede escribir escribe fuera del array!

A consecuencia de estos cambios también hay que modificar «input.cpp» para que pueda gestionar los nuevos joysticks:
En la línea 8:
unsigned long ExKey1=0;
unsigned long ExKey2=0;
unsigned long ExKey3=0;
unsigned long ExKey4=0;
unsigned long ExKey5=0; // Nuevo
unsigned long ExKey6=0; // Nuevo
unsigned long ExKeyKB=0;
// int num_joysticks=6; // Original: solo 4 joysticks
int num_joysticks=6; // Nuevo: ahora 6

En la función «void joyprocess(Uint8 button, SDL_bool pressed, Uint8 njoy)»
Uint32 val=0;
unsigned long *mykey=0;

if(njoy == 0) mykey = &ExKey1;
if(njoy == 1) mykey = &ExKey2;
if(njoy == 2) mykey = &ExKey3;
if(njoy == 3) mykey = &ExKey4;
if(njoy == 4) mykey = &ExKey5; // Nuevo
if(njoy == 5) mykey = &ExKey6; // Nuevo

y En la función «void gp2x_joystick_clear(void)»:

ExKey1=0;
ExKey2=0;
ExKey3=0;
ExKey4=0;
ExKey5=0; // Nuevo
ExKey6=0; // Nuevo

Lo mas rápido es descargar estos parches que ya he preparado con los cambios:
https://heli.xbot.es/wp-content/uploads/2016/10/minimal.patch_.txt
https://heli.xbot.es/wp-content/uploads/2016/10/input.patch_.txt
cd mame4allpi-code/src/rpi
wget https://heli.xbot.es/wp-content/uploads/2016/10/minimal.patch_.txt
mv minimal.patch_.txt minimal.patch
patch minimal.cpp minimal.patch
wget https://heli.xbot.es/wp-content/uploads/2016/10/input.patch_.txt
mv input.patch_.txt input.patch
patch input.cpp input.patch

Compilar y copiar el ejecutable al directorio que usa retropie:

cd ..
cd ..
make
sudo mv /opt/retropie/emulators/mame4all/mame /opt/retropie/emulators/mame4all/mame.old
sudo cp mame /opt/retropie/emulators/mame4all

Driver para joystick multiplexado para Raspberry PI: hasta 160 switches con 26 GPIOs

El pasado mes de Noviembre le regalé a mi hijo una consola arcade (concretamente una de estas http://arcademadrid.com/50-mando-consola-arcade-hdmi-tv-arcade-2-jugadores). Funciona mediante una Raspberry PI 2, el mueble esta bastante bien y tiene 2 joysticks y 16 pulsadores de buena calidad.
Trasteando con ella he observado que consume casi todos los GPIOs de la raspberry pi 2 para los switches de los pulsadores. Son 24 switches, conectados cada uno a un GPIO, y la raspberry PI 2 tiene 26 GPIOs.
Como me interesa añadir mandos de SNES y un volante de PS2 usando el driver «gamecon_gpio_rpi» https://github.com/RetroPie/RetroPie-Setup/wiki/GPIO-Modules he diseñado una esquema de conexionado nuevo, multiplexando la lectura de los switches, de forma que puedo conectar los 24 switches usando solo 10 GPIOs. Así puedo conectar los mandos SNES y PS2 en los pines que quedan libres
Usando este conexionado se pueden conectar los 24 switches incluso a una raspberry PI 1 que solo tiene 17 GPIOs disponibles en el conector de 26 pines.
Claro que para que esto funcione bien es necesario escribir un driver del kernel de linux que se encargue de leer el hardware y lo muestre en un dispositivo (en el arbol /dev) de forma que los programas lo puedan utilizar.

Una complicación autoimpuesta es que se pueda usar tanto para raspberry pi 1 con conector de 26 pines como con raspberry pi B+ ó 2 con conector de 40 pines intentando dejar siempre como última elección los pines de funciones especiales.
Gracias a esto es posible conectar 2 joysticks con 8 pulsadores (mas 4 de dirección) cada uno dejando libres los pines de TX y RX de UART0 y SDA1 SCL1 del I2C. En la versión 0.0.2 del driver intento también dejar libres los pines que necesita el driver «gamecon_gpio_rpi».

El conexionado eléctrico es fácil, solo se necesita un diodo de señal (1N4148, por ejemplo) por cada pulsador para evitar interferencias al actuar varios pulsadores a la vez. El driver permite 18 tipos distintos de esquemas de conexionado dependiendo del número de switcheslos y joysticks que se deseen usar y del número de GPIOs disponibles.
Yo usaré el «type=14» que permite hasta 5 joysticks de 2 ejes y 8 botones auque el mueble solo necesita 2 de ellos.
El conexionado que he usado es este:
Esquema type=14

En el esquema solo se nombreb los switches con «swX» donde X es un número. Dependiendo del parámetro del driver «map=n» se mapean a los distintos pulsadores de los joysticks siguiendo este mapa:
Mapa SWx

El conexionado multiplexado se basa en cablear los switches en forma de filas y columnas. Las filas se conectan a SALIDAS GPIO de la raspberry y las columnas a ENTRADAS GPIO con el pullup activo. De esta forma con un único grupo de entradas GPIO se pueden leer, de forma alternativa, cada una de las filas. Para leer una fila es necesario poner a nivel BAJO el GPIO correspondiente. Entonces existe un nivel bajo en la fila que los pulsadores pueden enviar a las entradas (columnas) cuando de actuan. El resto de filas se mantienen a nivel alto que es bloqueado por los diodos y es como si no estuvieran conectadas.
Para usar el menor número de GPIOs he subdividido cada fila en dos, de forma que hay dos GPIO de salida por cada fila pero solo la mitad de GPIOs de entrada (columnas).
Con 27 GPIOS disponibles en los conectores de 40 pines de las raspberry se pueden conectar hasta 160 switches (usando el conexionado «type=11») en una matriz de 8 x 20 (en realidad 16 x 10 por que he partido cada fila en dos, asi solo se usan 10 entradas en lugar de 20, pero se usan 16 + 10 pines de GPIO en lugar de 8 + 20).

El driver se instala desde un paquete .deb que he preparado. Se compila en la propia raspberry porque depende del hardware.
Antes de instalarlo es recomendable actualizar la raspberry con:
sudo apt-get update
sudo apt-get dist-upgrade -y
sudo reboot

Luego pueden eliminarse los paquetes fuente de la actualización para ahorrar espacio con:
sudo apt-get clean

Descargar el instalador, worpress no me permite subir .sh «por seguridad» y lo he ‘targzipeado’:
wget https://heli.xbot.es/wp-content/uploads/2016/05/install.tar.gz
tar -xzvf install.tar.gz
sudo ./install.sh

Primero descargará varios paquetes necesarios para la compilación: dkms, cpp-4.7, gcc-4.7 y joystick
Luego descargará los headers del kernel adecuado a la versión instalada, necesarios para la compilación del driver, con un «wget http://www.niksula.hut.fi/~mhiienka/Rpi/linux-headers-rpi/linux-headers-`uname -r`_`uname -r`-2_armhf.deb» y lo instalará con «sudo dpkg -i linux-headers-`uname -r`_`uname -r`-2_armhf.deb»
A continuación conectará con esta página, hará un wget del .deb heli-mpx-joystick-rpi-0.0.2.tar.gz y lo instalará con «sudo dpkg -i heli-mpx-joystick-rpi-0.0.2.deb». Por último eliminará el paquete fuente de los headers, que ya no es necesario, pero los headers se quedan instalados la raspberry en /usr/src/linux-headers-x.x.x.

Todo esto llevará bastante tiempo y es necesario tener una conexión a internet operativa en la raspberry.

En una de mis raspberries he observado un problema en la compilación, debido a la actualización de los headers a a la versión 4.4.9+
"No rule to make target 'kernel/time/timeconst.bc'"

Lo he solucionado copiando el fichero timeconst.bc de http://mirrors.neusoft.edu.cn/rpi-kernel/kernel/time/timeconst.bc a ‘kernel/time/timeconst.bc’

Una vez instalado puede cargarse con
sudo modprobe heli_mpx_joystick_rpi map=2 devices=2 type=14
y probarse con
jstest /dev/input/js0
jstest /dev/input/js1

Jstest tiene un fallo, conocido pero no parcheado (al menos en la versión del paquete ‘joystick’ del repositorio de la raspberry). No muestra correctamente los nombres de los botones del joystick. Es debido a un array de nombres donde faltan tres elementos y eso hace que queden descolocados los demás.
Mientras preparaba esta entrada veo que han actualizado linuxconsoletools, que es el paquete de fuentes donde viene jstest, a la versión 1.5.1 (la anterior era la 1.4.9). Supongo que habrán incluido el parche.
https://sourceforge.net/projects/linuxconsole/files/

El driver puede descargarse del kernel con
sudo rmmod heli_mpx_joystick_rpi

También puede desinstalarse totalmente con
sudo apt-get remove heli-mpx-joystick-rpi-dkms

Fuentes y el resto de los los ficheros del proyecto aqui: https://heli.xbot.es/wp-content/uploads/2016/05/heli_mpx_joystick_rpi_0.0.2_src.tar.gz

Documentos y esquemas del proyecto aqui: https://heli.xbot.es/wp-content/uploads/2016/05/Docs-0.0.2.rar

Para que cargue de forma automática al arrancar la raspberry es necesario añadir en ‘/etc/modules’ una línea:
heli-mpx-joystick-rpi
y crear un fichero de configuración ‘/etc/modprobe.d/heli-mpx-joystick-rpi.conf’ con los parámetros deseados:
options heli-mpx-joystick-rpi map=2 devices=2 type=14

Una vez recableados los switches del mueble original e instalado este driver quedan 16 pines libres donde se pueden cablear los los conectores de la SNES y de la PS2 extraidos de consolas averiadas que he montado en el mueble asi:
Conectores SNES y PS2

Luego uso el driver «gamecon_gpio_rpi» según se explica en https://github.com/RetroPie/RetroPie-Setup/wiki/GPIO-Modules.

Y todo ha quedado asi:
Consola Retropie con SNES y PS2

Usando un display indocumentado de DealExtreme YL-3 con drivers 595

Hace una semana compré unos displays de LED de 7 segmentos, de 8 dígitos, en DealExtreme pensando en un visualizador de coordenadas para un CNC.

Display YL-3

El sdisplay se suministra sin documentación esquema ni nada. En la serigrafía de la placa solo aparece el texto «YL-3» por lo que yo llamaré a este display así. No he sido capaz de encontrar informacion acerca de su uso, esquemas, ni nada. Tendré que hacer yo mismo el esquema y el código para su uso.

Un poco de ingenieria inversa:

En primer lugar será necesario el esquema para poder empezar a escribir el código que lo haga funcionar. Lo primero es buscar la documentación de los elementos que usa el display para saber or donde empezar a trazar el esquema.
Este modelo usa drivers HC595 que son simples registros de desplazamiento con latches de salida. De esta forma los datos desplazados no aparecen en la salida hasta que se activa el latch y se evita imagen fantasma en el display. Es curioso pero el sn74hc595 común es un registro de desplazamiento con salidas TTL, no adecuadas para encender LED, pero existen versiones de alta corriente de salida que son las que se usan aquí.
Los dos displays de 4 dígitos por 7 segmentos y punto decimal estan marcados «3461BS» y tampoco he encontrado un esquema, con el SuperProbe en modo prueba de diodos voy averiguanduando su conexionado. Están conectados los ánodos en común.
Por suerte en la placa esta serigrafiada la utilidad de los terminales de conexión y es facil seguir con el tester de continuidad el esquema.

Esquema YL-3

Ademas voy a probarlo con un Teensy 3.1 en lugar de usar un arduino convencional.

Solo son necesarios 5 cables, dos de alimentación, un clock, un data y un estrobe. Este es el montaje de pruebas, con una tarjeta SD para apreciar el tamaño de los componentes:

Prueba Teensy 3.1 + YL-3

El display trabaja multiplexado ya que los LED estan conectados en forma de matriz de 8×8.
Este es el código que uso: YL-3.RAR
El .rar contiene una libreria «hc595x2» para colocar en el directorio «libraries» de arduino y un sketch «Test_hc595x2″ para compilar y probar el display (para Teensy 3.1, no lo he probado con otros arduino).
El programa acepta caracteres ASCII por el puerto serie virtual USB y los visualiza en el display, también algunos símbolos y algunos caracteres de control.
Los caractres aceptados son:
Números 0-9, letras minúsculas a-z y letras mayúsculas A-Z.
Letra ñ (ASCII 209 ó 241)
Espacio en blanco » «, guión «-«, guión bajo «_», barra «/», grado «º» ASCII 186, punto «.», coma «,» (los dos encienden el punto decimal y no avanza el cursor), comilla «‘» ASCII 39 y comillas «»» ASCII 34.

Los códigos de control son:
Retroceso (Backspace) CTRL-H ASCII 8, retorno del carro (retorno del cursor al inicio del display) CTRL-M ASCII 13, Delete ASCII 127, Limpiar el display y retorno del cursor CTRL-J ASCII 10.

Mejor revisar el código para ver las funciones…

Otro detalle, el entorno arduino 1.0.5 se cuelga si en el nombre del archivo hay un guión: «test yl-3.ino» lo cuelga, «test yl_3.ino» funciona bien…

Asi funciona:

El display es muy barato y brillante, y no es dificil usarlo aunque el micro tenga que hacer el multiplexado no es mucha carga de trabajo.
Me comentan en el foro de ARDE que se pueden encontrar unos displays muy similares en EBAY con un enlace a su esquema en PDF.

PLC en Raspberry PI: classicladder

El proyecto «classicladder» consiste en un PLC (en inglés Programmable Logic Controller, autómata programable o solo autómata en español) programable en ladder (diagrama de contactos en español) o en grafcet. También integra un entorno de monitorización y comunicaciones, incluyendo MODBUS para las entradas y salidas. Esta escrito en C y usa el entorno GTK+2, puede compilarse para Windows y para Linux.
El autor de este programa es Marc Le Douarain, yo he hecho pequeñas contribuciones: https://sites.google.com/site/classicladder/
El software interpreta el programa, al contrario que otros PLCs que ejecutan código compilado en un PLC virtual, y es totalmente funcional. Es posible ejecutar el software en una máquina sin entorno gráfico y controlarlo desde otra con entorno gráfico mediante comunicaciones (tcp/ip o serie).
Compilarlo para Raspberry pi no debería ser dificil, corre un linux.

Trabajando en la propia raspberry pi con conexión a internet, primero descargamos los fuentes en C de la última versión a 18/2/2013 classicladder 0.9.6 desde el directorio de usuario PI:
«wget http://sourceforge.net/projects/classicladder/files/classicladder/classicladder-0.9.006.tar.gz»
Y lo descomprimimos con:
«tar -xvzf classicladder-0.9.006.tar.gz»
Esto crea el arbol de diecorios en ~/classicladder, ahora cambiamos los permisos de los ficheros, por seguridad.
Entrar en el directorio:
«cd «~/classicladder/projects_examples»
y hacer
«chmod 644 *»
Salir al directorio «~/classicladder»:
«cd ..»
y hacer:
«chmod 644 *»
«chmod 755 projects_examples»

Ya tenemos todos os fuentes listos.
Ahora podemos compilar el software CON o SIN entorno gráfico. Si lo hacemos sin entorno gráfico no podremos controlar el PLC classicladder si no es comunicándolo con otro classicladder que si tenga entorno gráfico.

Para compilar con entorno gráfico es necesario instalar las librerías del entorno GTK+2:
«sudo apt-get install libgtk2.0-dev»

Ya esta todo listo, compilar simplemente ejecutando make desde el directorio de los fuentes, el makefile que acompaña al royecto ya esta configurado para linux y funcionará perfectamente en la raspberry pi:
«cd «~/classicladder»
«make»
Esto habrá creado un fichero ejecutable «classicladder». Ya podemos probarlo ejecutarlo «./classicladder». Se desplegrán varias ventanas y podremos ver el estado del PLC…:

Escritorio de raspberry con classicladder

Podemos salvar esta versión del ejecutable con entorno gráfico con otro nombre:
«cp classicladder classicladder_gtk»

Para compilarlo SIN entorno gráfico y usarlo como aplicación embebida, mucho mas ligero (la aplicación gráfica con GTK+2 consume bastante CPU de la raspberry), hay que modificar un para de cosas en el fichero «Makefile»:

Comentar la siguiente línea:
«GTK_INTERFACE = 1» -> «#GTK_INTERFACE = 1»
Esto le dice al makefile que compile el proyecto SIN entorno gráfico.
Comentar las siguientes líneas:
«OWN_CFLAGS = -march=i486» -> «#OWN_CFLAGS= -march=i486»
«OWN_LIBS = -march=i486» -> «#OWN_LIBS = -march=i486»
Estas líneas son específicas para entornos intel x86, nosotros vamos a compilarlo para ARM.
Salvar el fichero modificado, hacer:
«make clean»
para limpiar cualquier compilación anterior y compilar de nuevo con:
«make»
Se habrá creado un nuevo ejecutable «classicladder».

Para que funcione correctamente en modo embebido SIN entorno gráfico hay que crear un directorio donde se almacenarán los programas recibidos y donde classicladder buscará para cargar automáticamente el programa en el arranque:
«cd /usr/local»
«md classicladder»
Esto creará un directorio «/usr/local/classicladder»

Ejecutar classicladder desde el directorio donde se creó:
«cd ~/classicladder/
«./classicladder»
Podremos ver una serie de mensajes y al final «SOCKET WAITING». Este será el PLC tarjet y ya esta funcionando y esperando órdenes. Ahora podremos comunicarnos con este PLC desde otra máquina con entorno gráfico.
Conectar la red a la raspberry y hacer «ifconfig» para ver su IP, si no la hemos anotado cuando arrancó.
En otro PC o raspberry arrancar el classicladder con entorno gráfico.
Cargar un programa con File->Load
Transferirlo al PLC tarjet con PLC->FileTransfer->Send Current Project To Tarjet y poner la IP del PLC tarjet (la raspberry pi).
Una vez que el PLC tarjet tenga el programa cargado arrancará en RUN cada vez que arranquemos classicladder en la raspberry pi.
Ahora podremos hacer PLC->Connect y poner la IP del PLC tarjet para monitorizar el estado y las variables del PLC. También podemos pararlo etc.

Podrá verse en el PLC tarjet distintos mensajes durante la recepción de datos.
Si todo va bién el programa recibido se grabará en «/usr/local/classicladder/nombredelprograma.clprjz»

CONECTANDOLO CON EL MUNDO REAL
Vale, esto es muy bonito, pero ¿y controlar directamente entradas y salidas reales desde la reaspberry pi y classicladder?. En principio basta con conectar el puerto serie de la raspberry, en el conector P1 pines 6(GND), 8(TXD) y 10(RXD) a cualquier dispositivo que use protocolo MODBUS (con el adaptador de nivel adecuado, la raspberry pi usa TTL a 3,3V).
Se puede usar un módulo IO MODBUS el propio autor del programa Marc Le Douarain: https://sites.google.com/site/classicladder/classicladder_io_module
También se pueden usar módulos ADAM de Advantech: http://www.advantech.es/producto/adquisicion-de-datos/data-acquisition-modules

Los pines tienen dos nombres: uno el original del chip (broadcom) y otro el que da el sistema operativo (raspberry pi):
Pines GPIO

¿Y por que no usar los pines GPIO directamente?. Son pocos, y puede que nos interese usarlos para mas cosas… pero como hace años ya diseñé una placa de ampliación de I/O (SIO) basada en registros de desplazamiento voy a revivirla y usarla aquí!!!!
Esta es el esquema adaptado a la raspberry pi, hay que conectar 8 hilos del conector P1 (6 señales y dos de alimentación) y listo.:

Esquema Shifted Input Output
Esquemas Eagle: https://heli.xbot.es/wp-content/uploads/2014/01/Raspberry_SIO.zip

La placa de registros de desplazamiento queda alimentada desde la raspberry pi. Ahora hay que modificar classicladder para que use este hardware. Hay varias formas de usar los GPIOs de la raspberry pi:
Mediante el sistema de archivos virtual «/sys/class/gpio»
Usando una librería como: http://www.open.com.au/mikem/bcm2835.
Accediendo directamente al hardware, esta es la que yo usaré: http://elinux.org/RPi_Low-level_peripherals#GPIO_Driving_Example_.28C.29
Despues de escribir el código mostrado y hacer unas pruebas veo que puedo escribir en los puertos sin problemas. Pero ¿y leer?. No hay ninguna función para leer los puertos en el ejemplo… Busco la datasheet del chip bcm2835 y busco el periférico GPIO. Perfecto en el apartado 6.1 (página 90), describe las direcciones de memoria donde estan mapeados los GPIOs, los pines se pueden en el offset 34h desde el inicio del mapa de GPIO. Como los accesos a memoria a 32 bit, para acceder a la dirección 34h usaré (gpio+13) porque (13*4) = 53d = 34h
Por lo tanto para leer los 32 GPIOs sería (g es el número de GPIO 0-53, gpio es la dirección base del periférico):
PINS_READ(g) *(gpio+(13+(g*3)) // Lee los 32 bits donde esta incluido el GPIO g
y para leer un pin individual:
PIN_READ(g) (((*(gpio+13)) & 1<< g)==1<< g) // Retorna el estado del GPIO g: 0 or 1 Me ha costado mucho que esto funcione, aunque hay mucha información acerca de la raspberry pi es dificil reunirla de forma consistente. Un problema que me ha hecho perder varias horas picando código y mirando con el osciloscopio es que el pin 13 de P1 (GPIO21 según Broadcom, o GPIO2 según Raspberry pi) en la versión V2 esta conectado a GPIO27 (según broadcom). El sistema operativo de la raspberry lo mapea a GPIO2 igual que en las V1, pero si se accede al hardware y no se usa el sistema operativo hay que tenerlo en cuenta!!! Ahora solo hay que incluir todo lo probado en el fichero "hardware.c" de classicladder y modificar "Makefile" para que se pueda compilar con o sin este hardware experiemental. Mis versiones de Makefile y hardware.c: https://heli.xbot.es/wp-content/uploads/2014/01/Makefile_y_hardware.zip
En Makeile ahora hay dos nuevos switches:
RASPBERRY_PI = 1
Si no se comenta con # al principio compila para raspberry pi.
MAKE_SIO_ACCESS = 1
Si no se comenta con # al principio compila con el hardware experimental SIO, esta opción puede usarse también para windows y para linux en entorno PC usando el puerto paralelo. Es similar a MAKE_IO_ACCESS.
Descargarse mi version desde la raspberry pi en el directorio «~/classicladder»:
«wget https://heli.xbot.es/wp-content/uploads/2014/01/Makefile_y_hardware.zip»
descomprimirla:
«unzip Makefile_y_hardware.zip»
Contestar «yes» cuando nos pregunte que si sobreescribe los ficheros existentes.
Compilarla:
«make»
Ahora para ejecutarla hay que hacerlo como superusuario. Esto es así porque necesita acceder a la menoria física del sistema (para leer y escribir en los GPIOs). Supongo que también funcionaría si el usuario tiene permisos de lectura y escritura sobre el dispositivo «/dev/mem».
«sudo ./classicladder»
Si alguien esta interesado en inspeccionar el código, las modificaciones hechas en «hardware.c» estan entre las directivas
#if defined (MAKE_SIO_ACCESS) – #endif

Asi se ve la placa SIO con la raspberry pi funcionando:
Esquema Shifted Input Output

CLASSICLADDER CON SIO EN PC
También podemos compilarlo para PC, si comentamos:
#RASPBERRY_PI = 1
en makefile. Si vamos a compilar bajo windows descomentamos:
WINDOWS = 1
Si lo hacemos bajo linux es necesario dejarlo comentado:
#WINDOWS = 1
Para usar el la placa SIO conectada al puerto paralelo hay que poner en «hardware.c» la dirección física del puerto LPT del PC:
#define SIO_PORT 0x378 // Base port for PC hardware LPT1, LPT2=0x278, LPT3=0x3BC
Y usamos este cable para conectar el PC con la placa SIO:

Esquema Shifted Input Output
Esquemas Eagle: https://heli.xbot.es/wp-content/uploads/2014/01/Raspberry_SIO.zip (El fichero contiene los dos esquemas, placa SIO para raspberry pi y cable PC).

El software es experimental, los parámetros de configuración deberían poder modificarse a través de los menús de «config_gtk.c», y estar definidos en «classicladder.h» en la estructura «infos_gene», por ejemplo. Pero para comenzar sirve…

He comprobado que con la raspberry pi es muy estable, sin embargo bajo windows se producen glitches periódicos que desactivan las salidas… Bajo linux (suse 12) también, pero en menor medida.
En windows con mas de un procesador va francamente mal, he tenido que incluir código para forzar el proceso en una sola CPU:
SetProcessAffinityMask(GetCurrentProcess(), 1); // Ejecutar solo en la CPU #1
Supongo que estos problemas son debidos al entorno multitarea, este mismo hardware con un micro PIC, atmel o similar y las mismas rutinas funciona perfectamente.

Yo no he usado una placa completa de 32 salidas y 32 entradas, sino una mas pequeña pero con entradas optoaisladas y con relés en las salidas (16 entradas y 8 salidas).

Super Probe Plus: Sencillo multitester con PIc y 20 funciones

Rebuscando por la red encontré hace tiempo el SuperProbe aquí: http://mondo-technology.com/super.html
El diseño original con firmware V38 cuenta con 18 funciones. Me pareció un proyecto muy sencillo para un aficionado, y muy completo para llevar siempre en la caja de herramientas. El coste del proyecto es de solo unos 15 Euros!!
Usando partes del código original y otras escritas por mi he creado este clon con 20 funciones.
La única diferencia con el SuperProbe original es que el SuperProbePlus lleva intercambiadas entre si las resistencias R13 y R14 de 150 Ohmios y 100K. Esto es necesario para usar el generador de tensión de referencia interno del PIC a través del pin 4 (RA2) y dejar libre el pin 17 (RC6). Este pin antes se usaba para crear un divisor resistivo y generar 2.5 V para la detección de nivel flotante en el probador lógico. Ahora se usa para detectar el estado del nuevo selector de voltaje alto (25V) – bajo (5V). Permutando estas dos resistencias puede usarse mi código en un SuperProbe original. Si no se usa el conmutador del selector de voltaje alto – bajo poner el pin 17 (RC6) a nivel bajo (masa).
Opcionalmente puede conectarse un altavoz sustitución de la resistencia de 150 Ohmios y, prescindiendo de la generación de señal NTSC que necesita esa resistencia, tener un zumbador para medir cotinuidad.

Esquema Super Probe Plus 1.1

Las mejoras sobre el SuperProbe original son muchas:

Prob: nuevos modos
Puls: nuevas frecuencias y calibración exacta.
Voll: Calibración exacta y filtrado.
Diod: Salida de 10mA al pulsar PB1 para encender LED.
Ohms: Nuevo modo.
Cap: Mejorada la precisión.
Coil: Ahora solo inicia medida al pulsar PB1 para evitar bloqueo al entrar en el modo.
Freq: Calibrado exacto, nuevo modo RPM.
Cnt: Mejorada la visualización low-all.
Sig: Calibrado exacto.
Ser: Nuevas velocidades y modo auto.
rc.ou: repetición de los pulsos exacta a 50hz.
rc.in: Nuevo modo.
[]: Nueva forma de cambiar frecuencia, calibración exacta a 1Hz.
ir.ou: Nuevas frecuencias.
stop: ahora trabaja en milisegundos y formato h:mm:ss:nnn

Además ahora el programa fuente compatible con MPLAB esta mejor comentado y es mas versatil. Usando las directivas #define puede configurarse para distintas versiones de hardware y con distintas funciones.
Los datos de calibración y escalado se guardan en EEPROM de forma que es posible cambiarlos sin reprogramar el IC, por ejemplo para usar un divisor de tensión distinto.
Usando el regulador LP2950 se mejora la precisión analógica hasta 1,5%, bastante mejor del 5% del LM28L05 o del LM2931. El consumo es de alrededor de 40mA a 9V con multiplexado 1:32 (el original) ó 75mA a 9V con multiplexado 4:32 (usando transistores, da mas brillo y menos parpadeo).

Este es el manual del Super Probe Plus V42:

A fecha 8 de Marzo de 2012 he actualizado algunos errores y POR FIN HAY PCB!!

SuperProbe2

En el siguiente RAR hay: Fuentes para MPASM, esquema con Eagle, ficheros .ps listos para imprimir y «planchar» la placa, lista de componentes con los precios y códigos de RS etc.
He ensamblado dos versiones lista para usar, sin transistores para displays de ánodo común, una con generador NTSC y otra con zumbador en medición de continuidad. Cambiando los defines adecuados en el código fuente puede compilarse con o sin transistores, para displays de ánodo o cátodo común, con generador de señal o no y con ntsc o zumbador.

Descargar todos los ficheros del proyecto.

Esquema Super Probe Plus 1.1

Galeria de fotos de SuperProbe