ESP32 오토바이 헬멧 HUD 펌웨어 프롬프트
Wikiprompt, 무료 프롬프트 백과사전에서
ESP32 오토바이 헬멧 HUD 펌웨어 프롬프트 ESP32 모터사이클 헬멧 헤드업 디스플레이용 펌웨어 생성 프롬프트 - BLE 연결, 내비게이션, 알림 및 디스플레이 요구사항 포함.
프롬프트 내용저장
🌐
ESP32 펌웨어 - TTGO T-Display 기반 오토바이 헬멧 HUD
```cpp
/*
* TTGO T-Display 오토바이 헬멧 HUD 펌웨어
* BLE를 통해 스마트폰에서 데이터 수신 및 표시
*
* 하드웨어: TTGO T-Display (ESP32 + ST7789 240x135 TFT)
*
* BLE 메시지 형식 (JSON, UTF-8):
* {
* "type": "speed" | "nav" | "alert" | "battery",
* "value": <숫자 또는 문자열>,
* "sub": <선택적 보조 데이터>
* }
*
* 예시:
* {"type":"speed","value":85}
* {"type":"nav","value":"left","sub":"300m"}
* {"type":"alert","value":"police"}
* {"type":"battery","value":75}
*/
#include <TFT_eSPI.h>
#include <SPI.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <ArduinoJson.h>
// 디스플레이 설정
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite sprite = TFT_eSprite(&tft);
// BLE 설정
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
// 화면 크기 (TTGO T-Display)
#define SCREEN_W 240
#define SCREEN_H 135
// 레이아웃 설정 (조정 가능)
#define SPEED_X 120
#define SPEED_Y 60
#define SPEED_SIZE 6
#define NAV_X 120
#define NAV_Y 100
#define NAV_SIZE 4
#define ALERT_X 120
#define ALERT_Y 30
#define ALERT_SIZE 3
#define BATTERY_X 220
#define BATTERY_Y 10
#define BATTERY_SIZE 1
// 상태 변수
int currentSpeed = 0;
String navDirection = "";
String navDistance = "";
String alertMessage = "";
int hudBattery = 100;
unsigned long lastAlertTime = 0;
const unsigned long ALERT_DURATION = 5000; // 알림 표시 시간 (5초)
// BLE 콜백 클래스
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String value = pCharacteristic->getValue();
if (value.length() > 0) {
processBLEMessage(value);
}
}
};
void setup() {
Serial.begin(115200);
// 디스플레이 초기화
tft.init();
tft.setRotation(1); // 가로 방향
tft.fillScreen(TFT_BLACK);
// 스프라이트 초기화 (더 빠른 렌더링)
sprite.createSprite(SCREEN_W, SCREEN_H);
sprite.setSwapBytes(true);
// BLE 초기화
BLEDevice::init("HelmetHUD");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->addDescriptor(new BLE2902());
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
Serial.println("HUD 준비 완료");
}
void loop() {
// 알림 만료 처리
if (alertMessage.length() > 0 && millis() - lastAlertTime > ALERT_DURATION) {
alertMessage = "";
}
// 화면 업데이트
updateDisplay();
delay(50); // 20 FPS
}
void processBLEMessage(String message) {
Serial.println("수신: " + message);
DynamicJsonDocument doc(256);
DeserializationError error = deserializeJson(doc, message);
if (error) {
Serial.println("JSON 파싱 오류");
return;
}
String type = doc["type"] | "";
if (type == "speed") {
currentSpeed = doc["value"] | 0;
} else if (type == "nav") {
navDirection = doc["value"] | "";
navDistance = doc["sub"] | "";
} else if (type == "alert") {
alertMessage = doc["value"] | "";
lastAlertTime = millis();
} else if (type == "battery") {
hudBattery = doc["value"] | 100;
}
}
void updateDisplay() {
// 검은 배경으로 지우기 (반사 최소화)
sprite.fillSprite(TFT_BLACK);
// 속도 표시 (큰 숫자)
sprite.setTextDatum(MC_DATUM);
sprite.setTextColor(TFT_WHITE, TFT_BLACK);
sprite.setTextSize(SPEED_SIZE);
sprite.drawString(String(currentSpeed), SPEED_X, SPEED_Y, 7); // 7 = 큰 폰트
// 속도 단위
sprite.setTextSize(2);
sprite.drawString("km/h", SPEED_X, SPEED_Y + 40, 4);
// 내비게이션 화살표
if (navDirection.length() > 0) {
drawNavArrow(navDirection, NAV_X, NAV_Y);
if (navDistance.length() > 0) {
sprite.setTextSize(2);
sprite.drawString(navDistance, NAV_X, NAV_Y + 30, 4);
}
}
// 알림 배너
if (alertMessage.length() > 0) {
drawAlertBanner(alertMessage);
}
// 배터리 표시
drawBatteryIndicator(hudBattery);
// 스프라이트를 화면에 출력
sprite.pushSprite(0, 0);
}
void drawNavArrow(String direction, int x, int y) {
sprite.setTextColor(TFT_GREEN, TFT_BLACK);
sprite.setTextSize(NAV_SIZE);
if (direction == "left") {
sprite.drawString("<<<", x, y, 7);
} else if (direction == "right") {
sprite.drawString(">>>", x, y, 7);
} else if (direction == "straight") {
sprite.drawString("^^^", x, y, 7);
} else if (direction == "left_soon") {
sprite.drawString("<", x, y, 7);
} else if (direction == "right_soon") {
sprite.drawString(">", x, y, 7);
} else if (direction == "arrive") {
sprite.drawString("OK", x, y, 7);
}
}
void drawAlertBanner(String alert) {
// 알림 색상 설정
uint16_t color;
if (alert == "police") {
color = TFT_RED;
} else if (alert == "crash") {
color = TFT_ORANGE;
} else if (alert == "hazard") {
color = TFT_YELLOW;
} else {
color = TFT_WHITE;
}
// 배너 배경 (반투명 효과를 위한 어두운 회색)
sprite.fillRect(0, 0, SCREEN_W, 30, 0x4208); // 어두운 회색
// 알림 텍스트
sprite.setTextColor(color, 0x4208);
sprite.setTextSize(ALERT_SIZE);
sprite.drawString(alert, ALERT_X, ALERT_Y, 4);
}
void drawBatteryIndicator(int percentage) {
// 배터리 프레임
sprite.drawRect(BATTERY_X - 20, BATTERY_Y - 8, 40, 16, TFT_WHITE);
sprite.fillRect(BATTERY_X + 20, BATTERY_Y - 4, 4, 8, TFT_WHITE);
// 배터리 충전량
int fillWidth = map(percentage, 0, 100, 0, 36);
uint16_t batteryColor;
if (percentage > 50) {
batteryColor = TFT_GREEN;
} else if (percentage > 20) {
batteryColor = TFT_YELLOW;
} else {
batteryColor = TFT_RED;
}
sprite.fillRect(BATTERY_X - 18, BATTERY_Y - 6, fillWidth, 12, batteryColor);
// 배터리 퍼센트 텍스트
sprite.setTextColor(TFT_WHITE, TFT_BLACK);
sprite.setTextSize(BATTERY_SIZE);
sprite.drawString(String(percentage) + "%", BATTERY_X - 20, BATTERY_Y + 12, 2);
}
```
---
**스마트폰 측 BLE 메시지 형식**
스마트폰 앱은 다음 JSON 형식으로 BLE 특성(`beb5483e-36e1-4688-b7f5-ea07361b26a8`)에 데이터를 씁니다:
| 메시지 유형 | 형식 | 설명 |
|------------|------|------|
| 속도 | `{"type":"speed","value":85}` | 현재 속도 (km/h) |
| 내비게이션 | `{"type":"nav","value":"left","sub":"300m"}` | 방향: `left`, `right`, `straight`, `left_soon`, `right_soon`, `arrive` |
| 알림 | `{"type":"alert","value":"police"}` | `police`, `crash`, `hazard` |
| 배터리 | `{"type":"battery","value":75}` | HUD 배터리 잔량 (0-100) |
**참고 사항:**
- 화면은 가로로 미러링되어 반사 렌즈에서 정상적으로 보입니다 (코드에서 `tft.setRotation(1)` 및 스프라이트 사용으로 구현).
- 검은 배경은 반사를 최소화하고 밝은 텍스트만 보이게 합니다.
- 레이아웃 좌표는 상단 `#define` 섹션에서 조정 가능합니다.
- 폰트 크기와 위치는 주석을 참고하여 개인 취향에 맞게 튜닝하세요.
전체 프롬프트를 보려면 로그인하세요
Continue with:
By logging in, you agree to our Terms of Use and Privacy Policy
사용법
이 프롬프트는 coding와 함께 사용하도록 설계되었습니다. 위의 프롬프트 내용을 복사하여 원하는 AI 도구에 붙여넣으세요.
최상의 결과를 얻으려면 자리 표시자(대괄호 또는 대문자로 표시)를 특정 요구 사항으로 사용자 지정할 수 있습니다.
토론
댓글 0개