Tutorial – sending values from PC to Arduino by serial communication

Arduino-tutorial-serial-2Foreward

Hello everyone. Today I want to write a short tutorial in response to a request that we received yesterday on the Meccanismo Complesso site by pensodisi.

I hope that will be useful both to him and to all others who have similar needs.

Any request or suggestion will always be an incentive for us to improve.

Introduction

For those who delight in carrying out projects with Arduino, sooner or later they will have to deal with the exchange of values between the Arduino and the PC to which it is connected.

If you use Arduino connected to a sensor (see Fig.1), Arduino produce a series of data that may be sent to a computer to be stored in a file, displayed or processed in some way. If you use the Arduino connected to an actuator (see Fig.2), such as a stepper motor, most likely, the computer will send a series of data to the Arduino. The latter will process the received data by converting suitably into commands to send to the motor to make it move in the amount of necessary steps.

tutorial-serial-data-sensor

Fig.1:Arduino sends the sensor data to the PC

tutorial-serial-data-actuator

Fig.2: Arduino receives data from the PC to drive the actuator

I’ll discuss this topic in two different articles.

In this tutorial we will see an example of the use of Arduino as a control for an actuator. To make this tutorial as simple as possible, we will use a servo motor as an actuator.

servo motore

Fig.3: A servo motor

Instead, in an upcoming article, I will collect data from a sensor connected to the Arduino and sending these values to a PC.

Regarding the various commands to drive the servo motor or other motor types (DC or stepper motors) I suggest you refer to the article Motor Control with Arduino and the Adafruit Motorshield v2 board.

Drive a servo motor with a sequence of angles in a file

I chose a servo motor due to its simplicity, especially with regard to the controls. In this tutorial, the servo motor will assume the angles in a list within a TXT or CSV, moving sequentially in time, reading line by line.

arduino-servo-csv-data

Fig.4: The CSC fiel contains the sequence of the angles of rotation

I chose this example, because despite its simplicity, it contains all the essential elements remaining simple and easy intuitibile. It will then be easy to extend this example to more complex projects.

Let’s take a look at the general outline of what we will achieve in this tutorial:

sketch-python-arduino-serial2

Fig.5: This is the tutorial scenario

As you can see, you will activate a serial connection between the Arduino board and the PC. On the Arduino board you will implement a sketch that will take care of “to listen” for any value (angle) sent from the PC. From the PC side, instead, you will activate a serial session in a Python shell (but it can be replaced by any program in Python) that will read the contents of the file (CSV or TXT) by sending appropriate signals via serial to the Arduino.

I chose the servo motor as an actuator also because it can be connected directly to the Arduino without the use of appropriate control boards. Refer to Figure 6 for the connections.

arduino_servo_sketch

Fig.6: The yellow wire must be connected to the PIN 10

If you had the Motorshield v2 Arduino, you can refer to the following figure (Fig. 7).

adafruit_motorshield_servo

Fig.7: How to connect the servo motor to the Motorshield

The Arduino sketch

First, let us develop the sketch with the Arduino IDE. (Click here to go to the official page and download the latest release of the Arduino IDE).

First, you have to include the Servo library already included within dell’Arduino IDE

This library provides us with a whole series of commands to manage Servo Motors in an easy and intuitive way. This library is specialized for controlling this type of motors when they are directly connected to the Arduino. (If you are interested, you can consult the official page here).

First you define a myservo object, which corresponds to the servo motor. Define also the angle and newAngle variables that will hold the values of the angles. Then you will define a strValues array of characters that will hold up to 4 characters (for example, ‘123,’). This array is used to store the values of the angles sent to the PC via serial port. Finally, an index that will help you later to scan the array of characters.

Define now the two standard functions setup() and loop().

The setup function practically takes care of initializing the board, and then, first of all activate a serial communication at 9600 baud. Then you have to define the servo motor to be connected to pin 10 through the function attach() of the Servo library. Finally, define a starting angle for the motor (HOME position) which in my case I defined as 90°.

The function instead must contain all of the commands that will be executed from the board in a continuous cycle. I left empty this function, but here you can implement everything you need to fulfill your specific needs.

Finally, define a new function called serialEvent(). This feature, although it is not included within the loop(), is always listening, and when a serial event is captured by the Arduino board, as in our case, the sending from the PC to a numeric value, the serialEvent function is activated, and the code inside is executed.

Each value sent from the PC is read character by character and inserted into the strValue array. If the character read will be a number (0 to 9) then it is stored in the array, if it will be a non-numeric character (in this case the comma ,’) the reading will be stopped and the value inside the array is converted to a numeric value through the atoi() function.

The numerical value so obtained is stored in the newAngle variable, and represents a new angle at which it must set  the servo motor. This value to be acceptable must be between 0 and 180 degrees. This will then be compared with the current angle angle, and depending on whether major or minor, we will increase or decrease gradually (degree by degree) the angle of the servo motor. This is to avoid sudden jumps by the servo motor. The angle at which the engine must be set is defined by the write() function of the Servo library.

Arduino-sketch-code-01

Fig.8: The sketch (part one)

Arduino-sketch-code-02

Fig.9: The sketch (part two)

If you now execute the code, you will see the servo motor rotating to the corresponding position angle of 90°. Then it will wait motionless listening to the values sent from the PC.

Before moving to Python, you can do some tests. Activate the Serial Monitor within the Arduino IDE, clicking on the menu item Tools> Serial Monitor.
Arduino-serial-monitor

Fig.10: you can open the serial Monitor from the menu

