Skip to main content

Command Palette

Search for a command to run...

Controlling Arduino With Python: Serial Communication Made Simple

Stop poking at buttons manually and script your hardware like a boss

Published
10 min read
Controlling Arduino With Python: Serial Communication Made Simple
A

Aeon Flex is the writer behind Chaincoder, a blog about automation, infrastructure, and the quiet failures hiding inside modern systems. Their work focuses on how scripts reproduce bias, how abstraction erodes accountability, and why tools tend to drift toward control when nobody is watching. Chaincoder sits somewhere between technical analysis and cultural critique, written by someone who has spent too much time reading logs, reverse engineering workflows, and distrusting anything that claims to be clean, neutral, or finished.

So you have an Arduino. You have Python. You probably have a cup of coffee that is slowly going cold because you are too busy debugging code. We have all been there.

You might think these two worlds are separated by a vast digital ocean. The Arduino is the hardware guy, handling the volts and the amps. Python is the software wizard, handling the logic and the internet. But what if I told you that getting them to talk to each other is actually easier than explaining to your non-technical friends what you do for a living?

Today we are going to bridge that gap. We are going to send data from your Python script to your Arduino board using Serial communication. No complex networking libraries, no headaches, just pure unadulterated data flow.

By the end of this, you will be flipping LEDs on and off with a Python script like some kind of digital puppet master. And once you understand the fundamentals, you can scale this up to control motors, read sensors, trigger alarms, and build systems that respond to the real world in real time.

Why Serial Communication Actually Matters

Before we dive into the code, let's talk about why this matters. Serial communication is one of the oldest tricks in the digital book. It is simple, reliable, and universal. Nearly every microcontroller on the planet speaks serial. Your Arduino has it baked in. Your Raspberry Pi has it. Even ancient hardware from the 1980s had serial ports.

The beauty of serial is that it is just a stream of bytes. One device sends, the other receives. No handshakes, no authentication protocols, no SSL certificates. Just raw data flowing down a wire at a specific speed. This makes it perfect for rapid prototyping and direct hardware control.

In the real world, serial communication is everywhere. Industrial machines use it. Medical devices rely on it. If you have ever plugged a device into your computer and watched it "just work," there is a good chance serial communication was involved.

And here is the kicker. Once you know how to do this with an Arduino, the same principles apply to any serial device. GPS modules, barcode scanners, industrial sensors, all of them. You are not just learning one trick. You are learning a foundational skill that will make you dangerous.

The Hardware Setup

Keep it simple. You need an Arduino board and a USB cable. That is it. For this example, we are just going to use the built-in LED on pin 13. No need to burn your fingers on a soldering iron today. Just plug the board into your computer and let the software magic begin.

Most Arduino boards have an LED hardwired to pin 13. It is there for exactly this kind of thing. Testing. Debugging. Showing off to your friends. When you plug the board in via USB, it creates a virtual serial port on your computer. This is the bridge. Your Python script will write to this port, and the Arduino will read from it.

If you want to get fancy later, you can hook up external LEDs, motors, relays, or sensors. But for now, that little onboard LED is all we need to prove the concept.

The Arduino Code

First, we need to give the Arduino a set of instructions. It needs to know how to listen. Open up your Arduino IDE and paste this in. It is a standard sketch that waits for a specific character to turn an LED on or off.

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    char command = Serial.read();

    if (command == '1') {
      digitalWrite(13, HIGH);
    } 
    else if (command == '0') {
      digitalWrite(13, LOW);
    }
  }
}

Let's break this down. In the setup() function, we initialize the serial connection at 9600 baud. That is the speed at which data will be transmitted. Think of it like a highway speed limit. Both sides of the conversation need to agree on this speed, or the data turns into gibberish.

We also set pin 13 as an output. This tells the Arduino that we want to control this pin, not read from it.

In the loop() function, the Arduino constantly checks if any data has arrived on the serial line. If it has, it reads one character. If that character is the ASCII character '1', it turns the LED on. If it is '0', it turns the LED off. Everything else gets ignored.

Upload this to your board. Now your Arduino is sitting there, listening patiently on the serial line at 9600 baud. It is waiting for orders like a well trained soldier.

The Python Script

Now we switch sides. We are going to write a Python script that acts as the commander. You will need the pyserial library for this. If you do not have it, open your terminal and type pip install pyserial. Do it, I will wait.

Here is the script. It opens the serial port, waits a moment for the connection to stabilize, and then fires off the commands.

import serial
import time

# You might need to change 'COM3' to '/dev/ttyUSB0' or similar on Mac/Linux
arduino = serial.Serial(port='COM3', baudrate=9600, timeout=.1)
time.sleep(2) # This is crucial. Give the Arduino a moment to reset.

print("Sending the signal to turn the LED on...")
arduino.write(bytes('1', 'utf-8'))

time.sleep(2)

print("And now, darkness.")
arduino.write(bytes('0', 'utf-8'))

Run that script. Watch the little LED on your board blink in obedience to Python. It is a beautiful sight, isn't it?

Let's break this down too. We import the serial library and time for delays. We create a serial object and point it at the correct port. On Windows, this is usually something like COM3 or COM4. On Mac, it looks like /dev/tty.usbmodem14201. On Linux, it is usually /dev/ttyUSB0 or /dev/ttyACM0.

