回答

收藏

《2024 DigiKey 汽车应用创意挑战赛》基于树莓派的汽车安全...

#竞赛 #竞赛 678 人阅读 | 0 人回复 | 2025-02-28

本帖最后由 eefocus_3897960 于 2025-2-28 23:53 编辑

一、项目名称:基于树莓派的汽车安全防护系统
二、项目概述:随着汽车保有量的增加,交通事故频发,尤其在倒车、变道、盲区等场景下安全隐患突出。传统车载安全系统(如倒车雷达)存在检测范围有限、抗干扰能力弱等问题。本项目基于树莓派4B/5主控平台,结合超声波传感器(近距离探测)、毫米波雷达(中远距离探测)、LED灯(光提示)和蜂鸣器(声音警告),设计一套低成本、高精度、多层次的汽车主动安全防护系统,实现环境感知-数据分析-实时预警-人机交互的闭环控制,降低碰撞风险。
三、作品实物图:
四、项目代码
  1. import RPi.GPIO as GPIO
  2. import time

  3. # 硬件引脚定义
  4. TRIG_PIN = 23    # 超声波Trig引脚(GPIO23/物理引脚16)
  5. ECHO_PIN = 24    # 超声波Echo引脚(GPIO24/物理引脚18)
  6. BUZZER_PIN = 18  # 蜂鸣器控制引脚(GPIO18/物理引脚12)
  7. LED_PIN = 25     # LED控制引脚(GPIO25/物理引脚22)

  8. # 初始化设置
  9. def setup():
  10.     GPIO.setmode(GPIO.BCM)          # 使用BCM编号
  11.     GPIO.setup(TRIG_PIN, GPIO.OUT)  # Trig引脚输出模式
  12.     GPIO.setup(ECHO_PIN, GPIO.IN)   # Echo引脚输入模式
  13.     GPIO.setup(BUZZER_PIN, GPIO.OUT)
  14.     GPIO.setup(LED_PIN, GPIO.OUT)
  15.    
  16.     # 初始化关闭蜂鸣器和LED
  17.     GPIO.output(BUZZER_PIN, False)
  18.     GPIO.output(LED_PIN, False)

  19. # 超声波测距函数
  20. def get_distance():
  21.     # 发送触发信号
  22.     GPIO.output(TRIG_PIN, True)
  23.     time.sleep(0.00001)  # 持续10微秒
  24.     GPIO.output(TRIG_PIN, False)

  25.     # 记录回波时间
  26.     timeout = 0.1  # 100ms超时时间(约对应5.8米)
  27.     t_start = time.time()
  28.     while GPIO.input(ECHO_PIN) == 0:
  29.         if (time.time() - t_start) > timeout:
  30.             return -1  # 超时返回错误
  31.         pulse_start = time.time()

  32.     t_start = time.time()
  33.     while GPIO.input(ECHO_PIN) == 1:
  34.         if (time.time() - t_start) > timeout:
  35.             return -1  # 超时返回错误
  36.         pulse_end = time.time()

  37.     # 计算距离(单位:厘米)
  38.     pulse_duration = pulse_end - pulse_start
  39.     distance = pulse_duration * 34300 / 2  # 声速343m/s=34300cm/s
  40.     return round(distance, 1)

  41. # 报警控制函数
  42. def alert_control(distance):
  43.     if distance < 50 and distance > 0:  # 有效报警范围
  44.         # 蜂鸣器高频鸣叫(0.1秒间隔)
  45.         GPIO.output(BUZZER_PIN, True)
  46.         GPIO.output(LED_PIN, True)
  47.         time.sleep(0.1)
  48.         GPIO.output(BUZZER_PIN, False)
  49.         GPIO.output(LED_PIN, False)
  50.         time.sleep(0.1)
  51.     else:
  52.         GPIO.output(BUZZER_PIN, False)
  53.         GPIO.output(LED_PIN, False)

  54. # 主程序
  55. def main():
  56.     setup()
  57.     try:
  58.         while True:
  59.             dist = get_distance()
  60.             print(f"当前距离: {dist}cm")
  61.             alert_control(dist)
  62.             time.sleep(0.2)  # 每次测量间隔200ms
  63.     except KeyboardInterrupt:
  64.         GPIO.cleanup()

  65. if __name__ == "__main__":
  66.     main()
