Arduino经Python Socket传空文件致Matplotlib绘图崩溃问题排查
解决Arduino-Socket传输空文件导致Matplotlib崩溃的问题
我之前做类似的Arduino-PC数据传输项目时,也碰到过空文件导致绘图崩溃的问题,咱们从几个维度来排查和解决:
一、先堵上Socket传输的漏洞
空文件的核心原因要么是Arduino没发数据/发了空数据,要么是Python接收端没做校验直接写入,先从这两块入手:
1. Python接收端加数据校验
不要直接把接收到的内容写入文件,先判断数据是否有效,空数据直接跳过,甚至记录错误日志:
import socket HOST = "你的PC IP" PORT = 12345 # 自定义端口 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f"已连接 {addr}") data = conn.recv(1024).decode('utf-8').strip() # 核心校验:数据为空就跳过写入 if not data: print(f"从{addr}接收到空数据,跳过写入") conn.sendall(b"FAIL") # 告诉Arduino发送失败 return # 写入日志文件 with open("sensor_log.txt", "a", encoding="utf-8") as f: f.write(data + "\n") conn.sendall(b"OK") # 发送确认信号给Arduino
2. Arduino端加发送确认机制
让Arduino知道数据确实被PC接收了,避免重复发送或者发送空内容:
#include <WiFi.h> // 用WiFi模块的话,Ethernet模块类似 const char* ssid = "你的WiFi名"; const char* password = "WiFi密码"; const char* serverIP = "你的PC IP"; const uint16_t serverPort = 12345; WiFiClient client; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi连接成功"); } void loop() { // 如果没连接上PC,先重连 if (!client.connected()) { Serial.println("尝试连接PC..."); if (client.connect(serverIP, serverPort)) { Serial.println("连接PC成功"); } else { delay(2000); return; } } // 准备要发送的数据(替换成你的实际数据) String sensorData = String(millis()) + "," + String(analogRead(A0)); client.println(sensorData); // 等待PC的确认信号,超时就重连 unsigned long timeout = millis(); while (!client.available()) { if (millis() - timeout > 3000) { Serial.println("等待确认超时,断开重连"); client.stop(); delay(1000); return; } } // 读取确认信号 String ack = client.readStringUntil('\n'); if (ack.trim() == "OK") { Serial.println("数据发送成功"); } else { Serial.println("数据发送失败,重试"); } delay(1000); // 调整发送间隔 }
二、修复批处理循环的隐患
批处理循环运行Python脚本时,容易出现前一个Socket进程没完全关闭,新进程端口被占用的问题,导致连接异常:
修改你的批处理脚本,先清理旧进程再启动:
@echo off set "PY_SCRIPT=your_socket_receiver.py" # 替换成你的Python脚本名 :LOOP :: 杀掉之前的Python进程(避免端口占用) taskkill /f /im python.exe >nul 2>&1 :: 等待2秒确保进程完全退出 timeout /t 2 /nobreak >nul :: 启动接收脚本 python "%PY_SCRIPT%" :: 脚本退出后循环重启 goto LOOP
三、给Matplotlib加“防崩”逻辑
就算前面的步骤都做了,还是可能有漏网的空日志,直接在绘图前做校验:
import matplotlib.pyplot as plt def load_log_data(file_path): valid_data = [] with open(file_path, "r", encoding="utf-8") as f: for line_num, line in enumerate(f, 1): line = line.strip() if not line: print(f"第{line_num}行为空,跳过") continue # 根据你的日志格式解析,比如CSV格式拆分 try: timestamp, value = line.split(",") valid_data.append(float(value)) except Exception as e: print(f"第{line_num}行数据无效:{e},跳过") return valid_data # 加载数据并绘图 log_data = load_log_data("sensor_log.txt") if not log_data: print("日志中无有效数据,不绘图") else: plt.plot(log_data) plt.title("Sensor Data Log") plt.xlabel("Sample Index") plt.ylabel("Value") plt.show()
四、额外排查点
- 检查Arduino的网络稳定性:如果用WiFi,看看信号强度(
WiFi.RSSI()),信号弱容易丢包; - 给Python Socket加超时:在
s.listen()后加s.settimeout(10),避免进程一直卡在等待连接的状态; - 查看Serial Monitor:Arduino端的串口日志能帮你快速定位是连接失败还是发送失败。
内容的提问来源于stack exchange,提问作者notsolowki
相关产品推荐
相关产品推荐

