Introduction: Arduino Python Communication Via USB
Sometimes when working on an Ardunio project, it is necessary to send data back and forth between a computer. Now, you could use something like the arduino ethernet shield, which would send data over a network, but if you want something easy and free the simplest solution is USB communication.
There are several ways to approach Ardunio USB communication, but in this case we will be using Python on the computer side to send and receive information. As such, this instructable expects that you have some prior knowledge of Ardunio, and of Python (or other similar scripting language).
Why Python?
Python is a versatile, easy to learn, and easy to use scripting language. Its power, and huge library of user-created modules (everything from keyboard emulation to game programming) makes it an ideal language for a wide verity of computer side tasks. You could easy parse network information and make an Arduino visualizer, create a game controller, or make a keypad computer login system. Arduino with Python opens up a word of possibilities.
Step 1: The Computer Environment
On the Computer side of things, we will be using a Python module called PySerial. PySerial, coincidentally, allows for the use of serial connections with Python. Installing PySerial on Windows is a pretty simple process. Note: this 'ible assumes you have Python 2.* installed! If you do not, PySerial will still work, but you may need to change the code slightly to fit with the new standards.
To install on Windows, simply visit PySerial's Download Page, download the Windows binary, and run it (at the time of writing, it's pyserial-2.7.win32.exe). Afterwards, test your installation by opening up a new instance of the Python interpreter, and running:
import serial
Step 2: Initial Connection
To initiate a connection with the Arduino from Python, we first have to figure out which COM Port the Arduino is on. This task is luckily made simple by the Ardunio programming environment.
Simply look in the bottom right corner of your Arduino IDE, and you will see some text containing the COM Port number. We will use this to initiate our Python serial connection, like so:
arduino = serial.Serial('COM1', 115200, timeout=.1)
The above code will create a new serial object called "ardunio" on "COM1" with a "115200" baud-rate and a .1 second timeout. It is extremely important that you keep the chosen baud-rate on hand, as it must match exactly with the baud-rate on the Ardiuno side of things.
Step 3: Ardiuno to Python Communication
Communicating between the Ardunio and Python is somewhat easier than the other way around. First, we will want a bit of code that will initiate the Ardunio's serial connection, and pass a message along. We can do this with Arduino's Serial.write() function, like so:
void setup() { Serial.begin(115200); // use the same baud-rate as the python side } void loop() { Serial.println("Hello world from Ardunio!"); // write a string delay(1000); }
This code will write a "Hello world from Ardunio!" line to the serial connection once every second. We will now build a Python script capable for receiving these messages, and doing with them as we wish. First, we must initiate the connection as we did on the previous page, and then we will create a loop that grabs the current information from the stream, and prints it to the console.
import serial arduino = serial.Serial('COM1', 115200, timeout=.1)
while True:
data = arduino.readline()[:-2] #the last bit gets rid of the new-line chars
if data:
print data
Note that in this case, readline() is blocking, so it will wait until a new line is passed entirely through the serial buffer. Quite often, readline() will grab a blank line, so I threw in an if statement to check that data actually contained anything. If you wanted more precise non-blocking data grabbing, you could use read(), and use Serial.write() (for bytes) or Serial.print() (for ASCII chars) on the Arduino side, but you would need to parse character by character.
Step 4: Python to Arduino Communication
This step is a tad harder, as it requires us to parse the data on the Arduino side of things. To help speed things up, I've gone ahead and written a simple loop that grabs the current data from the Serial buffer, and creates a null-terminated string (C string), which it then passes back to the Serial connection. You can use this technique to write an actual parser by designating your own packet prefix and suffix, and scanning the serial buffer for those, creating strings accordingly.
void setup() { Serial.begin(); } void loop() { if(Serial.available() > 0) { char data = Serial.read(); char str[2];
str[0] = data;
str[1] = '\0'; Serial.print(str); } }
Now we can write a simple script that sends data from Python to the Arduino, and then prints out what it gets back.
import serial, time arduino = serial.Serial('COM1', 115200, timeout=.1)
time.sleep(1) #give the connection a second to settle
arduino.write("Hello from Python!")
while True:
data = arduino.readline()
if data: print data.rstrip('\n') #strip out the new lines for now
# (better to do .read() in the long run for this reason
It's easy to see how this method can be extended further to allow for complex communication between the two devices. I will be covering an example of this communication in a future 'ible, where I will make a game-pad device capable of working on any kind of PC game!
24 Comments
2 years ago on Step 1
the link to pyserial is broken.
Reply 2 years ago
Hello @dnbarriosr
You can use https://pypi.org/project/pyserial/ to install Python Serial Port Extension
2 years ago
[Finished in 0.5s]
please help
Reply 2 years ago
Did you install pyserial or did you just install serial.
2 years ago
thank you so much! it solved my problem
Question 3 years ago
i am getting permission denied error. Help please
Answer 3 years ago
the reasons can be:
-close the serial monitor of arduino IDE
-close python idle (if you launch a module whit serial.Serial instructions, IDLE keeps the COM port busy, even you stop the program with ctrl+c)
Answer 3 years ago
Same, did you solve it?
3 years ago
ı took " port busy" or access denied com 8 error. do you know how solve th problem??
Reply 3 years ago
Maybe you opened a connection but did not close it. So it remained open. Before you end the program, you should close the connection with "arduino.close()"
Or maybe your arduino serial screen is open, so serial port is busy. You should close that serial screen before you run the python script
Tip 3 years ago on Step 1
You can communicate between Python and an Arduino a lot easier if you use libraries. On the Python side, you can use pySerialTransfer (pip installable). On the Arduino side, you can use SerialTransfer.h (installable through the Arduino IDE).
pySerialTransfer: https://github.com/PowerBroker2/pySerialTransfer
SerialTransfer.h: https://github.com/PowerBroker2/SerialTransfer
Question 3 years ago
Hi, was wondering if you did end up making the game pad, and if so, if you have a link to a tutorial?
Thanks :)
Question 5 years ago on Step 2
What does the timeout value signify
Answer 3 years ago
timeout I believe is the time required to receive a reply from port after transmitting a query
5 years ago
please help me out
Reply 5 years ago
https://github.com/notered234/Arduino_usb_test
this is my test on python 3. please take a look and give some suggest
5 years ago
https://github.com/notered234/Arduino_usb_test
this is my test on python 3. please take a look and give some suggest
5 years ago
i am getting error when i am running the python script...
Error: AttributeError: 'module' object has no attribute 'Serial'
I already installed the pyserial library
6 years ago
Thank you.But,Python.3 cannot downward compatibility.That's a little pity.
Reply 5 years ago
Hi.
I used Python 3 for this project, and it worked fine.
All I had to do was add parenthesis to the print statement on line 6.