[Aporte] Panel de instrumentos para automóviles (En fase de desarrollo)

puede que tambien tengan termostato (si no lo canibalizaron), que debe trabajar a un cierto rango de temperatura, proba a cuantos grados abre y cierra calentandolo en un recipiente con agua
Consulté con el mecánico de cabera de la ratanave el porque no tenía el condenado termostato y me explicó que debido a la salinidad y la temperatura de esta zona, lo que hace es traer problemas como quedarse pegado y sobre calentar innecesariamente el motor, además con la temperatura promedio de acá que no baja de 30°C es medio absurdo tener algún dispositivo que ayude al motor a calentar :LOL:
 
hola amigasos mios
ahi debe ir, fijate que debe ser la entrada de agua fria(desde el radiador), la temperatura del motos es casi diria constante, la del agua debe estar fria para refrigerar el motor, si la del radiador se calienta, ahi esta el problema....
cuando el agua llega a 100 C° en el radiador genera vapor, hierve y pummm explotan mangueras y "demases" perifericos

puede que tambien tengan termostato (si no lo canibalizaron), que debe trabajar a un cierto rango de temperatura, proba a cuantos grados abre y cierra calentandolo en un recipiente con agua

http://www.mitaller.com/sites/default/files/images/ventilador1.jpg

http://1.bp.blogspot.com/-LyKBsMqYB-U/TsJUfwBiT2I/AAAAAAAAADU/zl_PIDPXXIA/s1600/Imagen14.png
bueno vamos por partes dijo yack el destripador (don rat vercion mecanica )​
yo tengo bastante experiencia con el ford ( lo odio ., mi amor es el chevrolet)​
bien ahora lo importante dicen que si tiene 100° es malo ...... mmmmmmmmm​
¿¿¿¿¿ alguien leyo el manual del mecanico del ford ?????​
por lo visto nop ., chicos el termostato empieza a abrir a los 82° y su plena apertura es a los 89°​
el agua empieza a hervir a los 90°​
un grado de diferencia no es nada ., si tomamos en cuenta que los equipos de mediccion tiene un margen de error de 5%​
entonces es comun que trabaje cerca de los 100°
ahora esto nos dice que el mejor trabajo es en esa temperatura .,y todo es por la tapa de cilindro​
y entonces el mejor rendimiento es en ese rango de temperatura​
¿¿¿¿ quien dijo que es bueno sacar el termostato ?????​
porfi lean en manual hay partes de motor que por lo general tiene mas de 100° el agua​
es facil comprobarlo en los famosos " FUSIBLES DE BLOCK "​
Consulté con el mecánico de cabera de la ratanave el porque no tenía el condenado termostato y me explicó que debido a la salinidad y la temperatura de esta zona, lo que hace es traer problemas como quedarse pegado y sobre calentar innecesariamente el motor, además con la temperatura promedio de acá que no baja de 30°C es medio absurdo tener algún dispositivo que ayude al motor a calentar :LOL:
bueno don rat busque uno nuevo y de buena calidad ., eso por un lado por el otro​
hay una adptacion el el codo que va al radiador., donde seria lo ideal medir la tenparatura ., porque alli es donde abre y cierra​
lo otro ., que seria exelente es que si cambia el clima donde trabaja el vehiculo(caluroso)., es usar refrigerante., no agua ., el refrigerante empieza a hervir a grados mas altos que el agua​
es tonto .,por no decir inutil que use agua y mas si es salada .,​
tambien seria bueno "desincrustar" de oxido la tapa y el block (si el motor esta desarmado ) por horno ., los medios quimicos .,con el motor armado es muy malo y no se logra nada​
si consigue un manual del mecanico del vehiculo seria buenisimo asi sabe en que rango trabaja​
tambien seria bueno si hace calor., conseguir un radiador de aceite eso estabiliza la temperatura del motor( aunque no lo crean)​
 
entonces es comun que trabaje cerca de los 100°

si!!, lo que quise decir es que esa temperatura es la de trabajo, pero hay que refrigerarla en el radiador, sino si pum, porque don rat esta midiendo en la bomba de agua la temperarura....

hay una adptacion el el codo que va al radiador., donde seria lo ideal medir la tenparatura ., porque alli es donde abre y cierra

ahi debe estar el sensor....entoses motor a 100° aprox, radiador unos 80....y todo bien
(no entremos en detalles de presion,tapon y otros menesteres)

de acuerdo con el termostato, un motor que trabaje a 100°, es independiente si afuera hace 20 0 40° para eso esta el susodicho....ahhh y si refrigerante si es clima calido
 
