Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

HUD автомобиля - отображение скорости и компаса на ветровом стекле

Компоненты и расходные материалы

Arduino Nano R3
× 1

Об этом проекте

Описание:

Я хотел этого! Я был оскорблен большой машиной моего друга Тагги, показывающей на лобовом стекле скорость. Я должен был это иметь, конечно, я должен был сделать это сам!

Точка зрения программного обеспечения:

При проектировании схемы самой сложной и запутанной частью было подключение 7-сегментных дисплеев к декодерам BCD, потому что числа "инвертированы" (зеркально).

Есть 3 кнопки :+ и - для увеличения / уменьшения яркости и S / H для переключения между скоростью в км / ч и курсом в градусах ; в случае направления также горит красный светодиод, это означает «градусы» компаса (1-360 °) при движении. Это не электронный компас, это GPS, и вам нужно двигаться, чтобы иметь правильную информацию о направлении, в котором вы движетесь. Яркость сохраняется в EEPROM память через минуту. Яркость меняется как на дисплеях, так и на светодиодах с помощью выводов ШИМ.

Важная часть кода предназначена для сбора данных от GPS, в основном скорости и направления, извлекая их из каждого предложения NMEA. Даже при использовании класса String, в основном для манипуляций с последовательными предложениями NMEA, весь процесс разработки остается стабильным и надежным; он использует "serialEvent ()" для получения данных от GPS один раз в секунду , затем вызывает "nmeaExtractData ()" и, наконец, он проверяет пакет данных с помощью "nmea0183_checksum (), чтобы убедиться в целостности данных. Если вы используете другой GPS-навигатор марки и модели, убедитесь, что предложения имеют ту же структуру, или вам придется внести здесь некоторые изменения. . Например, EM406A использует идентификатор пакета «$ GPRMC», BT220 использует «$ GNRMC» . вместо этого ... небольшое изменение имени ... Полезная ссылка может помочь вам с проверкой контрольной суммы:https://nmeachecksum.eqth.net - Вот пример полного предложения NMEA, которое содержит:идентификатор, время, срок действия, широта, долгота, скорость, истинный курс, дата, вариация и контрольная сумма.

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

Скетч предусматривает включение защелки для каждого отдельного дисплея декодера BCD по одному, установку номера кода на двоичной 4-битной шине, отключение защелки и т. Д. При изменении значения. Незначительные нули слева не отображаются (не отображаются).

Перед загрузкой нового эскиза в the MCU не забудьте вынуть перемычку :он подключен к выводу Rx Arduino и во время загрузки наверняка конфликтует с GPS Tx. После загрузки программного обеспечения снова установите перемычку для восстановления нормальной работы.

Список компонентов:

  • 1 микроконтроллер Arduino Nano
  • 3 x 5161 как семисегментный дисплей, общий катод, красный
  • 1 x Beitian BN-220, последовательный TTL GPS (предложения GNRMC с частотой 1 Гц)
  • 1 джемпер
  • 3 кнопки (нормально открытые) + 3 заглушки
  • Резисторы 220 Ом, 22 x 1/4 Вт
  • 1 светодиод x 3 мм, красный
  • 2 конденсатора по 100 н.
  • 3 x 14511 декодеров BCD + защелка
  • 1 гнездо USB типа B
  • 1 полоска 2 штекера (для перемычки)
  • 1 полоска, 4 штыря с наружной резьбой для изгиба до 90 ° (для GPS).
  • 1 х соединительный кабель для подключения GPS к 4 контактам на борту.
  • 22 штыря штрипса для соединения двух печатных плат в стек.
  • 1 кусок двустороннего клея для наклеивания GPS на печатную плату.
  • 6 точеных полосовых штифтов 5 штекеров (для дисплеев)
  • 50 медных заклепок диаметром 0,6 мм.
  • 8 винтов M3
  • 4 башни с внутренней резьбой M3 высотой 20 мм
  • 1 пластиковая коробка + крышка (см. мои 3D-файлы, готовые к печати, ниже)

