基于esp32 Arduino自制蓝牙HUD显示

物料

1. Esp32开发板(带蓝牙)--19元

2. 1.6寸 130*130 半反半透屏 SPI接口(强烈建议半反半透屏,整体效果均衡,阳光下效果也不错)   ---- 15元, 现在涨到20+了

3. 万能 PCB板,排针,排针座(如果屏幕直插,注意排针和排针座高度,或者直接用排线),蜂鸣器(可选) ---算10元吧

4. 蓝牙OBD(建议选拔掉壳后,薄薄的哪种,不影响把盖子盖回去)  ---10十~40元,基本最便宜的都能满足需求

连线也极其简单,就是屏幕,另外有一个按键,这个按键完全可以不要

/*******************************************************************************
   Start of Arduino_GFX setting

   Arduino_GFX try to find the settings depends on selected board in Arduino IDE
   Or you can define the display dev kit not in the board list
   Defalult pin list for non display dev kit:
   Arduino Nano, Micro and more: TFT_CS:  9, TFT_DC:  8, TFT_RST:  7, TFT_BL:  6
   ESP32 various dev board     : TFT_CS:  5, TFT_DC: 27, TFT_RST: 33, TFT_BL: 22
   ESP8266 various dev board   : TFT_CS: 15, TFT_DC:  4, TFT_RST:  2, TFT_BL:  5
   Raspberry Pi Pico dev board : TFT_CS: 17, TFT_DC: 27, TFT_RST: 26, TFT_BL: 28
   RTL872x various dev board   : TFT_CS: 18, TFT_DC: 17, TFT_RST:  2, TFT_BL: 23
   Seeeduino XIAO dev board    : TFT_CS:  3, TFT_DC:  2, TFT_RST:  1, TFT_BL:  0
   Teensy 4.1 dev board        : TFT_CS: 39, TFT_DC: 41, TFT_RST: 40, TFT_BL: 22
 ******************************************************************************/
#include <Arduino_GFX_Library.h>
#include "FreeMonoBold14pt7b.h"
#include "FreeMonoBold36pt7b.h"

#include "BluetoothSerial.h"
#include "ELMduino.h"
#include "time.h"
#include "esp_system.h"

uint8_t address[6]  = {0x34, 0x90, 0x1b, 0x20, 0xa6, 0x92};
String name = "OBDII";
BluetoothSerial SerialBT;
#define ELM_PORT SerialBT
#define DEBUG_PORT Serial
#define MAX_SPEED 512
#define INVALID_SPEED -1
#define BUTTON_PIN 32
#define BUZZER_VCC 18
#define BUZZER_GND 19

struct Button {
  const uint8_t PIN;
  uint32_t numberKeyPresses;
  unsigned long lastInterrupt;
  bool pressed;
};

Arduino_DataBus *bus = new Arduino_ESP32SPI(4 /* DC */, 15 /* CS */, 17 /* SCK */, 16 /* MOSI */, -1 /* MISO */, VSPI /* spi_num */);
Arduino_GFX *gfx = new Arduino_SSD1283A(bus, 2 /* RST */, 2 /* rotation */);
Button button1 = {BUTTON_PIN, 0, 0, false};
ELM327 myELM327;
int32_t oriSpeed = 0;
int32_t fixSpeed = 0;
int32_t lastOriSpeed = 0;

unsigned long bootTime = 0 ;
unsigned long runTime = 0;
bool isBuzzerEnable = true;
bool lastStatusOk = false;

void buzzerOn() {
  digitalWrite(BUZZER_VCC, HIGH);
}

void buzzerOff() {
  digitalWrite(BUZZER_VCC, LOW);
}

void buzzerTime(uint8_t t) {
  if (!isBuzzerEnable) {
    return;
  }
  for (uint8_t i = 0 ; i < t; i++) {
    buzzerOn();
    delay(200 + i * 30);
    buzzerOff();
    delay(50 + i * 10);
  }
}

//void measure(char *s, int16_t x, int16_t y) {
//
//  int16_t x1, y1;
//  uint16_t w, h;
//  gfx->getTextBounds(s, x, y, &x1, &y1, &w, &h);
//  //  gfx->fillRect(x1, y1, w, h, BLACK);
//  Serial.printf("x1 = %d , y1 = %d, w = %d, h = %d\n", x1, y1, w, h);
//}