复制代码
  1. import serial
  2. import RPi.GPIO as GPIO
  3. import time
  4. from struct import unpack

  5. # 硬件配置
  6. BUZZER_PIN = 18
  7. LED_PIN = 25
  8. SERIAL_PORT = "/dev/ttyAMA0"  # 树莓派5 UART默认设备
  9. BAUD_RATE = 256000

  10. # LD2451协议常量
  11. HEADER = bytes([0xF4, 0xF3, 0xF2, 0xF1])
  12. ALERT_DISTANCE = 10.0  # 报警阈值(单位:米)

  13. def setup():
  14.     GPIO.setmode(GPIO.BCM)
  15.     GPIO.setup(BUZZER_PIN, GPIO.OUT)
  16.     GPIO.setup(LED_PIN, GPIO.OUT)
  17.     GPIO.output(BUZZER_PIN, False)
  18.     GPIO.output(LED_PIN, False)

  19. def parse_binary_data(data):
  20.     """
  21.     解析二进制数据帧
  22.     返回:目标列表,每个目标为字典格式
  23.     """
  24.     targets = []
  25.     try:
  26.         # 校验帧头
  27.         if data[0:4] != HEADER:
  28.             return []
  29.         
  30.         # 获取数据长度(小端序)
  31.         data_len = unpack('<H', data[4:6])[0]
  32.         
  33.         # 校验数据完整性
  34.         if len(data) < 6 + data_len + 1:  # Header+Len+Data+Checksum
  35.             return []
  36.         
  37.         # 计算校验和
  38.         checksum = sum(data[0:6+data_len]) & 0xFF
  39.         if checksum != data[6+data_len]:
  40.             print(f"校验错误: 计算值{checksum} vs 接收值{data[6+data_len]}")
  41.             return []
  42.         
  43.         # 解析目标数据(每24字节一个目标)
  44.         target_count = data_len // 24
  45.         for i in range(target_count):
  46.             start = 6 + i*24
  47.             end = start + 24
  48.             target_bytes = data[start:end]
  49.             
  50.             # 解析结构体
  51.             x, y, speed, _, distance, energy, status = unpack(
  52.                 '<hhhHHHBB', target_bytes[:16]  # 仅解析前16字节关键数据
  53.             )
  54.             
  55.             # 单位转换
  56.             target = {
  57.                 'x': x / 1000.0,         # mm → m
  58.                 'y': y / 1000.0,
  59.                 'speed': speed / 1000.0, # mm/s → m/s
  60.                 'distance': distance / 1000.0,
  61.                 'energy': energy,
  62.                 'status': '运动' if (status & 0x01) == 0 else '静止'
  63.             }
  64.             targets.append(target)
  65.         return targets
  66.    
  67.     except Exception as e:
  68.         print(f"解析异常: {e}")
  69.         return []

  70. def alert_control(enable):
  71.     GPIO.output(BUZZER_PIN, enable)
  72.     GPIO.output(LED_PIN, enable)

  73. def main():
  74.     setup()
  75.     try:
  76.         with serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) as ser:
  77.             # 发送进入Binary模式指令(可选)
  78.             ser.write(bytes([0xF4, 0xF3, 0xF2, 0xF1, 0x04, 0x00, 0x02, 0xAA, 0x55]))
  79.             
  80.             buffer = bytes()
  81.             while True:
  82.                 buffer += ser.read_all()
  83.                
  84.                 # 查找帧头
  85.                 while len(buffer) >= 6:
  86.                     header_pos = buffer.find(HEADER)
  87.                     if header_pos == -1:
  88.                         buffer = bytes()
  89.                         break
  90.                     
  91.                     # 截取完整帧
  92.                     if len(buffer) >= header_pos + 6:
  93.                         data_len = unpack('<H', buffer[header_pos+4:header_pos+6])[0]
  94.                         total_len = 4 + 2 + data_len + 1  # Header+Len+Data+Checksum
  95.                         if len(buffer) >= header_pos + total_len:
  96.                             frame = buffer[header_pos:header_pos+total_len]
  97.                             buffer = buffer[header_pos+total_len:]
  98.                             targets = parse_binary_data(frame)
  99.                            
  100.                             # 报警逻辑
  101.                             min_dist = min((t['distance'] for t in targets) if targets else 999
  102.                             alert_control(min_dist < ALERT_DISTANCE)
  103.                             print(f"最近目标: {min_dist:.2f}m 报警状态: {min_dist < ALERT_DISTANCE}")
  104.                            
  105.                     else:
  106.                         break
  107.                
  108.                 time.sleep(0.05)
  109.                
  110.     except KeyboardInterrupt:
  111.         GPIO.cleanup()

  112. if __name__ == "__main__":
  113.     main()
复制代码
五、项目文档
ld2451_alert.py.txt (4.03 KB, 下载次数: 0)
SR04.py.txt (1.98 KB, 下载次数: 0)





分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条