Última edición:
hola amigo
si!!, lo que quise decir es que esa temperatura es la de trabajo, pero hay que refrigerarla en el radiador, sino si pum, porque don rat esta midiendo en la bomba de agua la temperarura....
ahi debe estar el sensor....entoses motor a 100° aprox, radiador unos 80....y todo bien
(no entremos en detalles de presion,tapon y otros menesteres)
de acuerdo con el termostato, un motor que trabaje a 100°, es independiente si afuera hace 20 0 40° para eso esta el susodicho....ahhh y si refrigerante si es clima calido
!!!!!!!! exacto don solaris ¡¡¡¡ a eso hiba​
no va en en la economia .,ni nada de eso (a don rat en su pais no le importa lo que gaste jajajajajajajajaja)​
sino en la famosa estabilidad termica., importanticima en el funcionamiento lubricacion ., detonacion y demaces cosas​
evita el famoso pistoneo ., o fallas en la aceleracion ( ademas de afectar el rendimiento y demas cosas​
en nuestro famoso falcon la peleamos duro con mi viejo., se paso a GNC ( gas) pero viviamos con problemas​
hasta que el viejo mecanico dela familia lo hagarro ( talleres oficiales de la chevrolet)​
bueno alli nos explico eso de la temperatura.y la importancia de la estabilidad termica y mas si es a GNC​
se colocaron dos relojes .,uno el original reformado en el tablero de fabrica​
ese se cambio de la la bonba de agua ., a la brida del codo que va al radiador., (lo unico que se hizo fue cambiar el tapon de lugar ) ., en los dos era la misma rosca​
el otro era con aguja pero con sensor por gas (cañito de cobre y bulbo) y se coloco en la tapa de cilindo en la parte tracera y contra lo que seria el torpedo​
tambien por la convercion a GNC ., se cambio el termostato ., (un injerto., en el cuerpo original se cambio el bi-metalico., por uno de R19 a 100°)​
y obiamente dejo de llevar agua., le poniamos refrigerante puro.,​
en resumida cuenta el sensor del termostato marcaba la temperatura ideal y si subia mucho., ya sabiamos habia problemas ., correa floja o bomba​
y el otro nos servia de guia para le temperatura de trabajo optima ., asi sabiamos si teniamos que tapar el radiador ., o levantar un poco el capot para que entrara aire​
en resumen don rat el lugar corecto y ulil e importanticimo​
es en el lugar que marque con la flecha verde es antes del termostato., si la temperatura sube demaciado alli esta el problema detectado​
que es la parte que nos interesa asique ya sabe donde es lo correcto y el termostato original de 221 es 82°/89°​
(y)aaaaaaaaaa ventilador1.jpg
 
Última edición:
Bueno... Don Rat

Con los aportes de Fogo, Solaris y Phonola, uno más sobra, en especial porqué están bien claros en sus aportes y experiencias, y las mías no son mejores ni peores.

Solo les indico que, a parte de la experiencia de unos 30 años con este carro y también una PickUp F100 durante 9 años, compré un manual de mantenimiento que cubre los modelos Fairmont, Zephir y motores 2,3 l (4 Cyl), 3,3 y 4,2 l (6 cyl) y 5,0 l (V8).
Todos vienen preparados para trabajar en climas septentrionales. Cuando trabajan en entornos tropicales, con climas que promedian los 30º sostenidos, todos esos aditamentos son prácticamente inútiles. En estos climas, más bien se debe prevenir el exceso de temperatura, tal como te indican los demás.
Lo indicado por Phonola, de tratar de nivelar la temperatura del aceite de motor, es buena pero de ejecución muy complicada. Pero ciertamente sería de mucha ayuda.

El los modelos similares al mío, el aceite de la caja circula a través de un serpentín inserto en el propio radiador del agua. El pequeño radiador localizado debajo del radiador de agua, delante del puente, es para refrigerar el aceite de la dirección hidráulica. Claro está que también refrigeraría el aceite de la caja, si lo hacen pasar por él pero, aparentemente, ese aceite, tampoco debe trabajar completamente frío.

En fin, con los saludos a todos... aquí les dejo eso.
 
Última edición:
Recabada toda la información, cambiaré el sensor de temperatura de lugar.

Ahora bien, actualicé el software para mejorar la multiplexión del display del velocímetro, pero pasa algo curioso, cuando ocurre algún error, y el display muestra más de 2 dígitos, baja la velocidad de multiplexión sin razón aparente :confused:
 
En estos días estuve trabajando arduamente y avancé bastante con el proyecto y al fin lo pude poner a andar como se debe, sin errores ni cosas raras...

En primer lugar hice modificaciones importantes en el código de manera que quedara lo más optimizado posible, y este fue el resultado.

PHP:
//***************************************************//
//   Panel de instrumentos digital para vehículos    //
//                   Versión 5.2                     //
// Este sistema consta de:                           //
// *Velocímetro                                      //
// *Medidor de presión de aceite                     //
// *Medidor de temperatura                           //
// *Medidor de tensión                               //
// *Detección de palanca de cambios (T. Automática)  //
//***************************************************//
// Este programa ha sido creado por: Carlos Alvarez  //
// (Ratmayor)                                        //
//***************************************************//
#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=8000000)

#include <LCD420.C>
#ZERO_RAM

//Inicio de variables
int a, b, sensor, temper, oil, psi, fuel, dis, shift, alt, fail[6], unit, decs, cent, od;
int16 adc=0, speed, volt;
unsigned char segunit[10] = {0b00000100,0b00001100,0b01000100,0b01001100,0b00100100,0b00101100,0b01100100,0b01101100,0b00010100,0b00011100};
unsigned char segdecs[10] = {0b00000010,0b00001010,0b01000010,0b01001010,0b00100010,0b00101010,0b01100010,0b01101010,0b00010010,0b00011010};
unsigned char segcent[10] = {0b00000001,0b00001001,0b01000001,0b01001001,0b00100001,0b00101001,0b01100001,0b01101001,0b00010001,0b00011001};

void main(){
   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   //Inicio de display
   lcd_init();
   output_c(0x00);
   //Iniciamos el sistema
   output_high(PIN_B3); //LCD Backlight.
   output_high(PIN_D5); //Cinturones de seguridad.
   //Presentación
   lcd_gotoxy(1,1);
   printf(lcd_putc "     RatNET     ");
   lcd_gotoxy(1,2);
   printf(lcd_putc "  ElectroGears  ");
   delay_ms(3000);
   lcd_putc("\f");
   output_low(PIN_D5);
   
   for(;;){
      //Los valores se actualizan cada 100mS
      if(adc == 0){
         //Lectura de ADCs
         set_adc_channel(0);
         delay_us(2);
            sensor = read_adc();
            temper = (1.97 * sensor);
         set_adc_channel(1);
         delay_us(2);
            volt = read_adc();
         set_adc_channel(2);
         delay_us(2);
            psi = read_adc();
            oil = (1.76 * psi);
         set_adc_channel(3);
         delay_us(2);
            shift = read_adc();
         set_adc_channel(4);
         delay_us(2);
            speed = read_adc();
         set_adc_channel(5);
         delay_us(2);
            fuel = read_adc();
         set_adc_channel(6);
         delay_us(2);
            alt = read_adc();
      }
      //Detección de fallas, si se detecta algún problema, se guarda en una posición del Array.
      if(temper > 100){fail[0]=1;}else{fail[0]=0;}
      if(oil < 8){fail[1]=1;}else{fail[1]=0;}
      if(fuel < 16){fail[2]=1;}else{fail[2]=0;}
      if(volt > 200){fail[3]=1;}else{fail[3]=0;}
      if(volt < 100){fail[4]=1;}else{fail[4]=0;}
      if(alt > 60){fail[5]=1;}else{fail[5]=0;}
      
      //Actualiza los valores de los ADC
      if(adc>30){adc=0;}else{adc=adc+1;}
      
      //Detecta si el motor está encendido
      if(!input(PIN_D3)){
         lcd_gotoxy(1,1);
         printf(lcd_putc "                ");
         lcd_gotoxy(1,2);
         printf(lcd_putc "  Stop  Engine  ");
      }
      //Activa el directorio de fallas en caso de haber alguna
      else if((fail[0] == 1 || fail[1] == 1 || fail[2] == 1 || fail[3] == 1 || fail[4] == 1 || fail[5] == 1)){
         switch(b){
            case 0:
            if(fail[0]==1){
            lcd_gotoxy(1,1);
            printf(lcd_putc "     %d%CC      ",temper,0xDF);
            lcd_gotoxy(1,2);
            printf(lcd_putc "HIGH TEMPERATURE");
            }
            break;
            case 1:
            if(fail[1]==1){
               lcd_gotoxy(1,1);
               printf(lcd_putc "    %d PSI    ",oil);
               lcd_gotoxy(1,2);
               printf(lcd_putc "LOW OIL PRESSURE");
               output_high(PIN_D7);
            }
            else{
               output_low(PIN_D7);
            }
            break;
            case 2:
            if(fail[2]==1){
               lcd_gotoxy(1,1);
               printf(lcd_putc "       %d%C       ",fuel,0x25);
               lcd_gotoxy(1,2);
               printf(lcd_putc " LOW LEVEL FUEL ");
               output_high(PIN_D4);
            }
            else{
               output_low(PIN_D4);
            }
            break;
            case 3:
            if(fail[3]==1){
               lcd_gotoxy(1,1);
               printf(lcd_putc "      %lu%lu.%luV     ",(volt/100),((volt % 100) / 10),(volt % 10));
               lcd_gotoxy(1,2);
               printf(lcd_putc "  OVER TENSION  ");
            }
            break;
            case 4:
            if(fail[4]==1){
               lcd_gotoxy(1,1);
               printf(lcd_putc "      %lu%lu.%luV     ",(volt/100),((volt % 100) / 10),(volt % 10));
               lcd_gotoxy(1,2);
               printf(lcd_putc "   OVER  LOAD   ");
            }
            break;
            case 5:
            if(fail[5]==1){
               lcd_gotoxy(1,1);
               printf(lcd_putc "      %lu%lu.%luV     ",(volt/100),((volt % 100) / 10),(volt % 10));
               lcd_gotoxy(1,2);
               printf(lcd_putc "  Alt  Failure  ");
               output_high(PIN_D6);
            }
            else{
               output_low(PIN_D6);
            }
            break;
         }
         //Recorre el directorio de fallas
         if(a>100){a=0; if(b>6){b=0;}else{b=b+1;}}else{a=a+1;}
         //Hace parpadear el backlight de la LCD para captar la atención del conductor
         if((a%50)==0){output_toggle(PIN_B3);}
      }
      //Activa el modo de indicador de posición de la palanca de cambios
      else if(input(PIN_A4)){
         lcd_gotoxy(1,1);
         if(shift >= 10 && shift <= 25){
            printf(lcd_putc "     Reverse    ");
            output_high(PIN_D0);
         }
         else if(shift >= 26 && shift <= 36){
            printf(lcd_putc "     Neutral    ");
            output_low(PIN_D0);
         }
         else if(shift >= 37 && shift <= 47){
            printf(lcd_putc "      Drive     ");
            output_high(PIN_D0);
         }
         else if(shift >= 48 && shift <= 58){
            printf(lcd_putc "     Lower 2    ");
            output_high(PIN_D0);
         }
         else if(shift > 60){
            printf(lcd_putc "     Lower 1    ");
            output_high(PIN_D0);
         }
         else{
            printf(lcd_putc "     Parking    ");
            output_low(PIN_D0);
         }
         lcd_gotoxy(1,2);
         printf(lcd_putc "                ");
      }
      //Modo de descanso
      else{
         lcd_gotoxy(1,1);
         printf(lcd_putc "%d%CC  %lu%lu.%luV  %d ",temper,0xDF,(volt/100),((volt % 100) / 10),(volt % 10),oil);
         lcd_gotoxy(1,2);
         printf(lcd_putc "Temp  Volts  Oil");
         output_high(PIN_B3);
         output_low(PIN_D4);
         output_low(PIN_D6);
         output_low(PIN_D7);
      }
      
      //Velocímetro / Multiplexación de displays
      dis = dis+1;
      delay_ms(2);
      //Usando un switch para asignar cada display, controlamos mejor la multiplexación y evitamos sobre cargar el micro
      switch(dis){
         case 1:
         if(speed > 99){
            cent = speed / 100;
            output_c(segcent[cent]);
         }
         break;
         case 2:
         if(speed > 9){
            decs = (speed % 100) / 10;
            output_c(segdecs[decs]);
         }
         break;
         case 3:
         unit = speed % 10;
         output_c(segunit[unit]);
         break;
      }
      if(dis>2){dis=0;}
      
      //Divisor de pulsos para el odómetro
      if(input(PIN_D2)){od=od+1;}
      if(od>150){output_high(PIN_D1); od=0;}
      else{output_low(PIN_D1);}
   }
}

Y este es el del odómetro:

PHP:
//***************************************************//
//   Panel de instrumentos digital para vehículos    //
//                   Versión 4.0                     //
// Este sistema consta de:                           //
// *Odómetro, contador de recorrido.                 //
//***************************************************//
// Este programa ha sido creado por: Carlos Alvarez  //
// (Ratmayor) Bajo la licencia GNU GPL.              //
//***************************************************//
#include <16F628A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection

#use delay(clock=4000000)

#zero_ram
#include <LCD420.C>

int km0, km1, km2, km3, km4, km5, od0, od1, od2, od3, a=0, b=0;

void main(){
   lcd_init();
   //Leemos los datos guardados en memoria para comenzar.
   km0 = read_eeprom (0x01);
   km1 = read_eeprom (0x02);
   km2 = read_eeprom (0x03);
   km3 = read_eeprom (0x04);
   km4 = read_eeprom (0x05);
   km5 = read_eeprom (0x06);
   od0 = read_eeprom (0x07);
   od1 = read_eeprom (0x08);
   od2 = read_eeprom (0x09);
   od3 = read_eeprom (0x10);
   
   for(;;){
      //Mostramos los datos cargados.
      lcd_gotoxy(1,1);
      printf(lcd_putc "%d%d%d%d%d%dKm",km5,km4,km3,km2,km1,km0);
      lcd_gotoxy(1,2);
      printf(lcd_putc "Tp %d%d%d.%d",od3,od2,od1,od0);
      
      //Reinicia contador (Reset).
      if(input(PIN_A2)){
         od0 = 0; od1 = 0; od2 = 0; od3 = 0;
      }
      //Reinicio general de los contadores (Hard reset).
      if(input(PIN_A2) && input(PIN_A4)){
         delay_ms(100);
         if(b==5){
            km0 = 0; km1 = 0; km2 = 0; km3 = 0; km4 = 0; km5 = 0; od0 = 0; od1 = 0; od2 = 0; od3 = 0;
         }
         b=b+1;
      }
      //Contador, requiere de la habilitación del micro principal para evitar conteos erróneos.
      if(input(PIN_A3)){
         //La variable a funciona como anti-rebotes.
         if(input(PIN_A1) && a==0){
            od0=od0+1;
            a=1;
         }
         else{
            a=0;
            //Terminado el conteo, se guardan los datos en la memoria interna del micro.
            write_eeprom (0x01, km0);
            write_eeprom (0x02, km1);
            write_eeprom (0x03, km2);
            write_eeprom (0x04, km3);
            write_eeprom (0x05, km4);
            write_eeprom (0x06, km5);
            write_eeprom (0x07, od0);
            write_eeprom (0x08, od1);
            write_eeprom (0x09, od2);
            write_eeprom (0x10, od3);
         }      
      }
      
      //Manejamos cada cifra por separado para no sobrecargar el PIC.
      //Además ayuda a la presentación.
      if(od0>9){od0=0; od1=od1+1;}
      if(od1>9){od1=0; od2=od2+1; km0=km0+1;} 
      if(od2>9){od2=0; od3=od3+1;}
      if(od3>9){od3=0;}
      
      if(km0>9){km0=0; km1=km1+1;}
      if(km1>9){km1=0; km2=km2+1;}
      if(km2>9){km2=0; km3=km3+1;}
      if(km3>9){km3=0; km4=km4+1;}
      if(km4>9){km4=0; km5=km5+1;}
      if(km5>9){km5=0;}
   }
}

A este solo se le cambió la forma de guardar los datos en la memoria interna...

Luego de ver como funciona, dije: Valió la pena quedarme programando hasta las 2AM :LOL:


Adjunto dejo los archivos HEX y el PCB nuevo que si algún mod pudiera ponerlos en el post principal, se lo agradecería.

Saludos :D :apreton:
 

Adjuntos

  • Cluster.rar
    457.4 KB · Visitas: 31
Última edición:
Olvidé mencionar algo sobre los sensores de presión de aceite de los que son bien machos, llameseles estos:

100_4695.jpg

La programación del PIC está preparada para trabajar con ellos, sin embargo, el de la izquierda tiene una tensión de salida de 0 ~ 10V y el de la derecha es de 0 ~ 4.5V por tanto si usan el de la derecha, usen el divisor de tensión que está en el PCB, si usan el de la izquierda, reemplacen la R de 51KΩ por un puente, de lo contrario daría valores erroneos :D
 
Última edición por un moderador:
Algunas ideas ;)

stock-vector-skull-and-pistons-68025181.jpg


CALAVERA%20PISTONES.jpeg-228x228.png


dos-pistones-fuertes-18002434.jpg


24231963-piston-humaniforme-aislado-en-un-fondo-blanco.jpg
 
hola
Sip, uno de el del nivel de gasolina y el otro es el nivel de aceite, esos los puse con un par de LM3914...
Podría colocar una lámina oscura sobre esa, así los LEDs no me encandilarían :LOL:
don rat como esta no esta aclarado para que es cada cosa​
podria poner una imagen de fondo ., por ejemplo impresa sobre vinilo ., y sobre algo trasparente .,​
luego la ilumina de fondo .,(led muy tenues para que no morleste) ., de paso le coloca la carteleria a los indicadores .,​
o podria ser impresa con impresora de tinta en una hoja en blanco y luego la plastifica ., he visto en internet unos tableros asi pero no encuentro la imagenes .,​
 
Ante todo disculpas por tener el post algo abandonado, pero el trabajo me quita mucho tiempo para jugar ;)

Pensando un poco, como podría mejorar/abaratar el cluster manteniéndolo cool? :LOL: La solución principal fue pensar en un solo PIC para todo...

Todo muy bien hasta ahí, pero, ¿Como manejar 2 LCDs con un único PIC? La solución vino modificando la librería nativa de CCS "lcd420.c" para que mutiplexara los display :devilish:

