1. 雷达模块简介
此雷达模块通过UART和MCU通信,其中查询雷达算法结果的命令如下所示:
Bash |
雷达回复算法结果数据帧以0x59开始,一个C语言的算法如下所示:
#define RADAR_RESP_FRAME_HEADER 0x59
#define RADAR_RESP_FRAME_DET_INFO_SIZE 25 /* 雷达感应信息 0x30 回复帧长度 */
typedef struct {
uint8_t is_deteced; /* 是否有效,1 有效,0 无效。如果无效,后面的数据都不用看 */
uint8_t det_result; /* 区分运动、微动、呼吸 */
uint16_t range_val; /* 距离值,单位是 mm */
int16_t angle_val; /* 角度值,单位是度 */
int16_t velo_val; /* 速度值,单位是 m/s */
uint8_t reserved[6];/* 保留 */
uint8_t rb_conf; /* 距离置信度,范围 [0, 16],如果置信度 < 12,那么距离值可以视为无效 */
uint8_t angle_conf; /* 角度置信度,范围 [0, 16],如果置信度 < 8,那么角度值可以视为无效 */
uint32_t frame_idx; /* 帧序号,从 0 开始,每帧加 1 */
} radar_det_info_t;
/**
* @brief 回复帧校验,比较帧头和计算校验和
*
* @param buf
* @param bufLen
* @return
*/
static bool radar_resp_frame_verify(char* buf, int bufLen)
{
uint16_t checkSum = 0, checkSumCalc = 0;
if ((!buf) || (bufLen <= 0)) {
return false;
}
// Dump frame first
// buffer_dump(buf, bufLen);
// [1] Check frame head
if (buf[0] != RADAR_RESP_FRAME_HEADER) {
Serial.println("Frame header error!");
return false;
}
// [2] Check frame
checkSum = (uint16_t)((buf[bufLen - 1] << 8) | buf[bufLen - 2]);
// 第一个字节到倒数第三个字节的累加和
for (int i = 0; i < bufLen - 2; ++i) {
checkSumCalc += buf[i];
}
if (checkSum != checkSumCalc) {
Serial.println("CheckSum Error: " + String(checkSumCalc) + " != " + String(checkSum));
return false;
}
// Serial.println("CheckSum OK: " + String(checkSum));
return true;
}
static bool radar_parse_scan_result(char* buf, int bufLen, radar_det_info_t* detInfo)
{
if (!buf || bufLen < RADAR_RESP_FRAME_DET_INFO_SIZE) {
return false;
}
if (!detInfo) {
return false;
}
// 手动从 buf 字节转换到 detInfo 结构体,注意字节序,小端模式
detInfo->is_deteced = buf[3];
detInfo->det_result = buf[4];
detInfo->range_val = (uint16_t)((buf[6] << 8) | buf[5]);
detInfo->angle_val = (int16_t)((buf[8] << 8) | buf[7]);
detInfo->velo_val = (int16_t)((buf[10] << 8) | buf[9]);
detInfo->rb_conf = buf[17];
detInfo->angle_conf = buf[18];
detInfo->frame_idx = (uint32_t)((buf[22] << 24) | (buf[21] << 16) | (buf[20] << 8) | buf[19]);
return true;
}1.1 硬件连接
Tab5 的 J9 扩展口,把其中 GPIO49 作为 UART_TX, GPIO50 作为 UART_RX,与雷达模块通信。

1.2 实物连接
• GPIO49 (Tab5 UART_TX) <---> Radar UART_RX
• GPIO50 (Tab5 UART_RX) <--> Radar UART_TX
• GND <---> Radar GND
• 3.3V <---> Radar 3.3V

