Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

HUD del automóvil - Pantalla de parabrisas para velocidad y brújula

Componentes y suministros

Arduino Nano R3
× 1

Acerca de este proyecto

Descripción:

¡Lo quería! Me he burlado del gran coche de mi amigo Taggi que muestra en el parabrisas la velocidad. ¡Tenía que tenerlo, tenía que hacerlo yo mismo, por supuesto!

Punto de vista del software:

Proyectar el circuito la parte más difícil y confusa ha sido la conexión de las pantallas de 7 segmentos a los decodificadores BCD porque los números están "invertidos" (reflejado).

Hay 3 botones :+ y - para aumentar o disminuir el brillo y S / H para cambiar entre Velocidad en km / hy Rumbo en grados ; en caso de rumbo también el LED rojo está encendido, significa "grados" de brújula (1-360 °) cuando se mueve. No es una brújula electrónica, es un GPS y debes moverte para tener la información correcta de la dirección a la que te diriges. El brillo se guarda en EEPROM memoria después de un minuto. El brillo se cambia tanto en las pantallas como en los LED mediante los pines PWM.

Una parte importante del código es recopilar datos del GPS, principalmente velocidad y dirección, sacándolos de cada oración NMEA. Incluso usando la clase String, principalmente para la manipulación de oraciones en serie NMEA, todo el flujo de elaboración es estable y sólido; utiliza "serialEvent ()" para recibir datos del GPS una vez por segundo , luego llama a "nmeaExtractData ()" y finalmente verifica el paquete de datos con "nmea0183_checksum () para asegurarse de la integridad de los datos. Si usa otra marca y modelo de GPS, asegúrese de que las oraciones tengan la misma estructura o debe hacer algunos cambios aquí . Por ejemplo, EM406A usa el ID de paquete "$ GPRMC", BT220 usa "$ GNRMC" en su lugar ... solo un pequeño cambio de nombre ... Un enlace útil puede ayudarlo con la prueba de suma de comprobación:https://nmeachecksum.eqth.net - Aquí un ejemplo de una oración NMEA completa, contiene:id, time, validity, latitud, longitud, velocidad, rumbo verdadero, fecha, variación y suma de comprobación.

$ GNRMC, 095836.000, A, 4551.9676, N, 01328.7118, E, 2.09, 341.84, 280519 ,, * 08

El esquema permite habilitar el pestillo para cada decodificador BCD de una sola pantalla de uno en uno, establecer el número de código en el bus binario de 4 bits, deshabilitar el pestillo, y así sucesivamente cuando el valor cambia. Los ceros no significativos del lado izquierdo están en blanco (no se muestran).

Antes de cargar un nuevo boceto a el MCU recuerda sacarte el jersey :está conectado al pin Rx de Arduino y durante la carga seguramente está en conflicto con GPS Tx. Después de cargar el software, vuelva a colocar el puente para restaurar la funcionalidad normal.

Lista de componentes:

  • 1 x MCU Arduino Nano
  • 3 x 5161 como pantallas de siete segmentos, cátodo común, rojo
  • 1 x GPS TTL serie Beitian BN-220 (sentencias GNRMC de 1 Hz)
  • 1 x jersey
  • 3 x botones (normalmente abiertos) + 3 x mayúsculas
  • 22 resistencias de 1 / 4W 220 ohmios
  • 1 LED de 3 mm, rojo
  • 2 condensadores de 100n
  • 3 decodificadores BCD 14511 + pestillo
  • 1 x USB "B" hembra
  • 1 x línea de tira 2x pines macho (para Jumper)
  • 1 línea de tira 4 pines macho para doblar a 90 ° (para GPS)
  • 1 x cable flexible que conecta el GPS a 4 pines a bordo
  • 22 pines macho de línea de tira para unir dos PCB en una pila
  • 1 pieza de adhesivo de doble cara para pegar GPS en PCB
  • 6 x línea de tira torneada 5x pines hembra (para pantallas)
  • 50 remaches de cobre de 0,6 mm
  • 8 x tornillos M3
  • 4 torres hembra M3 de 20 mm de altura
  • 1 x caja de plástico + cubierta (mira mis archivos 3D listos para imprimir, a continuación)

PCB (placas de circuito impreso):

