[i=s] 本帖最后由 WildboarG 于 2025-3-18 20:39 编辑 [/i]
AI-WB2+RD04 雷达检测

说明
来填一下上次挖的坑,一个人租房不安全,要用RD04雷达检测家里是否进贼了,通知到个人手机,可以配合摄像头抓拍(等你来实现)
当有障碍物在雷达前,输出高电平,通知消息到个人手机上。
材料
- WB2-12F
- RD04
原理图


雷达RD04
Rd-04 一共引出6pin 2.0mm 的排针,引脚如下:

本文需要使用到I2C引脚,所以正式接线之前,需要把Rd-04的板载MCU 拆掉,MCU的位置如下:

rd04模组说明书
通知推送
这里采用的是gotify需要搭建服务端。参考AI-WB2消息推送到个人通知
或者大家可以用微信公众号的推送,巴法云,pushplus,server酱。
代码实例
void rd_task(void *pvParameters) {
// 构建消息内容结构体
static const char title[] = "RD04";
static const char message[] = "Trigger the radar notification";
static const char priority[] = "0";
static Message msg = {title, message, priority};
printf("title=%s \r\nmessage=%s\r\npriority=%s\r\n", msg.title, msg.message,
msg.priority);
while (1) {
// 循环检测rd输出
hosal_gpio_input_get(&show, status);
vTaskDelay(3000);
// 触发通知
if (status[0]) {
// 推送消息到手机
xTaskCreate(¬ify_task, "notify_task", 1024 * 10, &msg, 5, NULL);
}
}
}
#include "FreeRTOS.h"
#include "hosal_i2c.h"
#include "task.h"
#include <rd04.h>
#include <stdint.h>
#include <stdio.h>
#define RD_ADDR 0x71
extern hosal_i2c_dev_t i2c0;
void IIC_WriteData(uint8_t reg_addr, uint8_t Buff) {
uint8_t Data[2];
uint8_t ret = -1;
Data[0] = reg_addr;
Data[1] = Buff;
ret = hosal_i2c_master_send(&i2c0, RD_ADDR, Data, sizeof(Data),
HOSAL_WAIT_FOREVER);
if (ret != 0) {
printf("err:%c\n", Buff);
}
}
uint8_t IIC_ReadData(uint8_t reg_addr) {
uint8_t read_data[1];
read_data[0] = reg_addr;
hosal_i2c_master_recv(&i2c0, RD_ADDR, read_data, 1, HOSAL_WAIT_FOREVER);
return read_data;
}
void RD_04_Init(void) {
printf("init radar\r\n");
uint8_t value;
for (uint8_t i = 0; i < 5; i++) {
IIC_WriteData(0x13, 0x9B);
vTaskDelay(1);
value = IIC_ReadData(0x13);
printf("READ VALUE =0x%02X\r\n", value);
}
IIC_WriteData(0x24, 0x03);
IIC_WriteData(0x04, 0x20);
IIC_WriteData(0x10, 0x20);
IIC_WriteData(0x03, 0x40);
IIC_WriteData(0x1C, 0x21);
IIC_WriteData(0x18, 0x6a);
IIC_WriteData(0x19, 0x00);
IIC_WriteData(0x1A, 0x55);
IIC_WriteData(0x1B, 0x01);
IIC_WriteData(0x1D, 0x80);
IIC_WriteData(0x1E, 0x0C);
IIC_WriteData(0x1F, 0x00);
IIC_WriteData(0x20, 0x00);
IIC_WriteData(0x21, 0x7D);
IIC_WriteData(0x22, 0x00);
IIC_WriteData(0x23, 0x0C);
vTaskDelay(3000);
printf("init radar successfuly\r\n");
}
void notify_task(void *pvParameters) {
Message *params = (Message *)pvParameters; // 接收参数
printf("title=%s \r\nmessage=%s\r\npriority=%s\r\n", params->title,
params->message, params->priority);
//
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *res;
struct in_addr *addr;
int s, r;
char recv_buf[4096];
while (1) {
int err = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &res);
if (err != 0 || res == NULL) {
blog_error("DNS lookup failed err=%d res=%p", err, res);
vTaskDelay(1000 / portTICK_PERIOD_MS);
continue;
}
/* Code to print the resolved IP.
Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code
*/
addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
blog_info("DNS lookup succeeded. IP=%s", inet_ntoa(*addr));
s = socket(res->ai_family, res->ai_socktype, 0);
if (s < 0) {
blog_error("... Failed to allocate socket.");
freeaddrinfo(res);
vTaskDelay(1000 / portTICK_PERIOD_MS);
continue;
}
blog_info("... allocated socket");
if (connect(s, res->ai_addr, res->ai_addrlen) != 0) {
blog_error("... socket connect failed errno=%d", errno);
close(s);
freeaddrinfo(res);
vTaskDelay(4000 / portTICK_PERIOD_MS);
continue;
}
blog_info("... connected");
freeaddrinfo(res);
// 构造请求体
char body[1024];
snprintf(body, sizeof(body),
"--%s\r\n"
"Content-Disposition: form-data; name=\"title\"\r\n\r\n"
"%s\r\n"
"--%s\r\n"
"Content-Disposition: form-data; name=\"message\"\r\n\r\n"
"%s\r\n"
"--%s\r\n"
"Content-Disposition: form-data; name=\"priority\"\r\n\r\n"
"%s\r\n"
"--%s--\r\n",
BOUNDARY, params->title, BOUNDARY, params->message, BOUNDARY,
params->priority, BOUNDARY);
snprintf(REQUEST, sizeof(REQUEST),
"POST %s%s HTTP/1.0\r\n"
"Host: %s:%s\r\n"
"User-Agent: aithinker wb2\r\n"
"Content-Type: multipart/form-data; boundary=%s\r\n"
"Content-Length: %d\r\n"
"\r\n"
"%s",
WEB_PATH_BASE, QUERY_STRING, WEB_SERVER, WEB_PORT, BOUNDARY,
strlen(body), body);
printf(REQUEST);
if (write(s, REQUEST, strlen(REQUEST)) < 0) {
blog_error("... socket send failed");
close(s);
vTaskDelay(4000 / portTICK_PERIOD_MS);
continue;
}
blog_info("... socket send success");
struct timeval receiving_timeout;
receiving_timeout.tv_sec = 5;
receiving_timeout.tv_usec = 0;
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout,
sizeof(receiving_timeout)) < 0) {
blog_error("... failed to set socket receiving timeout");
close(s);
vTaskDelay(4000 / portTICK_PERIOD_MS);
continue;
}
blog_info("... set socket receiving timeout success");
// FIXME fix putchar
extern int bl_putchar(int c);
/* Read HTTP response */
do {
bzero(recv_buf, sizeof(recv_buf));
r = read(s, recv_buf, sizeof(recv_buf) - 1);
for (int i = 0; i < r; i++) {
bl_putchar(recv_buf[i]);
}
} while (r > 0);
blog_info("... done reading from socket. Last read return=%d "
"errno=%d\r\n",
r, errno);
close(s);
for (int countdown = 10; countdown >= 0; countdown--) {
blog_info("%d... ", countdown);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
blog_info("Starting again!");
vTaskDelete(NULL);
}
}
最终效果

