Finalmente me he decidido a presentar mi primer proyecto y primer contacto con Arduino.
Antes que nada aclarar que he programado en assembler para Z80, 8085, 6502, 8086, en ese órden.
Y lenguajes como Fort, Fortran, Cobol, Pascal y Turbo Pascal, Basic, Visual Basic y Python
Finalmente Pic assembler gracias a Monty (¿Alguno se acuerda del robot Monty?).
Quiero decir, experiencia en programación tengo pero nada de C, menos de Arduino.
Bueno, volvamos a lo que me llevó a hacer el proyecto.
Hace unos meses adquirí un Toyota Corolla 2010 que trae un estéreo bastante básico, solo radio y lector de CDs. No trae entrada auxiliar ni puerto USB, menos aún conexión bluetooth. Lo más moderno que trae es control remoto en el volante.
Por eso decidí cambiarlo por un estéreo Pioneer MVH-285BT que tenía instalado en otro auto y que, para mis necesidades, es suficiente y tiene justamente lo que al del Corolla le falta, además tiene entrada para un control remoto cableado.
A pesar de que venden interfaces adaptadoras, no le veía sentido pagar por una de ellas más que el valor del estereo que estaba instalando, así que me puse a investigar con la idea de hacer algo con algún PIC ya que, como conté antes, hice con ellos algunas cosas aunque hace ya muchos años pero, bueno, eramos viejos conocidos.
El primer paso fue conseguir los esquemas eléctricos del auto para ver qué tenía en la botonera del volante y entender su funcionamiento. ¿Usaría algún protocolo como CANBUS? ¿Cómo sería el cableado?
Finalmente dí con el esquema necesario
Ya se develaron los primeros interrogantes:
- El botón [ MODE ] cierra a masa, es independiente, tiene su propio pin y podría fácilmente leerse con un puerto digital.
- Los otros, conmutan resistencias a masa, tienen un pin común de salida, podrían leerse con un ADC.
- Ningún protocolo con que liarse.
Nótese que hay resistencias pull-down en las salidas de la botonera (más adelante las denominaré "Rf").
Luego vino encontrar información sobre el funcionamiento del control remoto de Pioneer con similares interrogantes.
Dí con algunos links interesantes como este en donde encontre la información necesaria.
Esto me permitió ir evaluando cual PIC podría necesitar.
El 16F84A que tengo en una placa de un viejo proyecto no me iba a servir porque no tiene ADC, tendría que ir por un 16F628 o algo parecido (tampoco quería un PIC monstruoso para usar unas pocas entradas y salidas)
Hasta que la búsqueda me llevó a este link y me abrió la cabeza ya que Arduino ni se había cruzado por la mente porque nunca habia tocado uno.
Viendo las opciones, en principio, pensé usar directamente un ATtiny85, que alcanzaría justo, pero leyendo un poco más se me ocurrieron algunas cosas que podría agregar a futuro, así que en tren de experimentar y aprender me decidí por el Nano, y me hice de un par (uno para este proyecto y el otro para seguir "jugando").
Luego de hacer las correspondientes mediciones en el auto, así quedo la información unificada.
Después de realizar algunos cálculos, me pareció apropiado, además de la resistencia de referencia para el ADC que generará un divisor de tensión, poner otra en serie con la botonera "analógica" para separar un poco los niveles que tenía que medir.
Aquí los valores que esperaba medir luego del agregado.
Y éste es el primer esquema a mano alzada.
Este esquema tenía todavía un gran interrogante: ¿Cómo conmutar las resistencias?
Primero pensé en usar reed relés, pero se encarecería bastante el proyecto. ¿Podría hacerlo solo con transistores?.
En resumen, todavía tenía que instruirme un poco más, pero el esquema brinda una idea general de lo que pensaba hacer.
Ahora tocaba el turno del soft...
Lo que me resultaría más práctico sería poder trabajar con el celular (el mío tiene función OTG) ya que me evitaría tener que llevar la notebook al garage donde guardo el auto, sobre todo teniendo en cuenta que mi notebook HP530 es vieja, tiene la batería muerta, y en el garage no tengo ningún toma cercano.
Rápidamente di con ArduinoDroid para programar y con Sofia, que a pesar de sus limitaciones, me serviría perfectamente para emular y probar el soft sin siquiera usar el protoboard.
Y en la notebook instalé la IDE para Ubuntu y UnoArduSim que corre perfectamente con Wine.
Ya teniendo el soft, lo primero fue generar el sketch que me permitiera verificar la lectura de los botones (principalmente los "analógicos").
// CorollaSWButtonsReader.ino
// Lee los controles del volante de Toyota Corolla
const unsigned long DEBOUNCE_TIME = 20;
const int NO_BTN = 3000;
const int MODE_BTN = 2000;
const int ADC_TOP = 950;
const int PIN_MODEBTN = 2;
const int PIN_SWCTRL = A0;
const int PIN_LED = LED_BUILTIN;
int oldValue = NO_BTN;
int newValue = NO_BTN;
int ledState = LOW;
// funcion para chequear si hay algun boton pulsado
// devuelve el valor de ADC correspondiente al boton
// si no hay ninguno pulsado devuelve NO_BTN
// ** Corolla:
// cable 6= GND
// cable 8= [MODE] cierra a masa
// cable 7= [+][-][^][v] con resistencias
int get_btn_value() {
if (digitalRead(PIN_MODEBTN) == LOW) return MODE_BTN;
int r = analogRead(PIN_SWCTRL);
if (r <= ADC_TOP) return r;
return NO_BTN; // ninguno pulsado
}
void setup() {
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_MODEBTN, INPUT_PULLUP);
digitalWrite(PIN_LED, LOW);
Serial.begin(9600);
delay(3000); // para darme tiempo a abrir la terminal ;)
Serial.println(F("Listo para leer botones"));
Serial.println(F("-----------------------"));
Serial.println("");
delay(1000);
}
void loop() {
newValue = get_btn_value();
if (newValue != oldValue) {
delay(DEBOUNCE_TIME);
newValue = get_btn_value(); // confirma el boton pulsado
if (newValue != oldValue) {
oldValue = newValue;
ledState = LOW;
if (newValue != NO_BTN) {
ledState = HIGH;
if (newValue == MODE_BTN){
Serial.println(F("Boton MODE"));
}
else {
Serial.print(F("Valor ADC = "));
Serial.println(newValue);
}
}
}
digitalWrite(PIN_LED, ledState);
}
}
Los valores leídos fueron igual a los calculados +/- 1 en sucesivas lecturas, nada mal.
Finalmente quedaba el tema de la conmutación de resistencias que lo resolví mucho más rápido de lo suponía y con cero costo.
Me hice el siguiente planteo: Un botón no pulsado está dejando la resistencia "en el aire", lo que sería lo mismo que decir que está conectada a alta impedancia (en este caso infinita). La gran pregunta era si podía poner un pin de Arduino en alta impedancia, y sí, poniendo el pin como entrada y sin habilitar la resistencia pull-up queda en alta impedancia. De todos modos el pin respectivo nunca quedaría "en el aire" porque del estéreo sale una tensión de 3.3V con una resistencia interna de 10k.
Fin del asunto, manos a la obra.
El esquema en Eagle
El layout en Fritzing