Usé dos PCB de doble cara por esa razón se utilizan alrededor de 50 remaches o pasadores de paso para resolver recorridos de circuitos completos. También hay 5 orificios de alineación hacer primero. Diseñé en cada PCB estos 5 puntos de alineación. En la sección de descargas tienes todos los archivos de PCB, componentes y caras de soldadura, reflejados, para descargar e imprimir mediante una impresora láser en hojas "amarillas" o "azules".; esta vez usé los azules pero también los amarillos son buenos y el precio es más bajo. Tengo que decir que las hojas azules son mejores ... Cuando imprima, recuerde deshabilitar la configuración de ahorro de tóner, use en su lugar una resolución de 1200 ppp para obtener un resultado de negro real profundo. El proceso de transferencia de tóner de las hojas mágicas a la PCB se realiza mediante el uso de una plancha caliente ... En la red hay algunos tutoriales que muestran cómo producir una buena PCB pero recuerda estos puntos importantes:limpia perfectamente y cepilla ligeramente el cobre con una esponja de cocina ruvid, 5 minutos de planchado, choque térmico de agua, alineación de dos caras a modo de 5 agujeros (usé 5 pines en una gran superficie LED blanca para ver agujeros), proteja la otra cara durante el proceso de corrosión. Imprimir también la cara de los componentes hace que el proyecto sea "profesional" :-)

NOTAS: las imágenes se toman antes de la última versión, significa que algunos detalles pueden ser diferentes:es decir, el extraño cable verde alrededor de los PCB en la versión final desaparece, o el puente se ha movido de PCB # 1 a PCB # 2. Debe configurar el GPS a una velocidad de 9600 bps, solo una oración GNRMC NMEA de 1Hz; esto se puede hacer usando su propio software de configuración. Finalmente, antes de soldar el conector USB hembra, pegue un pequeño trozo de cinta aislante debajo para evitar el contacto no deseado con una línea de cobre, en el lado del componente, justo debajo de él.

Dando energía por primera vez descubrirás que los números son "ilegibles", porque está hecho para mirarlos reflejados en el parabrisas (espejo). Instálelo en el automóvil en la parte delantera del asiento del conductor , busca un lugar cómodo y arréglalo. Sugiero conectar el cable de alimentación USB después de la posición de encendido para que se encienda / apague cuando el motor se encienda / apague. ¡Eso es todo, damas y caballeros!

Noticias y mejoras:

  • 25.03.2021:para completar el proyecto preparé dos modelos 3D .STL en este enlace:https://grabcad.com/library/car-hud-1 donde puede descargar archivos sobre una caja con forma y su panel de cubierta para este proyecto para imprimir mediante una impresora 3D.
  • 20.07.2021:está disponible una V2 (versión dos) del software que, junto con dos cables y una resistencia, tendrá información de altitud en la pantalla como miles de metros (es decir, 0,89 =890 m), simplemente presione otra vez el botón S / H. Instrucciones:1) configurar el GPS para generar también la sentencia $ GNGGA nmea mediante su propio software; 2) corte la conexión real entre el pin d5 Arduino pwm y el resto del circuito, conéctelo al pin de punto decimal de la pantalla central con una resistencia de 220ohm; 3) conecte el pin digital d13 Arduino al circuito donde se conectó d5; mira algunas fotos aquí abajo; 4) instale el boceto V2 en su Arduino Nano.
  • 01.11.2021:la versión V2.2 está lista para ti. Que nuevo Acerca de la altitud (ya presente con V2), el hud muestra el valor completo hasta 999 m, a partir de 1000 m muestra valores en miles, es decir, 1,24 (1240 m) o 2,02 (2020 m). Agregué un fotorresistor LDR GL5539, un resistor de 10kOhm y 2 cables. Mire las imágenes a continuación para ver las modificaciones V2.2 e instale el boceto V2.2 en su Arduino. El sensor LDR modificará el brillo automáticamente (3 niveles) dependiendo del nivel de luz (día, nublado o noche). Los botones (+) y (-) siguen funcionando para modificar manualmente el brillo, tienen prioridad; para volver al modo automático, simplemente presione juntos los botones (+) y (-) durante un rato. La EEPROM interna para almacenar el nivel de brillo ya no se usa. ¡Hagamos los mods V2 primero!

Cuando conduzca, simplemente conduzca. ¡Conduce seguro!

Código

  • Bosquejo de Arduino Car-HUD
