139|0

108

帖子

8

TA的资源

一粒金砂(高级)

楼主
 

2024DigiKey创意大赛】【自行车智能灯】汇总提交 [复制链接]

  本帖最后由 alanlan86 于 2024-10-30 10:00 编辑

作品名称

自行车智能灯

一、作品简介

  • (1)作品照片
  •  

 

(2)简介

自行车智能车灯安装在自行车把手位置,能够根据光传感器自动点亮LED灯,用于做车头照明;能够根据IMU监测车把的左转右转动作,实现方向闪灯提醒;能够根据毫米波雷达探测前方是否有障碍物,发出警告提醒。

ESP32-S3-LCD-EV-Board做为主控板,外接光敏电阻传感器,通过ADC采集光的强度。通过I2C采集ICM-20948的姿态数据,进行车把方向监测。通过读取毫米波传感器的终端输出,监测前方是否有障碍物。

(3)物料清单

物料

型号

功能

1

ESP32-S3-LCD-EV-Board

主控、LCD显示交互、LED三色灯

2

ADAFRUIT TDK INVENSENSE ICM-20948

9轴传感器

3

MerryTek MC01-5G

毫米波传感器(集成光敏电阻)

 

         

 

A、ESP32-S3-LCD-EV-Board

ESP32-S3-LCD-EV-Board 是一款基于 ESP32-S3 芯片的屏幕交互开发板,通过搭配不同类型的 LCD 子板,可以驱动 IIC、SPI、8080 以及 RGB 接口的 LCD 显示屏。同时它还搭载双麦克风阵列,支持语音识别和近/远场语音唤醒,具有触摸屏交互和语音交互功能,满足用户对多种不同分辨率以及接口的触摸屏应用产品的开发需求。

目前从Digikey上采购到的开发板:搭配 480x480 LCD 的 ESP32-S3-LCD-EV-Board,有丰富的外设和强大的显示能力。

该款开发板核心模组型号ESP32-S3-WROOM-1-N16R16V, 该模组是一款通用型 Wi-Fi + 低功耗蓝牙 MCU 模组,搭载 ESP32-S3 系列芯片,内置 16 MB flash 以及 16 MB PSRAM。除具有丰富的外设接口外,模组还拥有强大的神经网络运算能力和信号处理能力,适用于 AIoT 领域的多种应用场景。

B、ICM-20948模组

ICM-20948是TDK(InvenSense)推出的9轴系列的9轴运动跟踪设备,专为电池供电的高性能消费电子产品设计。

 9轴产品系列采用了经过市场验证的MotionFusion以及运行时校准,该校准由InvenSense市场的MPU-65xx系列产品支持。此解决方案已售出数百万台,并经过了市场验证。

 9轴运动跟踪已成为包括智能手机、平板电脑和可穿戴设备在内的许多消费电子设备的关键功能。与离散解决方案相比,集成9轴设备的尺寸优势对于空间有限的产品(如智能手机和可穿戴传感器)来说是引人注目的。

 InvenSense的9轴设备将3轴陀螺仪、3轴加速计和3轴指南针与车载数字运动处理器结合在一起(DMP) 能够处理复杂的运动融合算法。

C、MerryTek MC01-5G

MC01-5G是一款5.8G微波感应模块,它支持5~12VDC宽输入电压,工作电流小,待机功耗低。 产品体积小,易于安装。 采用低阻抗专利天线技术,抗干扰能力强。 内置抗微风、细雨多重数字滤波器算法、稳定输出高低电平、PWM、UART等控制信号。 预留灵敏度,延时时间,光控阀值等参数设置脚位,功能设置灵活。

产品具有感应距离远、可内置、无死区、不受温湿度、噪音、灰尘、气流、环境光影响等优点。广泛 应用于感应灯具、自动门控制、智能家居、智能卫浴、小家电、安防、IOT、智能终端等产品,及走廊、 车库、洗手间、庭院、阳台等场所。

 

二、系统框图

 
 

主控模组 

整个系统构成相对简单,采用ESP32-S3-WROOM-1-N16R16V模块作为主控,它是一款拥有2.4 GHz WiFi (802.11 b/g/n) + Bluetooth® 5 (LE)的无线高集成度模组,内置 ESP32S3 系列芯片,Xtensa® 双核 32 位 LX7 处理器 Flash最大可选 16 MB,PSRAM最大大可选 8/16 MB,最多支持36个GPIO,丰富的外设 板上带PCB天线非常便利于集成化设计。开发板上有WS2812,三色LED灯,可用于做用户交互指示。

 

整个ESP32-S3-LCD-EV-Board开发板的功能框图如下所示:

 

板载带有的Audio部分,暂时未有使用到,后续可作为扩展使用。

 

传感器ICM20948

