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

如何修改代码实现树莓派与Arduino同步的3分钟定频LED闪烁数据采集

代码修改方案与同步建议

树莓派Python代码修改(实现3分钟定时采集+同步指令发送)

以下代码实现3分钟定点数据采集,同时通过串口向Arduino发送LED频率与启停指令,确保两者同步:

import time
import csv
from ina219 import INA219
import serial

# 硬件配置参数
SHUNT_OHMS = 0.1  # 按你的INA219分流电阻实际值调整
MAX_EXPECTED_AMPS = 3.2
COLLECTION_DURATION = 180  # 采集时长:3分钟=180秒
LED_FREQUENCY = 100  # 可选值:1/5/10/50/100Hz
SERIAL_PORT = '/dev/ttyACM0'  # Arduino串口号,可能是ttyUSB0
BAUD_RATE = 9600

# 初始化传感器与串口
ina = INA219(SHUNT_OHMS, MAX_EXPECTED_AMPS)
ina.configure()
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
time.sleep(2)  # 等待Arduino完成初始化

# 发送配置与启动指令
ser.write(f"FREQ:{LED_FREQUENCY}\n".encode())
time.sleep(0.1)
ser.write(b"START\n")

# 写入CSV数据
with open('sensor_data.csv', 'w', newline='') as csvfile:
    fieldnames = ['timestamp', 'shunt_voltage(mV)', 'bus_voltage(V)', 'current(mA)', 'power(mW)']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()

    start_time = time.time()
    while time.time() - start_time < COLLECTION_DURATION:
        # 采集传感器数据
        shunt_v = ina.shunt_voltage()
        bus_v = ina.bus_voltage()
        current = ina.current()
        power = ina.power()

        # 写入CSV
        writer.writerow({
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
            'shunt_voltage(mV)': round(shunt_v, 4),
            'bus_voltage(V)': round(bus_v, 4),
            'current(mA)': round(current, 2),
            'power(mW)': round(power, 2)
        })

        # 控制采集频率(可根据需求调整,示例为每秒10次)
        time.sleep(0.1)

# 发送停止指令,结束同步
ser.write(b"STOP\n")
ser.close()
print("采集完成,LED已停止闪烁")

核心要点

  • 用time.time()计算运行时长,确保严格执行3分钟采集
  • 串口先发送频率参数,再发送启动信号,保证Arduino与采集同步开始
  • 采集循环的time.sleep(0.1)可按需调整数据采样密度
  • 采集结束后发送停止信号,LED同步终止闪烁

Arduino代码修改(实现指定频率闪烁+同步启停)

采用非阻塞式逻辑实现精准频率闪烁,避免高频率下的延迟误差:

const int LED_PIN = 13;  // LED连接引脚(需串联220Ω限流电阻)
unsigned long previousMillis = 0;
long interval = 500;  // 默认闪烁周期(对应1Hz)
bool ledState = LOW;
bool isRunning = false;
int targetFreq = 1;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
  while (!Serial) {}  // 等待USB串口连接(仅用于电脑调试)
}

void loop() {
  // 处理串口指令
  if (Serial.available() > 0) {
    String cmd = Serial.readStringUntil('\n');
    cmd.trim();
    
    if (cmd.startsWith("FREQ:")) {
      targetFreq = cmd.substring(5).toInt();
      // 计算闪烁周期:1次闪烁=亮+暗,所以单状态时长为(1000ms/频率)/2
      interval = 500 / targetFreq;
      if (interval < 1) interval = 1;  // 最小周期限制,避免溢出
    } else if (cmd == "START") {
      isRunning = true;
      previousMillis = millis();
    } else if (cmd == "STOP") {
      isRunning = false;
      digitalWrite(LED_PIN, LOW);  // 停止后熄灭LED
    }
  }

  // 非阻塞式闪烁逻辑
  if (isRunning) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      ledState = !ledState;
      digitalWrite(LED_PIN, ledState);
    }
  }
}

核心要点

  • 用millis()替代delay(),避免高频率下的阻塞问题,保证闪烁次数精准
  • 自动根据接收的频率计算闪烁周期,亮暗状态各占一半时长
  • 严格响应树莓派的启停指令,实现完全同步

关键注意事项

  • 树莓派与Arduino的串口波特率必须完全一致(示例为9600)
  • 树莓派需赋予串口权限:执行sudo usermod -a -G dialout pi后重启生效
  • 高频率(50/100Hz)闪烁人眼无法察觉,可通过示波器验证闪烁次数
  • 若需更高同步精度,可改用树莓派GPIO引脚发送硬件触发信号替代串口

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 11:24:23