PCB (печатные платы):

Я использовал две двусторонние печатные платы по этой причине около 50 сквозных заклепок или штифтов используются для решения маршрутов для целых цепей. Также есть 5 центровочных отверстий . сделать первым. Я разработал на каждой печатной плате эти 5 точек выравнивания. В разделе загрузки у вас есть все файлы печатных плат, компоненты и поверхности пайки, зеркальные, для загрузки и печати с помощью лазерного принтера на «желтых» или «синих» листах ; На этот раз я использовал синие, но и желтые тоже хороши, и цена ниже. Я должен сказать, что синие листы лучше ... При печати не забудьте отключить настройки экономии тонера, вместо этого используйте разрешение 1200 dpi, чтобы получить глубокий настоящий черный результат. Процесс переноса тонера с волшебных листов на печатную плату осуществляется с помощью горячего утюга ... В сети есть несколько руководств, показывающих как создать хорошую печатную плату но помните эти важные моменты:тщательно очистите и слегка почистите медь кухонной губкой, 5 минут глажки, водный термический шок, выравнивание двух поверхностей с помощью 5 отверстий (я использовал 5 контактов на большой белой светодиодной поверхности, чтобы увидеть отверстия), защитите другую поверхность во время процесса коррозии. Печать также лица компонентов делает проект «профессиональным» :-)

ПРИМЕЧАНИЯ: изображения сделаны до самой последней версии, это означает, что некоторые детали могут отличаться:например, странный зеленый провод вокруг печатных плат в окончательной версии исчезает, или перемычка перемещается с печатной платы №1 на печатную плату №2. Вы должны настроить GPS на скорость 9600 бит / с, только предложение GNRMC NMEA 1 Гц; это можно сделать с помощью собственного программного обеспечения для установки. Наконец, перед тем, как паять гнездовой разъем USB, приклейте под него небольшой кусок изоленты, чтобы избежать нежелательного контакта с медной линией на стороне компонентов, чуть ниже нее.

Давая мощность в первый раз, вы обнаружите, что числа «нечитаемы», потому что они созданы так, чтобы смотреть на них, отражаясь на ветровом стекле (зеркале). Установите его в автомобиле перед сиденьем водителя , найди удобное место и исправь. Я предлагаю подключить кабель питания USB . после положения зажигания, поэтому он будет включаться / выключаться при включении / выключении двигателя. Это все, дамы и господа!

Новости и улучшения:

  • 25.03.2021:для завершения проекта я подготовил две 3D-модели .STL по этой ссылке:https://grabcad.com/library/car-hud-1, где вы можете загрузить файлы, касающиеся фигурного ящика и его панели-обложки для этого проекта для печати на 3D-принтере.
  • 20.07.2021:доступна V2 (вторая версия) программного обеспечения, которое вместе с двумя проводами и одним резистором будет отображать на дисплее информацию о высоте в тысячах метров (т.е. 0,89 =890 м), просто нажмите еще раз кнопку S / H! Инструкции:1) настройте GPS для вывода также предложения $ GNGGA nmea посредством собственного программного обеспечения; 2) разорвите фактическое соединение между выводом pwm d5 Arduino и остальной частью схемы, подключите его к выводу десятичной точки центрального дисплея с помощью резистора 220 Ом; 3) подключите цифровой вывод d13 Arduino к цепи, к которой был подключен d5; посмотрите несколько картинок ниже; 4) установите скетч V2 на свой Arduino Nano.
  • 01.11.2021:готова версия V2.2 для тебя. Что нового? Что касается высоты (уже представленной с V2), hud показывает полное значение до 999 м, начиная с 1000 м, он показывает значения в тысячах, то есть 1,24 (1240 м) или 2,02 (2020 м). Я добавил фоторезистор LDR GL5539, резистор 10кОм и 2 провода. Посмотрите на изображения ниже для модов V2.2 и установите скетч V2.2 на свой Arduino. Датчик LDR автоматически изменяет яркость (3 уровня) в зависимости от уровня освещенности (днем, облачно или ночью). Кнопки (+) и (-) все еще работают для ручного изменения яркости, они имеют приоритет; для возврата к автоматическому режиму просто одновременно нажмите на некоторое время кнопки (+) и (-). Внутренняя EEPROM для хранения уровня яркости больше не используется. Давайте сначала сделаем моды для V2!

