基于Python控制Arduino实现智能交通灯Demo的技术咨询
Arduino USB代码上传与Python动态控制方案
一、让Arduino通过USB读取代码并运行
Arduino默认通过USB串口接收编译后的二进制代码并烧录运行,分手动和自动化两种方式:
手动基础流程
- 编写控制LED的Arduino代码(比如串口指令接收框架),保存为
.ino文件 - 打开Arduino IDE,选择对应板型(如Uno)和USB端口(如COM3)
- 点击「上传」按钮,IDE自动编译并烧录代码,完成后Arduino自动重启运行
自动化脚本上传(适合Python集成)
用arduino-cli工具实现Python触发上传:
- 安装
arduino-cli,添加到系统PATH - 初始化配置:
arduino-cli config init - 安装对应板型核心包(以Uno为例):
arduino-cli core install arduino:avr - Python中用
subprocess调用上传命令:
import subprocess def upload_sketch(port, sketch_folder, board="arduino:avr:uno"): cmd = [ "arduino-cli", "upload", "-p", port, "-b", board, sketch_folder ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0: print("代码上传成功") else: print(f"上传失败:{result.stderr}")
sketch_folder是包含.ino文件的Arduino项目文件夹路径
二、参数变更时更新Arduino逻辑的两种方案
方案1:动态生成并上传新脚本(适合逻辑大幅变更)
如果需要修改引脚定义、底层触发逻辑等,可通过Python生成新的Arduino代码再上传:
- 准备Arduino代码模板(
sketch_template.ino),用占位符替代可变参数:
const int car_lights[] = {CAR_PINS}; const int pedestrian_lights[] = {PED_PINS}; void setup() { Serial.begin(9600); for(int i=0; i<sizeof(car_lights)/sizeof(int); i++) pinMode(car_lights[i], OUTPUT); for(int i=0; i<sizeof(pedestrian_lights)/sizeof(int); i++) pinMode(pedestrian_lights[i], OUTPUT); } void loop() { if(Serial.available() > 0){ String cmd = Serial.readStringUntil('\n'); if(cmd.startsWith("CAR")){ int idx = cmd.split(',')[1].toInt(); int state = cmd.split(',')[2].toInt(); digitalWrite(car_lights[idx], state); } else if(cmd.startsWith("PED")){ int idx = cmd.split(',')[1].toInt(); int state = cmd.split(',')[2].toInt(); digitalWrite(pedestrian_lights[idx], state); } } }
- Python中替换占位符生成新代码:
def generate_sketch(car_pins, ped_pins, template_path, output_path): with open(template_path, 'r') as f: template = f.read() car_str = ",".join(map(str, car_pins)) ped_str = ",".join(map(str, ped_pins)) new_sketch = template.replace("CAR_PINS", car_str).replace("PED_PINS", ped_str) with open(output_path, 'w') as f: f.write(new_sketch)
- 参数变更时,先调用
generate_sketch生成代码,再用upload_sketch上传
方案2:串口发送控制指令(适合时序参数微调,无需重启)
如果只是调整绿灯时长、切换顺序等时序参数,直接通过串口发指令更高效:
- 先上传上述模板中的Arduino代码(固定引脚,只处理串口指令)
- Python用
pyserial库发送控制指令:
import serial import time class TrafficController: def __init__(self, port, baud=9600): self.ser = serial.Serial(port, baud, timeout=1) time.sleep(2) # 等待Arduino初始化 def set_light(self, light_type, idx, state): cmd = f"{light_type},{idx},{state}\n" self.ser.write(cmd.encode()) def run_sequence(self, sequence): for item in sequence: typ, idx, state, dur = item self.set_light(typ, idx, state) time.sleep(dur) # 示例:机器学习输出新时序后执行 if __name__ == "__main__": ctrl = TrafficController("COM3") new_sequence = [ ("CAR", 0, 1, 40), # 0号车绿灯亮40秒 ("CAR", 0, 0, 2), # 灭2秒 ("PED", 0, 1, 20), # 0号行人绿灯亮20秒 # 更多时序步骤... ] ctrl.run_sequence(new_sequence)
- 安装依赖:
pip install pyserial
内容的提问来源于stack exchange,提问作者Alex Dragut
相关产品推荐
相关产品推荐

