Tutorial – sending values from PC to Arduino by serial communication

Arduino-tutorial-serial-2

Foreward

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

#include

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).

Servo myservo;
int angle = 0;
int newAngle = 0;
const int MaxChars = 4;
char strValue[MaxChars+1];
int index = 0;

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.

void setup()
{
 Serial.begin(9600);
 myservo.attach(10);
 angle = 90;
}
void loop()
{}

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.

void serialEvent()
{
   while(Serial.available()) 
   {
      char ch = Serial.read();
      Serial.write(ch);
      if(index < MaxChars && isDigit(ch)) { 
            strValue[index++] = ch; 
      } else { 
            strValue[index] = 0; 
            newAngle = atoi(strValue); 
            if(newAngle > 0 && newAngle < 180){
                   if(newAngle < angle) 
                       for(; angle > newAngle; angle -= 1) {
                             myservo.write(angle);
                       }  
                    else 
                       for(; angle < newAngle; angle += 1){
                          myservo.write(angle);
                    } 
            }
            index = 0;
            angle = newAngle;
      }  
   }
}

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.

import serial
ser = serial.Serial('/dev/ttyACM1',9600)

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:

ser.write('110,')

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:

import os
os.getcwd()

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

import time
file = open('samples.csv')
while 1:
   line = file.readline()
   if not line:
         break
   ser.write(line)
   time.sleep(3)

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.

file.close

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.

[:]



Leave a Reply