ICM20948是一款来自于TDK InvenSense推出的一款9轴运动检测传感器,它与主控板模块连接比较简单,采用I2C方式进行通信,支持400K Hz通信速率。

 

MC01-5G微波感应模组

微波感应模块MC01-5G支持5~12V的DC直流电源输入,可取开发板扩展电源5V输入作为工作电源,识别到人体或障碍物时,将通过I/O以电平方式进行输出。针对发射功率、感应延时、环境光探测等均可以通过配置I/O进行输入。其中感应模块支持探测4米的半径范围。

如下是模组的典型应用电路图:

 

三、各部分功能说明

整个软件基于ESP32-S3的idf开发环境进行编写和调试,基于SDK中的lvgl_demo这份示例代码进行的代码添加。

(1)开发环境

IDF开发环境的安装可以从官网下载SDK 和演示|乐鑫科技,在实现一键安装完成。安装完成后有命令行的工具以及IDE的工具,可以根据用户喜好进行选择应用。

(2)环境光采集部分

环境光照强度采集采用了比较简单和原始的做法,就是通过ADC采集毫米波感应模块上的光敏电阻,通过判断光敏电阻上的电压值,来调节照明LED的点亮和熄灭。

如下截图是ESP32-S3的ADC部分配置及执行代码:

void app_light_sensor_task(void *arg)
{
    //-------------ADC1 Init---------------//
	//ADC转换器初始化
    adc_oneshot_unit_handle_t adc1_handle;
    adc_oneshot_unit_init_cfg_t init_config1 = {
        .unit_id = ADC_UNIT_1,
    };
    ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));

    //-------------ADC1 Config---------------//
	//配置ADC转换通道
    adc_oneshot_chan_cfg_t config = {
        .bitwidth = ADC_BITWIDTH_DEFAULT,
        .atten = EXAMPLE_ADC_ATTEN,
    };
    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN0, &config));

    //-------------ADC1 Calibration Init---------------//
	//ADC转换器校准
    adc_cali_handle_t adc1_cali_chan0_handle = NULL;
    adc_cali_handle_t adc1_cali_chan1_handle = NULL;
    bool do_calibration1_chan0 = example_adc_calibration_init(ADC_UNIT_1, EXAMPLE_ADC1_CHAN0, EXAMPLE_ADC_ATTEN, &adc1_cali_chan0_handle);

    while (1) {
        ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN0, &adc_raw[0][0]));
        ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN0, adc_raw[0][0]);
        if (do_calibration1_chan0) {
            ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan0_handle, adc_raw[0][0], &voltage[0][0]));
            ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN0, voltage[0][0]);
			
			//根据光敏电阻感应电压调节LED的亮度
			if (voltage[0][0] > 1.5)
			{
			   LED_PowerON((3.3 - voltage[0][0])/3.3 * 100);
			} else {
			   LED_PowerOFF();
			}
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }

    //Tear Down
    ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle));
    if (do_calibration1_chan0) {
        example_adc_calibration_deinit(adc1_cali_chan0_handle);
    }
}

 

(3)动作检测部分

关于motion sensor -ICM20948的陀螺仪角速度、加速度的数值采集将会复杂一些。通过调用ESP32-S3的I2C驱动API接口实现传感器的数值读取(此处参考了TDK InvenSense MP9250的一些代码)。

/**
 * @brief  Read a sequence of bytes from a MPU9250 sensor registers
 */