void initBuzzer() {
  pinMode(BUZZER_VCC, OUTPUT);  // Buzzer VCC
  pinMode(BUZZER_GND, OUTPUT);  // Buzzer GND
  digitalWrite(BUZZER_VCC, HIGH);
  digitalWrite(BUZZER_GND, LOW);
  delay(50);
  digitalWrite(BUZZER_VCC, LOW);
}

void initTFT() {
  gfx->begin();
  gfx->fillScreen(BLACK);
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);
  gfx->setFont(&FreeMonoBold14pt7b);
  gfx->fillScreen(BLACK);
}


void showRuntime() {
  uint16_t x = 1;
  uint16_t y = 20;

  gfx->setTextColor(YELLOW, BLACK);
  gfx->setCursor(x, y);
  gfx->setFont(&FreeMonoBold14pt7b);

  uint8_t h = runTime / 3600;
  uint8_t m = runTime / 60 % 60;
  uint8_t s = runTime % 60;
  gfx->printf("%02d:%02d:%02d", h, m, s);

}

void showFixSpeed(int32_t speed) {
  uint16_t x = 0;
  uint16_t y = 80;
  gfx->setTextColor(WHITE, BLACK);
  gfx->setCursor(x, y);
  gfx->setFont(&FreeMonoBold36pt7b);
  gfx->printf("%3d", speed);
}


void showOriSpeed(int32_t speed) {
  uint16_t x = 0;
  uint16_t y = 120;
  gfx->setFont(&FreeMonoBold14pt7b);
  gfx->setTextColor(GREEN, BLACK);
  gfx->setCursor(1, 120);
  gfx->printf("%3d", speed);
  gfx->setTextColor(PINK, BLACK);
  gfx->setCursor(60, 120);
  gfx->printf("km/h");
}

void initOBD() {
  int8_t retryCount = 0;
  gfx->setFont(&FreeMonoBold14pt7b);
  gfx->setCursor(0, 60);
  gfx->println("initOBD");

  DEBUG_PORT.begin(115200);
  //  SerialBT.setPin("1234");
  ELM_PORT.begin("ArduHUD", true);

  while (!ELM_PORT.connect(address)) {
    //  while (!ELM_PORT.connect("MI9")) {
    DEBUG_PORT.println("Couldn't connect to OBD scanner - 1");
    gfx->fillScreen(BLACK);
    gfx->setCursor(0, 60);
    gfx->printf("Connect\n   %d", ++retryCount);
    if (retryCount > 5) {
      gfx->fillScreen(BLACK);
      gfx->setCursor(0, 60);
      gfx->println("Restart");
      delay(2000);
      esp_restart();
    }
  }

  if (!myELM327.begin(ELM_PORT, true, 2000)) {
    DEBUG_PORT.println("Couldn't connect to OBD scanner - 2");
    gfx->fillScreen(BLACK);
    gfx->setCursor(0, 60);
    gfx->println("No connection");
  }

  DEBUG_PORT.println("Connected to ELM327");
}


void printSpeed() {
  static uint8_t noDataCount = 0;
  oriSpeed = myELM327.kph();
  if (myELM327.status != ELM_SUCCESS) {
    noDataCount++;
    if (noDataCount >= 3) {
      myELM327.printError();
      gfx->fillScreen(BLACK);
      gfx->setCursor(0, 60);
      gfx->println("no data");
      lastStatusOk = false;
    }
  } else {
    if (oriSpeed > MAX_SPEED) {
      oriSpeed = INVALID_SPEED;
    }
    fixSpeed = (int)(oriSpeed * 1.05 );
    if (!lastStatusOk) {
      gfx->fillScreen(BLACK);
    }
    showFixSpeed(fixSpeed);
    showOriSpeed(oriSpeed);
    lastStatusOk  = true;
    DEBUG_PORT.printf("oriSpeed = %d , lastOriSpeed = %d\n", oriSpeed, lastOriSpeed);
    if (oriSpeed > 120 && lastOriSpeed <= 120) {
      buzzerTime(3);
    } else if ( oriSpeed > 100 && lastOriSpeed <= 100) {
      buzzerTime(2);
    } else if (oriSpeed > 80 && lastOriSpeed <= 80) {
      buzzerTime(1);
    }
    lastOriSpeed = oriSpeed;
    noDataCount = 0;
  }
}