A new window will appear to us, the Monitor Serial precisely and with it you will be able to experiment by writing directly the angles you want the servo motor to be moved. Write, for example, ‘123; and press ENTER.

Arduino-serial-monitor-2

Fig.11: Enter directly the values of the angles

If you have correctly written the sketch and making all the connections, you’ll rotate the servo motor from the HOME position (90°) to 123°.

Python_shell

Commands from Python

Now you will look the Python part regarding the PC side.

First, start a Python Shell. If you have not already installed on your PC go here.

Python_shell

Fig.12: The Python shell

Once you open the shell import the serial library, and create a serial connection with ser listening to the Arduino board at 9600 bauds.

Beware the USB port in listening may vary, so check from the Arduino IDE the active port (eg. COM on Windows can be a 1,2,3 or 4). Then replace the serial port within the function Serial().

Now if you write:

you will get a result identical to that obtained previously with the Serial Monitor. The servo motor will rotate until it assumed the position corresponding angle of 110 °.

But the purpose of this tutorial is to read a sequence of values listed in a CSV file. Create a CSV file with a sequence of angles and save it as samples.csv.

Arduino-angoli-csv

Copy the file you just created in the working directory of the Python Shell. If you do not remember or do not know what it is, enter the following commands:

Vi apparirà la directory dove la shell di Python va a leggere direttamente. Copiato il file, scriviamo

Every 3 seconds (defined by time.sleep()) the Python Shell will read a line from the CSV file by sending the value, ie the angle, to the listening Arduino board, which in turn will trigger the servo motor.

Once the file is completed, close the reading of the file with the command.

Conclusions

As you can see the tutorial is basic, simple and easy to produce. it is a good starting point for any project that has among its functions the exchange of data.

Command lines of Python can be implemented in a program, and for serial communication you use a specific library, such as the pySerial library.

As regards the values I used angles, but you could use any type of value, for example steps of a stepper motor, a distance, etc..

Furthermore, in the case of several motors, for example in automation CNC with 2 motors (XY) or three motors (XYZ) it is possible to pass a line with multiple values, for example the first value as the number of steps and the second value as the motor to move (X, Y, or Z).

In short this tutorial should open the way to many projects. And if you will be inspired, we would be proud of publishing your projects in this site.

8 Comments:

  1. I just love the way you poste it guys, realy complete tutorial, very well explaind and easy to understant. Thank you for learning us. I hope you post more Arduino tutorials.

  2. I have been trying to follow this tutorial, but have run across a problem, some help would be greatly appreciated.

    All fine up until I try to
    use the code line in python:
    ser = serial.Serial(‘/dev/ttyACM1’,9600)

    It comes up with an error:

    Traceback (most recent call last):
    File “”, line 1, in
    ser = serial.Serial(‘/dev/ttyACM2’,9600)
    File “C:\Users\xxx\Python35-32\lib\site-packages\serial\serialwin32.py”, line 31, in __init__
    super(Serial, self).__init__(*args, **kwargs)
    File “C:\Users\xxx\Python35-32\lib\site-packages\serial\serialutil.py”, line 236, in __init__
    self.open()
    File “C:\Users\Python35-32\lib\site-packages\serial\serialwin32.py”, line 62, in open
    raise SerialException(“could not open port {!r}: {!r}”.format(self.portstr, ctypes.WinError()))
    serial.serialutil.SerialException: could not open port ‘/dev/ttyACM2’: FileNotFoundError(2, ‘The system cannot find the path specified.’, None, 3)

    I am pretty stumped on what this means, I have tried with ACM1, ACM2, ACM3, ACM 4 but will still not work,

    Any ideas?

    • Hi, from the error message I understand that you are using Windows. Thus, the USB port are not named ttyXXXX but COM1, COM2, … and so on. Replace the ttyACM1 in your code with the current COM used from you Arduino.
      You can check this directly from the ArduinoIDE.

  3. simone.bergamo

    Ciao Fabio,
    con un approccio simile, al posto del pc potrei collegare anche un dispositivo (es. una bilancia elettronica) che spara stringhe sempre tramite seriale? Ovviamente non con la logica di comandare un servo motore…

  4. Thank you for this great tutorial , I am willing to send from python to arduino “only” one no. for now representing no. to turn the dc motor on and count the rotation encoder steps ,the arduino code is working fine when I write in serial window also form python IDE but when reading from csv file not ! my code is from your suggestion with no error and printing on python shell the no. I want

    import serial
    import time
    import os
    os.getcwd()
    ser = serial.Serial(‘com3’,9600)
    file = open(‘C:\\Python27\\robosampl.csv’,’rb’)
    while 1:
    line = file.readline()
    if not line:
    break
    print(line)
    ser.write(line)
    time.sleep(3)

    knowing that the csv file was text file and I changed its extension to csv

  5. Hi : sorry for th eprevious “messy” code but I solved the issue of sending one no. from csv to arduino LED and Servo but as I mentioned sending one no. (representing no. of encoder steps for dc motor) is still not solved,the code for python csv to LED/servo I used

    import serial
    import time
    import csv
    i=0
    ser=serial.Serial(‘com3’,9600)
    f = open (‘C:\\Python27\\robosampl.csv’,’rb’)
    readFile=csv.reader(f)

    for row in readFile:

    ser.write(row[i])
    print(row[i])

  6. Hi
    Thanks for the great tutorial!
    I came in this page looking for help regarding reading the PC language status (for multi language users) and sending it to the arduino

    Can I do it with python and make a windows app using it? I would love for some help in writing such a code

    thanks!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.