免费申请 | 挑战智能家居!毫米波雷达模组,100个名额,先到先得!(活动已停)
https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=44214
活动要求:雷达模组完成灯控项目,做到“人来灯亮、人走灯灭”,任何灯具皆可。任何灯具 OK 那就Ai-M61-32S板载LED 吧,毕竟好像手上目前也没什么可用的灯具了。Ai-M61-32S板载LED灯正合适 。话不多说先上图。
人走灯灭
目前距离在30-50cm之间有活动的话就认为有人亮灯,其他活动不亮灯。
接线方式:
Rd-03E |
M61-32S |
VCC |
5V |
GND |
GND |
OT1 |
GPIO24 |
RX |
GPIO23 |
数据解析:
Rd-03E数据格式为两个AA开头: AA AA ,由两个55结束: 55 55。
第三个byte对应的是目标状态,分别是:无目标、微动目标、运动目标。一般情况下微动和运动会“同时”多次触发。
无目标的时候距离信息和目标状态都是00
距离信息为小端十六进制,所以获取到数据应该调换一下位置。
下面上代码
#include "bflb_mtimer.h"
#include "board.h"
#include "bflb_uart.h"
#include "bflb_gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "math.h"
#define DBG_TAG "MAIN"
#include "log.h"
// gpio 用来点亮led 初始化uart
struct bflb_device_s *gpio;
// uart串口读取 rd03e
struct bflb_device_s *rd03e;
// 缓存数据总数,默认Rd03E 数据,是7位舍去开头两个 AA AA
int BUFFER_LEN = 5;
// 换出数据缓存数组
uint8_t UART_RECEIVE_BUFFER[5];
void _rd03eTask(void* pvParameters){
// 当前数组下标
int index = 0;
// 读取数据状态标记
int flag = 0;
// 是否读取到数据末尾
int end = 0;
// led 灯状态
int led_state = 0;
while (1)
{
// 通过 uart 异步接收一个字符
int ch = bflb_uart_getchar(rd03e);
// 防止 数据读取完成不需要再读取,同时防止index越界
if(ch!=-1 && index < BUFFER_LEN){
if(flag == 2){
// 缓存数据
UART_RECEIVE_BUFFER[index++] = ch;
switch (end) {
case 0:
// 检测第一个 55
if(ch == 0x55){
end = 1;
}else{
end = 0;
}
break;
case 1:
// 检测第二个 55 结束
if(ch == 0x55){
end = 2;
}else{
end = 0;
}
break;
default:
break;
}
}else{
switch (flag){
case 0:
// 读取到第一个 AA 改变标记 1 读取第二个 AA 确定数据头
if(ch == 0xAA){
flag = 1;
}else{
flag = 0;
}
break;
case 1:
// 读取到第二个 AA 改变标记 2 准备读取数据
if(ch == 0xAA){
flag = 2;
memset(UART_RECEIVE_BUFFER,0 , sizeof(UART_RECEIVE_BUFFER));
index = 0;
}else{
flag = 0;
}
break;
default:
break;
}
}
}
// 读取到结束标记 处理数据
if(end == 2){
// 打印看下读取的数据
for (size_t i = 0; i < sizeof(UART_RECEIVE_BUFFER); i++) {
printf("0x%02x ", UART_RECEIVE_BUFFER[i]);
}
// 查看目标状态
if(UART_RECEIVE_BUFFER[0] == 0x00){
printf("无目标\r\n");
}else if(UART_RECEIVE_BUFFER[0] == 0x01){
printf("运动目标\r\n");
}else if(UART_RECEIVE_BUFFER[0] == 0x02){
printf("微动目标\r\n");
}
// 有目标检查距离亮灯灭灯操作
if(UART_RECEIVE_BUFFER[0] == 0x01 || UART_RECEIVE_BUFFER[0] == 0x02){
printf("有目标\r\n");
uint16_t distance = (UART_RECEIVE_BUFFER[2] << 8) | UART_RECEIVE_BUFFER[1];
printf("距离 :%d\r\n", distance);
// 距离在50-70cm之间亮灯
if(distance > 30 && distance < 50){
// 防止灯亮着还执行亮灯
if(led_state == 0){
led_state = 1;
// 亮灯
bflb_gpio_set(gpio, GPIO_PIN_14);
}
}else{
if(led_state == 1){
led_state = 0;
// 灭灯
bflb_gpio_reset(gpio, GPIO_PIN_14);
}
}
}
// 处理完数据 恢复状态
end = 0;
flag = 0;
index = 0;
}
vTaskDelay(1);
}
}
int main(void)
{
board_init();
// 初始化gpio
gpio = bflb_device_get_by_name("gpio");
// 初始化led针脚gpio
bflb_gpio_init(gpio, GPIO_PIN_14, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
bflb_gpio_reset(gpio, GPIO_PIN_14);
// 初始化uart
rd03e = bflb_device_get_by_name("uart1");
// 初始化uart gpio
bflb_gpio_uart_init(gpio, GPIO_PIN_23, GPIO_UART_FUNC_UART1_TX);
bflb_gpio_uart_init(gpio, GPIO_PIN_24, GPIO_UART_FUNC_UART1_RX);
// 初始化uart配置参数
struct bflb_uart_config_s conf = {
.baudrate = 256000,
.data_bits = UART_DATA_BITS_8,
.stop_bits = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.flow_ctrl = UART_FLOWCTRL_NONE,
.rx_fifo_threshold = 7,
.tx_fifo_threshold = 7
};
bflb_uart_init(rd03e, &conf);
// 创建任务接收数据
xTaskCreate(_rd03eTask, (char*)"rd03e", 1024, NULL, 1, NULL);
vTaskStartScheduler();
while (1) {
}
}
代码写的有点糙,功能实现就好。希望有一些参考价值。
Rd-03E 出厂默认是手势识别固件,可以识别手势,但距离识别基本不能用。如果有手势识别要求的可以直接用,参考
【雷达灯控】安信可 Rd-03E+ 灯 + Ai-M61-32S 手势亮灯
http://bbs.aithinker.com/forum.php?mod=viewthread&tid=44289
如果需要精准测距就需要烧写 精准测距固件,烧录方式目前我这里知道的有两种,一种是官方使用J-LINK方式烧录,另外一种就是使用串口工具烧录。
J-LINK方式参考官方教程
Rd-03E快速入门使用文档
串口工具烧录参考:
使用ch340给rd03_e雷达烧录固件[有手就行]
http://bbs.aithinker.com/forum.php?mod=viewthread&tid=44286
[固件]Rd-03E UART 烧录固件
http://bbs.aithinker.com/forum.php?mod=viewthread&tid=44302
完整代码在评论区。
【Rd-03E + Ai-m61-32s 精准测距固件,人来灯亮人走灯灭】 https://www.bilibili.com/video/BV1Ku4m1G7Yj/?share_source=copy_web&vd_source=95f092a8edb82d1fb04a2d285b5f28a7