Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

HUD automobile : vitesse et boussole projetés sur pare-brise

Composants et fournitures

Composant Quantité
Arduino Nano R3 1
3 afficheurs 7 segments 5161AS (cathode commune, rouge) 3
GPS série TTL Beitian BN-220 (1 Hz, trames GNRMC) 1
3 décodeurs BCD à verrou 14511 (CD4511) 3
Boutons poussoirs (NO) + condensateurs de découplage 3
Résistances 220 Ω ¼ W 22
LED rouge 3 mm 1
Condensateurs 100 nF 2
Jumper (strap) pour déconnecter Rx pendant flash 1
Connecteurs : strip lines, prise USB-B femelle, câble pigtail GPS -
Boîtier imprimé 3D (fichiers STL sur GrabCAD) 1

À propos du projet

J'enviais l'affichage tête haute de la voiture d'un ami. Je l'ai donc construit moi-même : un HUD qui projette la vitesse (km/h) et le cap (degrés) sur le pare-brise via réflexion.

Principes logiciels

Évolutions

Code (sketch principal)

/* Car HUD - Marco Zonca 10/2020
   Arduino Nano, GPS BT-220, 3x 7seg + 3x CD4511, EEPROM, 3 boutons
   ATTENTION : retirer jumper Rx avant upload !
*/
#include <Wire.h>
#include <EEPROM.h>

String inputString = "";
String nm_time, nm_validity, nm_latitude, nm_longitude, nm_knots, nm_truecourse, nm_date;
float nmf_knots = 0, nmf_kmh = 0, nmf_truecourse = 360;
int nmi_kmh = 0, nmi_truecourse = 0;
byte kCent=0, kDeci=0, kUnit=0, tCent=0, tDeci=0, tUnit=0;
byte brightness = 120;
const byte latch_on = LOW, latch_off = HIGH;
unsigned long lastmemcheck = 0;
const unsigned long memcheck = 60000;
bool stringComplete = false, isKMH = true;
const int addr = 0;

// Broches
const int disp001 = 2, disp010 = 8, disp100 = 12;      // Latchs unités/dizaines/centaines
const int disp001dim = 9, disp010dim = 10, disp100dim = 11; // PWM luminosité
const int button_kt = 14, button_more = 15, button_less = 16;
const int degreesLED = 3;
const int bit_3 = 7, bit_2 = 6, bit_1 = 5, bit_0 = 4;
const int dly = 10;
const byte off = 0;
const byte numbers[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}};

void setup() {
  Serial.begin(9600); Wire.begin(); inputString.reserve(200);
  brightness = EEPROM.read(addr);
  if (brightness > 250 || brightness < 10) brightness = 120;
  
  pinMode(disp001, OUTPUT); pinMode(disp010, OUTPUT); pinMode(disp100, OUTPUT);
  pinMode(degreesLED, OUTPUT);
  pinMode(button_kt, INPUT_PULLUP); pinMode(button_less, INPUT_PULLUP); pinMode(button_more, INPUT_PULLUP);
  pinMode(bit_3, OUTPUT); pinMode(bit_2, OUTPUT); pinMode(bit_1, OUTPUT); pinMode(bit_0, OUTPUT);
  
  analogWrite(disp001dim, off); analogWrite(disp010dim, off); analogWrite(disp100dim, off);
  analogWrite(degreesLED, off);
  setBusNr(0);
  digitalWrite(disp001, latch_on); digitalWrite(disp010, latch_on); digitalWrite(disp100, latch_on);
  delay(dly);
  digitalWrite(disp001, latch_off); digitalWrite(disp010, latch_off); digitalWrite(disp100, latch_off);
  analogWrite(disp001dim, brightness); analogWrite(disp010dim, brightness); analogWrite(disp100dim, brightness);
}

void loop() {
  if (stringComplete) {
    bool ret = nmeaExtractData();
    inputString = ""; stringComplete = false;
    if (ret) {
      kCent = nmi_kmh/100; int n = nmi_kmh - kCent*100; kDeci = n/10; kUnit = n - kDeci*10;
      tCent = nmi_truecourse/100; n = nmi_truecourse - tCent*100; tDeci = n/10; tUnit = n - tDeci*10;
      display();
    }
  }
  if (millis() > lastmemcheck + memcheck) { EEPROM.update(addr, brightness); lastmemcheck = millis(); }
  checkButtons();
}

void display() {
  if (isKMH) { // Vitesse km/h
    analogWrite(degreesLED, off);
    setBusNr(kUnit); digitalWrite(disp001, latch_on); delay(dly); digitalWrite(disp001, latch_off);
    if (kDeci > 0 || kCent > 0) { setBusNr(kDeci); digitalWrite(disp010, latch_on); delay(dly); digitalWrite(disp010, latch_off); analogWrite(disp010dim, brightness); }
    else analogWrite(disp010dim, off);
    if (kCent > 0) { setBusNr(kCent); digitalWrite(disp100, latch_on); delay(dly); digitalWrite(disp100, latch_off); analogWrite(disp100dim, brightness); }
    else analogWrite(disp100dim, off);
  } else { // Cap degrés
    analogWrite(degreesLED, brightness);
    setBusNr(tUnit); digitalWrite(disp001, latch_on); delay(dly); digitalWrite(disp001, latch_off);
    if (tDeci > 0 || tCent > 0) { setBusNr(tDeci); digitalWrite(disp010, latch_on); delay(dly); digitalWrite(disp010, latch_off); analogWrite(disp010dim, brightness); }
    else analogWrite(disp010dim, off);
    if (tCent > 0) { setBusNr(tCent); digitalWrite(disp100, latch_on); delay(dly); digitalWrite(disp100, latch_off); analogWrite(disp100dim, brightness); }
    else analogWrite(disp100dim, off);
  }
}