static esp_err_t mpu9250_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
{
    return i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

/**
 * @brief Write a byte to a MPU9250 sensor register
 */
static esp_err_t mpu9250_register_write_byte(uint8_t reg_addr, uint8_t data)
{
    int ret;
    uint8_t write_buf[2] = {reg_addr, data};

    ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    return ret;
}

初始化传感器部分配置:

void motion_sensor_init(void)
{
    uint8_t data[2];
    ESP_ERROR_CHECK(i2c_master_init());
    ESP_LOGI(TAG, "I2C initialized successfully");

    /* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */
    ESP_ERROR_CHECK(mpu9250_register_read(MPU9250_WHO_AM_I_REG_ADDR, data, 1));
    ESP_LOGI(TAG, "WHO_AM_I = %X", data[0]);

    /* Demonstrate writing by reseting the MPU9250 */
    ESP_ERROR_CHECK(mpu9250_register_write_byte(MPU9250_PWR_MGMT_1_REG_ADDR, 1 << MPU9250_RESET_BIT));

    /*Set DATA RATE of 1KHz by writing SMPLRT_DIV register*/
    ESP_ERROR_CHECK(mpu9250_register_write_byte(MPU9250_SMPLRT_DIV_REG, 0x07));
    
    /*Set accelerometer configuration in ACCEL_CONFIG Register*/
    /*XA_ST=0,YA_ST=0,ZA_ST=0,  FS_SEL=0 ->±2g*/
    ESP_ERROR_CHECK(mpu9250_register_write_byte(MPU9250_ACCEL_CONFIG_REG, 0x00));
 
    /*Set Gyroscopic configuration in GYRO_CONFIG Register*/
    /*XG_ST=0,YG_ST=0,  FS_SEL=0 ->± 250 °/s*/
    ESP_ERROR_CHECK(mpu9250_register_write_byte(MPU9250_GYRO_CONFIG_REG, 0x00));
}

读取传感器角速度、加速度和温度值:

/*Read 14 BYTES of data starting from ACCEL_XOUT_H register*/

  mpu9250_register_read( MPU9250_ACCEL_XOUT_H_REG, Rec_Data, 14);

  DataStruct->Accel_X_RAW = (int16_t) (Rec_Data[0] << 8 | Rec_Data[1]);
  DataStruct->Accel_Y_RAW = (int16_t) (Rec_Data[2] << 8 | Rec_Data[3]);
  DataStruct->Accel_Z_RAW = (int16_t) (Rec_Data[4] << 8 | Rec_Data[5]);
  
  temp = (int16_t) (Rec_Data[6] << 8 | Rec_Data[7]);
  
  DataStruct->Gyro_X_RAW = (int16_t) (Rec_Data[8] << 8 | Rec_Data[9]);
  DataStruct->Gyro_Y_RAW = (int16_t) (Rec_Data[10] << 8 | Rec_Data[11]);
  DataStruct->Gyro_Z_RAW = (int16_t) (Rec_Data[12] << 8 | Rec_Data[13]);

  DataStruct->Ax = DataStruct->Accel_X_RAW / 16384.0;
  DataStruct->Ay = DataStruct->Accel_Y_RAW / 16384.0;
  DataStruct->Az = DataStruct->Accel_Z_RAW / ACCEL_Z_CORRECTOR;
  
  DataStruct->Temperature = (float) ((int16_t) temp / (float) 340.0 + (float) 36.53);
  
  DataStruct->Gx = DataStruct->Gyro_X_RAW / 131.0;
  DataStruct->Gy = DataStruct->Gyro_Y_RAW / 131.0;
  DataStruct->Gz = DataStruct->Gyro_Z_RAW / 131.0;

为确保采集到的角度速度和角速度能够稳定,并且融合成姿态角,增加了卡尔曼滤波器进行处理:

/*Kalman angle solve*/
  double dt = (double) (xTaskGetTickCount() - timer) / configTICK_RATE_HZ;
  
  timer = xTaskGetTickCount();
  double roll;
  
  /*勾股算出重力加速度在X-Z平面的投影长度*/
  double roll_sqrt = sqrt(DataStruct->Accel_X_RAW * DataStruct->Accel_X_RAW + DataStruct->Accel_Z_RAW * DataStruct->Accel_Z_RAW);
  if(roll_sqrt != 0.0) 
  {
    roll = atan(DataStruct->Accel_Y_RAW / roll_sqrt) * RAD_TO_DEG;
  } 
  else 
  {
    roll = 0.0;
  }
  double pitch = atan2(-DataStruct->Accel_X_RAW, DataStruct->Accel_Z_RAW) * RAD_TO_DEG;
  if((pitch < -90 && DataStruct->KalmanAngleY > 90) || (pitch > 90 && DataStruct->KalmanAngleY < -90)) 
  {
    KalmanY.angle = pitch;
    DataStruct->KalmanAngleY = pitch;
  }
  else 
  {
    DataStruct->KalmanAngleY = Kalman_getAngle(&KalmanY, pitch, DataStruct->Gy, dt);
  }
  if(fabs(DataStruct->KalmanAngleY) > 90)
  {
    DataStruct->Gx = -DataStruct->Gx;
  }
  DataStruct->KalmanAngleX = Kalman_getAngle(&KalmanX, roll, DataStruct->Gy, dt);

(4)微波感应部分

微波感应模块探测到障碍物将以I/O信号进行输出,引出配置ESP32的GPIO中断进行事件上报。

void app_radar_sensor_task(void)
{
    gpio_input_init();

    //change gpio interrupt type for one pin
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);

    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
	
    //start gpio task
    xTaskCreate(radar_gpio_int_task, "gpio_task_example", 2048, NULL, 10, NULL);

    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
	
    //remove isr handler for gpio number.
    gpio_isr_handler_remove(GPIO_INPUT_IO_0);
	
    //hook isr handler for specific gpio pin again
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
}

检测到I/O中断后以Queue队列的方式从中断发出到任务端,使得任务部分可以作出对应处理。

static QueueHandle_t gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

static void radar_gpio_int_task(void* arg)
{
    uint32_t io_num;
    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
        }
    }
}

 

(2)、LVGL图形部分