PHP:
// As defined in the following structure the pin connection is as follows:
//     B0  rs
//     B1  rw
//     B2  enb1
//     B2  enb2
//     B4  D4
//     B5  D5
//     B6  D6
//     B7  D7
//
//   LCD pins D0-D3 are not used.

struct lcd_pin_map {             // This structure is overlayed
           BOOLEAN rs;           // on to an I/O port to gain
           BOOLEAN rw;           // access to the LCD pins.
           BOOLEAN enb1;         // The bits are allocated from
           BOOLEAN enb2;         // low order up.  ENABLE will
           int     data : 4;     // be pin B1 and B2.
        } lcd;

#locate lcd = getenv("SFR:PORTB") // This puts the entire structure
                                  // on to port B 

#define lcd_type 2               // 0=5x7, 1=5x10, 2=2 lines


BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                             // These bytes need to be sent to the LCD
                             // to start it up.


                             // The following are used for setting
                             // the I/O port direction register.

struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in


BYTE lcdline;

BYTE lcd_read_byte(BYTE m) {
   BYTE low,high;

   set_tris_b(LCD_READ);
   lcd.rw = 1;
   delay_cycles(1);
   if(!m){lcd.enb1 = 1;}else{lcd.enb2 = 1;}
   delay_cycles(1);
   high = lcd.data;
   if(!m){lcd.enb1 = 0;}else{lcd.enb2 = 0;}
   delay_cycles(1);
   if(!m){lcd.enb1 = 1;}else{lcd.enb2 = 1;}
   delay_us(1);
   low = lcd.data;
   if(!m){lcd.enb1 = 0;}else{lcd.enb2 = 0;}
   set_tris_b(LCD_WRITE);
   return( (high<<4) | low);
}


void lcd_send_nibble( BYTE n, BYTE m ) {
   lcd.data = n;
   delay_cycles(1);
   if(!m){lcd.enb1 = 1;}else{lcd.enb2 = 1;}
   delay_us(2);
   if(!m){lcd.enb1 = 0;}else{lcd.enb2 = 0;}
}


void lcd_send_byte( BYTE address, BYTE n, BYTE m ) {
   lcd.rs = 0;
   while ( bit_test(lcd_read_byte(m),7) ) ;
   lcd.rs = address;
   delay_cycles(1);
   lcd.rw = 0;
   delay_cycles(1);
   if(!m){lcd.enb1 = 0;}else{lcd.enb2 = 0;}
   lcd_send_nibble(n >> 4,m);
   lcd_send_nibble(n & 0xf,m);
}


void lcd_init1() {
   BYTE i;
   
   set_tris_b(LCD_WRITE);
   lcd.rs = 0;
   lcd.rw = 0;
   lcd.enb1 = 0;
   delay_ms(15);
   for(i=1;i<=3;++i) {
      lcd_send_nibble(3,0);
      delay_ms(5);
   }
   lcd_send_nibble(2,0);
   for(i=0;i<=3;++i)
      lcd_send_byte(0, LCD_INIT_STRING[i],0);
}

void lcd_init2() {
   BYTE i;
   
   set_tris_b(LCD_WRITE);
   lcd.rs = 0;
   lcd.rw = 0;
   lcd.enb2 = 0;
   delay_ms(15);
   for(i=1;i<=3;++i) {
      lcd_send_nibble(3,1);
      delay_ms(5);
   }
   lcd_send_nibble(2,1);
   for(i=0;i<=3;++i)
      lcd_send_byte(0, LCD_INIT_STRING[i],1);
}


void lcd_gotoxy1( BYTE x, BYTE y) {
   BYTE address;

   switch(y) {
     case 1 : address=0x80;break;
     case 2 : address=0xc0;break;
     case 3 : address=0x94;break;
     case 4 : address=0xd4;break;
   }
   address+=x-1;
   lcd_send_byte(0,address,0);
}

void lcd_gotoxy2( BYTE x, BYTE y) {
   BYTE address;

   switch(y) {
     case 1 : address=0x80;break;
     case 2 : address=0xc0;break;
     case 3 : address=0x94;break;
     case 4 : address=0xd4;break;
   }
   address+=x-1;
   lcd_send_byte(0,address,1);
}

void lcd_putc1( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1,0);
                   lcdline=1;
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy1(1,++lcdline);        break;
     case '\b'   : lcd_send_byte(0,0x10,0);  break;
     default     : lcd_send_byte(1,c,0);     break;
   }
}

void lcd_putc2( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1,1);
                   lcdline=1;
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy2(1,++lcdline);        break;
     case '\b'   : lcd_send_byte(0,0x10,1);  break;
     default     : lcd_send_byte(1,c,1);     break;
   }
}

char lcd_getc1( BYTE x, BYTE y) {
   char value;

    lcd_gotoxy1(x,y);
    lcd.rs=1;
    value = lcd_read_byte(0);
    lcd.rs=0;
    return(value);
}

char lcd_getc2( BYTE x, BYTE y) {
   char value;

    lcd_gotoxy2(x,y);
    lcd.rs=1;
    value = lcd_read_byte(1);
    lcd.rs=0;
    return(value);
}

El funcionamiento se basa en el manejo de las LCDs y aprovecha la memoria interna. Lo que hacemos es jugar con el pin "Enable" de cada LCD.
lcds.png
Nótese que están en parelelo, salvo por ese pin. Si envío datos a una LCD, activo el "Enable" correspondiente, al terminar la "Data", desactivo la comunicación, pero quedarán guardados en la memoria de la LCD, hasta que los mande a cambiar... Cool, no? :cool::LOL:

Ahora tenía otro predicamento: ¿Como colocar los indicadores de fallas sin usar todos los puertos del PIC? La solución fue usar a mis amigo Registros de desplazamiento...
shift.png
Esto me permitió ahorrarme unos cuantos pines del micro y funcionó también, que usé otro para el indicador de posiciones de la palanca de cambios...
shift2.png

También se me ocurrió agregar un tacómetro, pero en la LCD no se vería bien y ya tenía ocupado todo el puerto de los displays ocupado... Así que usé un decodificador binario, solo para recorrer los displays, así podría agregar más sin problemas...
decoder.png
Aunque a nivel de hardware, puedo manejar 6 displays, a nivel de software, solo usé 5...

Solo me faltaba corregir un detalle... Cuando encendía el motor, el ruido del arranque era tan brutal que volvía loco el PIC :facepalm:. La solución fue usar este pequeño circuito que resetea el PIC mientras el motor de arranque está encendido...
start.png

Luego de tantos cambios, atosigué al pobre PIC16F877A y lo tuve que cambiar por el PIC18F4550 con más memoria interna :cool:

Bien, acá es dejo la simulación en proteus con el archivo hex y espero les gusten los cambios... :D
 

Adjuntos

  • Cluster.rar
    35.1 KB · Visitas: 11
Última edición:
Bien, como no tenía mucha batería no pude explicar bien los detalles de las nuevas funciones del cluster :oops: Ahora con energía podré explicar mejor como va la cosa... Pero primero, la nueva PCB de la controladora :cool:

PCBF.png

Entre las nuevas funciones, había comentado un tacómetro, este funciona al igual que el velocímetro, con un LM2917 de por medio como interface, y usamos el PIC como un simple voltímetro, no puse el PIC a hacer directamente la conversión frecuencia / RPM ó Velocidad debido a que requería de muchos delays en el código y eso me hacían funcionar muy mal los displays multiplexados... El circuito básico es el que está en el datasheet del LM2917 para evitar inconvenientes, además de agregarle jumpers a la tarjeta para seleccionar entre motores de 4, 6 ú 8 cilindros :D

La calibración del velocímetro es lo más complicado ya que deben hacerse 2 ajustes, uno digital y el otro analógico :facepalm:

La calibración analógica, debe hacerse con un GPS, el del teléfono sirve, hay muchas aplicaciones que miden la velocidad, no es nada del otro mundo, ir moviendo el multivueltas hasta que los valores del display y los del GPS sean iguales... Ahora lo del odómetro es algo más fastidioso...

caldis.png

Luego de buscar entre tantos sensores, en definitiva, el mejor fue usar un rotary encoder, este lo puse en el piñón donde originalmente va la guaya del velocímetro, así no pierdo la relación de la caja y no me complico la vida buscando donde ponerlo :LOL: Como ven, en el display en el modo de servicio, aparecen 2 valores "DIV" e "IN" donde IN son los pulsos que está enviando el rotary encoder al PIC y DIV son las veces que el micro debe dividir los pulsos para interpretarlo como 100 metros recorridos, para esto debemos saber cuando mide la rueda de transmisión, por ejemplo en mi caso mide 3,25M y en una vuelta da 30 pulsos, eso quiere decir que debo poner el DIV en 923 para que lo interprete como 100M :p. El software permite dividir hasta 1000, ya que dependiendo el tamaño de la rueda y la relación de caja puede variar la división...

Ahora bien, anteriormente había agregado un circuito para detectar el motor encendido, pero era bastante problemático, ya que eso de juntar la ignición con el PIC se veía medio feo :LOL:
alt3.png
Ahora sólo tomo la referencia del tacómetro para detectar si el motor está encendido... :cool:

La otra función que agregué es que el Multi Display ahora alterna la información, cada X segundos, muestra información del motor...:

alt1.png

alt2.png

Cabe destacar que para el amperímetro usé un INA283 y la verdad fue bastante complicado encontrar una R Shunt que se bancara toda la corriente que consume el auto :LOL: pero la verdad quedó muy bien :)

Bien, creo que eso es todo, tuve que parar porque sino no iba a terminar jamás :LOL: Y ahora les presento el código nuevo :D

PHP:
#include <18F4550.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=8000000)

#include <LCD421.C>
#ZERO_RAM

//Inicio de variables
int a, j, k, z, temper, fuel, shift, stick=1, alt, fail[6], vacio=0, dis, unit, decs, cent, mils, degs, km0, km1, km2, km3, km4, km5, od0, od1, od2, od3;
int16 timer=0, speed, rpm, volt, oil, div=0, cal;
byte valor, pos=0b11111111, posb, value[4];
byte const bitMask[8]={1,2,4,8,16,32,64,128};

//Arreglos generan los caracteres de los dígitos de los displays multilplexados
unsigned char segunit[10] = {0b00000001,0b10000001,0b00010001,0b10010001,0b00100001,0b10100001,0b00110001,0b10110001,0b01000001,0b11000001};
unsigned char segdecs[10] = {0b00000010,0b10000010,0b00010010,0b10010010,0b00100010,0b10100010,0b00110010,0b10110010,0b01000010,0b11000010};
unsigned char segcent[10] = {0b00000100,0b10000011,0b00010011,0b10010011,0b00100111,0b10100011,0b00110011,0b10110011,0b01000011,0b11000011};
unsigned char segmils[10] = {0b00000100,0b10000100,0b00010100,0b10011100,0b00100100,0b10100100,0b00110100,0b10110100,0b01000100,0b11000100};
unsigned char degmils[10] = {0b00000101,0b10000101,0b00010101,0b10011101,0b00100101,0b10100101,0b00110101,0b10110101,0b01000101,0b11000101};

void main(){

   //Inhabilitamos funciones del micro que no necesitamos
   setup_spi(SPI_SS_DISABLED);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   //Leemos los datos guardados en memoria para comenzar.
   km0 = read_eeprom (0x01);
   km1 = read_eeprom (0x02);
   km2 = read_eeprom (0x03);
   km3 = read_eeprom (0x04);
   km4 = read_eeprom (0x05);
   km5 = read_eeprom (0x06);
   od0 = read_eeprom (0x07);
   od1 = read_eeprom (0x08);
   od2 = read_eeprom (0x09);
   od3 = read_eeprom (0x10);
   
   //Configuramos los puertos analógicos
   setup_adc_ports(AN0_TO_AN7);
   setup_adc(ADC_CLOCK_DIV_64);
   
   //Inicio de los displays LCD
   lcd_init1();
   lcd_init2();
   
   //Iniciamos los puertos de salida en 0
   output_c(0x00);
   output_d(0x00);
   shift = stick;
   for(k=0;k<8;k++){
      output_low(PIN_C4);
      output_bit(PIN_C5,pos&bitMask[k]);
      output_high(PIN_C4);
   }
   
   //Iniciamos el sistema
   output_high(PIN_C2); //LCD Backlight.
   //Presentación
   lcd_gotoxy1(1,1);
   printf(lcd_putc1 "     RatNET     ");
   lcd_gotoxy1(1,2);
   printf(lcd_putc1 "  ElectroGears  ");
   delay_ms(3000);
   lcd_putc1("\f");

   for(;;){
      //Mostramos los datos cargados del odómetro.
      lcd_gotoxy2(1,1);
      printf(lcd_putc2 "%d%d%d%d%d%dKm",km5,km4,km3,km2,km1,km0);
      lcd_gotoxy2(1,2);
      printf(lcd_putc2 "Tp %d%d%d.%d",od3,od2,od1,od0);
      
      //Reinicia contador (Reset).
      if(input(PIN_C1)){
         od0 = 0; od1 = 0; od2 = 0; od3 = 0;

      }
      //Reinicio general de los contadores (Hard reset).
      else if(input(PIN_C0) && input(PIN_C1)){
         if((timer % 10) == 0){
            km0 = 0; km1 = 0; km2 = 0; km3 = 0; km4 = 0; km5 = 0; od0 = 0; od1 = 0; od2 = 0; od3 = 0;
            lcd_putc2("\f");
         }
      }
      //La variable z funciona como anti-rebotes.
      if(input(PIN_A4) && z==0){
         div=div+1;
         z=1;
      }
      else if(!input(PIN_A4) && z==1){
         z=0;
      }
      //Este condicional, permite calibrar la relación de recorrido enviado por el sensor de la caja
      if(div > read_eeprom (0xA0)){
         //Terminada la división, aumentamos el valor del odómetro
         od0=od0+1;
         //Terminado el conteo, se guardan los datos en la memoria interna del micro.
         write_eeprom (0x01, km0);
         write_eeprom (0x02, km1);
         write_eeprom (0x03, km2);
         write_eeprom (0x04, km3);
         write_eeprom (0x05, km4);
         write_eeprom (0x06, km5);
         write_eeprom (0x07, od0);
         write_eeprom (0x08, od1);
         write_eeprom (0x09, od2);
         write_eeprom (0x10, od3);
         div=0;
      }
      //Manejamos cada cifra por separado para no sobrecargar el PIC, además mejora la presentación.
      if(od0>9){od0=0; od1=od1+1;}
      if(od1>9){od1=0; od2=od2+1;} 
      if(od2>9){od2=0; od3=od3+1;}
      if(od3>9){od3=0; km0=km0+1;}
      
      if(km0>9){km0=0; km1=km1+1;}
      if(km1>9){km1=0; km2=km2+1;}
      if(km2>9){km2=0; km3=km3+1;}
      if(km3>9){km3=0; km4=km4+1;}
      if(km4>9){km4=0; km5=km5+1;}
      if(km5>9){km5=0;}
      
      //Los valores de los timer se actualizan cada 100mS
      if((timer % 100) == 0){
         //Lectura de ADCs
         set_adc_channel(0);
            delay_ms(1);
            temper = (1.97 * read_adc());
         set_adc_channel(1);
            delay_ms(1);
            volt = read_adc();
         set_adc_channel(2);
            delay_ms(1);
            oil = (1.76 * read_adc());
         set_adc_channel(3);
            delay_ms(1);
            shift = read_adc();
         set_adc_channel(4);
            delay_ms(1);
            speed = read_adc();
         set_adc_channel(5);
            delay_ms(1);
            rpm = (3.1416 * read_adc());
         set_adc_channel(6);
            delay_ms(1);
            fuel = (1.67 * read_adc());
         set_adc_channel(7); 
            delay_ms(1);
            alt = read_adc();
      }
      
      //Detección de fallas, si se detecta algún problema, se guarda en una posición del Array.
      if(temper > 100){fail[0]=1;}else{fail[0]=0;}
      if(oil < 11){fail[1]=1;}else{fail[1]=0;}
      if(fuel < 16){fail[2]=1;}else{fail[2]=0;}
      if(volt > 200){fail[3]=1;}else{fail[3]=0;}
      if(volt < 100){fail[4]=1;}else{fail[4]=0;}
      if(alt > 100 || alt < 10){fail[5]=1;}else{fail[5]=0;}
      
      //Menú interno de calibración del odómetro
      if(input(PIN_D3)){
         /*El pin D3 dehabilita la lectura de los ADC según el timer
         por eso llamamos al ADC 3 sólo para esta función */
         set_adc_channel(3);
            delay_ms(1);
            shift = read_adc();
         //Cargamos último valor guardado en memoria
         cal = read_eeprom (0xA0);
         //Aumenta el número divisor y guarda en memoria
         if(shift > 86){
            if(cal < 1000){
               cal = cal + 1;
               delay_ms(500);
               write_eeprom (0xA0, cal);
            }
         }
         //Disminuye el número divisor y guarda en memoria
         else if(shift > 29 && shift < 32){
            if(cal > 1){
               cal = cal - 1;
               delay_ms(500);
               write_eeprom (0xA0, cal);
            }
         }
         //Muestra la división en pantalla
         lcd_gotoxy1(1,1);
         printf(lcd_putc1 "  Calibration   ");
         lcd_gotoxy1(1,2);
         printf(lcd_putc1 "Div: %lu In: %lu   ",cal,div);
      }
      //Detecta si el motor está encendido
      else if(rpm < 50){
         lcd_gotoxy1(1,1);
         printf(lcd_putc1 "                ");
         lcd_gotoxy1(1,2);
         printf(lcd_putc1 "  Stop  Engine  ");
         valor = 64; //Cinturones de seguridad.
         for(j=0;j<8;j++){
            output_low(PIN_C7);
            output_bit(PIN_C6,valor&bitMask[j]);
            output_high(PIN_C7);
         }
         vacio=0;
      }
      //Activa el directorio de fallas en caso de haber alguna
      else if((fail[0] == 1 || fail[1] == 1 || fail[2] == 1 || fail[3] == 1 || fail[4] == 1 || fail[5] == 1)){
         switch(a){
            case 0:
            if(fail[0]==1){
               lcd_gotoxy1(1,1);
               printf(lcd_putc1 "     %d%CC      ",temper,0xDF);
               lcd_gotoxy1(1,2);
               printf(lcd_putc1 "HIGH TEMPERATURE");
               value[3] = 8;
            }
            break;
            case 1:
            if(fail[1]==1){
               lcd_gotoxy1(1,1);
               printf(lcd_putc1 "     %lu PSI      ",oil);
               lcd_gotoxy1(1,2);
               printf(lcd_putc1 "LOW OIL PRESSURE");
               value[0] = 1;
               value[3] = 8;
            }
            else{value[0] = 0;}
            break;
            case 2:
            if(fail[2]==1){
               lcd_gotoxy1(1,1);
               printf(lcd_putc1 "       %d%C       ",fuel,0x25);
               lcd_gotoxy1(1,2);
               printf(lcd_putc1 " LOW LEVEL FUEL ");
                 value[1] = 2;
            }
            else{value[1] = 0;}
            break;
            case 3:
            if(fail[3]==1){
               lcd_gotoxy1(1,1);
               printf(lcd_putc1 "      %lu%lu.%luV     ",(volt/100),((volt % 100) / 10),(volt % 10));
               lcd_gotoxy1(1,2);
               printf(lcd_putc1 "  OVER TENSION  ");
            }
            break;
            case 4:
            if(fail[4]==1){
               lcd_gotoxy1(1,1);
               printf(lcd_putc1 "      %lu%lu.%luV     ",(volt/100),((volt % 100) / 10),(volt % 10));
               lcd_gotoxy1(1,2);
               printf(lcd_putc1 "   OVER  LOAD   ");
            }
            break;
            case 5:
            if(fail[5]==1){
               lcd_gotoxy1(1,1);
               printf(lcd_putc1 "      %d%d.%dA     ",(alt/100),((alt % 100) / 10),(alt % 10));
               lcd_gotoxy1(1,2);
               printf(lcd_putc1 "  Alt  Failure  ");
               value[2] = 4;
               value[3] = 8;
            }
            else{value[2] = 0;}
            break;
         }
         //Envía información al registro de desplazamiento para los indicadores externos
         valor = value[0]+value[1]+value[2]+value[3];
         //El condicional evita el sobre envío de datos al registro de desplazamiento
         if(valor != vacio){
            for(j=0;j<8;j++){
               output_low(PIN_C7);
               output_bit(PIN_C6,valor&bitMask[j]);
               output_high(PIN_C7);
            }
         }
         //Recorre el directorio de fallas
         if((timer % 200)==0){if(a>6){a=0;}else{a=a+1;}}
         //Hace parpadear el backlight de la LCD para captar la atención del conductor
         if((timer % 100)==0){output_toggle(PIN_C2);}
         //Se igualan las variables para que el registro deje de actualizarce innecesariamente
         vacio = valor;
      }
      //Activa el modo de indicador de posición de la palanca de cambios
      else if(shift != stick){
         lcd_gotoxy1(1,1);
         if(shift >= 10 && shift <= 35){
            printf(lcd_putc1 "     Reverse    ");
            pos = 0b00110010;
         }
         else if(shift >= 36 && shift <= 61){
            printf(lcd_putc1 "     Neutral    ");
            pos = 0b00100010;
         }
         else if(shift >= 62 && shift <= 87){
            printf(lcd_putc1 "      Drive     ");
            pos = 0b00000101;
         }
         else if(shift >= 88 && shift <= 113){
            printf(lcd_putc1 "     Lower 2    ");
            pos = 0b00010001;
         }
         else if(shift > 114 && shift <= 139){
            printf(lcd_putc1 "     Lower 1    ");
            pos = 0b01100111;
         }
         else{
            printf(lcd_putc1 "     Parking    ");
            pos = 0b00110000;
         }
         lcd_gotoxy1(1,2);
         printf(lcd_putc1 "                ");
         //Envía información al registro de desplazamiento para el display de posición de la palanca de cambios
         if(pos != posb){
            for(k=0;k<8;k++){
               output_low(PIN_C4);
               output_bit(PIN_C5,pos&bitMask[k]);
               output_high(PIN_C4);
            }
         }
         //Compara las variables de cambio de velocidad hasta igualarlas, solo para que aparezcan unos segundos en el display
         posb = pos;
         if((timer % 256) == 0){stick = shift;}
      }
      //Modo de descanso (Funcionamiento normal del automovil)
      else{
         if(timer < 1024){
            lcd_gotoxy1(1,1);
            printf(lcd_putc1 "%d%CC  %lu%lu.%luV  %lu ",temper,0xDF,(volt/100),((volt % 100) / 10),(volt % 10),oil);
            lcd_gotoxy1(1,2);
            printf(lcd_putc1 "Temp  Volts  Oil");
         }
         else{
            lcd_gotoxy1(1,1);
            printf(lcd_putc1 "%lu0  %d%d.%d  %d%C  ",rpm,(alt/100),((alt % 100) / 10),(alt % 10),fuel,0x25);
            lcd_gotoxy1(1,2);
            printf(lcd_putc1 "RPM   Amps  Fuel");
         }
         output_high(PIN_C7);
         //Vacía la variable de errores.
         value[0] = 0;
         value[1] = 0;
         value[2] = 0;
         value[3] = 0;
         valor = 0;
         for(j=0;j<8;j++){
            output_low(PIN_C7);
            output_bit(PIN_C6,valor&bitMask[j]);
            output_high(PIN_C7);
         }
      }
      
      if(!input(PIN_D3)){
         //Velocímetro-Tacómetro / Multiplexación de displays LED
         dis = dis+1;
         //Usando un switch para asignar cada display, controlamos mejor la multiplexación y evitamos sobre cargar el micro
         switch(dis){
            case 1:
            if(speed > 99){
               cent = speed / 100;
               output_d(segcent[cent]);
            }
            break;
            case 2:
            if(speed > 9){
               decs = (speed % 100) / 10;
               output_d(segdecs[decs]);
            }
            break;
            case 3:
            unit = speed % 10;
            output_d(segunit[unit]);
            break;
            case 4:
            mils = rpm / 100;
            output_d(segmils[mils]);
            break;
            case 5:
            degs = (rpm % 100) / 10;
            output_d(degmils[degs]);
            break;
         }
         if(dis>4){dis=0;}
         
         /* Contador interno para sincronizar el código, así evitamos el uso de delays
         que alteren el correcto funcionamiento de los displays multiplexados */
         if(timer>2048){timer=0;}else{timer=timer+1;}
      }
      else{
         //Mientras esté activo el menú de calibración, bloqueamos los puertos de salida
         timer = 0;
         output_d(0x00);
      }
   }
}

Adjunto le dejo el PCB listo para planchar y si se portan bien, subiré un par de modelos para los medidores...

Seguiremos informando :LOL:
 

Adjuntos

  • PCB.pdf
    371.4 KB · Visitas: 4
Última edición:
Una posible idea, ya no tan electronica sino mas bien software:

- Pantalla LCD 7" estan baratas ahora. Esta a modo de panel reemplazando todos los indicadores de aguja normales del auto (frente al volante)
- Raspberry PI

La raspberry te levanta un linux con entorno grafico en aprox 10 segundos y funciona con 5 volts.

Tenes 40 pines de IO para todo los sensores y etc varios.

Se diseña un soft que ejecute al inicio y simule graficamente todos los indicadores + algunos extras como ser:

- Stereo MP3 integrado (salida de audio del raspi a un ampli, supongamos un class D para tener potencia y que sea chico)
- Modulo GPS comprado en china conectado a la raspi. Habria que ver que soft hay disponible para eso.

Solo imaginen las posibilidades de "tuneo" que daria esta bestia. Y hoy por hoy no es demasiaaaaado caro. Incluso esta la raspi Zero que es mucho mas barata. El LCD + controladora de video (basicamente un monitor) anda por los 27 obamas.

Y por ultimo, para aportar una idea al proyecto este en si: No te olvides de agregar un detector de luces quemadas y/o no encendidas!! Ya que estas cableando sensores, esto no seria mas que un shunt muy bajo y un par de componentes mas. En mi auto (no queria modificar cableado) me hice una "extension de fusible" que contiene un switch reed y una bobinita de 10 vueltas de alambre grueso. Con eso ya tuve mi sensor de luces quemadas + extras.

Otra: Servo de aeromodelismo para regular la baja (estilo paso a paso en motores inyeccion)
 
Última edición:
...anda por los 27 obamas.

:eek: 27 obamas??? :loco: justo a RAT queres hacerle gastar plata?! :LOL:
Volviendo al tema, es verdad... seria un proyecto muy lindo hacerlo con una raspi o una intel galileo con un tft por que no tiene salida de video.. Consulta... de donde sacaste ese precio :confused: si los compras aca en argentina, no baja de los rangos 100-200 obamas :oops:
 
Atrás
Arriba