Esbozo de Arduino de coche-HUD Arduino
 / * Este boceto actúa como HUD del parabrisas del automóvil (pantalla frontal), por Marco Zonca, Arduino Nano 10/2020 como CPU, GPS BT-220 nmea cada 1 segundo, 3 botones, 3 pantallas de siete segmentos, cátodo común , Decodificador de pestillo BCD 3 x 14511, memoria EEPROM MPU (1 byte) y muchas resistencias; ADVERTENCIA:=======Antes de actualizar el software, desconecte el pin RX en Arduino (TX del GPS) por medio del JUMPER * / # incluya  #include  String inputString =""; Cadena nm_time ="00:00:00"; Cadena nm_validity ="V"; Cadena nm_latitude ="dd ° mm.mmmm'N"; Cadena nm_longitude ="ddd ° mm.mmmm'E"; Cadena nm_knots ="0.0 kn "; float nmf_knots =0.0; float nmf_kmh =0.0; int nmi_kmh =0; String nm_truecourse =" 360 "; float nmf_truecourse =360; String nm_date =" dd / mm / aaaa "; int nmi_truecourse =0; byte kCent =0; byte kDeci =0; byte kUnit =0; byte tCent =0; byte tDeci =0; byte tUnit =0; byte brillo =120; byte latch_off =HIGH; byte latch_on =LOW; int n =0; unsigned long lastmemcheck =0; memcheck largo sin firmar =60000; // comprobar para guardar el valor de "brillo" en EEPROM cada 60 segundos bool stringComplete =false; bool isKMH =true; bool ret =false; const int disp001 =2; // mostrar las unidades latchconst int disp010 =8; // mostrar decenas latchconst int disp100 =12; // undreds muestran latchconst int disp001dim =9; // unidades muestran dimmer / off pinconst int disp010dim =10; // decenas muestran dimmer / off pinconst int disp100dim =11; // undreds muestra atenuador / apagado pinconst int button_kt =14; // kmh / truecourse buttonconst int button_more =15; // brillo + buttonconst int button_less =16; // brillo - buttonconst int gradosLED =3; // grados LEDconst int bit_3 =7; // bit 3const int bit_2 =6; // bit 2const int bit_1 =5; // bit 1const int bit_0 =4; // bit 0const int dly =10; // retardo del pestillo m / secconst byte off =0; // lo mismo que brillo =0const int addr =0; // Dirección EEPROM para el valor de brillo números de bytes constantes [10] [4] ={{0,0,0,0}, {1,0,0,0}, {0,1,0,0}, {1, 1,0,0}, {0,0,1,0}, {1,0,1,0}, {0,1,1,0}, {1,1,1,0}, {0, 0,0,1}, {1,0,0,1}}; // bits 0,1,2,3void setup () {Serial.begin (9600); Wire.begin (); inputString.reserve (200); brillo =EEPROM.read (addr); si (brillo> 250 || brillo <10) {brillo =120; } // evitar valores locos de la 1ª EEPROM read pinMode (disp001, OUTPUT); pinMode (disp010, SALIDA); pinMode (disp100, SALIDA); pinMode (gradosLED, SALIDA); pinMode (button_kt, INPUT_PULLUP); pinMode (button_less, INPUT_PULLUP); pinMode (button_more, INPUT_PULLUP); pinMode (bit_3, SALIDA); pinMode (bit_2, SALIDA); pinMode (bit_1, SALIDA); pinMode (bit_0, SALIDA); analogWrite (disp001dim, desactivado); // Apagado y cero muestra analogWrite (disp010dim, apagado); analogWrite (disp100dim, desactivado); analogWrite (gradosLED, apagado); setBusNr (0); escritura digital (disp001, latch_on); escritura digital (disp010, latch_on); escritura digital (disp100, latch_on); retraso (dly); digitalWrite (disp001, latch_off); digitalWrite (disp010, latch_off); digitalWrite (disp100, latch_off); analogWrite (disp001dim, brillo); // en pantalla analogWrite (disp010dim, brillo); analogWrite (disp100dim, brillo);} // setup () void loop () {// GPS NMEA ------------------ if (stringComplete ==true) {// recibió la sentencia nmea por el puerto serie RX ret =nmeaExtractData (); inputString =""; stringComplete =falso; si (ret ==verdadero) {kCent =nmi_kmh / 100; n =nmi_kmh- (kCent * 100); kDeci =n / 10; n =nmi_kmh- (kCent * 100) - (kDeci * 10); kUnit =n; tCent =nmi_truecourse / 100; n =nmi_truecourse- (tCent * 100); tDeci =n / 10; n =nmi_verdadero- (tCent * 100) - (tDeci * 10); tUnit =n; monitor(); }} if (millis ()> (lastmemcheck + memcheck)) {// poner en la memoria el valor de brillo (si se modifica) EEPROM.update (addr, brillo); lastmemcheck =millis (); } checkButtons ();} void display () {if (isKMH ==true) {// velocidad en km / h (isKMH =true) analogWrite (gradosLED, apagado); setBusNr (kUnit); escritura digital (disp001, latch_on); retraso (dly); digitalWrite (disp001, latch_off); if (kDeci> 0 || kCent> 0) {// desactiva decenas si decenas =0 (y también undreds =0) setBusNr (kDeci); escritura digital (disp010, latch_on); retraso (dly); digitalWrite (disp010, latch_off); analogWrite (disp010dim, brillo); } else {analogWrite (disp010dim, apagado); } if (kCent> 0) {// desactiva undreds if =0 setBusNr (kCent); escritura digital (disp100, latch_on); retraso (dly); digitalWrite (disp100, latch_off); analogWrite (disp100dim, brillo); } else {analogWrite (disp100dim, apagado); }} else {// rumbo verdadero en grados (isKMH =falso) analogWrite (gradosLED, brillo); setBusNr (tUnit); escritura digital (disp001, latch_on); retraso (dly); digitalWrite (disp001, latch_off); if (tDeci> 0 || tCent> 0) {// establece decenas si decenas =0 (y también undreds =0) setBusNr (tDeci); escritura digital (disp010, latch_on); retraso (dly); digitalWrite (disp010, latch_off); analogWrite (disp010dim, brillo); } else {analogWrite (disp010dim, apagado); } if (tCent> 0) {// desactiva undreds if =0 setBusNr (tCent); escritura digital (disp100, latch_on); retraso (dly); digitalWrite (disp100, latch_off); analogWrite (disp100dim, brillo); } else {analogWrite (disp100dim, apagado); }}} // display () void checkButtons () {if (digitalRead (button_kt) ==LOW) {if (isKMH ==true) {isKMH =false; } else {isKMH =true; } retraso (250); } if (digitalRead (button_more) ==LOW) {if (brillo <=240) {brillo =brillo + 10; } analogWrite (disp001dim, brillo); analogWrite (disp010dim, brillo); analogWrite (disp100dim, brillo); retraso (100); } if (digitalRead (button_less) ==LOW) {if (brillo> =20) {brillo =brillo-10; } analogWrite (disp001dim, brillo); analogWrite (disp010dim, brillo); analogWrite (disp100dim, brillo); retraso (100); }} // checkButtons () void setBusNr (int number) {// establece el bus de 4 bits para (byte b =0; b <=3; b ++) {if (números [número] [b] ==0) {if (b ==0) {digitalWrite (bit_0, LOW);} if (b ==1) {digitalWrite (bit_1, LOW);} if (b ==2) {digitalWrite (bit_2, LOW);} if (b ==3) {digitalWrite (bit_3, LOW);}} else {if (b ==0) {digitalWrite (bit_0, HIGH);} if (b ==1) {digitalWrite (bit_1, HIGH);} if ( b ==2) {digitalWrite (bit_2, HIGH);} if (b ==3) {digitalWrite (bit_3, HIGH);}}}} // setBusNr () // extraer datos de nmea inputStringbool nmeaExtractData () {int d =0; int s =0; int y =0; int z =0; flotar t =0; bool ret =falso; // verdadero si nmea oración =$ GNRMC y CHKSUM válido if ((inputString.substring (0,6) =="$ GNRMC") &&(inputString.substring (inputString.length () - 4, inputString.length () - 2) ==nmea0183_checksum (inputString))) {y =0; para (s =1; s <11; s ++) {y =inputString.indexOf (",", y); switch (s) {caso 1:// ----------------------- tiempo z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_time =inputString.substring (y + 1, y + 2 + 1) + ":" + inputString.substring (y + 1 + 2, y + 4 + 1) + " :"+ inputString.substring (y + 1 + 4, y + 6 + 1); } y =z; descanso; caso 2:// ----------------------- validez z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_validez =inputString.substring (y + 1, y + 1 + 1); } y =z; descanso; caso 3:// ----------------------- latitud z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_latitude =inputString.substring (y + 1, y + 2 + 1) + "°" + inputString.substring (y + 1 + 2, y + 10 + 1) + " '"; } y =z; descanso; caso 4:// ----------------------- norte / sur z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_latitude =nm_latitude + inputString.substring (y + 1, y + 1 + 1); } y =z; descanso; caso 5:// ----------------------- longitud z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_longitude =inputString.substring (y + 1, y + 3 + 1) + "°" + inputString.substring (y + 1 + 3, y + 11 + 1) + " '"; } y =z; descanso; caso 6:// ----------------------- este / oeste z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_longitude =nm_longitude + inputString.substring (y + 1, y + 1 + 1); } y =z; descanso; caso 7:// ----------------------- velocidad nudos z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nmf_knots =inputString.substring (y + 1, z) .toFloat (); t =roundOneDec (nmf_nudos); nm_knots =Cadena (t, 1) + "kn"; nmf_kmh =roundTwoDec (nmf_knots * 1.852); nmi_kmh =roundZeroDec (nmf_knots * 1.852); } y =z; descanso; caso 8:// ----------------------- curso verdadero z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nmf_truecourse =inputString.substring (y + 1, z) .toFloat (); t =roundZeroDec (nmf_verdadero); nmi_truecourse =t; d =t; nm_truecourse =d; } y =z; descanso; caso 9:// ----------------------- fecha z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_date =inputString.substring (y + 1, y + 2 + 1) + "/" + inputString.substring (y + 1 + 2, y + 4 + 1) + " /20"+inputString.substring(y+1+4,y+6+1); } y =z; descanso; caso 10:// declaraciones n.u. descanso; predeterminado:// declaraciones n.u. descanso; }} ret =verdadero; } return ret;} // nmeaExtractData () / * SerialEvent ocurre cada vez que llegan nuevos datos en el RX serial del hardware. Esta rutina se ejecuta entre cada ejecución de loop (), por lo que el uso de retardo dentro del ciclo puede retrasar la respuesta. Pueden estar disponibles varios bytes de datos. * / Void serialEvent () {while (Serial.available ()) {char inChar =(char) Serial.read (); inputString + =inChar; // si el carácter entrante es una nueva línea, establezca una bandera para que el bucle principal pueda // hacer algo al respecto if (inChar =='\ n') {stringComplete =true; }}} // serialEvent () // calcular la suma de comprobación de nmea statementString nmea0183_checksum (String nmea_data) {int crc =0; String chSumString =""; int i; // ignora el primer signo $, suma de comprobación en la oración para (i =1; i <(nmea_data.length () - 5); i ++) {// elimina el - 5 si no hay "*" + cksum + cr + Si están presentes crc ^ =nmea_data [i]; } chSumString =String (crc, HEX); if (chSumString.length () ==1) {chSumString ="0" + chSumString.substring (0,1); } chSumString.toUpperCase (); return chSumString;} // nmea0183_checksum (String nmea_data) // redondea cero decimalesfloat roundZeroDec (float f) {float y, d; y =f * 1; d =y - (int) y; y =(flotante) (int) (f * 1) / 1; si (d> =0.5) {y + =1; } más {si (d <-0,5) {y - =1; }} return y;} // redondea uno decimalfloat roundOneDec (float f) {float y, d; y =f * 10; d =y - (int) y; y =(flotante) (int) (f * 10) / 10; si (d> =0,5) {y + =0,1; } más {si (d <-0,5) {y - =0,1; }} return y;} // redondea dos decimales flotar roundTwoDec (float f) {float y, d; y =f * 100; d =y - (int) y; y =(flotante) (int) (f * 100) / 100; si (d> =0.5) {y + =0.01; } más {si (d <-0,5) {y - =0,01; }} return y;} 

Esquemas

car-hud_m5RwPQqpxH.fzz ard-carhud-v2_3N5756haNI.ino ard-carhud-v2-2_XhXHFJu0T8.ino

Proceso de manufactura

  1. Derribo de un automóvil semiautónomo para conductores discapacitados
  2. AI de conducción autónoma para el recolector de basura de burro
  3. Planificación de movimiento en tiempo real para vehículos autónomos en varias situaciones, en entornos urbanos simulados
  4. ¿Qué puede ofrecer 5G para el automóvil conectado?
  5. Seguridad:la máxima prioridad para los automóviles del futuro
  6. Cables de motor para variadores de velocidad
  7. Tornos mejorados para pulido y desbarbado
  8. Torno diseñado para precisión y velocidad
  9. Intercambio de datos de productos:un punto crítico para los fabricantes de automóviles
  10. ¿Cómo elegir un turbocompresor para su automóvil?
  11. ¿Cuál es el motivo de las fugas de aceite en mi coche cuando está embalado?