关于ESP32-S3-LCD这个开发板,乐鑫原厂官方原有SDK即有移植好支持LVGL的实例。需要执行UI的开发可以采用调用LVGL的API逐个控件进行布局和显示调试,但是难免效率太低了,所以需要借助UI开发助手Square Line Studio和PC模拟器进行帮助。

有PC模拟器的加持将会减少反复编译下载到嵌入式端芯片的时间,提高开发效率,直接可实现所见即所得。

通过Square Line Studio可以将图形UI的界面进行设计完成。

整个UI的代码文件结构:

Square Line Studio自动生成以上代码,他们的功能作用分别是:

Component

功能控件

自动生成,无需修改

Fonts

字体资源

自动生成,无需修改

Image

图片资源

自动生成,无需修改

Screen

屏幕资源

自动生成,无需修改

Ui.c/ui_event.c/ui_helpers.c

界面交互事件

用户交互与硬件逻辑交互的代码添加位置

代码准备好后,可以在idf的集成环境下编译通过,并烧录到开发板上。

四、作品源码

lvgl_demos.7z (57.96 MB, 下载次数: 5)
DigiKey_contest_2024-自行车智能灯.doc (66.93 MB, 下载次数: 1)

五、作品功能演示视频

【2024DigiKey创意大赛】【自行车智能灯】开箱贴ESP32-S3-LCD-EV-BOARD&ICM2094 - DigiKey得捷技术专区 - 电子工程世界-论坛

 

演示视频

 

 

六、项目总结

本次活动对于本人来说,最大的遗憾是由于工作的原因,并不能在预定的时间内,完全按照最初的功能设想把所有功能和代码调试完整,导致整个功能的演示完整性不高。但是,也有所收获——最大的收获是本次通过ESP32-S3带彩屏LCD的开发板,对于LVGL进行了一些探究,虽然现在离做出美轮美奂的UI界面还有一些距离(之前疑惑:如果嵌入式工程人员,如果用一款好用的切图软件,把UI做得简洁漂亮?B站上,大家探讨和分享的比较多都是一些移植、LVGL的一些控件的一些普通用法。探讨到实操把square line studio用好的比较少干货!)

最后,总结一句,还是非常感谢Digikey和EEWorld给那么好的学习机会和提供了一个大家交流的平台!

 

七、其他

题外话,出于工作因素考虑,可能稍后一段很长时间的Follow Me或DIY创新活动都没法参加了~~~静待闲暇之时!

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
争排名很幼稚——台积电工程师写给学弟学妹们的信

争排名很幼稚——台积电工程师写给学弟学妹们的信 都说三十而立,但是回头看看却几乎一事无成。 维护中东和平这种大事咱做 ...

DIY三轴加速度传感器STEP 1:震动报警

基于LPC1343与三轴加速度传感器 的震动报警装置 Author: chenzhufly Email: chenzhufly@126.com 2010-05-18 系统硬件框图: ...

【赛题大汇总】(5.23更新)2011全国各省市、高校“电子设计”选拔赛、校内赛题目汇总

本帖最后由 paulhyde 于 2014-9-15 02:58 编辑

旋转编码器解码

随着电子技术的发展,旋转编码器的应用越来越广泛。下面我们谈谈对旋转编码器的解码。 旋转编码器是用来测量转速的装置 ...

数字示波器的FFT快速傅立叶变换功能及运用

大多数示波器上都有个FFT功能,也叫快速傅立叶变换,但很多人不了解这个功能是做什么用的,百度以后又会遇到各种各样的高数公式 ...

【LAUNCHXL-CC1350-4】- 0:开箱帖

本帖最后由 MianQi 于 2021-6-7 17:27 编辑 被TI这款产品2.4G+433M的双频段搭配吸引,申请参予评测活动。 说到蓝牙,最早 ...

第七篇 UART的使用-轮询与中断方式

GD32L23x的UART有很多实用的功能,比如接收超时中断、接收缓冲区FIFO等。不过首先还是要掌握基本的功能。 一、初始化 初 ...

为了解决网络拥塞,Wi-Fi 6采用了哪些黑科技?

Wi-Fi的真正普及,是从2008年的Wi-Fi 4(802.11n)开始。可以说,从那时起,Wi-Fi真正成为家庭和企业互联网接入最常见的方式。支 ...

关于mos作开关的缺陷

例如nmos 在gs为0时,d向s流的电流可以阻断,但由于寄生二极管的存在,导致电流由s向d极流。简而言之,mos作开关时,只能可靠截 ...

【兆易GD32H759I-EVAL】 外接5寸LCD显示屏测试

本帖最后由 TL-LED 于 2024-6-1 14:20 编辑 测试驱动手上的5寸分辨率800x480显示屏。 一、硬件电路 1.1、开发 ...

关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表