void checkButtons() {
  if (digitalRead(button_kt) == LOW) { isKMH = !isKMH; delay(250); }
  if (digitalRead(button_more) == LOW) { if (brightness <= 240) brightness += 10; updateBrightness(); delay(100); }
  if (digitalRead(button_less) == LOW) { if (brightness >= 20) brightness -= 10; updateBrightness(); delay(100); }
}

void updateBrightness() {
  analogWrite(disp001dim, brightness); analogWrite(disp010dim, brightness); analogWrite(disp100dim, brightness);
}

void setBusNr(int number) {
  for (byte b = 0; b <= 3; b++) {
    int pin = (b==0)?bit_0:(b==1)?bit_1:(b==2)?bit_2:bit_3;
    digitalWrite(pin, numbers[number][b] ? HIGH : LOW);
  }
}

// Extraction données NMEA $GNRMC + checksum
bool nmeaExtractData() {
  if (!(inputString.substring(0,6) == "$GNRMC" && inputString.substring(inputString.length()-4, inputString.length()-2) == nmea0183_checksum(inputString)))
    return false;
  int y = 0, z;
  for (int s = 1; s < 11; s++) {
    y = inputString.indexOf(",", y);
    z = inputString.indexOf(",", y+1);
    String val = (z > y+1) ? inputString.substring(y+1, z) : "";
    switch(s) {
      case 1: if(val.length()) nm_time = val.substring(0,2)+":"+val.substring(2,4)+":"+val.substring(4,6); break;
      case 2: if(val.length()) nm_validity = val; break;
      case 3: if(val.length()) nm_latitude = val.substring(0,2)+"°"+val.substring(2,10)+"'"; break;
      case 4: if(val.length()) nm_latitude += val; break;
      case 5: if(val.length()) nm_longitude = val.substring(0,3)+"°"+val.substring(3,11)+"'"; break;
      case 6: if(val.length()) nm_longitude += val; break;
      case 7: if(val.length()) { nmf_knots = val.toFloat(); nmf_kmh = round(nmf_knots * 1.852); nmi_kmh = (int)round(nmf_kmh); } break;
      case 8: if(val.length()) { nmf_truecourse = val.toFloat(); nmi_truecourse = (int)round(nmf_truecourse); } break;
      case 9: if(val.length()) nm_date = val.substring(0,2)+"/"+val.substring(2,4)+"/20"+val.substring(4,6); break;
    }
    y = z;
  }
  return true;
}

void serialEvent() {
  while (Serial.available()) {
    char c = Serial.read(); inputString += c;
    if (c == '\n') stringComplete = true;
  }
}

String nmea0183_checksum(String s) {
  int crc = 0;
  for (int i = 1; i < s.length()-5; i++) crc ^= s[i];
  String h = String(crc, HEX); if (h.length()==1) h = "0"+h; h.toUpperCase(); return h;
}

Schémas et PCB

Deux PCB double face (≈50 rivets traversants + 5 trous d'alignement). Fichiers pour transfert toner (feuilles bleues/jaunes, laser 1200 dpi, fer à repasser). Gravure au perchlorure de fer. Masque composants imprimé aussi pour aspect pro.

HUD automobile : vitesse et boussole projetés sur pare-brise HUD automobile : vitesse et boussole projetés sur pare-brise HUD automobile : vitesse et boussole projetés sur pare-brise HUD automobile : vitesse et boussole projetés sur pare-brise

Conduite prudente : au volant, ne regardez que la route !

Processus de fabrication

  1. Révolutionner la mobilité : à l'intérieur de la voiture semi-autonome d'Arrow Electronics pour conducteurs handicapés
  2. Voiture autonome Donkey Car : IA TensorFlow MobileNetV2 pour collecte de déchets
  3. Planification de mouvement temps réel pour véhicules autonomes en milieu urbain : Étude prototype à échelle réduite
  4. Comment la 5G transforme les voitures connectées : Vitesse, sécurité et fonctions intelligentes
  5. Sécurité d'abord : comment les Européens voient la voiture connectée de demain
  6. Choisir le câble moteur optimal pour les variateurs de vitesse (VSD)
  7. Tours rapides Twister : Polissage et ébavurage avancés avec 50 % plus de puissance et contrôle régénératif
  8. Tour à lit incliné FBL-1233 : précision, vitesse et polyvalence pour grande et petite série
  9. Échange de données produit : le défi clé pour les fabricants automobiles