【雷达灯控】安信可 Rd-03E+灯+USB小夜灯

[复制链接]
查看874 | 回复15 | 2024-3-18 09:23:34 | 显示全部楼层 |阅读模式

本帖最后由 jkernet 于 2024-3-18 09:32 编辑

本帖最后由 jkernet 于 2024-3-18 09:30 编辑

本帖最后由 jkernet 于 2024-3-18 09:29 编辑

本帖最后由 jkernet 于 2024-3-18 09:26 编辑

前言

本来是想用来控制WS2812B灯带的,后来觉得不太实用,而且两个活动用同一个项目不太好(估计园长会揍我),于是...想起来以前TB白嫖的USB小夜灯(它终于派上用场了)

展示

1_c.jpg

【雷达灯控】安信可 Rd-03E+灯+USB小夜灯

代码

主要核心代码并不复杂,而我写得复杂了一点点,原因是多年的开发养成了一个习惯,就是不要把代码"写死",多一点"包容",这样做可能会让以后省很多事.

就这个项目来说要注意的问题

// 雷达数据格式 // 帧头(2) 目标信息(1) 距离信息(2) 帧尾(2) // AA AA 01 2F 00 55 55

1.帧头是两个"AA",可能为了图方便只判断了一个"AA",就开始填充帧数据了,没有考虑到距离信息的干扰,比如当距离是170厘米的时候,数据为"AA AA 01 AA 00 55 55",这样势必会导致填充到错误的数据,帧尾同理.

2.雷达模块可能不会给你"正确"的数据,比如刚发完帧头,它就宕机重启了,也就是说数据可能在任何时候中断,接收到的数据也许是这样的"AA AA AA 01 2F 00 55"或者这样的"AA AA 01 AA AA 01 2F"甚至这样的"01 2F 00 55 55 AA AA",要是没处理好,陷入死循环也是可能的.

总之一句话"不要太相信第三方获取到的数据",兼容校验都得做,这只是控制一个小夜灯,要是控制一些危险的设备,错误的数据可能会导致严重的后果,当然我给出的代码也不一定是最好方案,抛砖引玉而已.

#include "bflb_gpio.h"
#include "board.h"
#include "bflb_uart.h"

// 触发一次延时时长(毫秒)
#define LIGHT_TIMEOUT 5 * 1000
// 小夜灯控制引脚
#define LIGHT_CTRL_PIN GPIO_PIN_25

static struct bflb_device_s *uart1;
static struct bflb_device_s *gpio;

int main(void)
{
  board_init();
  printf("start\n");

  // 初始化小夜灯控制引脚
  gpio = bflb_device_get_by_name("gpio");
  bflb_gpio_init(gpio, LIGHT_CTRL_PIN, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
  // 默认关闭
  bflb_gpio_set(gpio, LIGHT_CTRL_PIN);

  // 初始化串口1(雷达模组通信)
  bflb_gpio_uart_init(gpio, GPIO_PIN_31, GPIO_UART_FUNC_UART1_TX);
  bflb_gpio_uart_init(gpio, GPIO_PIN_30, GPIO_UART_FUNC_UART1_RX);

  struct bflb_uart_config_s cfg;
  cfg.baudrate = 256000;
  cfg.data_bits = UART_DATA_BITS_8;
  cfg.stop_bits = UART_STOP_BITS_1;
  cfg.parity = UART_PARITY_NONE;
  cfg.flow_ctrl = 0;
  cfg.tx_fifo_threshold = 7;
  cfg.rx_fifo_threshold = 7;

  uart1 = bflb_device_get_by_name("uart1");
  bflb_uart_init(uart1, &cfg);

  // 接收到的字节
  int ch = -1;
  // 上一次接收到的字节
  char old_ch = 0;
  // 有效帧数据长度
  uint8_t data_len = 0;
  // 目标数据
  // 1字节 0x00 无目标 0x01 运动目标 0x02 微动目标
  uint8_t dst_data = 0;
  // 距离数据
  // 2字节 小端格式(16位整数)
  uint8_t dis_data[2] = {0};
  // 触发时间
  uint64_t trigger_time = 0;

  // 雷达数据格式
  // 帧头(2)        目标信息(1)        距离信息(2)        帧尾(2)
  // AA AA          01                2F 00             55 55
  while (1)
  {
    // 判断触发后是否超时(持续无人状态)
    if (trigger_time != 0)
    {
      if (bflb_mtimer_get_time_ms() - trigger_time >= LIGHT_TIMEOUT)
      {
        // 超时后重置为未触发状态
        trigger_time = 0;
        // 关闭小夜灯
        bflb_gpio_set(gpio, LIGHT_CTRL_PIN);

        printf("timeout:%d\n", LIGHT_TIMEOUT);
      }
    }
    // 判断接收缓冲区中是否有数据
    if (bflb_uart_rxavailable(uart1))
    {
      // 获取1字节的数据
      ch = bflb_uart_getchar(uart1);
      if (ch != -1)
      {
        // 判断是否已经开始接收一帧的数据
        if (data_len == 0)
        {
          // 帧头
          if (ch == 0xAA)
          {
            // 判断上一次接收到的字节是否也是0xAA,如果是则确定为帧头,开始接收帧数据,否则记录等待下次判断
            if (old_ch == ch)
            {
              // 帧头2个字节
              data_len = 2;
            }
          }
        }
        else
        {
          data_len++;
          // 帧尾
          if (ch == 0x55)
          {
            // 判断上一次接收到的字节是否也是0x55,如果是则确定为帧尾,开始新的帧判断,否则记录等待下次判断
            if (old_ch == ch)
            {
              // 校验数据,正确的一帧雷达数据应该是7个字节,不能多也不能少,否则视为无效数据,防止错误数据导致误触发,USB小夜灯还没事,要是其它的啥啥啥...
              if (data_len == 7)
              {
                // 检测到运动目标则刷新触发时间
                if (dst_data == 0x01)
                {
                  trigger_time = bflb_mtimer_get_time_ms();
                  // 开启小夜灯
                  bflb_gpio_reset(gpio, LIGHT_CTRL_PIN);

                  printf("light on:%d\n");
                }

                // 距离 *((uint16_t)&dis_data[0])
                printf("dst:%d dis:%d\n", dst_data, *((uint16_t *)&dis_data[0]));
              }
            }
          }
          // 无论是否接收到帧尾,只要数据长度大于等于了7字节,就开始新的帧判断
          if (data_len >= 7)
          {
            // 重置数据位置,跳过本次循环,开始新的帧判断
            data_len = 0;
            continue;
          }
          // 第3字节 目标信息
          if (data_len == 3)
          {
            dst_data = ch;
          }
          // 第4-5字节 距离信息
          else if (data_len == 4 || data_len == 5)
          {
            dis_data[data_len - 4] = ch;
          }
        }
        old_ch = ch;
      }
    }
  }
}
回复

使用道具 举报

jkernet | 2024-3-18 09:28:00 | 显示全部楼层
工程源码

rd03e-light.zip

3.74 KB, 下载次数: 8

工程源码

回复

使用道具 举报

1084504793 | 2024-3-18 09:53:03 | 显示全部楼层
回复

使用道具 举报

干簧管 | 2024-3-18 10:00:17 | 显示全部楼层
zan
回复

使用道具 举报

bzhou830 | 2024-3-18 10:27:36 | 显示全部楼层
刚哥厉害
选择去发光,而不是被照亮
回复

使用道具 举报

WT_0213 | 2024-3-18 23:53:00 | 显示全部楼层
回复

使用道具 举报

爱笑 | 2024-3-19 13:59:32 | 显示全部楼层
不错不错
用心做好保姆工作
回复

使用道具 举报

lazy | 2024-3-20 10:52:18 | 显示全部楼层
赞赞
回复

使用道具 举报

timo | 2024-3-20 11:05:23 | 显示全部楼层
赞一下
回复

使用道具 举报

sansui | 2024-3-20 15:03:32 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则