The baud rate has to match what we set in the Arduino code. 9600 in this case. The timeout is how long Python will wait for data before giving up. We set it to 0.1 seconds, which is plenty for this use case.

That time.sleep(2) line is critical. When you open a serial connection to an Arduino, the board resets itself. This is a quirk of how the Arduino bootloader works. If you try to send data immediately, the Arduino is still booting up and will miss it. Give it two seconds to wake up and get ready.

Then we send the command. We convert the string '1' into bytes using UTF-8 encoding and write it to the serial port. The Arduino receives it, reads it, and lights up the LED. Two seconds later, we send '0', and the LED goes dark.

Taking It Further: Reading Data Back

So far, we have only sent data to the Arduino. But serial communication is a two-way street. You can also read data back from the Arduino. This is where things get really interesting. Imagine reading temperature data, button presses, or sensor values directly into your Python script.

Here is an updated Arduino sketch that sends data back:

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    char command = Serial.read();

    if (command == '1') {
      digitalWrite(13, HIGH);
      Serial.println("LED is ON");
    } 
    else if (command == '0') {
      digitalWrite(13, LOW);
      Serial.println("LED is OFF");
    }
  }
}

And here is the Python code to read that response:

import serial
import time

arduino = serial.Serial(port='COM3', baudrate=9600, timeout=.1)
time.sleep(2)

print("Turning LED on...")
arduino.write(bytes('1', 'utf-8'))
time.sleep(0.5)
response = arduino.readline().decode('utf-8').strip()
print(f"Arduino says: {response}")

time.sleep(2)

print("Turning LED off...")
arduino.write(bytes('0', 'utf-8'))
time.sleep(0.5)
response = arduino.readline().decode('utf-8').strip()
print(f"Arduino says: {response}")

Now you have a full conversation happening. Python sends a command. Arduino acts on it and responds. Python reads the response and prints it. This is the foundation for building interactive systems.

Level Up Your Automation Game

Once you master serial communication, a whole new world opens up. You can read sensor data directly into pandas, control motors based on web scraping results, or trigger alarms when your server goes down. But to really dominate the automation scene, you need more than just Arduino tricks. You need a toolkit that makes you unstoppable.

Check out Python Automation Ninja: 10 Custom Python Automations. It is a collection of scripts designed to take the boring stuff out of your life and replace it with cold, hard efficiency.

Get Python Automation Ninja: 10 Custom Python Automations here

Troubleshooting Like a Pro

It rarely works perfectly on the first try. That is part of the fun. If your LED is stubbornly staying dark, check these common pitfalls.

Port Name: Are you sure you are on COM3 or /dev/ttyUSB0? Use the Arduino IDE Tools menu to check what port your board is actually using. On Windows, you can also check Device Manager under Ports. On Mac and Linux, you can list all serial devices with ls /dev/tty.* or ls /dev/ttyUSB*.

Baud Rate Mismatch: If the Arduino is listening at 9600 and Python is shouting at 115200, nobody is happy. Keep them the same. This is the number one cause of garbled data and silent failures.

The Serial Monitor: If you have the Arduino Serial Monitor open, your Python script cannot access the port. Close it before running the script. Only one program can talk to the serial port at a time.

Permission Issues on Linux: On some Linux systems, you need to add your user to the dialout group to access serial ports. Run sudo usermod -a -G dialout $USER, then log out and back in.

The Arduino is Not Responding: Make sure the sketch is actually uploaded and running. Sometimes the IDE says it uploaded, but there was a silent error. Try re-uploading and watch the console output carefully.

Data is Garbled: This usually means a baud rate mismatch or electrical noise on the line. Double-check your baud rates. If you are using long USB cables or cheap USB hubs, try a direct connection with a shorter cable.

Real World Use Cases

Alright, so you can blink an LED with Python. What now? Here are some real world projects you can build with this exact setup.

Home Automation: Control lights, fans, or appliances with relays connected to the Arduino. Write a Python script that checks the weather API and turns on your fan when it gets hot.

Data Logging: Connect sensors to the Arduino and have Python read the data every few seconds. Store it in a CSV file or a database. Build dashboards with matplotlib or plotly.

Alerting Systems: Set up a motion sensor on the Arduino. When it detects movement, have it send a signal to Python, which then sends you a text message or plays an alarm sound.

Robotics: Control motors and servos with the Arduino. Use Python to handle the high-level logic, path planning, and decision making. The Arduino handles the low-level motor control.

Testing and QA: If you are building hardware products, you can use Python to automate test sequences. Send commands to the Arduino, read back sensor values, and log the results. This is how professional hardware engineers test circuit boards at scale.

The pattern is always the same. Python handles the brains. The Arduino handles the muscles. Serial communication is the nervous system connecting them.

Go Forth and Hack

You now have the power to control the physical world with code. That LED might just be a tiny light, but it represents the first step in building robots, smart home systems, and whatever other dystopian or utopian devices you can dream up.

The serial protocol is old school, but it is reliable. It is the glue that holds the hardware and software worlds together. Now stop reading and go build something cool.

Want to Master the Art of Scripting?

If you enjoyed this, you are going to love the deep dive. Stop writing spaghetti code and start building professional grade automations.

Python Automation Secrets — Master Pack

Related Reading: