El siguiente proyecto se trata de un panel de instrumentos para automóviles que cuenta con:
Lo publico con 3 condiciones:
Como notaron, manejé número por número, esto por 2 razones: 1) Para que se viera como el de los autos
y 2) para no castigar al PIC manejando variables de 32bits con semejantes cantidades 
Ahora conozcamos el código de micro principal...
La explicación de como funciona, está en los comentarios del código...
Adjunto están los códigos, la simulación en proteus, los archivos hex, una foto mía en traje de baño...
Ok, no, eso no... 
Ahora algunas fotos...
A medida que vaya avanzando, iré subiendo más información. Saludos...
- Velocímetro.
- Contador de recorrido.
- Medidor de presión de aceite.
- Medidor de temperatura.
- Medidor de tensión.
- Avisos sobre el funcionamiento en general.
Lo publico con 3 condiciones:
- NO deberá emplearse para fines comerciales.
- Si hacen una mejora en el software o hardware, por favor, publicarla.
- Ya que NO TODOS los vehículos son iguales, ni los displays y LCD tampoco, solo postearé el PCB de la tarjeta principal, para que cada quien personalice los visores a su gusto, recordando la condición número 2.
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;
}
}
//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;}
//Terminado el conteo, se guardan los datos en la memoria interna del micro.
if(!input(PIN_A3)){
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);
}
}
}
Como notaron, manejé número por número, esto por 2 razones: 1) Para que se viera como el de los autos
Ahora conozcamos el código de micro principal...
PHP:
//***************************************************//
// Panel de instrumentos digital para vehículos //
// Versión 4.3 //
// 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 //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES PROTECT //Code protected from reads
#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
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock=8000000)
#include <LCD420.C>
//Inicio de variables
float sensor, temper, volt, oil, fuel;
int a=0, b=0, dis=0, shift, unit, decs, cent, speed, alt, ododiv=0, fail[6];
unsigned char segunit[10] = {0x04,0x0C,0x44,0x4C,0x24,0x2C,0x64,0x6C,0x14,0x1C};
unsigned char segdecs[10] = {0x02,0x0A,0x42,0x4A,0x22,0x2A,0x62,0x6A,0x12,0x1A};
unsigned char segcent[10] = {0x01,0x09,0x41,0x49,0x21,0x29,0x61,0x69,0x11,0x19};
//Inicio de programa principal
void main(){
//Configuración de ADC
setup_adc_ports(ALL_ANALOG);
setup_adc(adc_clock_internal);
//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);
//Inicio de bucle de programa.
for(;;){
//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);
oil = read_adc();
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();
//Divisor Odómetro
if(input(PIN_D2)){
ododiv=ododiv+1;
}
if(ododiv > 150){
output_high(PIN_D1);
delay_ms(2);
output_low(PIN_D1);
ododiv=0;
}
//Velocímetro
/*Los delay_ms() dispuestos a lo largo del código, son para mantener una velocidad
constante en la multiplexión, aún cuando los displays no están encendidos */
dis=dis+1;
delay_ms(1);
if(dis==1 && speed > 99){
cent = (speed / 100) > 99 ? ((speed / 100) % 100) : (speed / 100);
output_c(segcent[cent]);
}
else if(dis==2 && speed > 9){
decs = (speed / 10) > 9 ? ((speed / 10) % 10) : (speed / 10);
output_c(segdecs[decs]);
}
else if(dis==3){
unit = speed % 10;
output_c(segunit[unit]);
}
if(dis>3){dis=0;}
//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 < 20){fail[1]=1;}else{fail[1]=0;}
if(fuel < 16){fail[2]=1;}else{fail[2]=0;}
if(volt > 14){fail[3]=1;}else{fail[3]=0;}
if(volt < 11){fail[4]=1;}else{fail[4]=0;}
if(alt > 60){fail[5]=1;}else{fail[5]=0;}
/*Contador que genera un retrazo en el directorio para que no afecte la multiplexión del velocímetro.
a su vez un rastrea constantemente el directorio de fallas. Este contador solo afecta al directorio.*/
if(a < 100){
a=a+1;
}
else{
a=0;
b=b+1;
if(b > 6){b=0;}
}
//Detecta si el motor está encendido.
if(input(PIN_D3)){
//Falla detectada y se busca en el directorio.
if((fail[0] == 1 || fail[1] == 1 || fail[2] == 1 || fail[3] == 1 || fail[4] == 1 || fail[5] == 1)){
if(a%30 == 0){
output_toggle(PIN_B3);
}
//Encontrada alguna falla en el directorio, se vuelve a comprobar para así crear un listado, en caso de que ocurra más de un problema.
switch(b){
case 0:
if(fail[b]==1){
lcd_gotoxy(1,1);
printf(lcd_putc " %.1f%CC ",temper,0xDF);
lcd_gotoxy(1,2);
printf(lcd_putc "HIGH TEMPERATURE");
}
break;
case 1:
if(fail[b]==1){
lcd_gotoxy(1,1);
printf(lcd_putc " %.1f PSI ",oil);
lcd_gotoxy(1,2);
printf(lcd_putc "LOW OIL PRESSURE");
output_high(PIN_D7);
}
break;
case 2:
if(fail[b]==1){
lcd_gotoxy(1,1);
printf(lcd_putc " %.0f%C ",fuel,0x25);
lcd_gotoxy(1,2);
printf(lcd_putc " LOW LEVEL FUEL ");
output_high(PIN_D4);
}
break;
case 3:
if(fail[b]==1){
lcd_gotoxy(1,1);
printf(lcd_putc " %.1fV ",volt);
lcd_gotoxy(1,2);
printf(lcd_putc " OVER TENSION ");
}
break;
case 4:
if(fail[b]==1){
lcd_gotoxy(1,1);
printf(lcd_putc " %.1fV ",volt);
lcd_gotoxy(1,2);
printf(lcd_putc " OVER LOAD ");
}
break;
case 5:
if(fail[b]==1){
lcd_gotoxy(1,1);
printf(lcd_putc " %.1fV ",volt);
lcd_gotoxy(1,2);
printf(lcd_putc " Alt Failure ");
output_high(PIN_D6);
}
break;
}
}
else{
//Posición de palanca de cambios
//Dependiendo de la posición de la palanca, habilita o deshabilita el contador de recorrido.
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 " ");
}
else{
lcd_gotoxy(1,1);
printf(lcd_putc "%.1f %.2f %.0f ",temper,volt,oil);
lcd_gotoxy(1,2);
printf(lcd_putc "Temp Volts Oil");
output_high(PIN_B3);
output_low(PIN_D4);
output_low(PIN_D7);
output_low(PIN_D6);
}
}
}
else{
if(speed > 5 || shift > 10){
lcd_gotoxy(1,1);
printf(lcd_putc " Atention ");
output_toggle(PIN_B3);
}
else{
lcd_gotoxy(1,1);
printf(lcd_putc " ");
}
lcd_gotoxy(1,2);
printf(lcd_putc " Stop Engine ");
output_high(PIN_B3);
}
}
}
Adjunto están los códigos, la simulación en proteus, los archivos hex, una foto mía en traje de baño...
Ahora algunas fotos...
A medida que vaya avanzando, iré subiendo más información. Saludos...
Adjuntos
Última edición por un moderador: