Arduino
Connect Python to Arduino with PySerial. Auto-detect ports, send commands, and read sensor data over serial.
PySerial connects Python to Arduino over USB serial for sensor reading, device control, and data collection.
Quick Setup
Upload Arduino Sketch
A minimal sketch that echoes commands and reports sensor data:
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
}
void loop() {
if (Serial.available()) {
String command = Serial.readString();
command.trim();
if (command == "LED_ON") {
digitalWrite(13, HIGH);
Serial.println("LED ON");
} else if (command == "LED_OFF") {
digitalWrite(13, LOW);
Serial.println("LED OFF");
} else if (command == "PING") {
Serial.println("PONG");
}
}
}Send Commands from Python
import serial
import time
arduino = serial.Serial('/dev/ttyACM0', 9600, timeout=2)
time.sleep(2) # Wait for Arduino reset
def send_command(cmd):
arduino.write((cmd + '\n').encode())
return arduino.readline().decode().strip()
print(send_command("LED_ON")) # "LED ON"
time.sleep(1)
print(send_command("LED_OFF")) # "LED OFF"
arduino.close()Auto-Detect the Arduino Port
import serial.tools.list_ports
def find_arduino():
for port in serial.tools.list_ports.comports():
if 'Arduino' in port.description or 'CH340' in port.description:
return port.device
return None
port = find_arduino()
if port:
print(f"Found Arduino on {port}")
else:
print("Arduino not found")Log Arduino test data automatically
TofuPilot records test results from your PySerial scripts, tracks pass/fail rates, and generates compliance reports. Free to start.
Temperature Sensor Example
A DHT22 sensor sending JSON over serial, read by a Python script that logs to CSV.
Arduino side:
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
if (!isnan(temp) && !isnan(humidity)) {
Serial.print("{\"temp\":");
Serial.print(temp);
Serial.print(",\"humidity\":");
Serial.print(humidity);
Serial.println("}");
} else {
Serial.println("ERROR:Sensor read failed");
}
delay(2000);
}Python side:
import serial
import json
import csv
import time
from datetime import datetime
def log_sensor_data(port, csv_path="sensor_data.csv", duration=60):
ser = serial.Serial(port, 9600, timeout=2)
time.sleep(2)
with open(csv_path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["timestamp", "temperature", "humidity"])
start = time.time()
while time.time() - start < duration:
line = ser.readline().decode().strip()
if not line or line.startswith("ERROR"):
continue
try:
data = json.loads(line)
except json.JSONDecodeError:
continue
now = datetime.now().isoformat()
writer.writerow([now, data["temp"], data["humidity"]])
print(f"[{now}] {data['temp']:.1f} C, {data['humidity']:.1f}%")
ser.close()
print(f"Logged {duration}s of data to {csv_path}")
log_sensor_data("/dev/ttyACM0", duration=120)Reliable Connection with Retry
Arduino resets when PySerial opens the port. Always wait ~2 seconds before sending commands.
import serial
import time
def connect_arduino(port, baudrate=9600, retries=3):
for attempt in range(retries):
try:
ser = serial.Serial(port, baudrate, timeout=2)
time.sleep(2)
ser.reset_input_buffer()
ser.write(b"PING\n")
response = ser.readline().decode().strip()
if response == "PONG":
print(f"Connected to Arduino on {port}")
return ser
except serial.SerialException as e:
print(f"Attempt {attempt + 1} failed: {e}")
time.sleep(1)
raise ConnectionError(f"Could not connect to Arduino on {port}")
arduino = connect_arduino("/dev/ttyACM0")
print(send_command("LED_ON"))
arduino.close()Arduino Mega and Due use different USB endpoints. Check your board's documentation for the correct port name (/dev/ttyACM0 vs /dev/ttyUSB0 on Linux, COM3 etc. on Windows).
Common Serial Settings
| Parameter | Typical Arduino Value | Notes |
|---|---|---|
| Baud rate | 9600 or 115200 | Must match Serial.begin() in the sketch |
| Data bits | 8 | Standard for Arduino |
| Parity | None | Default |
| Stop bits | 1 | Default |
| Timeout | 1-2s | Set in serial.Serial(timeout=...) |
| Reset delay | 2s | time.sleep(2) after opening port |