void IRAM_ATTR isr() {
  unsigned long curT = millis();
  DEBUG_PORT.printf("isr, time : %d, lastTime : %d \n", curT, button1.lastInterrupt);
  if (curT - button1.lastInterrupt < 10) {
    DEBUG_PORT.printf("skip isr, time : %d \n", curT - button1.lastInterrupt);
    return;
  }
  button1.lastInterrupt = curT;
  button1.numberKeyPresses += 1;
  isBuzzerEnable = !isBuzzerEnable;
  button1.pressed = true;
}

void setup(void)
{
  Serial.begin(115200);
  bootTime = millis();
  initBuzzer();
  initTFT();
  initOBD();
  // init Button
  pinMode(button1.PIN, INPUT_PULLUP);
  attachInterrupt(button1.PIN, isr, RISING);
  //  attachInterrupt(button1.PIN, isr, FALLING);
}


void loop()
{
  static long lastRefresh = 0;
  if (millis() - lastRefresh > 500) {
    lastRefresh = millis();
    runTime =  (millis() - bootTime) / 1000;
    showRuntime();
    printSpeed();
  }
  if (button1.pressed) {
    button1.pressed = false;
    gfx->fillScreen(BLACK);
    gfx->setCursor(0, 60);
    gfx->println(isBuzzerEnable ? "Enable Buzzer" : "Disable Buzzer");
    delay(1000);
  }
}

 

 

版权声明:本文为CSDN博主「yongwn」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yongwn/article/details/121673302

物料

1. Esp32开发板(带蓝牙)--19元

2. 1.6寸 130*130 半反半透屏 SPI接口(强烈建议半反半透屏,整体效果均衡,阳光下效果也不错)   ---- 15元, 现在涨到20+了

3. 万能 PCB板,排针,排针座(如果屏幕直插,注意排针和排针座高度,或者直接用排线),蜂鸣器(可选) ---算10元吧

4. 蓝牙OBD(建议选拔掉壳后,薄薄的哪种,不影响把盖子盖回去)  ---10十~40元,基本最便宜的都能满足需求

连线也极其简单,就是屏幕,另外有一个按键,这个按键完全可以不要

/*******************************************************************************
   Start of Arduino_GFX setting

   Arduino_GFX try to find the settings depends on selected board in Arduino IDE
   Or you can define the display dev kit not in the board list
   Defalult pin list for non display dev kit:
   Arduino Nano, Micro and more: TFT_CS:  9, TFT_DC:  8, TFT_RST:  7, TFT_BL:  6
   ESP32 various dev board     : TFT_CS:  5, TFT_DC: 27, TFT_RST: 33, TFT_BL: 22
   ESP8266 various dev board   : TFT_CS: 15, TFT_DC:  4, TFT_RST:  2, TFT_BL:  5
   Raspberry Pi Pico dev board : TFT_CS: 17, TFT_DC: 27, TFT_RST: 26, TFT_BL: 28
   RTL872x various dev board   : TFT_CS: 18, TFT_DC: 17, TFT_RST:  2, TFT_BL: 23
   Seeeduino XIAO dev board    : TFT_CS:  3, TFT_DC:  2, TFT_RST:  1, TFT_BL:  0
   Teensy 4.1 dev board        : TFT_CS: 39, TFT_DC: 41, TFT_RST: 40, TFT_BL: 22
 ******************************************************************************/
#include <Arduino_GFX_Library.h>
#include "FreeMonoBold14pt7b.h"
#include "FreeMonoBold36pt7b.h"

#include "BluetoothSerial.h"
#include "ELMduino.h"
#include "time.h"
#include "esp_system.h"

uint8_t address[6]  = {0x34, 0x90, 0x1b, 0x20, 0xa6, 0x92};
String name = "OBDII";
BluetoothSerial SerialBT;
#define ELM_PORT SerialBT
#define DEBUG_PORT Serial
#define MAX_SPEED 512
#define INVALID_SPEED -1
#define BUTTON_PIN 32
#define BUZZER_VCC 18
#define BUZZER_GND 19

