Menú
Foros
Nuevos mensajes
Buscar en foros
Novedades
Nuevos mensajes
Nuevos recursos
Última actividad
Recursos
Últimas revisiones
Buscar recursos
Acceder
Registrarse
Novedades
Buscar
Buscar
Buscar sólo en títulos
De:
Nuevos mensajes
Buscar en foros
Menú
Acceder
Registrarse
Install the app
Instalar
Foros
Diseño digital
Microcontroladores y sistemas embebidos
[Aporte] Panel de instrumentos para automóviles (En fase de desarrollo)
JavaScript está desactivado. Para una mejor experiencia, por favor, activa JavaScript en el navegador antes de continuar.
Estás usando un navegador obsoleto. No se pueden mostrar este u otros sitios web correctamente.
Se debe actualizar o usar un
navegador alternativo
.
Responder al tema
Mensaje
[QUOTE="Ratmayor, post: 1093971, member: 16298"] 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: [CENTER][ATTACH]142207[/ATTACH][/CENTER] 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... [CENTER][ATTACH]142208[/ATTACH][/CENTER] 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 :reido: [CENTER][ATTACH]142211[/ATTACH][/CENTER] 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...: [CENTER][ATTACH]142212[/ATTACH] [ATTACH]142213[/ATTACH][/CENTER] Cabe destacar que para el amperímetro usé un [URL="http://www.ti.com/lit/ds/sbos485a/sbos485a.pdf"]INA283[/URL] 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); } } }[/php] Adjunto le dejo el PCB listo para planchar y si se portan bien, subiré un par de modelos para los medidores... Seguiremos informando :lol: [/QUOTE]
Verificación
Responder
Foros
Diseño digital
Microcontroladores y sistemas embebidos
[Aporte] Panel de instrumentos para automóviles (En fase de desarrollo)
Arriba