2. MicroPython 代码
• 屏幕初始化为横屏
• 显示欢迎界面(3秒自动跳转)
• 串口雷达通讯并把雷达结果显示在标签上
# SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
#
# SPDX-License-Identifier: MIT
# Tab5 和 雷达模块通过UART通信。
# 实现逻辑:欢迎页停留3秒后跳转,实时解析并显示雷达数据。
# 成功获取雷达数据,在屏幕上显示,并且也在终端中打印。
import os, sys, io
import M5
from M5 import *
from hardware import UART
import time
# --- 日志兼容性处理:防止 logger 未定义报错 ---
try:
import logging
logger = logging.getLogger("RadarApp")
logger.setLevel(logging.DEBUG)
except ImportError:
# 定义一个虚假类,确保 logger.debug() 等方法不报错
class DummyLogger:
def debug(self, msg): print("[DEBUG] " + str(msg))
def info(self, msg): print("[INFO] " + str(msg))
def error(self, msg): print("[ERROR] " + str(msg))
logger = DummyLogger()
print("Logging module not found, using print instead")
# --- 全局变量 ---
uart2 = None
label_title = None
label_data = None
app_page = 1 # 1: 欢迎页, 2: 主页
start_time = 0
def show_welcome_page():
"""绘制欢迎界面"""
Widgets.fillScreen(0x000000)
# 横屏下坐标调整 (Tab5 横屏通常为 1280x720)
Widgets.Label("Sedentary Reminder", 420, 300, 1.0, 0xFFFFFF, 0x000000, Widgets.FONTS.DejaVu40)
Widgets.Label("System Starting...", 530, 400, 1.0, 0x888888, 0x000000, Widgets.FONTS.DejaVu24)
def show_main_page():
"""绘制主显示界面"""
global label_title, label_data
Widgets.fillScreen(0x222222)
# 横屏布局调整
label_title = Widgets.Label("Radar Real-time Data (Hex):", 80, 50, 1.0, 0x00FF00, 0x222222, Widgets.FONTS.DejaVu24)
# 用于显示雷达返回的原始字节码
label_data = Widgets.Label("Waiting...", 80, 150, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu24)
def setup():
global uart2, start_time, app_page
M5.begin()
# --- 设置横屏显示 ---
# M5.Display.setRotation(0) # 竖屏,摄像头在上,Type-C在下
# M5.Display.setRotation(1) # 横屏,摄像头在左,Type-C在右
# M5.Display.setRotation(2) # 竖屏,摄像头在下,Type-C在上
M5.Display.setRotation(3) # 横屏,摄像头在右,Type-C在左
# 初始化串口:TX=49, RX=50
uart2 = UART(1, baudrate=921600, bits=8, parity=None, stop=1, tx=49, rx=50)
# 记录开机时间
start_time = time.time()
show_welcome_page()
app_page = 1
logger.info("Application Initialized in Landscape Mode")
def loop():
global app_page, label_data, uart2
M5.update()
# 1. 自动跳转逻辑
if app_page == 1:
# 检查是否过去 3 秒
if (time.time() - start_time) > 3:
app_page = 2
show_main_page()
logger.info("Page jumped to Main")
return # 欢迎页状态下不执行串口逻辑
# 2. 雷达数据读取逻辑
# 发送读取响应指令
uart2.write(bytearray([ 0x58, 0x30, 0x00, 0x88, 0x00 ]))
if uart2.any():
raw_data = uart2.read()
if raw_data:
# 将二进制转为十六进制字符串显示,避免 label 显示乱码
hex_str = "".join(["%02X " % b for b in raw_data])
# 更新屏幕显示
if label_data:
label_data.setText(hex_str)
# 日志输出
logger.debug("Radar RX: " + hex_str)
# 控制刷新频率,避免串口过于频繁导致 UI 卡顿
time.sleep(0.5)
if __name__ == "__main__":
try:
setup()
while True:
loop()
except (Exception, KeyboardInterrupt) as e:
try:
from utility import print_error_msg
print_error_msg(e)
except ImportError:
print("Fatal Error:", e)2.1 流程图

3. 运行结果


我要赚赏金
