我的 macOS 系统和 Arduino 设备之间遇到串行通信问题。除非 minicom 正在运行,否则我的 Rust 和 Python 脚本都无法向 Arduino 发送消息。以下是问题的详细描述:
问题总结
来自 Tauri 应用程序的 Rust 片段。
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use serialport::SerialPort;
use std::time::Duration;
use serde::Serialize;
#[cfg(feature = "hardware-support")]
use std::fs::File;
#[tauri::command]
fn get_temperature() -> Result<f32, String> {
#[cfg(feature = "hardware-support")]
{
// Path to the temperature sensor's device file
let path = "/sys/bus/w1/devices/28-01191ee2142f/w1_slave"; // Replace '28-xxxx' with your sensor's ID
let mut file = File::open(path).map_err(|e| e.to_string())?; // Convert the error to a String;
let mut contents = String::new();
file.read_to_string(&mut contents).map_err(|e| e.to_string())?;
// The temperature data is usually at the end of the second line, after 't='
let temp_str = contents.split_whitespace().last().unwrap().split("=").nth(1).unwrap();
let temp_raw: i32 = temp_str.parse().unwrap();
// Convert raw temperature to Celsius
Ok(temp_raw as f32 / 1000.0)
}
#[cfg(not(feature = "hardware-support"))]
{
println!("Hardware support is not enabled. Temp running in stub mode.");
Ok(69.69)
}
}
#[derive(Serialize)]
struct BlinkData {
blinks: u8,
}
#[derive(Serialize)]
struct BlinkMessage {
message_type: String,
data: BlinkData,
}
#[tauri::command]
fn send_blink_message(port_name: &str, num_blinks: u8) -> Result<(), String> {
// Open the serial port
let mut port = serialport::new(port_name, 9600).open().expect("Failed to open port");
// Create the JSON message
let message = BlinkMessage {
message_type: String::from("blink_led"),
data: BlinkData { blinks: num_blinks },
};
// Serialize the message to JSON
let json_message = match serde_json::to_string(&message) {
Ok(json) => json,
Err(e) => return Err(format!("Failed to serialize message: {}", e)),
};
// Send the JSON message over the serial port
if let Err(e) = port.write_all(json_message.as_bytes()) {
return Err(format!("Failed to write to port: {}", e));
}
// Print the JSON message to the console for debugging
println!("JSON Message Sent: {}", json_message);
// Add a newline to indicate the end of the message
if let Err(e) = port.write_all(b"\n") {
return Err(format!("Failed to write newline to port: {}", e));
}
Ok(())
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![get_temperature, send_blink_message])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
带有大量串行特定设置的 Python 示例。
import serial
import json
import time
def configure_serial_port(port_name):
ser = serial.Serial(
port=port_name,
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=10,
xonxoff=False,
rtscts=False,
dsrdtr=False
)
ser.dtr = False
ser.rts = False
ser.close()
def send_blink_message(port_name, num_blinks):
try:
# Configure the serial port settings
configure_serial_port(port_name)
# Open the serial port
ser = serial.Serial(port_name, 9600, timeout=10)
# Add a short delay to ensure the Arduino is ready to receive the message
time.sleep(0.1)
# Create the JSON message
message = {
"message_type": "blink_led",
"data": {"blinks": num_blinks}
}
# Serialize the message to JSON
json_message = json.dumps(message)
# Print the JSON message for debugging
print("JSON Message:", json_message)
# Send the JSON message over the serial port
print("Sending JSON message...")
ser.write(json_message.encode('utf-8'))
# Add a newline to indicate the end of the message
print("Sending newline...")
ser.write(b"\n")
# Flush the port to ensure all data is sent
print("Flushing port...")
ser.flush()
# Add a delay to ensure everything is sent before exiting the function
time.sleep(0.1)
print("Message sent to Arduino")
ser.close()
return True
except serial.SerialException as e:
print(f"Failed to open port: {e}")
return False
if __name__ == "__main__":
port_name = "/dev/cu.usbmodem101" # Change this to your port
num_blinks = 3 # Set the number of blinks
send_blink_message(port_name, num_blinks)
这是草图
#include <ArduinoJson.h>
// Define the built-in LED pin
const int ledPin = LED_BUILTIN;
void setup() {
// Initialize the built-in LED pin as an output
pinMode(ledPin, OUTPUT);
// Start the serial communication at 9600 baud rate
Serial.begin(9600);
}
void loop() {
// Check if there is any data available on the serial port
if (Serial.available() > 0) {
// Read the incoming serial data
String incomingMessage = Serial.readStringUntil('\n');
// Parse the JSON message
StaticJsonDocument<200> jsonDoc;
DeserializationError error = deserializeJson(jsonDoc, incomingMessage);
// Check if parsing was successful
if (!error) {
// Extract the message type and blinks value
const char* message_type = jsonDoc["message_type"];
int blinks = jsonDoc["data"]["blinks"];
// Check if the message type is 'blink_led'
if (strcmp(message_type, "blink_led") == 0) {
// Blink the LED the specified number of times
for (int i = 0; i < blinks; i++) {
digitalWrite(ledPin, HIGH); // Turn the LED on
delay(500); // Wait for 500 milliseconds
digitalWrite(ledPin, LOW); // Turn the LED off
delay(500); // Wait for 500 milliseconds
}
}
} else {
// If parsing failed, print an error message
Serial.println("Failed to parse JSONS");
}
}
}
问题
我在 ChatGPT 上花了很多时间、很多天来解决这个问题。来自知识渊博的人的任何见解或建议将不胜感激。谢谢!
问题在于 Arduino 没有等待足够长的时间来准备接收串行数据。在打开串行端口和发送数据之间添加 2 秒延迟解决了该问题。大概首先打开 minicom(您可以运行它并仍然使用端口),通过让 Arduino 准备好接收数据来解决问题。 2 秒似乎很长一段时间,这可能是我接下来要解决的问题。