- 2024-11-12
-
加入了学习《【2024 DigiKey创意大赛】+智慧焊接工作台》,观看 智慧焊接工作台
-
发表了主题帖:
冲【Follow Me第二季第4期】已下单,等板子!!!!
选了这3款板子拼单!等待收到板子~~~~
- 2024-10-30
-
加入了学习《ESP32-S3-LVGL》,观看 自行车智能灯
-
加入了学习《ESP32-S3-LVGL》,观看 ESP32-S3-LCD-LVGL
-
发表了主题帖:
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的集成环境下编译通过,并烧录到开发板上。
四、作品源码
五、作品功能演示视频
【2024DigiKey创意大赛】【自行车智能灯】开箱贴ESP32-S3-LCD-EV-BOARD&ICM2094 - DigiKey得捷技术专区 - 电子工程世界-论坛
演示视频
六、项目总结
本次活动对于本人来说,最大的遗憾是由于工作的原因,并不能在预定的时间内,完全按照最初的功能设想把所有功能和代码调试完整,导致整个功能的演示完整性不高。但是,也有所收获——最大的收获是本次通过ESP32-S3带彩屏LCD的开发板,对于LVGL进行了一些探究,虽然现在离做出美轮美奂的UI界面还有一些距离(之前疑惑:如果嵌入式工程人员,如果用一款好用的切图软件,把UI做得简洁漂亮?B站上,大家探讨和分享的比较多都是一些移植、LVGL的一些控件的一些普通用法。探讨到实操把square line studio用好的比较少干货!)
最后,总结一句,还是非常感谢Digikey和EEWorld给那么好的学习机会和提供了一个大家交流的平台!
七、其他
题外话,出于工作因素考虑,可能稍后一段很长时间的Follow Me或DIY创新活动都没法参加了~~~静待闲暇之时!
- 2024-10-29
-
上传了资料:
ESP32-S3源代码
- 2024-09-20
-
评论了课程:
EEWORLD大学堂----DigiKey 应用说:蓝牙5.4 新特性解读及实例演示
zjsyjbb 发表于 2024-7-5 12:47
新一代蓝牙技术,还是挺牛逼的
马上蓝牙6.0也要来了!
-
评论了课程:
EEWORLD大学堂----DigiKey 应用说:蓝牙5.4 新特性解读及实例演示
guojun0718 发表于 2024-7-17 20:55
厘米级的定位?定位范围?
要用蓝牙6.0的技术
-
评论了课程:
EEWORLD大学堂----DigiKey 应用说:蓝牙5.4 新特性解读及实例演示
guojun0718 2024-07-17 20:53жλ
λAoA AoDchannel sounding
- 2024-08-27
-
加入了学习《【Follow me第二季第1期】全部任务演示短视频》,观看 【Follow me第二季第1期】任务演示视频
- 2024-08-19
-
回复了主题帖:
【2024DigiKey创意大赛】【自行车智能灯】开箱贴ESP32-S3-LCD-EV-BOARD&ICM2094
wangerxian 发表于 2024-8-19 16:43
ADAFRUIT TDK INVENSENSE ICM-2094是什么传感器?三轴还是六轴?
9轴的,陀螺+G+地磁
-
发表了主题帖:
【Follow me第二季第1期】任务汇总+简单创意:摇摇乐
本帖最后由 alanlan86 于 2024-8-27 17:44 编辑
# 简介视频
[localvideo]7a65733650be79a13903c799a98ddb25[/localvideo]
[Follow Me 第二季第1期 创意任务演示](https://training.eeworld.com.cn/course/68609/learn?preview=1#lesson/40792 "Follow Me 第二季第1期 创意任务演示")
# 任务实现
## 入门任务
- CirrutPython:开发环境搭建,板载LED点亮
### (1)硬件介绍
本次活动的硬件主角是:
![](https://www.eeworld.com.cn/huodong/digikey_follow_me_2024/image/circuit_playground_cpx03.jpg)
初步了解一下这个板子的主控和周边外设:
![](https://www.eeworld.com.cn/huodong/digikey_follow_me_2024/image/circuit_playground_wgzst1.jpg)
搭建环境,我用到MicroUSB接口和对应的USB数据线。
**【重要提醒】:如果在PC电脑端连接了USB Hub导致CiruitPython识别不正常时,请采用USB线直连方式!**
我的笔记本电脑一开始就出现这种情况。
### (2)CiruitPython固件&代码编辑软件
整个搭建环境的过程可以参考:
[CiruitPython环境搭建,官方参考流程](https://learn.adafruit.com/welcome-to-circuitpython "CiruitPython环境搭建,官方参考流程")
板子固件下载:[CP固件下载](https://circuitpython.org/downloads "CP固件下载")
![](https://circuitpython.org/assets/images/boards/small/circuitplayground_express.jpg)
将下载的UF2文件,拖入CiruitPyhton在电脑端识别的盘符,即可完成固件的更新及下载。
我选择的代码编辑工具是沿用此前几次比赛在用的,MU Editor
![](https://cdn-learn.adafruit.com/assets/assets/000/105/677/medium640/circuitpython_WtCP_codewithdotmu_main_page.png?1634749167)
### (3)软件代码
- 输入简单LED灯闪烁控制代码,如下。
```python
import board
import digitalio
import time
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
while True:
led.value = True
time.sleep(0.5)
led.value = False
time.sleep(0.5)
```
### (4)演示
- 视频效果:
[localvideo]5e0f2d81c62df98c5720a1ff357e2c44[/localvideo]
## 基础任务一
- 控制板载炫彩LED,跑马灯点亮和颜色变换
### 原理
- 板载幻彩灯:
![](https://cdn-learn.adafruit.com/assets/assets/000/047/165/medium640/circuit_playground_neopix.jpg?1507830139)
- 参考WS2812的资料:[参考WS2812博文](https://i-blog.csdnimg.cn/blog_migrate/db654c3e11510abcd6dfcfffe97da35b.png "参考WS2812博文")
- 对于单总线控制幻彩灯,最关键就是发送准确的时序到逐个灯珠。
- 针对此CiruitPython进行编程的好处,就是可以调用写好的库:neopixel和rainbowio,使得整个控制效率大大提高。
### 硬件
- 板子10颗幻彩灯珠,采用单总线方式串联连接,主控通过发送控制时序,即可逐个点亮或全点亮,或控制颜色变化。
### 软件
演示任务的源代码:
```python
# SPDX-FileCopyrightText: 2017 John Edgar Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Circuit Playground NeoPixel
import time
import board
from rainbowio import colorwheel
import neopixel
# 配置WS2812的控制脚及亮度
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2, auto_write=False)
# 可配置4种三色灯点灯模式,配置1打开
# choose which demos to play
# 1 means play, 0 means don't!
color_chase_demo = 1
flash_demo = 1
rainbow_demo = 1
rainbow_cycle_demo = 1
# 流水灯
def color_chase(color, wait):
for i in range(10):
pixels = color
time.sleep(wait)
pixels.show()
time.sleep(0.5)
# 彩虹环
def rainbow_cycle(wait):
for j in range(255):
for i in range(10):
rc_index = (i * 256 // 10) + j * 5
pixels = colorwheel(rc_index & 255)
pixels.show()
time.sleep(wait)
# 彩虹颜色变化
def rainbow(wait):
for j in range(255):
for i in range(len(pixels)):
idx = int(i + j)
pixels = colorwheel(idx & 255)
pixels.show()
time.sleep(wait)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
OFF = (0, 0, 0)
while True:
# 流水效果
if color_chase_demo:
color_chase(RED, 0.1) # Increase the number to slow down the color chase
color_chase(YELLOW, 0.1)
color_chase(GREEN, 0.1)
color_chase(CYAN, 0.1)
color_chase(BLUE, 0.1)
color_chase(PURPLE, 0.1)
color_chase(OFF, 0.1)
# 纯色点亮
if flash_demo:
pixels.fill(RED)
pixels.show()
# Increase or decrease to change the speed of the solid color change.
time.sleep(1)
pixels.fill(GREEN)
pixels.show()
time.sleep(1)
pixels.fill(BLUE)
pixels.show()
time.sleep(1)
pixels.fill(WHITE)
pixels.show()
time.sleep(1)
# 彩虹色环流动效果
if rainbow_cycle_demo:
rainbow_cycle(0.05) # Increase the number to slow down the rainbow.
# 彩虹颜色变化
if rainbow_demo:
rainbow(0.05) # Increase the number to slow down the rainbow.
```
### 演示效果
[localvideo]c2ef1168762f7ef9af7aedac7452534b[/localvideo]
## 基础任务二
- 监测环境温度和光线,通过板载LED展示舒适程度
### 硬件
- 开发板描述:
o 1 x Temperature sensor (thermistor)
o 1 x Light sensor (phototransistor). Can also act as a color sensor and pulse sensor.
- 在板载带有温度传感器(电阻式)NTC thermistor (Murata NCP15XH103F03RC),可通过ADC检测其产生的电压作为输入
![](https://cdn-learn.adafruit.com/assets/assets/000/047/160/medium640/circuit_playground_temp.jpg?1507829582)
- 板载带有光电晶体管 亿光的 Ambient Light Sensor Surface-Mount ALS-PT19-315C/L177/TR8,该传感器模拟信号输出,可通过ADC检测其产生的电压作为检测输入
![](https://cdn-learn.adafruit.com/assets/assets/000/047/158/medium640/circuit_playground_lightsensor.jpg?1507829543)
### 软件
- 软件源码如下:
- A、主要过程:初始化温度及光传感器的模拟输入ADC
- B、根据采集得到的数值做LED幻彩灯的对应显示指示
```python
# SPDX-FileCopyrightText: 2017 John Edgar Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Circuit Playground Light Sensor
# Reads the on-board light sensor and graphs the brightness with NeoPixels
import time
import board
import neopixel
import analogio
import simpleio
import adafruit_thermistor
# 幻彩灯显示
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.05, auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()
# 初始化环境光检测ADC输入检测
light = analogio.AnalogIn(board.LIGHT)
# 初始化温度传感器ADC输入检测
thermistor = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950)
while True:
# 将光亮度值 对应到幻彩灯
# light value remapped to pixel position
peak = simpleio.map_range(light.value, 2000, 62000, 0, 9)
print(light.value)
print(int(peak))
# 输出采集到的温度值
temp_c = thermistor.temperature
temp_f = thermistor.temperature * 9 / 5 + 32
print("Temperature is: %f C and %f F" % (temp_c, temp_f))
# 根据光亮度及温度值 进行点亮不同颜色和不同灯珠数量
for i in range(0, 9, 1):
if i 32:
pixels = (255, 00, 00)
elif temp_c > 30:
pixels = (00, 00, 255)
else:
pixels = (0, 255, 0)
else:
pixels = (0, 0, 0)
pixels.show()
time.sleep(0.01)
```
### 演示
- 检测到光变化及温度变化的演示效果。
[localvideo]069942224e9c3f1a86a5ab0e3f398de4[/localvideo]
## 基础任务三
- 接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警
### 硬件
- 关于靠近检测,从论坛上有看到用光传感器检测光强度进行实现的。以下将利用板载的红外发射管和接收管来进行靠近检测功能。
![](https://cdn-learn.adafruit.com/assets/assets/000/047/182/medium640/circuit_playground_ir.jpg?1507831652)
### 软件
- 软件实现流程分为3个部分:
- A、控制红外IR进行脉冲发射
- B、打开IR接收的ADC检测,读取检测值
- C、根据检测到的ADC值进行蜂鸣告警和幻彩LED指示
```python
import time
import board
import analogio
import digitalio
from adafruit_circuitplayground import cp
# 关闭幻彩灯
cp.pixels.fill((0, 0, 0))
# 设置红外IR发射管脚
ir_led = digitalio.DigitalInOut(board.IR_TX)
ir_led.direction = digitalio.Direction.OUTPUT
# 设置红外检测,采用ADC检测
adc = analogio.AnalogIn(board.IR_PROXIMITY)
# 距离范围转换
def scale_range(value):
if value43000:
value = 43000
value = value - 29000
return round(value/(43000 - 29000)*10)
while True:
# 发射一个短脉冲时间
ir_led.value = True
time.sleep(0.05)
ir_led.value = False
# ADC对应值
dist = adc.value
print(dist)
time.sleep(0.2)
# 根据距离告警和指示幻彩灯
peak = scale_range(dist)
for i in range(10):
if i 3:
cp.play_tone(440, 1)
cp.pixels.show()
```
### 演示
开发板的演示效果如下:
[localvideo]273ffcd271e41869085d34ea5b0003c4[/localvideo]
## 进阶任务
- 制作不倒翁——展示不倒翁运动过程中的不同灯光效果
### 硬件
- 检测不倒翁的各个摇摆的方向是通过板载的G-Sensor实现。
![](https://cdn-learn.adafruit.com/assets/assets/000/047/162/medium640/circuit_playground_adxl.jpg?1507829763)
- 关于G-Sensor LIS3DH,是一颗非常通用的传感器:
- 3轴MEMS加速度计,超低功耗,±2g/±4g/±8g/±16g满量程,高速I2C/SPI数字输出,内置FIFO和高性能加速度传感器,LLGA 16 3x3x1.0封装
### 软件
- 不倒翁的演示代码实现过程包括:
- A、读取G-Sensor的数值
- B、根据G-Sensor Z轴的数据判断板子是否在水平状态
- C、根据X轴和Y轴的正负号,判断不倒翁偏向的方向,从而点亮对应区域的LED以及发出蜂鸣器响声
```python
import time
import board
from rainbowio import colorwheel
import neopixel
from adafruit_circuitplayground import cp
# 灯显示效果
def rainbow(wait):
for j in range(0,255,25):
for i in range(10):
idx = int(i + j)
cp.pixels = colorwheel(idx & 255)
cp.pixels.show()
while True:
# 读取LIS3DH的加速度传感器3轴数据
x, y, z = cp.acceleration
print(('x',x, 'y',y, 'z',z))
# 如果Z轴大于9.5说明处于相对水平静置状态
if z > 9.5:
rainbow(0.05)
cp.stop_tone()
else:
time.sleep(0.2)
# 熄灭各个幻彩灯
for i in range(10):
cp.pixels = (0, 0, 0)
# 判断4个区域的加速度正负范围,从而判断不倒翁偏向的方向
if x > 0.4 and y < -0.4:
for i in range(0,3,1):
cp.pixels = (255, 255, 255)
cp.start_tone(262)
elif x > 0.4 and y > 0.4:
for i in range(2,5,1):
cp.pixels = (255, 255, 255)
cp.start_tone(262)
elif x < -0.4 and y > 0.4:
for i in range(5,8,1):
cp.pixels = (255, 255, 255)
cp.start_tone(262)
elif x < -0.4 and y < -0.4:
for i in range(7,10,1):
cp.pixels = (255, 255, 255)
cp.start_tone(262)
cp.pixels.show()
```
### 演示
[localvideo]242145cc9043325d25a618e68178cd60[/localvideo]
## 创意任务
### 创意任务三
水果钢琴——通过触摸水果弹奏音乐,并配合灯光效果
#### 原理
- 通过圆形板子的周边铜Pad,人手触摸产生电容变化即可感应到输入,然后播放对应的wav音频文件。
#### 硬件
-用到板载的连接pad,可以用手直接触摸,或者外引出到一个金属铜箔(硬币)上。
![](https://cdn-learn.adafruit.com/assets/assets/000/047/303/large1024/circuit_playground_play808.png?1507940432)
#### 软件
- 软件源码可参考:[808_drum_machine的演示](https://learn.adafruit.com/adafruit-circuit-playground-express/playground-drum-machine "808_drum_machine的演示")
```python
# SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Circuit Playground 808 Drum machine
import time
import board
import touchio
import digitalio
try:
from audiocore import WaveFile
except ImportError:
from audioio import WaveFile
try:
from audioio import AudioOut
except ImportError:
try:
from audiopwmio import PWMAudioOut as AudioOut
except ImportError:
pass # not always supported by every board!
bpm = 120 # Beats per minute, change this to suit your tempo
# Enable the speaker
speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
speaker_enable.direction = digitalio.Direction.OUTPUT
speaker_enable.value = True
# Make the input capacitive touchpads
capPins = (board.A1, board.A2, board.A3, board.A4, board.A5,
board.A6, board.TX)
touchPad = []
for i in range(7):
touchPad.append(touchio.TouchIn(capPins))
# The seven files assigned to the touchpads
audiofiles = ["bd_tek.wav", "elec_hi_snare.wav", "elec_cymbal.wav",
"elec_blip2.wav", "bd_zome.wav", "bass_hit_c.wav",
"drum_cowbell.wav"]
audio = AudioOut(board.SPEAKER)
def play_file(filename):
print("playing file " + filename)
file = open(filename, "rb")
wave = WaveFile(file)
audio.play(wave)
time.sleep(bpm / 960) # Sixteenth note delay
while True:
for i in range(7):
if touchPad.value:
play_file(audiofiles)
```
#### 演示
[localvideo]81c2029e0261f5365ac960418f560cfc[/localvideo]
### 自定义:摇摇乐
#### 原理
- 利用板载的G-Sensor检测板子的倾角
- 计算得到对应倾角,对应当前重力倾角对应的LED灯珠
- 根据灯珠位置,播放不同的声音
#### 源码
```python
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
"""Gravity Pulls Pixel
This program uses the Circuit Playground's accelerometer to position
a white pixel as if gravity were pulling it.
Flip the switch left (toward the notes) to turn on debugging messages and
slow down the action. See a code walkthrough here: https://youtu.be/sZ4tNOUKRpw
"""
import time
import math
from adafruit_circuitplayground import cp
PIXEL_SPACING_ANGLE = 30
STANDARD_GRAVITY = 9.81
BACKGROUND_COLOR = 0, 0, 64
MIN_BRIGHTNESS = 15 # Minimum brightness for anti-aliasing
LIGHTING_ARC_LENGTH = 45
def compute_pixel_angles():
"""Return a list of rotation angles of the ten NeoPixels.
On the Circuit Playground there are ten pixels arranged like the 12 hours of a clock, except
that positions 6 and 12 are empty. The numbers in the list are the angles from the (x, y)
accelerometer values for each pixel when the Circuit Playground is rotated with that pixel at
the bottom. For example, with pixel 0 at the bottom (and pixel 5 at the top), the
accelerometer’s (x, y) values give an angle of 300°. Rotated clockwise 1/12 turn (30°), so
that pixel 1 is at the bottom, the angle is 330°.
"""
return [
(300 + PIXEL_SPACING_ANGLE * n) % 360 for n in range(12) if n not in (5, 11)
]
def degrees_between(a1, a2):
smaller = min(a1, a2)
larger = max(a1, a2)
return min(larger - smaller, 360 + smaller - larger)
def pixel_brightness(distance_from_down, accel_magnitude):
"""Return the a brightness for a pixel, or None if the pixel is not in the lighting arc"""
half_lighting_arc_length = LIGHTING_ARC_LENGTH / 2
if accel_magnitude < 0.1 or distance_from_down > half_lighting_arc_length:
return None
normalized_nearness = 1 - distance_from_down / half_lighting_arc_length
scale_factor = (255 - MIN_BRIGHTNESS) * accel_magnitude
color_part = MIN_BRIGHTNESS + round(normalized_nearness * scale_factor)
return color_part
def angle_in_degrees(x, y):
"""Return the angle of the point (x, y), in degrees from -180 to 180"""
return math.atan2(y, x) / math.pi * 180
def positive_degrees(angle):
"""Convert -180 through 180 to 0 through 360"""
return (angle + 360) % 360
cp.pixels.brightness = 0.1 # Adjust overall brightness as desired, between 0 and 1
pixel_positions = compute_pixel_angles()
# The seven files assigned to the touchpads
audiofiles = ["bd_tek.wav", "elec_hi_snare.wav", "elec_cymbal.wav",
"elec_blip2.wav", "bd_zome.wav", "bass_hit_c.wav",
"bd_tek.wav", "bd_zome.wav", "elec_cymbal.wav",
"drum_cowbell.wav"]
while True:
debug = cp.switch # True is toward the left
accel_x, accel_y = cp.acceleration[:2] # Ignore z
down_angle = positive_degrees(angle_in_degrees(accel_x, accel_y))
magnitude_limit = STANDARD_GRAVITY
normalized_magnitude = (
min(math.sqrt(accel_x * accel_x + accel_y * accel_y), magnitude_limit)
/ magnitude_limit
)
pixels_lit = []
for i, pixel_position in enumerate(pixel_positions):
pe = pixel_brightness(
degrees_between(pixel_position, down_angle), normalized_magnitude
)
cp.pixels = (pe, pe, pe) if pe else BACKGROUND_COLOR
if pe:
pixels_lit.append((i, pe))
cp.play_file(audiofiles)
if debug:
lit_formatted = ", ".join(("{}: {:>3d}".format(p, i) for p, i in pixels_lit))
print(
"x: {:>6.2f}, y: {:>6.2f}, angle: {:>6.2f}, mag: {:>3.2f}, pixels: [{}]".format(
accel_x, accel_y, down_angle, normalized_magnitude, lit_formatted
)
)
#time.sleep(0.5)
```
#### 演示
- 演示部分见本帖开头!
## 整合源码
- 以上任务所有源代码:
## 总结
- 2024 FM1已经是我参加的第5次的FM活动,非常感觉Digikey和EEWorld,让我有机会可以动手体验这些有趣好玩的板子!同时,也看到论坛其他出色的开发者的设计。
- 最后,感触最大的就是大家的动手能力太强了!大家都很踊跃在参加,在分享!2024的FM2我没有提交申请,当然也就没有机会玩到对应的板子。接着,需要投入时间到创意DIY上了~~~
-
回复了主题帖:
【2024 DigiKey创意大赛】RPI5翻译机---2 RPI5物料开箱-2
可以在52840上跑zephyr上的broadcast audio source(controller端),在RP5上跑BlueZ。
Bluetooth: Broadcast Audio Source — Zephyr Project Documentation
-
发表了主题帖:
【2024DigiKey创意大赛】【自行车智能灯】开箱贴ESP32-S3-LCD-EV-BOARD&ICM2094
本帖最后由 alanlan86 于 2024-8-19 20:04 编辑
# 拆箱
- 一大早上,到达公司,看到Digikey创意大赛的物料,厚实的一大箱子,立刻来一个拆箱!
- 迫不及待地,上电,试玩一下!!!
[localvideo]208d2f93fb3e3a1e1df41ea95b8f1e19[/localvideo]
# 核心主控
- ESP32-S3-LCD-EV-BOARD适合做86盒子、仪表等UI交互的一款板子!!!
![](https://mm.digikey.com/Volume0/opasdata/d220001/derivates/6/001/163/581/ESP32-S3-LCD-EV-BOARD_web%28640x640%29.jpg)
- 从官方规格书可以看到,这个开发板除了屏显和触摸外,还带了语音和一个三色灯,非常适合做为人机交互的主控!对于玩UI的应用有480x480的屏幕,相当的厚道了!!!:Onion-19:
# 传感器
- 选择的是Invensense(TDK)的ADAFRUIT TDK INVENSENSE ICM-2094
![](https://mm.digikey.com/Volume0/opasdata/d220001/medias/images/2745/MFG_4554.jpg)
- 规划了使用它来做车的姿态的判别。
# 总结
- 本次比赛前就“心动”ESP32-S3这款板子,拿到手玩起来,还是很有“质感”可玩性很强!虽然受到600RMB的限制,没有办法再备其他物料,但是可以累加之前比赛积攒的物料,做一个充分的再应用!希望能够是先出自己的想法!
- 期待其他爱好者的共同分享和交流!!!
- 2024-08-17
-
加入了学习《FollowMe 第二季: 1 Adafruit Circuit Playground Express及任务讲解》,观看 Adafruit Circuit Playground Express 及任务讲解
- 2024-08-11
-
加入了学习《【Follow me第二季第1期】全部任务演示》,观看 全部任务演示2.0
-
加入了学习《【Follow me第二季第1期】使用Makecode图形化完成任务》,观看 【Follow me第二季第1期】使用Makecode图形化完成任务
- 2024-07-25
-
回复了主题帖:
【Follow me第二季第1期】开箱帖:板子收到啦啦啦!!!
吾妻思萌 发表于 2024-7-25 10:26
圆的板子好好看啊~能拍细节大图吗?感谢
细节图官网有。。。先用CircuitPython试玩一下
-
回复了主题帖:
【Follow me第二季第1期】开箱帖:板子收到啦啦啦!!!
lugl4313820 发表于 2024-7-25 09:47
恭喜楼主,期待您的大作,这看起来非常小呀?
有一个网球的直径那么大
-
发表了主题帖:
【Follow me第二季第1期】开箱帖:板子收到啦啦啦!!!
板子开箱
必选板子,比预期的大!上面的物料扎实,还是可以把玩些时间的~~~
另外可选板子选了一个电机驱动的小板子!
第二季活动又可以玩起来啦~~~