Based on contributions by Jasonbrowne.
Use this setup when you want a Raspberry Pi to act as the “brain” (Wi-Fi, higher-level logic, vision, etc.) while an Arduino handles real-time control of motors and servos. The two boards talk to each other over a USB serial connection, the same way a PC and Arduino would (see How to control an Arduino from Python over a serial connection for the general pattern).
What you need
- Raspberry Pi (any model with a USB port)
- Arduino board
- USB cable between the Pi and the Arduino
pyserialon the Raspberry Pi:pip install pyserial- A stepper motor (for the example below) or other actuator
Steps
1. Connect the boards
Connect the Raspberry Pi to the Arduino with a USB cable. The Pi will recognize the Arduino as a serial device, typically /dev/ttyUSB0 or /dev/ttyACM0. Check which one with ls /dev/tty* before and after plugging in the Arduino.
2. Write the Arduino sketch
The Arduino listens for text commands over serial and drives the hardware. This example moves a stepper motor up or down one revolution per command:
#include <Stepper.h>
const int stepsPerRevolution = 200; // Adjust for your stepper motor
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11); // Motor pins
void setup() {
Serial.begin(9600); // Start serial communication
myStepper.setSpeed(60); // Set motor speed
Serial.println("Arduino ready");
}
void loop() {
if (Serial.available() > 0) {
String command = Serial.readStringUntil('\n');
if (command == "up") {
myStepper.step(stepsPerRevolution); // Move motor one revolution forward
Serial.println("Moved up");
} else if (command == "down") {
myStepper.step(-stepsPerRevolution); // Move motor one revolution backward
Serial.println("Moved down");
}
}
}
Check: pins 8–11 and 9600 baud are just this example’s values — match them to your own wiring and adjust
stepsPerRevolutionto your motor’s datasheet.
3. Write the Raspberry Pi (Python) side
Wrap the serial connection in a small class so the rest of your code doesn’t need to deal with the port directly:
# arduino.py
import serial
import time
class ArduinoConnection:
def __init__(self, port="/dev/ttyUSB0", baudrate=9600):
self.serial = serial.Serial(port, baudrate, timeout=1)
time.sleep(2) # Wait for the Arduino to reset after opening the port
def move_manual(self, direction):
if direction in ["up", "down"]:
self.serial.write(f"{direction}\n".encode())
feedback = self.serial.readline().decode().strip()
print(f"Arduino says: {feedback}")
def close(self):
self.serial.close()
4. Use it from your main script
from arduino import ArduinoConnection
if __name__ == "__main__":
arduino = ArduinoConnection()
arduino.move_manual("up")
arduino.move_manual("down")
arduino.close()
Troubleshooting
- Wrong serial device: if you have other USB-serial devices connected,
/dev/ttyUSB0might not be the Arduino. Runls /dev/tty*with the Arduino unplugged, then plugged in, to see which device appears. - Permission denied opening the port on Linux: see the permissions fix in How to read a weight scale over RS-232/serial in Python.
- Give the Arduino ~2 seconds after opening the serial port before sending commands — it resets when the port opens, and commands sent too early are lost.
Related
- How to control an Arduino from Python over a serial connection — controlling an Arduino from Python over serial (PC version of this pattern)
- How to drive a stepper motor with Arduino or Raspberry Pi — driving a stepper motor with Arduino or Raspberry Pi
- How to set up a Raspberry Pi (with or without a monitor) — setting up a Raspberry Pi
Rewritten and consolidated (Sept 2026) from the original student how-to’s: How to Communicate Between a Raspberry Pi and an Arduino.