Skip to content

由 WildboarG 贡献,Ai-Thinker 进行整理

AI-WB2+RD04 哨兵检查

AI-WB2+RD04 雷达检测


说明


来填一下上次挖的坑,一个人租房不安全,要用RD04雷达检测家里是否进贼了,通知到个人手机,可以配合摄像头抓拍(等你来实现)

当有障碍物在雷达前,输出高电平,通知消息到个人手机上。

材料


  1. WB2-12F
  2. RD04

原理图

雷达RD04


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

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

rd04模组说明书

通知推送


或者大家可以用微信公众号的推送,巴法云,pushplus,server酱。

启用推送

起了一个http服务器,开了一个静态开关页面,决定是否启用通知,防止自己频繁触发,更人性化一点吧

关闭哨兵,不会推送消息,开启后,正常推送消息到手机客户端。

代码实例

仓库地址:https://github.com/WildboarG/Picket.git

  • 主线程
📜 点击展开完整代码
c
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
);
    }
  }
}
  • 雷达驱动
📜 点击展开完整代码
c
#
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"
);
}
  • 通知任务
📜 点击展开完整代码
c
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
);
  }
}

最终效果

Released under the MIT License. Build Time 2026-09-11 14:52:23