Во время вождения просто садитесь за руль. Двигайтесь безопасно!

Код

  • Эскиз Car-HUD Arduino
Скетч Arduino Car-HUD Arduino
 / * Этот эскиз действует как HUD на лобовом стекле автомобиля, Марко Зонка, 10/2020 Arduino Nano в качестве процессора, GPS BT-220 nmea каждые 1 секунду, 3 кнопки, 3 семисегментные дисплеи с общим катодом , 3 x 14511 декодер защелки BCD, память MPU EEPROM (1 байт) и множество резисторов; ВНИМАНИЕ:=======Перед обновлением программного обеспечения позвольте отсоединить вывод RX на Arduino (TX от GPS) с помощью JUMPER * / # include  #include  String inputString =""; Строка nm_time ="00:00:00"; Строка nm_validity ="V"; Строка nm_latitude ="dd ° mm.mmmm'N"; Строка nm_longitude ="ddd ° mm.mmmm'E"; Строка 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 / yyyy "; int nmi_truecourse =0; byte kCent; byte kDeci =0; byte kUnit =0; byte tCent =0; byte tDeci =0; byte tUnit =0; byte Brightness =120; byte latch_off =HIGH; byte latch_on =LOW; int n =0; unsigned long lastmemcheck =0; беззнаковый длинный memcheck =60000; // проверка сохранения значения "яркости" в EEPROM каждые 60 секунд bool stringComplete =false; bool isKMH =true; bool ret =false; const int disp001 =2; // отображение единиц latchconst int disp010 =8; // отображение десятков latchconst int disp100 =12; // вывод красного цвета latchconst int disp001dim =9; // диммер / выключение дисплея единиц pinconst int disp010dim =10; // диммер / выключение дисплея десятков pinconst int disp100dim =11; // диммер / выключение дисплея без красного pinconst int button_kt =14; // кмч / truecourse buttonconst int button_more =15; // яркость + buttonconst int button_less =16; // яркость - buttonconst int градусовLED =3; // градусы LEDconst int bit_3 =7; // бит 3const int bit_2 =6; // бит 2const int bit_1 =5; // бит 1const int bit_0 =4; // бит 0const int dly =10; // защелка задержки м / секconst byte off =0; // то же, что и яркость =0const int addr =0; // адрес EEPROM для значения яркости число байтов [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}}; // биты 0,1,2,3void setup () {Serial.begin (9600); Wire.begin (); inputString.reserve (200); яркость =EEPROM.read (адрес); if (яркость> 250 || яркость <10) {яркость =120; } // избегаем сумасшедших значений из первого чтения EEPROM pinMode (disp001, OUTPUT); pinMode (disp010, ВЫХОД); pinMode (disp100, ВЫХОД); pinMode (степень светодиода, ВЫХОД); pinMode (button_kt, INPUT_PULLUP); pinMode (button_less, INPUT_PULLUP); pinMode (button_more, INPUT_PULLUP); pinMode (бит_3, ВЫХОД); pinMode (бит_2, ВЫХОД); pinMode (бит_1, ВЫХОД); pinMode (бит_0, ВЫХОД); analogWrite (disp001dim, выкл); // выкл и ноль отображает analogWrite (disp010dim, off); analogWrite (disp100dim, выкл.); analogWrite (градусовLED, выкл.); setBusNr (0); digitalWrite (disp001, latch_on); digitalWrite (disp010, latch_on); digitalWrite (disp100, latch_on); задержка (dly); digitalWrite (disp001, latch_off); digitalWrite (disp010, latch_off); digitalWrite (disp100, latch_off); analogWrite (disp001dim, яркость); // на дисплее analogWrite (disp010dim, яркость); analogWrite (disp100dim, яркость);} // setup () void loop () {// GPS NMEA ------------------ if (stringComplete ==true) {// получено nmea предложение через последовательный порт RX ret =nmeaExtractData (); inputString =""; stringComplete =false; если (ret ==true) {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_truecourse- (tCent * 100) - (tDeci * 10); tUnit =n; отображать(); }} if (millis ()> (lastmemcheck + memcheck)) {// помещаем в память значение яркости (если изменено) EEPROM.update (addr, яркость); lastmemcheck =millis (); } checkButtons ();} void display () {if (isKMH ==true) {// скорость в км / ч (isKMH =true) analogWrite (degLED, off); setBusNr (kUnit); digitalWrite (disp001, latch_on); задержка (dly); digitalWrite (disp001, latch_off); if (kDeci> 0 || kCent> 0) {// снимаем десятки, если десятки =0 (а также undreds =0) setBusNr (kDeci); digitalWrite (disp010, latch_on); задержка (dly); digitalWrite (disp010, latch_off); analogWrite (disp010dim, яркость); } else {analogWrite (disp010dim, выкл); } if (kCent> 0) {// отключаем красный цвет if =0 setBusNr (kCent); digitalWrite (disp100, latch_on); задержка (dly); digitalWrite (disp100, latch_off); analogWrite (disp100dim, яркость); } else {analogWrite (disp100dim, выкл); }} else {// истинный пеленг в градусах (isKMH =false) analogWrite (градусовLED, яркость); setBusNr (tUnit); digitalWrite (disp001, latch_on); задержка (dly); digitalWrite (disp001, latch_off); if (tDeci> 0 || tCent> 0) {// снимаем десятки, если десятки =0 (а также undreds =0) setBusNr (tDeci); digitalWrite (disp010, latch_on); задержка (dly); digitalWrite (disp010, latch_off); analogWrite (disp010dim, яркость); } else {analogWrite (disp010dim, выкл); } if (tCent> 0) {// отключаем красный цвет if =0 setBusNr (tCent); digitalWrite (disp100, latch_on); задержка (dly); digitalWrite (disp100, latch_off); analogWrite (disp100dim, яркость); } else {analogWrite (disp100dim, выкл); }}} // display () void checkButtons () {if (digitalRead (button_kt) ==LOW) {if (isKMH ==true) {isKMH =false; } else {isKMH =истина; } задержка (250); } if (digitalRead (button_more) ==LOW) {if (яркость <=240) {яркость =яркость + 10; } analogWrite (disp001dim, яркость); analogWrite (disp010dim, яркость); analogWrite (disp100dim, яркость); задержка (100); } if (digitalRead (button_less) ==LOW) {if (яркость> =20) {яркость =яркость-10; } analogWrite (disp001dim, яркость); analogWrite (disp010dim, яркость); analogWrite (disp100dim, яркость); задержка (100); }} // checkButtons () void setBusNr (int number) {// устанавливает 4-битную шину для (byte b =0; b <=3; b ++) {if (numbers [number] [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 () // извлекаем данные из nmea inputStringbool nmeaExtractData () {int d =0; int s =0; int y =0; int z =0; float t =0; bool ret =false; // истина, если nmea предложение =$ GNRMC и действительный CHKSUM if ((inputString.substring (0,6) =="$ GNRMC") &&(inputString.substring (inputString.length () - 4, inputString.length () - 2) ==nmea0183_checksum (inputString))) {y =0; для (s =1; s <11; s ++) {y =inputString.indexOf (",", y); переключатель (ы) {case 1:// ----------------------- время 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; ломать; case 2:// ----------------------- валидность z =inputString.indexOf (",", y + 1); если (z> (y + 1)) {nm_validity =inputString.substring (y + 1, y + 1 + 1); } y =z; ломать; case 3:// ----------------------- широта 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; ломать; case 4:// ----------------------- север / юг z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_latitude =nm_latitude + inputString.substring (y + 1, y + 1 + 1); } y =z; ломать; case 5:// ----------------------- долгота 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; ломать; case 6:// ----------------------- восток / запад z =inputString.indexOf (",", y + 1); if (z> (y + 1)) {nm_longitude =nm_longitude + inputString.substring (y + 1, y + 1 + 1); } y =z; ломать; case 7:// ----------------------- узлы скорости z =inputString.indexOf (",", y + 1); если (z> (y + 1)) {nmf_knots =inputString.substring (y + 1, z) .toFloat (); t =roundOneDec (nmf_knots); nm_knots =Строка (t, 1) + «kn»; nmf_kmh =roundTwoDec (nmf_knots * 1,852); nmi_kmh =roundZeroDec (nmf_knots * 1,852); } y =z; ломать; case 8:// ----------------------- true course z =inputString.indexOf (",", y + 1); если (z> (y + 1)) {nmf_truecourse =inputString.substring (y + 1, z) .toFloat (); t =roundZeroDec (nmf_truecourse); nmi_truecourse =t; d =t; nm_truecourse =d; } y =z; ломать; case 9:// ----------------------- дата 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; ломать; case 10:// заявления n.u. ломать; default:// операторы n.u. ломать; }} ret =true; } return ret;} // nmeaExtractData () / * SerialEvent возникает всякий раз, когда в аппаратный последовательный RX поступают новые данные. Эта процедура запускается между каждым запуском loop (), поэтому использование задержки внутри цикла может задержать ответ. Может быть доступно несколько байтов данных. * / Void serialEvent () {while (Serial.available ()) {char inChar =(char) Serial.read (); inputString + =inChar; // если входящий символ является новой строкой, установите флаг, чтобы // основной цикл мог что-то с этим сделать if (inChar =='\ n') {stringComplete =true; }}} // serialEvent () // вычисляем контрольную сумму nmea schemeString nmea0183_checksum (String nmea_data) {int crc =0; Строка chSumString =""; int i; // игнорируем первый знак $, контрольную сумму в предложении for (i =1; i <(nmea_data.length () - 5); i ++) {// удаляем - 5, если нет "*" + cksum + cr + lf присутствует crc ^ =nmea_data [i]; } chSumString =String (crc, HEX); если (chSumString.length () ==1) {chSumString ="0" + chSumString.substring (0,1); } chSumString.toUpperCase (); return chSumString;} // nmea0183_checksum (String nmea_data) // округление нуля десятичных дробейfloat roundZeroDec (float f) {float y, d; у =f * 1; d =y - (int) y; у =(число с плавающей запятой) (число) (е * 1) / 1; если (d> =0,5) {y + =1; } else {если (d <-0,5) {y - =1; }} return y;} // округление до одного десятичного числа с плавающей запятой roundOneDec (float f) {float y, d; у =f * 10; d =y - (int) y; y =(число с плавающей запятой) (число) (f * 10) / 10; если (d> =0,5) {y + =0,1; } else {если (d <-0,5) {y - =0,1; }} return y;} // округляем два десятичных знака float roundTwoDec (float f) {float y, d; у =f * 100; d =y - (int) y; у =(число с плавающей запятой) (число) (е * 100) / 100; если (d> =0,5) {y + =0,01; } else {если (d <-0,5) {y - =0,01; }} return y;} 

Схема

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

Производственный процесс

  1. Разрушение полуавтономного автомобиля для водителей-инвалидов
  2. ИИ для автономного вождения для сборщика мусора в машинах-ослах
  3. Планирование движения в реальном времени для автономного автомобиля в различных ситуациях , в смоделированн…
  4. Что 5G может предоставить подключенному автомобилю?
  5. Безопасность:главный приоритет для автомобилей будущего
  6. Кабели двигателя для приводов с регулируемой скоростью
  7. Усовершенствованные токарные станки для полировки и удаления заусенцев
  8. Токарный станок, созданный для точности и скорости
  9. Обмен данными о продуктах:проблема производителей автомобилей
  10. Как выбрать турбокомпрессор для своего автомобиля?