struct Button {
  const uint8_t PIN;
  uint32_t numberKeyPresses;
  unsigned long lastInterrupt;
  bool pressed;
};

Arduino_DataBus *bus = new Arduino_ESP32SPI(4 /* DC */, 15 /* CS */, 17 /* SCK */, 16 /* MOSI */, -1 /* MISO */, VSPI /* spi_num */);
Arduino_GFX *gfx = new Arduino_SSD1283A(bus, 2 /* RST */, 2 /* rotation */);
Button button1 = {BUTTON_PIN, 0, 0, false};
ELM327 myELM327;
int32_t oriSpeed = 0;
int32_t fixSpeed = 0;
int32_t lastOriSpeed = 0;

unsigned long bootTime = 0 ;
unsigned long runTime = 0;
bool isBuzzerEnable = true;
bool lastStatusOk = false;

void buzzerOn() {
  digitalWrite(BUZZER_VCC, HIGH);
}

void buzzerOff() {
  digitalWrite(BUZZER_VCC, LOW);
}

void buzzerTime(uint8_t t) {
  if (!isBuzzerEnable) {
    return;
  }
  for (uint8_t i = 0 ; i < t; i++) {
    buzzerOn();
    delay(200 + i * 30);
    buzzerOff();
    delay(50 + i * 10);
  }
}

//void measure(char *s, int16_t x, int16_t y) {
//
//  int16_t x1, y1;
//  uint16_t w, h;
//  gfx->getTextBounds(s, x, y, &x1, &y1, &w, &h);
//  //  gfx->fillRect(x1, y1, w, h, BLACK);
//  Serial.printf("x1 = %d , y1 = %d, w = %d, h = %d\n", x1, y1, w, h);
//}

void initBuzzer() {
  pinMode(BUZZER_VCC, OUTPUT);  // Buzzer VCC
  pinMode(BUZZER_GND, OUTPUT);  // Buzzer GND
  digitalWrite(BUZZER_VCC, HIGH);
  digitalWrite(BUZZER_GND, LOW);
  delay(50);
  digitalWrite(BUZZER_VCC, LOW);
}

void initTFT() {
  gfx->begin();
  gfx->fillScreen(BLACK);
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);
  gfx->setFont(&FreeMonoBold14pt7b);
  gfx->fillScreen(BLACK);
}


void showRuntime() {
  uint16_t x = 1;
  uint16_t y = 20;

  gfx->setTextColor(YELLOW, BLACK);
  gfx->setCursor(x, y);
  gfx->setFont(&FreeMonoBold14pt7b);

  uint8_t h = runTime / 3600;
  uint8_t m = runTime / 60 % 60;
  uint8_t s = runTime % 60;
  gfx->printf("%02d:%02d:%02d", h, m, s);

}

void showFixSpeed(int32_t speed) {
  uint16_t x = 0;
  uint16_t y = 80;
  gfx->setTextColor(WHITE, BLACK);
  gfx->setCursor(x, y);
  gfx->setFont(&FreeMonoBold36pt7b);
  gfx->printf("%3d", speed);
}


void showOriSpeed(int32_t speed) {
  uint16_t x = 0;
  uint16_t y = 120;
  gfx->setFont(&FreeMonoBold14pt7b);
  gfx->setTextColor(GREEN, BLACK);
  gfx->setCursor(1, 120);
  gfx->printf("%3d", speed);
  gfx->setTextColor(PINK, BLACK);
  gfx->setCursor(60, 120);
  gfx->printf("km/h");
}

void initOBD() {
  int8_t retryCount = 0;
  gfx->setFont(&FreeMonoBold14pt7b);
  gfx->setCursor(0, 60);
  gfx->println("initOBD");

  DEBUG_PORT.begin(115200);
  //  SerialBT.setPin("1234");
  ELM_PORT.begin("ArduHUD", true);

  while (!ELM_PORT.connect(address)) {
    //  while (!ELM_PORT.connect("MI9")) {
    DEBUG_PORT.println("Couldn't connect to OBD scanner - 1");
    gfx->fillScreen(BLACK);
    gfx->setCursor(0, 60);
    gfx->printf("Connect\n   %d", ++retryCount);
    if (retryCount > 5) {
      gfx->fillScreen(BLACK);
      gfx->setCursor(0, 60);
      gfx->println("Restart");
      delay(2000);
      esp_restart();
    }
  }

  if (!myELM327.begin(ELM_PORT, true, 2000)) {
    DEBUG_PORT.println("Couldn't connect to OBD scanner - 2");
    gfx->fillScreen(BLACK);
    gfx->setCursor(0, 60);
    gfx->println("No connection");
  }

  DEBUG_PORT.println("Connected to ELM327");
}


