You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派项目中带条件控制的多线程ADC与霍尔效应检测实现问题

解决方案:带条件控制的多线程ADC采集与霍尔检测

核心问题分析

你的代码缺少线程间通信机制来触发ADC停止,同时未实现采集-绘图的循环逻辑,主要问题包括:

  • 未初始化控制线程的信号对象,导致adcreceiver中self.event.is_set()调用报错
  • halleffect_monitor未在达到检测次数后触发ADC停止信号,也未调用绘图和循环重置
  • 主程序未实现重复采集的循环逻辑,资源释放不完整

修正后的完整代码

import spidev
import time
import numpy as np
import matplotlib.pyplot as plt
import RPi.GPIO as GPIO
import threading 

class halleffectandadc:
    def __init__(self, desired_clock_cycles, pin, clock_speed, buff_size):
        self.spi = spidev.SpiDev()
        self.spi.open(0, 0)
        self.spi.max_speed_hz = clock_speed
        self.buff_size = buff_size
        self.desired_clock_cycles = desired_clock_cycles
        GPIO.setmode(GPIO.BCM)
        self.pin = pin
        GPIO.setup(pin, GPIO.IN)
        # 初始化线程控制事件,用于通知ADC线程停止
        self.stop_event = threading.Event()
        # 初始化数据缓冲区
        self.reset_buffer()

    def reset_buffer(self):
        """重置数据缓冲区和计时,为下一轮采集做准备"""
        self.buff = np.ndarray((self.buff_size,), dtype="uint16")
        self.time_start = None
        self.time_end = None
        # 清空停止事件
        self.stop_event.clear()

    def get_adc_val(self):
        response = self.spi.xfer([0x00, 0x00])
        return (response[0] << 8) + response[1]

    def adcreceiver(self):
        self.time_start = time.perf_counter()
        i = 0
        # 循环条件:缓冲区未填满 且 未收到停止信号
        while i < self.buff_size and not self.stop_event.is_set():
            self.buff[i] = self.get_adc_val()
            i += 1
        self.time_end = time.perf_counter()
        if self.stop_event.is_set():
            print("ADC线程已停止,准备处理数据")

    def halleffect_monitor(self):
        hall_effect_clock_count = 0
        while hall_effect_clock_count < self.desired_clock_cycles:
            if GPIO.wait_for_edge(self.pin, GPIO.RISING, timeout=1000):
                hall_effect_clock_count += 1
                print(f"检测到磁场,累计次数: {hall_effect_clock_count}")
        # 达到指定次数,触发ADC停止信号
        self.stop_event.set()

    def plot_data(self):
        if self.time_start is None or self.time_end is None:
            print("无有效采集数据,跳过绘图")
            return
        elapsed_time = self.time_end - self.time_start
        time_points = np.linspace(0, elapsed_time, len(self.buff), endpoint=True)
        plt.plot(time_points, self.buff / 65535 * 5)
        plt.xlabel("时间 (s)", fontsize=12)
        plt.title("电位器电压变化", fontsize=12)
        plt.ylabel("电压 (V)", fontsize=12)
        plt.show()
        print(
            f"采集时长: {elapsed_time:.3f}s, 标准差: {np.std(self.buff):.2f}, 最小值: {min(self.buff)}, 最大值: {max(self.buff)}, 平均值: {np.mean(self.buff):.2f}"
        )

    def cleanup(self):
        """释放硬件资源"""
        self.spi.close()
        GPIO.cleanup()

if __name__ == "__main__":
    adc_device = halleffectandadc(desired_clock_cycles=2, pin=17, clock_speed=22000000, buff_size=100000)
    try:
        while True:
            print("=== 开始新一轮采集 ===")
            adc_device.reset_buffer()
            # 创建并启动线程
            hall_thread = threading.Thread(target=adc_device.halleffect_monitor, daemon=True)
            adc_thread = threading.Thread(target=adc_device.adcreceiver, daemon=True)
            hall_thread.start()
            adc_thread.start()
            
            # 等待霍尔线程完成检测
            hall_thread.join()
            # 等待ADC线程处理完剩余采集或停止
            adc_thread.join()
            
            # 绘制数据
            adc_device.plot_data()
            print("=== 本轮采集完成,等待下一轮 ===")
    except KeyboardInterrupt:
        print("\n用户终止程序,正在清理资源...")
        adc_device.cleanup()

关键改进点说明

  1. 线程控制机制:

    • 使用threading.Event()作为线程间信号,霍尔线程在达到检测次数后调用stop_event.set(),ADC线程在循环中实时检查stop_event.is_set(),及时停止采集
    • 线程设置为daemon=True,确保主程序退出时所有线程自动终止
  2. 循环采集逻辑:

    • 添加reset_buffer()方法重置缓冲区和事件状态,支持重复采集
    • 主循环中每次创建新线程,确保状态独立
  3. 资源管理:

    • 添加cleanup()方法统一释放SPI和GPIO资源
    • 主程序捕获KeyboardInterrupt,确保异常退出时资源被正确清理
  4. 鲁棒性提升:

    • 给GPIO.wait_for_edge()添加超时,避免线程永久阻塞
    • 绘图前检查计时是否有效,防止空数据报错

内容的提问来源于stack exchange,提问作者shaun0367

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:32:05