- 2024-12-29
-
发表了主题帖:
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 入门任务
本帖最后由 鲜de芒果 于 2024-12-29 13:32 编辑
1. 任务要求
搭建环境并开启第一步Blink三色LED / 串口打印Hello DigiKey & EEWorld!;
2. Arduino开发环境搭建
下载 Arduino IDE
解压,将下载的 Arduino IDE 解压到磁盘中。
打开解压后的文件夹,双击 运行 Arduino IDE.exe
首次打开的 Arduino IDE 如下图所示:
3. 功能实现
3.1 原理
Arduino Nano RP2040 Connect有一个板载 共阳极 RGB 三色 LED。通过如下原理图我们可以看到,RGB LED只是三个独立的LED,它们的 阳极 或 正极 连接到相同的电源,它们的负极连接到相应的网络标签 LEDB, LEDG 和 LEDR。 网络标签用以表示它们的颜色以及连接到的相应硬件网络:
如下图所示:如果我们看一下这些标签实际上连接的位置,我们可以看到它们连接到 UBlox NINA 模块上的16、17、18引脚。所以为了使用RGB LED,我们需要通过这个WiFi模块。为此,Arduino 官方已经存在一个库供我们使用。因此我们可以很简单地实现三色RGB LED的控制。
3.2 代码实现
/**
* FollowMe 2-4 任务1:
* 1. 搭建环境并开启第一步Blink三色LED
* 2. 串口打印Hello DigiKey & EEWorld!
*/
#include <Arduino.h>
#include <WiFiNINA.h>
#define MIN_VAL 0 // PWM分辨率最小值
#define MAX_VAL 255 // PWM分辨率最大值
/**
* 呼吸灯
*/
void breathe();
void setup() {
// 初始化串口
Serial.begin(115200);
delay(1500);
// 初始化三色 LED 为输出
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
delay(1000);
// 串口打印
Serial.println("Hello DigiKey & EEWorld!");
}
void loop() {
breathe(LEDR);
breathe(LEDG);
breathe(LEDB);
// 串口打印
Serial.println("Hello DigiKey & EEWorld!");
}
/**
* 呼吸灯
*/
void breathe(NinaPin pin) {
for (int i = 0; i < 256; i++) {
analogWrite(pin, i);
delay(1);
}
for (int i = 255; i >= 0; i--) {
analogWrite(pin, i);
delay(1);
}
}
4. 效果展示
-
发表了主题帖:
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 基础任务
本帖最后由 鲜de芒果 于 2024-12-29 13:33 编辑
1. 任务要求
学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据;
2. 基础知识
IMU (Inertial Measurement Unit) 惯性测量单元是一种检测物体三轴姿态角和加速度的装置,广泛应用于运动控制和精密位移推算。
IMU 主要由三轴陀螺仪和三轴加速度计组成,有时也包括磁力计,形成所谓的 9轴IMU。它通过测量物体在三维空间中的角速度和加速度来解算出物体的姿态。加速度计用于检测载体坐标系统独立三轴的加速度信号,而陀螺仪则检测载体相对于导航坐标系的角速度信号。
IMU被广泛用于需要进行运动控制的设备,如汽车、机器人、潜艇、飞机、导弹和航天器等。在这些应用中,IMU提供的数据有助于实现自主导航和定位,提高设备的导航精度和稳定性。例如,在无人机领域,IMU可以确保飞行器在空中保持稳定,并在GPS信号弱或不可用时提供可靠的导航信息。
总的来说,IMU作为一种高精度的运动状态测量装置,在现代科技和工业领域发挥着重要作用。随着技术的不断进步,IMU的性能和应用范围有望进一步扩展和提升。
根据 Arduino Nano RP2040 Connect 官方手册,如上图所示。Arduino Nano RP2040 Connect 板载了一颗由 ST 公司生产的 LSM6DSOXTR 6轴惯性测量单元(IMU)。使用 Arduino 开发时,有很多的库可供选择用于读取 LSM6DSOXTR 数据。
3. 功能实现
3.1 IMU可视化
本任务要求只需要通过串口打印六轴原始数据,这样无法直观地感知IMU的状态。因此,考虑使用可视化的形式将数据数据展示出来,而IMU比较广泛的一个应用场景便是无人机应用。可以找到很多的无人机上位机来可视化IMU数据,这里我选择使用 匿名上位机。匿名上位机 通信协议已经定义好了数据格式,并且也是通过串口通信。我们只需要按照匿名上位机通信协议中的格式,将IMU数据通过串口进行发送即可使开发板模拟成无人机的飞行姿态,从而达到IMU数据可视化的目的。
3.2 代码实现
/**
* FollowMe 2-4 任务2:
* 1. 学习IMU基础知识,调试IMU传感器,通过串口打印六轴原始数据
*/
#include <Arduino.h>
#include <Arduino_LSM6DSOX.h>
#include "Madgwick.h"
#define DATA_MULTIPLIER 10000 // 数据放大倍数
Madgwick filter; // 初始化 Madgwic 算法过滤器,用于姿态估
float Ax, Ay, Az; // 三轴加速度计数据
float Gx, Gy, Gz; // 三轴陀螺仪数据
uint8_t send_buf[32]; // 发送数据缓存
uint8_t cnt = 0; // 打包数据索引
/**
* 根据匿名上位机通信协议打包数据,并发送至上位机
*
*/
void packData(uint8_t fun, uint8_t *data, uint8_t len);
/**
* 四元数据 数据打包发送
*/
void sendQuaternionData(int16_t dat1, int16_t dat2, int16_t dat3, int16_t dat4, uint8_t dat5);
void setup() {
// 初始化串口
Serial.begin(115200);
delay(1500);
// IMU 初始化并启动通信
while (!IMU.begin()) {
Serial.println("IMU(LSM6DSOXTR) 初始化失败, 延时1秒后重试!");
IMU.end();
delay(1000);
}
// 打印采样速率
Serial.print("加速度计采样速率 ");
Serial.print(IMU.accelerationSampleRate());
Serial.println(" Hz");
Serial.print("陀螺仪采样速率 ");
Serial.print(IMU.gyroscopeSampleRate());
Serial.println(" Hz");
}
void loop() {
// 读取加速度计数据
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(Ax, Ay, Az);
}
// 读取陀螺仪数据
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(Gx, Gy, Gz);
}
// 更新IMU数据
filter.updateIMU(Gx, Gy, Gz, Ax, Ay, Az);
// 获取四元数据
float w = filter.getQuatW();
float x = filter.getQuatX();
float y = filter.getQuatY();
float z = filter.getQuatZ();
sendQuaternionData(w * DATA_MULTIPLIER, x * DATA_MULTIPLIER, y * DATA_MULTIPLIER, z * DATA_MULTIPLIER, 0); // 发送数据至上位机
delay(50);
}
/**
* 根据匿名上位机通信协议打包数据,并发送至上位机
*/
void packData(uint8_t fun, uint8_t *data, uint8_t len) {
cnt = 0;
uint8_t i = 0;
if (len > 28) return; // 最多28字节
send_buf[cnt++] = 0XAA; // 帧头
send_buf[cnt++] = 0xAA; // 目标地址
send_buf[cnt++] = fun; // 功能字
send_buf[cnt++] = len; // 数据长度
for (i = 0; i < len; i ++) send_buf[cnt++] = data[i]; // 复制数据
uint8_t sumcheck = 0;
uint8_t addcheck = 0;
for (i = 0; i < (len + 4); i ++) {
sumcheck += send_buf[i]; // 从帧头开始,对每一字节进行求和,直到DATA区结束
addcheck += sumcheck; // 每一字节的求和操作,进行一次sumcheck的累加
}
send_buf[cnt++] = sumcheck; // 和校验
send_buf[cnt++] = addcheck; // 附加校验
for (i = 0; i < cnt; i ++) { // 通过串口发送至上位机
Serial.write(send_buf[i]);
}
}
/**
* 四元数据 数据打包发送
*/
void sendQuaternionData(int16_t dat1, int16_t dat2, int16_t dat3, int16_t dat4, uint8_t dat5) {
uint8_t tbuf[18];
tbuf[0] = dat1 & 0XFF;
tbuf[1] = (dat1 >> 8) & 0XFF;
tbuf[2] = dat2 & 0XFF;
tbuf[3] = (dat2 >> 8) & 0XFF;
tbuf[4] = dat3 & 0XFF;
tbuf[5] = (dat3 >> 8) & 0XFF;
tbuf[6] = dat4 & 0XFF;
tbuf[7] = (dat4 >> 8) & 0XFF;
tbuf[8] = dat5 & 0XFF;
packData(0x04, tbuf, 9);
}
4. 效果展示
-
发表了主题帖:
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 进阶任务
本帖最后由 鲜de芒果 于 2024-12-29 13:34 编辑
1. 任务要求
学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形。
2. 基础知识
脉冲密度调制(Pulse Density Modulation,简称PDM)是一种数字调制技术,它使用二进制数0和1来表示模拟信号的幅值。在PDM中,模拟信号的幅值通过输出脉冲对应区域的密度来表示,即1的密度越大,代表该区域对应的模拟信号幅值越大,反之亦然。
麦克风是将物理声音转换为数字数据的部件。麦克风通常用于移动终端、语音识别系统甚至游戏和虚拟现实输入设备。 Arduino Nano RP2040 Connect 开发板上有一颗 MP34DT06JTR 传感器。如下图所示:
MP34DT06JTR 传感器是一种超紧凑型麦克风,使用PDM(脉冲密度调制)用二进制信号表示模拟信号。MP34DT06JTR 传感器典型参数如下: 信噪比:64dB 灵敏度:-26dBFS ±3dB 温度范围:-40 ~ 85℃
3. 功能实现
3.1 原理
使用PDM 采集数字音频数据,然后再通过串口将数字音频数据发送至上位机,上位机再通过串口接收数字音频数据,使用曲线图绘制音频曲线。
3.2 代码实现
/**
* FollowMe 2-4 任务3:
* 1. 学习PDM麦克风技术知识,调试PDM麦克风,通过串口打印收音数据和音频波形。
*/
#include <Arduino.h>
#include <PDM.h>
static const char channels = 1; // 音频通道数,1:单通道,2:立体声
static const int frequency = 20000; // PCM 输出频率
short sampleBuffer[512]; // 音频采样缓存区
volatile uint32_t samplesRead; // 读取到的音频样本数
void setup() {
// 初始化串口
Serial.begin(115200);
delay(1500);
// 设置PDM接收回调函数
PDM.onReceive(onPDMdata);
// 增益设置,可选
// PDM.setGain(30);
// 初始化 PDM
while (!PDM.begin(channels, frequency)) {
Serial.println("PDM 初始化失败!");
PDM.end();
// 延时重试
delay(3000);
}
}
void loop() {
if (samplesRead) { // 读取到了音频数据
// 对音频数据进行处理,这里使用串口输出。上位机可通过串口展示音频波形
for (int i = 0; i < samplesRead; i++) {
Serial.println(sampleBuffer[i]);
}
// 处理完毕,清零读取到的音频样本数
samplesRead = 0;
}
}
/**
* 数据处理回调函数,用于接收PDM麦克风的数据
*/
void onPDMdata() {
// Query the number of available bytes
int bytesAvailable = PDM.available();
// Read into the sample buffer
PDM.read(sampleBuffer, bytesAvailable);
// 16-bit, 2 bytes per sample
samplesRead = bytesAvailable / 2;
}
4. 效果展示
-
发表了主题帖:
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 坐姿检测应用
本帖最后由 鲜de芒果 于 2025-1-10 19:36 编辑
一、项目介绍
随着现代办公和学习方式的改变,长时间保持不正确的坐姿可能导致多种健康问题,如腰背疼痛、颈椎疾病等。为了帮助用户实时监测和纠正坐姿,提高健康管理能力,我决定开发一款基于 Arduino Nano RP2040 Connect 的坐姿检测应用。
本项目旨在开发一套智能坐姿检测系统,利用 Arduino Nano RP2040 Connect 进行数据采集与处理。系统通过传感器实时监测用户的坐姿,并在检测到不良坐姿时提供提醒,以帮助用户改善坐姿,减少因长时间不良坐姿导致的健康问题。
二、任务要求
坐姿检测,实时坐姿检测以帮助用户纠正不良坐姿。并将坐姿状态通过蓝牙传输至 Seeed Studio XIAO ESP32S3。
蓝牙通信,坐姿数据通过蓝牙同步,以帮助用户记录或分析坐姿数据。可以进一步优化算法和增加更多功能,如定制化的坐姿建议、长期数据分析等,为用户提供更全面的健康管理服务。
Seeed Studio XIAO ESP32S3 根据接收到的坐姿状态是否良好,显示在OLED屏幕上。并且当坐姿不良时,通过蜂鸣器发出警示音。
三、 硬件准备
Arduino Nano RP2040 Connect 搭载功能丰富的 Raspberry Pi RP2040 微控制器,将其融入到 Nano 尺寸封装中。充分利用双核32位Arm® Cortex®-M0+处理器,通过U-blox® Nina W102模块实现蓝牙和WiFi连接,集速度计、陀螺仪、RGB LED和麦克风于一体,是物联网应用的不错选择。
Seeed Studio XIAO ESP32S3 Seeed Studio XIAO 系列是小型开发板,共享类似的硬件结构,尺寸实际上是拇指大小。这里的代号“XIAO”代表它的一半特征 “小”,另一半将是 “羊角面包”。 Seeed Studio XIAO ESP32S3 结合嵌入式ML计算能力和摄影能力,这款开发板可以成为您开始使用智能语音和视觉AI的绝佳工具。
四、代码实现
4.1 软件流程图
4.2 坐姿检测外设实现代码
坐姿检测外设基于本次活动开发板 Arduino Nano RP2040 Connect 来实现,搭戴一块锂电池安装到模拟设备身上进行坐姿检测。
/**
* FollowMe 2-4 任务4:
* 1. 坐姿检测
* 2. 蓝牙通信
* 3. 坐姿数据通过蓝牙传输
*/
#include <Arduino.h>
#include <ArduinoBLE.h>
#include <Arduino_LSM6DSOX.h>
#include <GyverFilters.h>
#include <WiFiNINA.h>
#include "Madgwick.h"
#define CALIB_OFFSET_NB_MES 1000 // 计算IMU零漂次数
#define DATA_MULTIPLIER 100 // 欧拉角数据放大100倍
#define SITTING_STRAIGHT_THRESHOLD 1.0 // 坐姿加速度阈值
#define TOLERANCE 0.05 // 坐姿加速度阈值允许的误差范围
GKalman xAccKalmanFilter(2, 2, 0.01); // x轴加速度计卡尔曼滤波
GKalman yAccKalmanFilter(2, 2, 0.01); // y轴加速度计卡尔曼滤波
GKalman zAccKalmanFilter(2, 2, 0.01); // z轴加速度计卡尔曼滤波
GKalman xGyroKalmanFilter(2, 2, 0.01); // x轴陀螺仪卡尔曼滤波
GKalman yGyroKalmanFilter(2, 2, 0.01); // y轴陀螺仪卡尔曼滤波
GKalman zGyroKalmanFilter(2, 2, 0.01); // z轴陀螺仪卡尔曼滤波
// 初始化 MadgwickAHRS 算法过滤器,用于姿态估
Madgwick filter;
bool isSittingPostureOk = false; // 坐姿状态是否正常
float Ax, Ay, Az; // 三轴加速度计数据
float Gx, Gy, Gz; // 三轴陀螺仪数据
float roll, pitch, yaw; // 欧拉角数据
float xAccOffset = 0; // x轴加速度计零漂
float yAccOffset = 0; // y轴加速度计零漂
float zAccOffset = 0; // z轴加速度计零漂
float xGyroOffset = 0; // x轴陀螺仪零漂
float yGyroOffset = 0; // y轴陀螺仪零漂
float zGyroOffset = 0; // z轴陀螺仪零漂
float xAcc = 0; // x轴加速度计
float yAcc = 0; // y轴加速度计
float zAcc = 0; // z轴加速度计
float xGyro = 0; // x轴陀螺仪
float yGyro = 0; // y轴陀螺仪
float zGyro = 0; // z轴陀螺仪
uint32_t previousMillis = 0; // tick
// roll = pitch = yaw = Ax = Ay = Az = Gx = Gy = Gz = 0.0f;
BLEService IMUService("19B10000-E8F2-537E-4F6C-D104768A1214"); // IMU 服务
// IMU 特征符
BLEBoolCharacteristic sittingPostureCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // 坐姿,1:正常,0:不良
BLEFloatCharacteristic xAccCharacteristic("19B10002-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // x轴加速度计
BLEFloatCharacteristic yAccCharacteristic("19B10003-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // y轴加速度计
BLEFloatCharacteristic zAccCharacteristic("19B10004-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // z轴加速度计
BLEFloatCharacteristic xGyroCharacteristic("19B10005-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // x轴陀螺仪
BLEFloatCharacteristic yGyroCharacteristic("19B10006-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // y轴陀螺仪
BLEFloatCharacteristic zGyroCharacteristic("19B10007-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify); // z轴陀螺仪
/**
* 计算陀螺仪零漂
*/
void calcOffsets(bool is_calc_gyro, bool is_calc_acc);
void setup() {
// 串口初始化
Serial.begin(115200);
delay(1500);
// 初始化三色 LED 为输出
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
// IMU 初始化并启动通信
while (!IMU.begin()) {
Serial.println("IMU(LSM6DSOXTR) 初始化失败, 延时1秒后重试!");
IMU.end();
delay(1000);
}
// 打印采样速率
Serial.print("加速度计采样速率 ");
Serial.print(IMU.accelerationSampleRate());
Serial.println(" Hz");
Serial.print("陀螺仪采样速率 ");
Serial.print(IMU.gyroscopeSampleRate());
Serial.println(" Hz");
// 蓝牙初始化
if (!BLE.begin()) {
Serial.println("starting Bluetooth® Low Energy failed!");
}
// 设置发布的蓝牙服务本地名称和服务UUID
BLE.setLocalName("IMU Device");
BLE.setAdvertisedService(IMUService);
// 添加特征码至IMU服务
IMUService.addCharacteristic(sittingPostureCharacteristic);
IMUService.addCharacteristic(xAccCharacteristic);
IMUService.addCharacteristic(yAccCharacteristic);
IMUService.addCharacteristic(zAccCharacteristic);
IMUService.addCharacteristic(xGyroCharacteristic);
IMUService.addCharacteristic(yGyroCharacteristic);
IMUService.addCharacteristic(zGyroCharacteristic);
// 绑定蓝牙服务
BLE.addService(IMUService);
// 发布服务
BLE.advertise();
}
void loop() {
// 监听蓝牙外设连接
BLEDevice central = BLE.central();
// 中心连接到外设
if (central) {
Serial.print("Connected to central: ");
Serial.println(central.address());
// 连接状态
while (central.connected()) { // 连接成功,发布数据
uint32_t currentMillis = millis();
// 读取加速度计数据与陀螺仪数据
if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
IMU.readAcceleration(Ax, Ay, Az);
IMU.readGyroscope(Gx, Gy, Gz);
xAcc = (Ax - xAccOffset); // x轴加速度计
yAcc = (Ay - yAccOffset); // y轴加速度计
zAcc = (Az - zAccOffset); // z轴加速度计
xGyro = (Gx - xGyroOffset); // x轴陀螺仪
yGyro = (Gy - yGyroOffset); // y轴陀螺仪
zGyro = (Gz - zGyroOffset); // z轴陀螺仪
isSittingPostureOk = (SITTING_STRAIGHT_THRESHOLD - TOLERANCE) <= abs(xAcc) && abs(xAcc) <= (SITTING_STRAIGHT_THRESHOLD + TOLERANCE);
if(200 <= (currentMillis - previousMillis)) {
previousMillis = currentMillis;
sittingPostureCharacteristic.writeValue(isSittingPostureOk);
xAccCharacteristic.writeValue(xAcc); // x轴加速度计
yAccCharacteristic.writeValue(yAcc); // y轴加速度计
zAccCharacteristic.writeValue(zAcc); // z轴加速度计
xGyroCharacteristic.writeValue(xGyro); // x轴陀螺仪
yGyroCharacteristic.writeValue(yGyro); // y轴陀螺仪
zGyroCharacteristic.writeValue(zGyro); // z轴陀螺仪
Serial.print(xGyro);
Serial.print(",");
Serial.print(yGyro);
Serial.print(",");
Serial.print(zGyro);
Serial.print(",");
Serial.print(xAcc);
Serial.print(",");
Serial.print(yAcc);
Serial.print(",");
Serial.print(zAcc);
Serial.print(",");
Serial.println(isSittingPostureOk);
}
}
delay(50);
}
// 连接断开
Serial.print("Disconnected from central: ");
Serial.println(central.address());
}
}
/**
* 计算陀螺仪零漂
*/
void calcOffsets(bool is_calc_gyro, bool is_calc_acc) {
if(is_calc_gyro) {
xGyroOffset = 0;
yGyroOffset = 0;
zGyroOffset = 0;
}
if(is_calc_acc) {
xAccOffset = 0;
yAccOffset = 0;
zAccOffset = 0;
}
float ag[6] = {0,0,0,0,0,0}; // 3*acc, 3*gyro
for(int i = 0; i < CALIB_OFFSET_NB_MES; i++){
if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
IMU.readAcceleration(Ax, Ay, Az);
IMU.readGyroscope(Gx, Gy, Gz);
}
ag[0] += Ax;
ag[1] += Ay;
ag[2] += (Az-1.0); // 假设设备静止且Z轴向下
ag[3] += Gx;
ag[4] += Gy;
ag[5] += Gz;
delay(10);
}
if(is_calc_acc){
xAccOffset = ag[0] / CALIB_OFFSET_NB_MES;
yAccOffset = ag[1] / CALIB_OFFSET_NB_MES;
zAccOffset = ag[2] / CALIB_OFFSET_NB_MES;
}
if(is_calc_gyro){
xGyroOffset = ag[3] / CALIB_OFFSET_NB_MES;
yGyroOffset = ag[4] / CALIB_OFFSET_NB_MES;
zGyroOffset = ag[5] / CALIB_OFFSET_NB_MES;
}
}
4.3 作品源码
项目源码下载地址:https://download.eeworld.com.cn/detail/%E9%B2%9Cde%E8%8A%92%E6%9E%9C/635463
源码说明
followme2_4_task1 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 入门任务源码,Arduino 工程。
followme2_4_task2 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 基础任务源码,Arduino 工程。
followme2_4_task3 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 进阶任务源码,Arduino 工程。
followme2_4_task4 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 坐姿检测任务外设部分源码,Arduino 工程。
followme2_4_task4_central 文件夹:【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 坐姿检测任务接收部分源码,PlatformIO Arduino 工程。
五、效果展示
5.1 坐姿检测模拟实验
5.2 坐姿正常
5.3 不良坐姿
5.4 作品演示视频
六、结语
本项目利用先进的Arduino Nano RP2040 Connect开发板,结合多种传感器和反馈机制,利用简单的硬件和软件工具帮助用户纠正不良坐姿,促进健康生活方式。实现了实时、准确的坐姿检测和纠正功能。未来,我们可以进一步优化算法和增加更多功能,如定制化的坐姿建议、长期数据分析等,为用户提供更全面的健康管理服务。
通过这个项目,我们不仅提高了对物联网技术的理解和运用能力,也学会了如何将理论转化为解决实际问题的应用。希望这些经验和心得能为未来的项目提供参考和启发。
七、参考资料
Arduino® Nano RP2040 Connect教程
Arduino® Nano RP2040 Connect数据手册
Arduino® Nano RP2040 Connect引脚定义手册
Arduino® Nano RP2040 Connect原理图
https://www.st.com/resource/en/datasheet/lsm6dsox.pdf
https://www.st.com/resource/en/datasheet/mp34dt06j.pdf
八、传送门
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 入门任务
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 基础任务
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 进阶任务
-
加入了学习《得捷电子专区》,观看 Arduino Nano RP2040 Connect 坐姿检测应用
-
加入了学习《得捷电子专区》,观看 红外温度检测及火灾报警器
-
上传了资料:
【得捷电子Follow Me第二季第4期】Arduino Nano RP2040 Connect 坐姿检测应用
- 2024-12-27
-
加入了学习《得捷电子专区》,观看 【2024 DigiKey 创意大赛】红外温度检测及火灾报警器
- 2024-10-20
-
回复了主题帖:
【2024 DigiKey 创意大赛】红外温度检测及火灾报警器
JOEYCH 发表于 2024-10-20 13:53
想问问Homeassisant是部署在哪里的呀?
NAS服务器上
- 2024-10-16
-
发表了主题帖:
【2024 DigiKey 创意大赛】红外温度检测及火灾报警器
本帖最后由 鲜de芒果 于 2024-12-27 19:40 编辑
红外温度检测及火灾报警器
作者:鲜de芒果
一、作品简介
本项目旨在开发一种基于红外技术的智能温度检测与火灾报警系统。该系统通过高精度的红外传感器,实时监测环境温度变化,识别温度异常上升的情况,并在检测到异常高温或快速升温时立即发出声光报警信号,有效预防火灾事故的发生。同时,系统具备远程监控能力,可通过无线网络将数据传输至监控中心,实现远程预警和数据分析。
该系统核心硬件包括高灵敏度红外温度传感器、微控制器单元(MCU)、声光报警模块、无线通信模块以及电源管理模块。红外传感器负责捕捉环境温度数据;MCU作为系统的大脑,处理数据并做出逻辑判断;无线通信模块实现数据的远程传输;电源管理模块确保系统稳定运行,支持电池和外部电源供电,以确保在紧急情况下的稳定运行。
二、系统框图
设计思路
设计的核心思想是集成高精度温度测量和快速反应报警机制。系统设计以高可靠性和低功耗为指导原则,确保设备在长时间运行时的可靠性和灵活性。同时,通过合理的软件设计,实现实时温度监控和智能火灾判定。
采用模块化设计思想,各部分独立又协同工作。设计上注重低功耗与高效率,确保设备能在无持续电源供应的情况下长时间运行。软件方面,采用事件驱动编程模型,优化响应速度和准确性。
系统框图
如以上系统框图所示,左右两个模块分别为左侧的传感器模块,右侧的监控模块。它们之间通过 WiFi 连接到网络进行通讯。
左侧的传感器模块主要作用是监控并采集环境温度数据,并通过 MQTT 将数据上报至公有云服务器或私有云服务器。搭载了舵机模块,可以使得监控的区域变得更加广阔,可以实现 300° 范围内对整个房间或区域进行监控。
右侧的监控模块,使用的是 ESP32-S3-DEVKITC-1-N8R8 开发板搭配一块 1.8 英寸 TFT-LCD 显示模块组成,分辨率 128 * 160。用于接收左侧传感器模块上报的环境温度数据,以及温度图的显示与异常温度警报显示。
整个系统采用模块化设计,可实现无缝接入各种云端,实现远程监控。也可以将数据对接至监控中心,实现远程预警和数据分析。
硬件介绍
ESP32-S3-DEVKITC-1-N8R8 是一款入门级开发板,搭载 Wi-Fi + Bluetooth® LE 模组 ESP32-S3-WROOM-1、ESP32-S3-WROOM-1U 或 ESP32-S3-WROOM-2。在本应用中原本打算作为主控使用,但由于体积过大,因此作为远程协控制器使用。
MLX90640ESF-BAB-000-TU 是一款远红外热像仪传感器,MLX90640远红外热传感器阵列可精确检测特定区域和温度范围内的目标物体,尺寸小巧,可方便集成到各种工业或智能控制应用中。在本应用中作为红外温度测量传感器使用。
ESP32-S3-WROOM-1U-N16R8 是一款通用型 Wi-Fi + 低功耗蓝牙 MCU 模组,搭载 ESP32-S3 系列芯片。除具有丰富的外设接口外,模组还拥有强大的神经网络运算能力和信号处理能力,适用于 AIoT 领域的多种应用场景,例如唤醒词检测和语音命令识别、人脸检测和识别、智能家居、智能家电、智能控制面板、智能扬声器等。在本应用中作为红外传感器主控使用。
SER0056 是 DFRobot 推出的一款带离合功能的 300° 转向舵机,在本应用中作为转向机构使用,使得红外监控的范围变大。
软件实现
传感器模块
软件方面参考了很多成熟方案,综合评比各方面功能最终决定采用 ESPHome 完成固件开发。ESPHome 是一个通过简单而强大的配置文件控制您的 ESP8266/ESP32 的系统,并通过家庭自动化系统远程控制它们。
监控模块
监控模块采用 CircuitPython 进行开发。CircuitPython 是一种编程语言,目的是希望能在低成本微控制器板上用简化的Python进行编程。它使入门比以往更容易,无需预先下载桌面。设置好电路板后,打开任何文本编辑器,然后开始编辑代码,就这么简单。
三、各部分功能说明
红外温度采集
利用 ESP32-S3 的强大处理能力和 MLX90640 的高灵敏度红外测温功能,使用 ESPHome 环境下构建一个实时温度监测系统。通过ESP32-S3读取 MLX90640 传感器的温度数据,并通过 Wi-Fi 将数据传输到云端或本地服务器进行进一步分析和处理。以下是关键代码实现:
# 红外摄像头 MLX90640
camera_mlx90640:
id: thermal_cam
update_interval: 1s # 温度数据更新间隔
sda: 4 # I2C SDA PIN
scl: 5 # I2C SCL PIN
frequency: 400000 # I2C Clock Frequency
address: 0x33 # MLX90640 Address
mintemp: 0 # Minimal temperature for color mapping
maxtemp: 90 # Maximal temperature for color mapping
refresh_rate: 0x05 # For 16Hz or 0x04 for 8Hz
filter_level: 10.0 # 温度数据过滤等级
min_temperature:
id: mlx90640_min
name: "MLX90640 最小温度"
max_temperature:
id: mlx90640_max
name: "MLX90640 最大温度"
mean_temperature:
id: mlx90640_mean
name: "MLX90640 平均温度"
median_temperature:
id: mlx90640_median
name: "MLX90640 中间温度"
上述代码为 ESPHome 采集 MLX90640 温度数据的实现,可对温度数据进行平滑过滤。实现 最小温度、最大温度、平均温度、中间温度 的采集,采集的温度还可以通过 Wi-Fi 将数据传输到云端或本地服务器进行进一步分析和处理。下图为智能家居平台以可视化形式将温度展示出来。
电池电压采集
通过测量电池单体或电池组的电压值,来监测电池的工作状态和健康程度。这一功能对于确保电池在安全范围内运行、预防过充过放、延长电池寿命等方面具有重要意义。
ESP32-S3的ADC模块具有高精度和高分辨率的特点,能够准确测量电池电压的变化。通过选择合适的 GPIO 引脚和衰减倍数,ESP32-S3 可以灵活适应不同电压范围的测量需求。
本项目中,使用两颗 470KΩ 的电阻分压后,接入 ESP32-S3 的 IO2 引脚。如下图所示,可在智能家居平台可看电池电压的历史数据。
环境温度数据发布
MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,广泛应用于物联网设备之间的通信。其基于发布/订阅模式,能够实现高效、可靠的数据传输。在环境温度数据发布功能中,MQTT协议扮演着至关重要的角色,确保温度数据从传感器节点准确无误地传输到云平台或监控中心。以下为温度数据发布的实现,以 1Hz 的频率进行发布,确保温度数据实时准确地发布至云平台、监控节点或监控中心。
time:
- platform: homeassistant
on_time:
# 每秒发布温度数据,包含 最小温度、最大温度、平均温度、中值温度
- seconds: /1
then:
- mqtt.publish_json:
topic: "/esphome/sensor/mlx90640"
payload: |-
root["min"] = id(mlx90640_min).state;
root["max"] = id(mlx90640_max).state;
root["mean"] = id(mlx90640_mean).state;
root["median"] = id(mlx90640_min).state;
智能家居平台集成
智能家居平台能够实现设备的互联互通和集中控制,提供简单易懂的用户界面和操作方式,同时采取严格的安全措施来保护用户的信息和设备的安全。通过实时监测环境温度并上传到智能家居平台,可以实现对家居环境的智能化控制和管理。例如,当室内温度过高时,智能家居平台可以自动打开空调进行降温;当室外温度过低时,可以触发暖气设备的开启等。这种集成功能不仅提高了居住环境的舒适度和便利性,还有助于节能减排和环保。当然本例中的作用为监控环境温度更重要的是监控并预警火灾的发生,通过与智能家居平台集成后,可以很方便地实现异常温升的报警与监控,同时如果有其它辅助灭火的智能设备,还可以进行联动控制进行灭火操作,进一步且更智能化地保障人们的生命与财产安全。
下图为智能家居平台集成后的控制面板展示:
温度可视化
通过其红外温度可视化功能,用户可以将不可见的红外辐射转化为可见的热图像,从而直观地了解物体表面的温度分布情况。
MLX90640通过其内部的红外热电堆阵列接收物体表面的红外辐射,并将其转换为电信号。这些电信号经过处理后,可以得到物体表面各点的温度值。然后,通过特定的算法将这些温度值转化为热图像,并在屏幕上进行显示。用户可以通过观察热图像来了解物体表面的温度分布情况,从而进行进一步的分析和应用。
下图为通过算法将温度值转化为热图像后的效果图,分另为两根手指加一个热源和一个手掌的温度数据转换后的热图像:
异常温度警报
异常温度警报是一种基于温度监测的安全预警机制,旨在及时发现并提醒用户潜在的温度异常情况,以防止火灾、设备过热等危险事件的发生。
异常温度警报功能广泛应用于各种场所,如工厂、仓库、数据中心、医院、学校等。在这些场所中,由于设备运行、人员活动等原因,可能存在温度异常的风险。通过部署异常温度警报系统,可以及时发现并处理这些风险,保障人员和财产的安全。同时,该功能还可以应用于智能家居领域,为用户提供更加舒适和安全的居住环境。
异常温度警报功能通常由温度传感器、数据处理单元和警报系统组成。温度传感器负责实时监测特定区域或设备的温度数据,并将数据传输至数据处理单元。数据处理单元对接收的温度数据进行分析,判断是否存在异常温度情况。一旦检测到异常温度,数据处理单元会立即触发警报系统,发出声光或其他形式的警报信号,以提醒用户采取相应措施。
在本应用中使用监控单元,远程监控最大温度的异常温度情况,出现异常温度则以红色字体形式表示最大温度。
正常温度效果图
异常温度效果图,实际为在传感器前方点燃了一盏酒精灯
启动或关闭区域自动扫描
区域自动扫描功能是一种智能化的功能,它允许设备在设定的区域内自动进行扫描,以获取相关信息或数据。这种功能广泛应用于各种领域,如安全监控、环境监测、智能家居等。通过启动或关闭该功能,用户可以灵活地控制设备的扫描行为,以满足不同的应用需求。
本项目中使用的温度传感器 MLX90640ESF-BAB-000-TU 在 X 轴方向只有 55°,Y 轴方向只有 35° 的视角。因此想要对大片区域监控需要借助一个可转动机构进行扫描来实现,类似摄像头的云台功能。本项目中选用了一个 SER0056 舵机来实现 X 轴的控制来实现范围扫描。如需要实现更大范围的扫描可以通过再增加一个舵机,实现 Y 轴方面的扫描。硬件上已实现两路舵机的控制。
当用户需要对设定的区域进行自动扫描时,可以通过特定的操作来启动扫描功能。可通过智能家居平台上的启动自动扫描开关来发送远程指令。一旦扫描功能被启动,设备将开始按照预设的 X 轴路径每 5秒 转动一次角度对目标区域进行扫描。
四、作品源码
项目源码下载地址:https://download.eeworld.com.cn/detail/%E9%B2%9Cde%E8%8A%92%E6%9E%9C/634584
源码说明
传感器模块源码 目录下为 ESPHome 项目源码,使用 ESPHome 进行编译。
监控模块源码 目录下为 CircuitPython 项目源码,需要先烧录 CircuitPython 固件后,将源码拷贝至设备中运行。
adafruit-circuitpython-espressif_esp32s3_devkitc_1_n8r2-en_US-8.2.6.bin 文件为项目中使用的 CircuitPython 固件, 可使用 ESPTools 进行烧录,也可使用 CircuitPython 的 Web-tools 进行烧录。
五、作品功能演示视频
六、项目总结
红外温度检测及火灾报警器通过集成高效传感器和可靠处理器,实现了实时温度监控和火灾早期预警的功能。它为提升安全预防措施提供了一种智能化解决方案,具有广泛的应用前景。然而,还通过远程监控技术实现了对潜在风险的早期识别与及时响应。未来,我们计划进一步优化算法,增强系统的智能化水平,如引入机器学习算法以提高误报率的降低,并探索更多应用场景,为公共安全贡献更大力量。
最后,感谢电子工程世界与得捷电子联合举办的【2024 DigiKey 创意大赛】活动,非常荣幸第一次参与这个活动。本次活动使我学到了不少的新知识,在项目过程中也遇到不少困难,最终实现的成品虽然有些潦草,但好在最终实现了相应的功能。祝愿 EEWorld 越办越好!
七、参考文献
https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html
https://esphome.io/
https://www.arduino.cc/
https://github.com/infotronic218/esphome-mlx9060
https://circuitpython.org/board/espressif_esp32s3_devkitc_1_n8r8/
https://docs.circuitpython.org/en/9.1.x/docs/index.html
八、项目文档
-
上传了资料:
【2024-DigiKey-创意大赛】红外温度检测及火灾报警器源码
- 2024-10-02
-
加入了学习《智能书房》,观看 智能书房
-
发表了主题帖:
【Follow me第二季第2期】智能家居之智能书房
本帖最后由 鲜de芒果 于 2024-10-2 17:28 编辑
1. 任务要求
通过外部LTR-329 环境光传感器,上传温湿度到HA,通过HA面板显示数据
通过外部AHT20温湿度传感器,上传温湿度到HA,通过HA面板显示数据
使用板载LED模拟台灯,可通过HA面板控制其开关与亮度调节
书房自动光线调节是一个智能书房的重要组成部分,它能够根据环境光线的变化自动调整台灯的亮度或开关状态,以确保阅读或工作时的光线既充足又舒适
2. 硬件准备
Arduino UNO R4 WiFi 开发板 * 1块
Adafruit LTR-329 Light Sensor 环境光传感器模块 * 1块
Adafruit AHT20 - Temperature & Humidity Sensor Breakout Board 温湿度传感器模块 * 1块
STEMMA QT / Qwiic JST SH 4-pin Cable 连接线 * 2根
3. HomeAssistant集成
**MQTT** 设备的发现将使人们能够在 [HomeAssistant](https://www.home-assistant.io) 方面只需要很少的配置工作就可以使用 **MQTT** 设备。配置是在设备本身和设备使用的主题上完成的。
> MQTT 发现默认启用,但可以禁用。发现主题的前缀(默认:`homeassistant`)可以更改。配置详情请参阅 [MQTT 选项部分](https://www.home-assistant.io/integrations/mqtt#configure-mqtt-options)
3.1 配置主题
向 MQTT 发送配置主题后, HomeAssistant 会自动发现当前传感器。 当前任务中使用了一个板载LED灯,作为 HomeAssistant 中的 Light 组件。该组件在 HomeAssistant 的 仪表盘 中可以远程控制板载LED的开和关。使用 MQTT 客户端向配置主题发送消息即可。本项目中使用了三个传感器 + 一个台灯,具体配置主题如下:
// 台灯 消息
{
"name":"table-lamp",
"device_class": "light",
"command_topic":"homeassistant/light/FollowMe2-2-table-lamp/switch",
"state_topic":"homeassistant/sensor/FollowMe2-2/state",
"brightness_command_topic": "homeassistant/light/FollowMe2-2-table-lamp/brightness/set",
"brightness_state_topic": "homeassistant/sensor/FollowMe2-2/state",
"state_value_template": "{{ value_json.builtinLed }}",
"brightness_value_template": "{{ value_json.brightness }}",
"unique_id":"FollowMe2-2-table-lamp",
"device":{
"identifiers":[
"Arduino UNO R4 WiFi"
],
"name":"UNO R4 WiFi",
"manufacturer": "Arduino",
"model": "UNO R4 WiFi",
"hw_version": "1.0"
}
}
// 书房 温度传感器 消息
{
"device_class":"temperature",
"state_topic":"homeassistant/sensor/FollowMe2-2/state",
"unit_of_measurement":"°C",
"value_template":"{{ value_json.temperature}}",
"unique_id":"FollowMe2-2-study-temperature",
"device":{
"identifiers":[
"Arduino UNO R4 WiFi"
],
"name":"UNO R4 WiFi",
"manufacturer": "Arduino",
"model": "UNO R4 WiFi",
"hw_version": "1.0"
}
}
// 书房 湿度传感器 消息
{
"device_class":"humidity",
"state_topic":"homeassistant/sensor/FollowMe2-2/state",
"unit_of_measurement":"%",
"value_template":"{{ value_json.humidity}}",
"unique_id":"FollowMe2-2-study-humidity",
"device":{
"identifiers":[
"Arduino UNO R4 WiFi"
],
"name":"UNO R4 WiFi",
"manufacturer": "Arduino",
"model": "UNO R4 WiFi",
"hw_version": "1.0"
}
}
// 书房 环境光传感器 消息
{
"device_class":"illuminance",
"state_topic":"homeassistant/sensor/FollowMe2-2/state",
"unit_of_measurement":"lx",
"value_template":"{{ value_json.ambientLight}}",
"unique_id":"FollowMe2-2-study-illuminance",
"device":{
"identifiers":[
"Arduino UNO R4 WiFi"
],
"name":"UNO R4 WiFi",
"manufacturer": "Arduino",
"model": "UNO R4 WiFi",
"hw_version": "1.0"
}
}
4. 代码实现
/**
* FollowMe 2-2 任务4:
* 1. 通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
*/
#include <Wire.h>
#include <WiFiS3.h>
#include <ArduinoMqttClient.h>
#include <ArduinoJson.h>
#include <Adafruit_AHTX0.h>
#include <Adafruit_LTR329_LTR303.h>
#include "arduino_secrets.h"
#define LOOP_DELAY 10 // loop函数延时(单位:毫秒)
#define SENSOR_REPORT_INTERVAL 5 // 传感器数据更新间隔(单位:秒)
#define STATE_ON "ON" // HA LED开状态
#define STATE_OFF "OFF" // HA LED关状态
char ssid[] = SECRET_SSID; // WIFI SSID
char pass[] = SECRET_PASS; // WIFI PASSWD
int status = WL_IDLE_STATUS; // WIFI 状态
// MQTT
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "192.168.2.120"; // HomeAssistant MQTT服务器地址
int port = 1883; // HomeAssistant MQTT服务器端口
char mqtt_user[] = MQTT_USER; // MQTT 用户名
char mqtt_pass[] = MQTT_PASS; // MQTT 密码
// 订阅主题(接收 HomeAssistant 控制板载LED开关指令)
const char switch_subscribe_topic[] = "homeassistant/light/FollowMe2-2-table-lamp/switch";
// 订阅主题(接收 HomeAssistant 控制板载LED亮度调节指令)
const char brightness_subscribe_topic[] = "homeassistant/light/FollowMe2-2-table-lamp/brightness/set";
bool isNeedReportState = true; // 是否需要更新状态到HA
bool ledState = false; // 板载LED状态
// 发布主题(上报板载LED状态至 HomeAssistant的状态主题)
const char publish_topic[] = "homeassistant/sensor/FollowMe2-2/state";
uint32_t tick = 0; // loop循环次数
uint8_t brightness = 0; // 灯亮度调节
Adafruit_AHTX0 aht; // AHT20 传感器
float temperature = 0; // AHT20 采集到的温度值
float humidity = 0; // AHT20 采集到的湿度值
Adafruit_LTR329 ltr = Adafruit_LTR329(); // LTR329传感器
float ambientLight = 0; // 环境光强度
ltr329_gain_t gain = LTR3XX_GAIN_1; // ALS增益
ltr329_integrationtime_t integrationTime = LTR3XX_INTEGTIME_100; // 积分时间
float integrationTimeVal = 0.1;
uint16_t visible_plus_ir; // 可见光
uint16_t infrared; // 红外
/**
* 设置板载LED状态
*/
void setLightState() {
if (ledState) {
if(0 == brightness) {
brightness = 255;
}
analogWrite(LED_BUILTIN, brightness);
} else {
analogWrite(LED_BUILTIN, 0);
}
}
void setup() {
// 初始化串口
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT); // 初始化板载LED引脚为输出
// 初始化 QWIIC 接口的 I2C 总线
Wire1.begin();
// 检查WIFI模块
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("WiFi模块通信失败!");
while (true);
}
// 连接到WIFI
Serial.print("尝试连接到 WIFI SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
Serial.print(".");
delay(5 * 1000);
}
Serial.println("WIFI 连接成功!");
// 连接MQTT
mqttClient.setUsernamePassword(mqtt_user, mqtt_pass);
Serial.print("尝试连接到MQTT服务器: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT 连接失败! ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("MQTT连接成功!");
// 订阅主题
mqttClient.onMessage(onMqttMessage);
mqttClient.subscribe(switch_subscribe_topic);
mqttClient.subscribe(brightness_subscribe_topic);
// AHT20 初始化
if (!aht.begin(&Wire1)) {
Serial.println("未找到 AHTX0 传感器!");
while (1) delay(10);
}
Serial.println("AHTX0 传感器初始化成功!");
if (!ltr.begin(&Wire1)) {
Serial.println("未找到 LTR329 传感器!");
while (1) delay(10);
}
Serial.println("LTR329 传感器初始化成功!");
}
void loop() {
if(isNeedReportState) {
// 汇报当前板载LED状态到HA
char msg[100] = {0};
sprintf(msg, "{\"builtinLed\": \"%s\", \"brightness\": %d,\"temperature\":%.2f,\"humidity\":%.2f, \"ambientLight\":%.2f}",
ledState ? STATE_ON : STATE_OFF, brightness, temperature, humidity, ambientLight);
mqttClient.beginMessage(publish_topic);
mqttClient.print(msg);
mqttClient.endMessage();
isNeedReportState = false; // 上报板载LED状态到HA后重置汇报状态
}
if(0 == (tick % (SENSOR_REPORT_INTERVAL * 1000 / LOOP_DELAY))) { // 根据传感器数据更新间隔 SENSOR_REPORT_INTERVAL 宏定义进行上报传感器数据
// 读取 AHT20 传感器数据
sensors_event_t humi, temp;
aht.getEvent(&humi, &temp);
temperature = temp.temperature;
humidity = humi.relative_humidity;
// 读取 LTR329 传感器数据
if (ltr.newDataAvailable()) {
ltr.readBothChannels(visible_plus_ir, infrared);
// 环境光照度计算
float ratio = infrared / (visible_plus_ir + infrared);
if(ratio < 0.45) {
ambientLight = (1.7743 * visible_plus_ir + 1.1059 * infrared) / (1 << gain) / integrationTimeVal;
} else if(ratio < 0.64 && ratio >= 0.45) {
ambientLight = (4.2785 * visible_plus_ir - 1.9548 * infrared) / (1 << gain) / integrationTimeVal;
} else if(ratio < 0.85 && ratio >= 0.64) {
ambientLight = (0.5926 * visible_plus_ir + 0.1185 * infrared) / (1 << gain) / integrationTimeVal;
} else {
ambientLight = 0;
}
}
// 更新状态,更新传感器数据到HA
isNeedReportState = true;
}
// 更新板载LED状态
setLightState();
mqttClient.poll(); // 定期检查新MQTT消息
delay(LOOP_DELAY); // 主循环延时时长
tick ++;
}
// MQTT 订阅消息回调,接收HA控制板载LED的指令(ON:开,OFF:关)
void onMqttMessage(int messageSize) {
char topic[100] = {0};
String message;
// 打印消息主题
Serial.print("Received message from topic: ");
strcpy(topic, mqttClient.messageTopic().c_str());
Serial.println(topic);
// 读取消息内容
for (int i = 0; i < messageSize; i++) {
message += (char)mqttClient.read();
}
// 打印消息的内容
Serial.print("Received message: ");
Serial.println(message);
if(0 == strcmp(switch_subscribe_topic, topic)) {
// 开关
if(0 == strcmp(STATE_ON, message.c_str())) {
if(false == ledState) {
// 需要更新板载LED状态到HA
isNeedReportState = true;
}
ledState = true;
} else {
if(true == ledState) {
// 需要更新板载LED状态到HA
isNeedReportState = true;
}
ledState = false;
}
} else if(0 == strcmp(brightness_subscribe_topic, topic)) {
// 亮度
uint8_t b = message.toInt();
if (brightness < 0 || brightness > 255) { // 范围校验
// do nothing...
return;
} else {
brightness = b;
setLightState();
isNeedReportState = true;
}
}
}
5. 智能家居自动化
本项目中结合 Adafruit LTR-329 Light Sensor 环境光传感器模块作为书房环境光照监测。当光照低于阀值时,自动打开台灯(本例中没有对接真实的智能台灯,使用板载LED模拟,可以控制开关与亮度)。光照充足时自动关闭台灯。实现自动调整书房光线,无需手动干预。在节能方面,避免不必要的照明,节省电力。同时保持书房光线在最佳水平,保护眼睛,提高阅读和工作效率。
6. 效果展示
7. 演示视频
8. 结语
Arduino Uno R4 WiFi智能书房是一个基于Arduino Uno R4开发板和ESP8266 Wi-Fi模块的智能家居项目。这个项目的主要功能是通过Wi-Fi连接,实现对书房内环境以及各种设备的远程控制和管理。
通过这个项目,我们不仅提高了对物联网技术的理解和运用能力,也学会了如何将理论转化为解决实际问题的应用。希望这些经验和心得能为未来的项目提供参考和启发。
9. 参考资料
https://docs.arduino.cc/tutorials/uno-r4-wifi/r4-wifi-getting-started/
https://edm.eeworld.com.cn/Arduino_UNO_R4_WiFi-schematics.pdf
https://mm.digikey.com/Volume0/opasdata/d220001/medias/docus/5407/ABX00087_Web.pdf
https://www.eeworld.com.cn/huodong/digikey_follow_me_2024_02/image/Arduino_UNO_R4_WiFi_pinout.png
10. 传送门
【Follow me第二季第2期】智能家居之智能书房 - 入门任务
【Follow me第二季第2期】智能家居之智能书房 - 基础任务
【Follow me第二季第2期】智能家居之智能书房 - 进阶任务
11. 项目源码
- 2024-09-08
-
发表了主题帖:
【Follow me第二季第2期】智能家居之智能书房 - 进阶任务
本帖最后由 鲜de芒果 于 2024-9-8 15:13 编辑
1. 任务要求
通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
2. HomeAssistant集成
MQTT 设备的发现将使人们能够在 HomeAssistant 方面只需要很少的配置工作就可以使用 MQTT 设备。配置是在设备本身和设备使用的主题上完成的。
MQTT 发现默认启用,但可以禁用。发现主题的前缀(默认:homeassistant)可以更改。配置详情请参阅 MQTT 选项部分
2.1 配置主题
向 MQTT 发送配置主题后, HomeAssistant 会自动发现当前传感器。 当前任务中使用了一个板载LED灯,作为 HomeAssistant 中的 Light 组件。该组件在 HomeAssistant 的 仪表盘 中可以远程控制板载LED的开和关。使用 MQTT 客户端向配置主题发送消息即可,配置主题如下:
// 板载LED灯 主题消息
{
"name":"led-builtin-Light",
"device_class": "light",
"command_topic":"homeassistant/light/FollowMe2-2-LED_BUILTIN/switch",
"state_topic":"homeassistant/sensor/FollowMe2-2/state",
"state_value_template": "{{ value_json.builtinLed }}",
"unique_id":"FollowMe2-2-LED_BUILTIN-light",
"device":{
"identifiers":[
"Arduino UNO R4 WiFi"
],
"name":"UNO R4 WiFi",
"manufacturer": "Arduino",
"model": "UNO R4 WiFi",
"hw_version": "1.0"
}
}
3. 代码实现
/**
* FollowMe 2-2 任务3:
* 1. 通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
*/
#include <WiFiS3.h>
#include <ArduinoMqttClient.h>
#include <ArduinoJson.h>
#include "arduino_secrets.h"
#define STATE_ON "ON" // HA LED开状态
#define STATE_OFF "OFF" // HA LED关状态
char ssid[] = SECRET_SSID; // WIFI SSID
char pass[] = SECRET_PASS; // WIFI PASSWD
int status = WL_IDLE_STATUS; // WIFI 状态
// MQTT
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "192.168.2.120"; // HomeAssistant MQTT服务器地址
int port = 1883; // HomeAssistant MQTT服务器端口
char mqtt_user[] = MQTT_USER; // MQTT 用户名
char mqtt_pass[] = MQTT_PASS; // MQTT 密码
// 订阅主题(接收 HomeAssistant 控制板载LED开关指令)
const char subscribe_topic[] = "homeassistant/light/FollowMe2-2-LED_BUILTIN/switch";
bool isNeedReportLedState = true; // 是否需要更新板载LED状态到HA
bool ledState = false; // 板载LED状态
// 发布主题(上报板载LED状态至 HomeAssistant的状态主题)
const char publish_topic[] = "homeassistant/sensor/FollowMe2-2/state";
void setup() {
// 初始化串口
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT); // 初始化板载LED引脚为输出
// 检查WIFI模块
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("WiFi模块通信失败!");
while (true);
}
// 连接到WIFI
Serial.print("尝试连接到 WIFI SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
Serial.print(".");
delay(5 * 1000);
}
Serial.println("WIFI 连接成功!");
// 连接MQTT
mqttClient.setUsernamePassword(mqtt_user, mqtt_pass);
Serial.print("尝试连接到MQTT服务器: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT 连接失败! ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("MQTT连接成功!");
// 订阅主题
mqttClient.onMessage(onMqttMessage);
mqttClient.subscribe(subscribe_topic);
}
void loop() {
if(isNeedReportLedState) {
// 汇报当前板载LED状态到HA
char msg[30] = {0};
sprintf(msg, "{\"builtinLed\": \"%s\"}", ledState ? STATE_ON : STATE_OFF);
mqttClient.beginMessage(publish_topic);
mqttClient.print(msg);
mqttClient.endMessage();
isNeedReportLedState = false; // 上报板载LED状态到HA后重置汇报状态
}
// 更新板载LED状态
if(ledState) { // 亮
digitalWrite(LED_BUILTIN, HIGH);
} else { // 灭
digitalWrite(LED_BUILTIN, LOW);
}
mqttClient.poll(); // 定期检查新MQTT消息
}
// MQTT 订阅消息回调,接收HA控制板载LED的指令(ON:开,OFF:关)
void onMqttMessage(int messageSize) {
// 读取消息内容
String message;
for (int i = 0; i < messageSize; i++) {
message += (char)mqttClient.read();
}
// 打印消息的内容
Serial.print("Received message: ");
Serial.println(message);
if(0 == strcmp(STATE_ON, message.c_str())) {
if(false == ledState) {
// 需要更新板载LED状态到HA
isNeedReportLedState = true;
}
ledState = true;
} else {
if(true == ledState) {
// 需要更新板载LED状态到HA
isNeedReportLedState = true;
}
ledState = false;
}
}
4. 效果展示
智能家居平台HA(HomeAssistant)中操作关灯后的效果
智能家居平台HA(HomeAssistant)中操作开灯后的效果
串口打印日志
效果动图
-
发表了主题帖:
【Follow me第二季第2期】智能家居之智能书房 - 基础任务
1. 任务要求
驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
2. 硬件准备
Arduino R4 WIFI板子上自带一个内置的放大器,可以将 A1 引脚作为正向输入、A2 引脚作为反向输入、A3 引脚作为输出。电压放大器,顾名思义是放大电压的。一个简单的 2 倍放大器可以使用两个 10k 电阻来构建,计算公式如上图所示。在反向输入 和 GND 之间连接一个电阻。然后使用第二个电阻连接输出和 反向输入 在一起。电路图如下所示。在 正向输入 的任何信号现在将以输出引脚的两倍幅度出现。注意,输入信号 和Arduino板应该共享同一个 GND。这里我将 A0 引脚作为 DAC 输出连接到 A1 引脚,作为放大器的正向输入。
3. 代码实现
/**
* FollowMe 2-2 任务2:
* 1. 驱动12x8点阵LED;
* 2. 用DAC生成正弦波;
* 3. 用OPAMP放大DAC信号;
* 4. 用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
*/
#include "Arduino_LED_Matrix.h"
#include "analogWave.h"
#include "OPAMP.h"
// LED矩阵
ArduinoLEDMatrix matrix;
// 使用DAC(A0)引脚模拟波形
analogWave wave(DAC);
uint32_t tick = 0;
bool isWink = false;
int freq = 10; // 正弦波频率
void setup() {
// 初始化串口
Serial.begin(115200);
// LED矩阵初始化
matrix.begin();
delay(1000);
// 初始化ADC
// 根据指定正弦波频率产生正弦波
wave.sine(freq);
// 限制 DAC 正弦波幅值,避免经过放大后超出ADC的随范围而导致器件损坏
wave.amplitude(0.2f);
// 开启放大器
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
}
// LED 矩阵帧映射
uint8_t frame[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
// 绘制微笑表情 左眼
void leftEye(){
frame[1][3] = 1;
frame[1][4] = 1;
frame[2][3] = 1;
frame[2][4] = 1;
}
// 绘制微笑表情 右眼
void rightEye(){
frame[1][8] = 1;
frame[1][9] = 1;
frame[2][8] = 1;
frame[2][9] = 1;
}
// 绘制微笑表情 嘴吧
void mouth(){
frame[5][3] = 1;
frame[5][9] = 1;
frame[6][3] = 1;
frame[6][4] = 1;
frame[6][5] = 1;
frame[6][6] = 1;
frame[6][7] = 1;
frame[6][8] = 1;
frame[6][9] = 1;
}
// 绘制微笑表情 眨右眼
void wink(){
frame[1][3] = 0;
frame[1][4] = 0;
frame[2][3] = 1;
frame[2][4] = 1;
}
// 绘制微笑表情 眨双眼
void winkAll(){
frame[1][3] = 0;
frame[1][4] = 0;
frame[1][8] = 0;
frame[1][9] = 0;
}
void loop(){
if(0 == (tick % 1000)) {
if(isWink) {
// wink();
winkAll(); // 眨双眼
// 使用LED矩阵渲染 眨双眼微笑表情
matrix.renderBitmap(frame, 8, 12);
isWink = false;
} else {
// 生成微笑表情
leftEye();
rightEye();
mouth();
// 使用LED矩阵渲染 微笑表情
matrix.renderBitmap(frame, 8, 12);
isWink = true;
}
}
Serial.println(analogRead(A4));
delay(1); // 延时1毫秒
tick ++;
}
4. 效果展示
下图为使用面包板搭建的 2 倍放大电路,从左侧的示波器可看出 蓝色曲线 为 DAC 输出信号,幅值上限大概 1V 左右,黄色曲线为放大 2 倍后的信号,可以看到频率是一样的,幅值为 DAC 输出信号的 2 倍。
下图为使用 ADC 采样的 DAC 输出信号放大后的结果,使用串口发送数据到电脑端的上位机 Vofa+ 绘制的图形。可以看到最大值为 413
, ADC 使用 10bit 精度进行采样,得出放大后的信号最大约为:2V
-
发表了主题帖:
【Follow me第二季第2期】智能家居之智能书房 - 入门任务
本帖最后由 鲜de芒果 于 2024-9-8 15:11 编辑
1. 任务要求
搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
2 . Arduino开发环境搭建
下载 Arduino IDE
解压,将下载的 Arduino IDE 解压到磁盘中。
打开解压后的文件夹,双击 运行 Arduino IDE.exe
首次打开的 Arduino IDE 如下图所示:
3. 代码实现
/**
* FollowMe 2-2 任务1:
* 1. 搭建环境并开启第一步Blink
* 2. 串口打印 Hello EEWorld!
*/
#define MIN_VAL 0 // PWM分辨率最小值
#define MAX_VAL 255 // PWM分辨率最大值
uint32_t tick = 0; // loop 循环次数
uint32_t fadeValue = 0; // 呼吸灯PWM占空比
uint8_t fadeStep = 5; // 呼吸灯步长
bool isFadeIn = true; // 当前呼吸灯状态,true:表示由暗转亮,false:表示由亮转暗
void setup() {
// 初始化串口
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
delay(1000);
// 串口打印
Serial.println("Hello EEWorld!");
}
void loop(){
if(0 == (tick % 40)) { // 每隔1秒串口打印一次loop函数当前循环次数。loop中每次执行延时25毫秒,因此,loop每执行40次正好是1秒钟。
Serial.print("loop count: "); // 打印loop函数当前循环次数
Serial.println(tick);
}
// PWM输出驱动板载LED
analogWrite(LED_BUILTIN, fadeValue);
// 呼吸灯由暗转亮
if(isFadeIn) {
fadeValue += fadeStep;
if(MAX_VAL <= fadeValue) {
// 当呼吸灯PWM占空比大于等于 PWM 分辨率最大值时,翻转呼吸灯状态。
fadeValue = MAX_VAL;
isFadeIn = !isFadeIn;
}
} else { // 呼吸灯由亮转暗
fadeValue -= fadeStep;
if(MIN_VAL >= fadeValue) {
// 当呼吸灯PWM占空比小于等于 PWM 分辨率最小值时,翻转呼吸灯状态。
fadeValue = MIN_VAL;
isFadeIn = !isFadeIn;
}
}
delay(25); // 每30毫秒更新一次PWM占空比
tick ++;
}
4. 效果展示
-
发表了主题帖:
【2024 DigiKey 创意大赛】红外温度检测及火灾报警器 - 搞定红外热成像图像生成
随着科技的不断进步,安全监控领域也迎来了创新技术的融合。其中,红外温度检测技术和火灾报警器的红外矩阵成像技术是两个重要的发展方向。这些技术的应用不仅提高了火灾预防和响应的效率,还增强了我们对潜在危险区域的监控能力。今天,我们将深入探讨这两种技术的原理、优势以及它们如何共同作用于提升火灾安全系统的整体性能。
一、红外温度检测技术概述 红外温度检测技术利用物体表面发射的红外辐射来测量其温度。该技术基于所有物体根据其温度会发出红外辐射这一物理特性。通过专业的红外传感器,我们可以无需接触即可快速准确地获取目标的温度信息。在火灾防控中,这种非接触式的温度监测对于早期发现过热现象至关重要,从而可以及时采取措施防止火情发生。
二、火灾报警器红外矩阵成像技术 红外矩阵成像技术则是将多个红外传感器组合成一个阵列,用于构建热像图或热分布图。这种技术能够提供更广阔的视角和更高的分辨率,使得监控区域的温度分布一目了然。在火灾报警系统中,红外矩阵成像可以帮助操作人员快速定位热点区域,并实时监控火势发展,为紧急疏散和火灾扑救提供了宝贵的时间。
三、技术结合的优势 当红外温度检测与红外矩阵成像技术相结合时,我们得到的是一个高度精确且响应迅速的安全监控系统。这样的系统不仅可以在火灾发生初期就进行预警,还能够持续追踪火源的位置变化,为消防人员的救援行动提供关键信息。此外,这种技术的组合还可以减少误报的可能性,因为通过成像技术可以直观地确认温度异常是否真的由火灾引起。
本次分享红外热成像生成的bmp图片两张,分别位置红外传感器前方大概15厘米处拍摄所得,依稀能辨别出手势为五指分开与双指分开。
双指分开的旁边,可以看到有一个热源,是远处的灯板。
结语: 红外温度检测与火灾报警器红外矩阵成像技术的结合代表了现代火灾预防和控制领域的前沿方向。通过不断的技术创新和应用实践,我们有望建立一个更加智能、高效的火灾安全网络,保护人们的生命财产安全不受火灾威胁。随着这些技术的不断完善和普及,未来的火灾防控工作将变得更加科学和精准。
- 2024-08-12
-
发表了主题帖:
【2024 DigiKey 创意大赛】红外温度检测及火灾报警器 - 物料开箱
本帖最后由 鲜de芒果 于 2024-8-12 19:36 编辑
大家好!今天非常兴奋地分享我最近的一个小收获——一个装有《2024 DigiKey 创意大赛》器件的包裹收到啦!
这次的包裹是一个大号的纸盒包装,有之前 3 ~ 4 个包装盒那么大。拆开包装,发货清单映入眼帘。这次活动选择了红外温度传感器以及ESP32开发板,等几个核心器件。
下面简单介绍一下各个器件以用途吧
ESP32-S3-DEVKITC-1-N8R8 是一款入门级开发板,搭载 Wi-Fi + Bluetooth® LE 模组 ESP32-S3-WROOM-1、ESP32-S3-WROOM-1U 或 ESP32-S3-WROOM-2。在本应用中原本打算作为主控使用,但由于体积过大,因此作为远程协控制器使用。
MLX90640ESF-BAB-000-TU 是一款远红外热像仪传感器,MLX90640远红外热传感器阵列可精确检测特定区域和温度范围内的目标物体,尺寸小巧,可方便集成到各种工业或智能控制应用中。在本应用中作为红外温度测量传感器使用。
ESP32-S3-WROOM1U-N16R8 是一款通用型 Wi-Fi + 低功耗蓝牙 MCU 模组,搭载 ESP32-S3 系列芯片。除具有丰富的外设接口外,模组还拥有强大的神经网络运算能力和信号处理能力,适用于 AIoT 领域的多种应用场景,例如唤醒词检测和语音命令识别、人脸检测和识别、智能家居、智能家电、智能控制面板、智能扬声器等。在本应用中作为红外传感器主控使用。
SER0056 SER0056 是 DFRobot 推出的一款带离合功能的 300 转向舵机,在本应用中作为转向机构使用,使得红外监控的范围变大。
由于打样的PCB和其它元器件还未到齐,暂时不拆开包装展示了。最后,再来一张器件全家福吧!
- 2024-02-23
-
回复了主题帖:
【得捷Follow me第4期】综合实践之智能家居控制器
秦天qintian0303 发表于 2024-2-23 08:36
这个手机APP是一个在线网页?
这是手机访问的 HA 视图界面
-
回复了主题帖:
【得捷Follow me第4期】综合实践之智能家居控制器
pomin 发表于 2024-2-23 09:11
看起来是 HomeAssistant的界面
没错,正是 HA 的界面