void printSpeed() {
  static uint8_t noDataCount = 0;
  oriSpeed = myELM327.kph();
  if (myELM327.status != ELM_SUCCESS) {
    noDataCount++;
    if (noDataCount >= 3) {
      myELM327.printError();
      gfx->fillScreen(BLACK);
      gfx->setCursor(0, 60);
      gfx->println("no data");
      lastStatusOk = false;
    }
  } else {
    if (oriSpeed > MAX_SPEED) {
      oriSpeed = INVALID_SPEED;
    }
    fixSpeed = (int)(oriSpeed * 1.05 );
    if (!lastStatusOk) {
      gfx->fillScreen(BLACK);
    }
    showFixSpeed(fixSpeed);
    showOriSpeed(oriSpeed);
    lastStatusOk  = true;
    DEBUG_PORT.printf("oriSpeed = %d , lastOriSpeed = %d\n", oriSpeed, lastOriSpeed);
    if (oriSpeed > 120 && lastOriSpeed <= 120) {
      buzzerTime(3);
    } else if ( oriSpeed > 100 && lastOriSpeed <= 100) {
      buzzerTime(2);
    } else if (oriSpeed > 80 && lastOriSpeed <= 80) {
      buzzerTime(1);
    }
    lastOriSpeed = oriSpeed;
    noDataCount = 0;
  }
}

void IRAM_ATTR isr() {
  unsigned long curT = millis();
  DEBUG_PORT.printf("isr, time : %d, lastTime : %d \n", curT, button1.lastInterrupt);
  if (curT - button1.lastInterrupt < 10) {
    DEBUG_PORT.printf("skip isr, time : %d \n", curT - button1.lastInterrupt);
    return;
  }
  button1.lastInterrupt = curT;
  button1.numberKeyPresses += 1;
  isBuzzerEnable = !isBuzzerEnable;
  button1.pressed = true;
}

void setup(void)
{
  Serial.begin(115200);
  bootTime = millis();
  initBuzzer();
  initTFT();
  initOBD();
  // init Button
  pinMode(button1.PIN, INPUT_PULLUP);
  attachInterrupt(button1.PIN, isr, RISING);
  //  attachInterrupt(button1.PIN, isr, FALLING);
}


void loop()
{
  static long lastRefresh = 0;
  if (millis() - lastRefresh > 500) {
    lastRefresh = millis();
    runTime =  (millis() - bootTime) / 1000;
    showRuntime();
    printSpeed();
  }
  if (button1.pressed) {
    button1.pressed = false;
    gfx->fillScreen(BLACK);
    gfx->setCursor(0, 60);
    gfx->println(isBuzzerEnable ? "Enable Buzzer" : "Disable Buzzer");
    delay(1000);
  }
}

 

 

版权声明:本文为CSDN博主「yongwn」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yongwn/article/details/121673302

生成海报
点赞 0

yongwn

我还没有学会写个人说明!

暂无评论

相关推荐

基于esp32 Arduino自制蓝牙HUD显示

物料 1. Esp32开发板(带蓝牙)--19元 2. 1.6寸 130*130 半反半透屏 SPI接口(强烈建议半反半透屏,整体效果均衡,阳光下效果也不错&#xff09

arduino与激光雷达?

先上图片: 一般来说,这样子的激光雷达都是与电脑或者树莓派等等配合使用的,但是暂时没有时间去捣鼓slam算法相关的东西,那有没有方法把它应用在其他简单的项目中呢? 。。。。我

STM32+HC-05蓝牙模块学习与使用

HC-05蓝牙串口通信 HC05模块是一款高性能主从一体蓝牙串口模块,是一种集成蓝牙功能的PCBA板,用于短距离无线通信,十分方便。 从某宝商家那里可以看到,蓝牙可以使用多种方法使用&