[2024 DigiKey Innovation Contest] Smart Cycling Helmet Based on ESP32 S3
[Copy link]
This post was last edited by reayfei on 2024-11-6 20:13
1. Project Overview
This project aims to design a smart helmet that integrates multiple functions to meet the needs of riders in terms of navigation, safety tips, etc. The smart helmet uses ESP32 as the main control chip, equipped with OLED display, MPU6050 sensor, RGB light bar and other modules, and realizes functions such as real-time display of mobile phone navigation information, steering and braking prompts, etc.
2. Main components and functions
- ESP32 main control chip
- Responsible for processing all sensor data, controlling the display screen and RGB light strip.
- Supports Bluetooth and Wi-Fi communications, and can connect to mobile phones for data transmission.
- OLED display
- Display mobile phone navigation information, including route, direction, distance, etc.
- High resolution and clear display make it easy for riders to view.
- MPU6050 Sensor
- It integrates a 3-axis gyroscope and a 3-axis acceleration sensor to measure the posture and movement status of the helmet.
- Through data processing, posture perception can be achieved to provide auxiliary information for navigation and brake reminders.
- RGB Light Strip
- Displays safety tips such as left turn, right turn, double flash indicators, brake reminders, etc.
- Bright colors make it easy to be recognized by other road users.
3. Hardware connection and configuration
- Connecting ESP32 to OLED display
- Use the I2C interface to connect ESP32 and OLED display to save pin resources.
- Initialize the OLED display and set the display area and font size.
- ESP32 and MPU6050 connection
- Use the I2C interface to connect ESP32 and MPU6050 and configure the accelerometer and gyroscope range of MPU6050.
- Initialize the MPU6050, set the sampling rate and digital low-pass filter.
- ESP32 connected with RGB light strip
- Use GPIO pins to control the brightness and color of the RGB light strip.
- Write a control function to change the state of the RGB light bar according to the rider's operation or the data from the MPU6050.
4. Software Design and Function Implementation
- Navigation information display
- Connect your phone to ESP32 via Bluetooth or Wi-Fi to receive navigation information.
- Navigation information including route, direction, distance, etc. is displayed in real time on the OLED display.
- Posture perception and brake reminder
- The data from MPU6050 is used to determine the posture and motion status of the helmet.
- When sudden braking is detected, a brake reminder is issued through the RGB light bar.
- Turning Tips
- By obtaining navigation information, left turn and right turn instructions are realized.
- Double flash indication is achieved by utilizing instantaneous acceleration changes.
- Control the RGB light bar to display corresponding turn prompts.
- Night driving lights
- By emitting high-brightness RGB lights, smart helmets can significantly improve riders' visibility at night or in low-light conditions, reducing the risk of traffic accidents.
- Multiple lighting modes and intelligent control functions allow riders to adjust the lighting effects according to different environments and needs, thereby better protecting the safety of themselves and others.
- RGB night running lights not only have practical functions, but also can bring cooler visual effects and personalized riding experience to riders.
- System initialization and configuration
- In the ESP32 code, all hardware modules are initialized and configured.
- Set up interrupts and timers for real-time detection and processing of sensor data.
5. Debugging and Optimization
- Hardware Debugging
- Check that all hardware connections are correct and make sure the sensors and display are functioning properly.
- Use an oscilloscope or logic analyzer to detect the I2C communication signals.
- Software Debugging
- Write test code to verify whether the functions of each module are implemented.
- Use the serial port debugging assistant to view sensor data and system status in real time.
- Performance Optimization
- Optimize the code to improve the real-time performance and stability of the system.
- Adjust the brightness and flashing frequency of the RGB light strip to make it more eye-catching and energy-saving.
6. Video Demonstration
WeChat_20241105215557
VII. Conclusion
This design realizes a feature-rich smart helmet. Through the integration of ESP32, OLED display, MPU6050 sensor and RGB light bar, it realizes functions such as mobile phone navigation information display, posture perception, brake reminder, turn prompt, etc. This smart helmet not only improves the safety and convenience of riders, but also demonstrates the application potential of IoT technology in smart wearable devices.
8. Source Code
#define BLYNK_PRINT Serial
#define BLYNK_USE_DIRECT_CONNECT
#include <U8g2lib.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <MPU6050_tockn.h>
#include <BlynkSimpleEsp32_BLE.h>
#include <BLEDevice.h>
#include <BLEServer.h>
volatile int page;
volatile int item;
volatile byte flag;
volatile byte value;
volatile unsigned int alive_counter;
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 14, 13, U8X8_PIN_NONE);
Adafruit_NeoPixel rgb_display_47 = Adafruit_NeoPixel(12,47,NEO_GRB + NEO_KHZ800);
MPU6050 mpu6050(Wire);
char auth[] = "840807db99794545b20a76528f273c91";
int vpin_value;
int v5pin_value;
int v6pin_value;
int v7pin_value;
BlynkTimer timer;
void task_1( void * pvParameters ){
for(;;){
if (page == 1) {
u8g2.firstPage();
do
{
u8g2.setFontPosBottom();
u8g2.setFont(u8g2_font_open_iconic_all_4x_t);
u8g2.drawGlyph(16,15+4*8,76);
u8g2.setFont(u8g2_font_timR14_tf);
u8g2.setFontPosTop();
u8g2.setCursor(70,24);
u8g2.print(v5pin_value);
u8g2.setCursor(110,24);
u8g2.print("m");
}while(u8g2.nextPage());
}
if (page == 2) {
u8g2.firstPage();
do
{
u8g2.setFontPosBottom();
u8g2.setFont(u8g2_font_open_iconic_all_4x_t);
u8g2.drawGlyph(16,15+4*8,73);
u8g2.setFont(u8g2_font_timR14_tf);
u8g2.setFontPosTop();
u8g2.setCursor(70,24);
u8g2.print(v5pin_value);
u8g2.setCursor(110,24);
u8g2.print("m");
}while(u8g2.nextPage());
}
if (page == 3) {
u8g2.firstPage();
do
{
u8g2.setFontPosBottom();
u8g2.setFont(u8g2_font_open_iconic_all_4x_t);
u8g2.drawGlyph(16,15+4*8,74);
u8g2.setFont(u8g2_font_timR14_tf);
u8g2.setFontPosTop();
u8g2.setCursor(70,24);
u8g2.print(v6pin_value);
u8g2.setCursor(110,24);
u8g2.print("m");
}while(u8g2.nextPage());
}
if (page == 4) {
u8g2.firstPage();
do
{
u8g2.setFontPosBottom();
u8g2.setFont(u8g2_font_open_iconic_all_4x_t);
u8g2.drawGlyph(16,15+4*8,75);
u8g2.setFont(u8g2_font_timR14_tf);
u8g2.setFontPosTop();
u8g2.setCursor(70,24);
u8g2.print(v6pin_value);
u8g2.setCursor(110,24);
u8g2.print("m");
}while(u8g2.nextPage());
}
vTaskDelay(1);
}
}
void task_3( void * pvParameters ){
for(;;){
delay(1000);
vTaskDelay(1);
}
}
void task_4( void * pvParameters ){
for(;;){
if (item == 1 && v6pin_value <= 30) {
for (int i = 1; i <= 12; i = i + (1)) {
rgb_display_47.setPixelColor((i)-1, (((255 & 0xffffff) << 16) | ((255 & 0xffffff) << 8) | 0));
rgb_display_47.show();
delay(30);
}
for (int i = 1; i <= 12; i = i + (1)) {
rgb_display_47.setPixelColor((i)-1, (((0 & 0xffffff) << 16) | ((0 & 0xffffff) << 8) | 0));
rgb_display_47.show();
}
delay(300);
}
if (item == 2 && v6pin_value <= 30) {
for (int i = 12; i >= 1; i = i + (-1)) {
rgb_display_47.setPixelColor((i)-1, (((255 & 0xffffff) << 16) | ((255 & 0xffffff) << 8) | 0));
rgb_display_47.show();
delay(30);
}
for (int i = 1; i <= 12; i = i + (1)) {
rgb_display_47.setPixelColor((i)-1, (((0 & 0xffffff) << 16) | ((0 & 0xffffff) << 8) | 0));
rgb_display_47.show();
}
delay(300);
}
if (item == 3) {
for (int i = 1; i <= 12; i = i + (1)) {
rgb_display_47.setPixelColor((i)-1, (((255 & 0xffffff) << 16) | ((0 & 0xffffff) << 8) | 0));
rgb_display_47.show();
}
delay(100);
for (int i = 1; i <= 12; i = i + (1)) {
rgb_display_47.setPixelColor((i)-1, (((0 & 0xffffff) << 16) | ((0 & 0xffffff) << 8) | 0));
rgb_display_47.show();
}
delay(100);
}
if (v7pin_value == 0) {
for (int i = 1; i <= 12; i = i + (1)) {
rgb_display_47.setPixelColor((i)-1, (((0 & 0xffffff) << 16) | ((0 & 0xffffff) << 8) | 0));
rgb_display_47.show();
}
delay(500);
}
if (v7pin_value == 55) {
if (flag == 0) {
value++;
if (value >= 255) {
flag = 1;
}
} else if (flag == 1) {
value--;
if (value <= 0) {
flag = 0;
}
}
for (int i = 1; i <= 12; i = i + (1)) {
rgb_display_47.setPixelColor((i)-1, (((0 & 0xffffff) << 16) | ((0 & 0xffffff) << 8) | value));
rgb_display_47.show();
}
delayMicroseconds(200);
}
vTaskDelay(1);
}
}
void task_2( void * pvParameters ){
for(;;){
mpu6050.update();
if (mpu6050.getAccY() > 0.8) {
item = 3;
}
delay(500);
vTaskDelay(1);
}
}
BLYNK_WRITE(V1) {
vpin_value = param.asInt();
item = 0;
page = 1;
}
BLYNK_WRITE(V2) {
vpin_value = param.asInt();
item = 0;
page = 2;
}
BLYNK_WRITE(V3) {
vpin_value = param.asInt();
item = 1;
page = 3;
}
BLYNK_WRITE(V4) {
vpin_value = param.asInt();
item = 2;
page = 4;
}
BLYNK_WRITE(V5) {
v5pin_value = param.asInt();
Serial.println(v5pin_value);
}
BLYNK_WRITE(V6) {
v6pin_value = param.asInt();
Serial.println(v6pin_value);
}
BLYNK_WRITE(V7) {
v7pin_value = param.asInt();
Serial.println(v7pin_value);
}
void myTimerEvent1() {
alive_counter++;
Blynk.virtualWrite(V8, alive_counter);
}
void setup(){
page = 0;
item = 0;
flag = 0;
value = 0;
alive_counter = 0;
u8g2.setI2CAddress(0x3C*2);
u8g2.begin();
u8g2.enableUTF8Print();
xTaskCreatePinnedToCore(task_1, "task_1", 4096, NULL, 2, NULL, 0);
xTaskCreatePinnedToCore(task_3, "task_3", 4096, NULL, 2, NULL, 0);
rgb_display_47.begin();
xTaskCreatePinnedToCore(task_4, "task_4", 4096, NULL, 2, NULL, 0);
Wire.begin();
mpu6050.begin();
mpu6050.calcGyroOffsets(true);
xTaskCreatePinnedToCore(task_2, "task_2", 4096, NULL, 2, NULL, 0);
Serial.begin(9600);
Serial.println("Waiting for connections...");
Blynk.setDeviceName("Blynk");
Blynk.begin(auth);
timer.setInterval(1000L, myTimerEvent1);
}
void loop(){
vTaskDelay(1);
vTaskDelay(1);
vTaskDelay(1);
vTaskDelay(1);
Blynk.run();
timer.run();
}
|