Linux Format

Arduino for Pi users

Get used to the Arduino series of boards, with the help of Les Pounder and the Raspberry Pi, to build better projects.

- Les Pounder is a freelance creative technologi­st who works with companies such as Raspberry Pi Foundation, Cisco, and Micro:bit Foundation to promote maker skills to all ages.

Get used to the Arduino series of boards with the help of Les Pounder and the Raspberry Pi, and build better projects.

The Arduino is a powerful board. It may not have the same processing power as a Raspberry Pi – in fact it cannot even match the original Raspberry Pi – but it has power in its simplicity and connectivi­ty. It has protocols such as I2C, SPI, UART and serial, in addition to digital IO (on/off) and analogue IO.

But why is this important? With an Arduino we can write the code on our computer, in this case a Raspberry Pi, and then flash the code onto the Arduino where it is stored. We can remove the Arduino from the Pi, and as long as we can supply power to the project, it can run quite happily with no screen. With the newer batch of Arduinos we can connect to the internet and networks, send data over said networks and even send data back to the Arduino.

The power of the Arduino is that it can be independen­t and gather data for you in the field. Sure, the Raspberry Pi can also do this, but why use an entire Linux computer just to gather data when you can run a tiny, power-efficient microcontr­oller?

In this project we are going to create a simple motorcontr­ol project that will control the speed of a motor using a rotary encoder, and the status of the motor will be displayed to the user via an LCD screen. As we move through the project, we will also compare the Arduino programmin­g language to Python, the typical language used on the Raspberry Pi.

Hardware setup

The Arduino should be connected to a free USB port on the Raspberry Pi via a known good-quality data cable (not all USB cables carry data lines). Using four male-to-female jumper wires, connect the I2C LCD screen to the Arduino’s I2C pins (5V, GND, SCL and SDA). Then connect the rotary encoder to the Arduino via a breadboard and three male-to-male jumper wires. The centre pin of the three connects to GND. We then need to connect pin 9, our motor pin, to IN1 on the L298N motor controller, and then connect GND from the Arduino to GND on the L298N and to IN2. This will force the motor to spin in one direction only.

Connect a 5V power supply to the L298N, and ensure that the GND connection of the power supply is connected to the GND of the L298N, and the Arduino. This creates a “Common Ground” used as reference for all voltages.

Double-check all of the connection­s via the circuit diagram – a high-resolution version is available in the download for this project.

Software installati­on

We start the software aspect of the project by first visiting the Arduino website at www.arduino.cc and clicking on Software > Downloads. For all models of the Raspberry Pi, even the Pi 4, we need to download the 32-bit ARM Linux version of the Arduino IDE. Once downloaded, extract the contents of the file to your

home directory (/home/pi/) and then, using the terminal, navigate to the Arduino-1.8.12/ directory – the version number may change over time so please look for a similar directory name. In this directory we need to run a command to install the Arduino IDE to the Pi. In the terminal type the following command:

$ sudo ./install.sh

Once installed we still need to issue one more command to add our user, pi, to a group called “dialout”, as this will enable us to upload (flash) code to the Arduino via USB. In the terminal type the following:

$ sudo usermod -a -G dialout pi

Once complete, reboot the Pi, and we are ready to open the Arduino IDE.

In the Arduino IDE we need to install a library of code that will enable our Arduino to communicat­e with the LCD screen over I2C. Go to Tools > Manage Libraries and open the Library Manager. It will take a few seconds to open, even on the powerful Pi 4. Once it has loaded, type in Liquidcrys­tal i2c in the search box, and the filter should reveal a series of libraries. We are looking for the Liquidcrys­tal I2C library by Frank de Brabander. Once you’ve located it, click install and the library will be downloaded and set-up, ready for use. Once done, close the Library Manager.

Project code

This project uses a rotary encoder – a dial with incrementa­l steps that we can use to detect and identify the direction of rotation to control the speed of a motor. The speed of the motor is expressed as a percentage, in 20% steps, and the speed data is output to an LCD screen and the serial console.

To start the code, we need to include the libraries that are necessary for working with the I2C LCD screen. If you are familiar with Python you’ll see that this is similar to importing a library. The library has to be installed on the Raspberry Pi in order for us to use it. The address in brackets (0x27,20,4) is a typical I2C address for the LCD screen when used with a PCF8574 Backpack. But if in doubt there is a free I2C scanner.

Connect your screen to the Arduino, load this script,

https://playground.arduino.cc/main/i2cscanner and flash it to the Arduino. In the Serial Monitor it will show all of the I2C devices present.

#include Liquidcrys­tal_i2c lcd(0x27,20,4);

The pins used to connect our electronic­s to the Arduino need to be identified in our code, so we use three constant values to name and identify each pin. Creating variables in the Arduino programmin­g language is a little different to in a Raspberry Pi, but nothing too difficult:

#define A 6

#define B 7

#define motor 9

Three more variables are created to store a counter value, used to identify where we are when scrolling around the various motor-power settings. The other two variables store the current and previous state of the rotary encoder. Each of these variables is storing an integer (numerical) value, and we need to tell the code this as we create the variable, unlike in Python where we can just create the variable by storing any data type inside of it:

int counter = 0;

int astate;

int alaststate;

Inside the setup function we now initialise the LCD screen ready for use, then set the two rotary encoder connection­s (A and B) as inputs before we set our motor pin to be an output. The setup function is similar to defining all of the pins, functions and variables in our code before we start any loops. These are tasks that need to be done only once before we move into the main code.

void setup()

{ lcd.init();

pinmode (A,INPUT);

pinmode (B,INPUT); pinmode(motor, OUTPUT);

The two input pins, A and B, are connected to the rotary encoder, which will detect movement based on connecting pin A or B to the centre pin, connected to GND. When A or B is connected to GND, this will trigger the A/B pin to pull low, effectivel­y dropping the voltage of that pin from 5V to 0V. But we need to set these pins up to start up high, with 5V flowing to the pins. To do this we use digitalwri­te to set each of the pins HIGH.

digitalwri­te(a, HIGH);

digitalwri­te(b, HIGH);

When the Arduino powers up, it would help the user if we gave them a simple instructio­n. Using the LCD screen, we tell the user to rotate the rotary encoder. First we turn on the backlight so that we can see the text. Then we set the cursor to the top left of the screen and print the first part of the message. We then set the cursor to the second line, and finish the message.

lcd.backlight();

lcd.setcursor(1,0);

lcd.print(“turn dial to “);

lcd.setcursor(1,1);

lcd.print(“start motor”);

To start a serial console, we begin the serial connection with a speed of 9600 baud, fast enough for this low-speed project. Then we read the state of pin A and store the value in the variable alaststate, which will be used for comparison later.

Serial.begin (9600);

alaststate = digitalrea­d(a);

}

We are now finished with the setup function and can move on to the main body of code, which is a loop(),set to repeat as long as the Arduino is powered. Inside the loop we read the current state of pin A and store that to the astate variable. The loop() function is essentiall­y the same as a while True loop in Python. The contents just constantly run when the Arduino is powered up.

void loop() {

astate = digitalrea­d(a);

To check if the rotary encoder has been used, the two variables, astate and alaststate, are compared using a comparison operator, in this case !=, which means that the first variable is not equal to the second. If that is the case then a nested conditiona­l test checks pin B against the current state of A, and if B is different to A then the rotary encoder is being rotated clockwise.

if (astate != alaststate){

if (digitalrea­d(b) != astate) {

What happens if the rotary encoder is turned clockwise? The value stored in the variable counter is incremente­d by 1. But if the value stored in the counter variable goes above 12, then the counter is reset back to zero.

if (digitalrea­d(b) != astate) {

counter ++;

if (counter > 12){

counter = 0;

}

If the value of the counter variable is less than -1 then the variable is reset to zero.

} else if (counter < -1){

counter = 0;

}

}

The value store in the counter is printed to the serial monitor in order for us to debug any issues.

Serial.print(“value: “);

Serial.println(counter);

How do we detect and react to the counter value? Using another series of if, else if conditiona­l tests we check the value stored in the counter variable, and if the value matches then a section of code is triggered. In the first example if the value of the counter variable is 2, then two lines of text, the Motor On, and percentage of power, are printed to the serial monitor.

if (counter == 2) {

Serial.println(“motor On”);

Serial.println(“20%”);

Then the same data is sent to the LCD screen, with the Motor On text appearing on the top line, and the percentage on the bottom.

lcd.setcursor(1,0);

lcd.print(“motor On”);

lcd.setcursor(1,1);

lcd.print(“20%”);

To finish this conditiona­l test, we use the

analogwrit­e function to control the motor pin, and set it to 20% power output. The analogwrit­e function uses pulse width modulation (PWM) to send values between 0 and 255. So 20% of 255 is approximat­ely 51, and this is the value that we pass in order to turn the motor on, albeit slowly.

analogwrit­e(motor, 51);

}

To test the other conditions, for the values 4, 6, 8 and 10 to be stored in the counter variable we use else if to check one by one. We set the motor speed for 4 to 40%, which is 102.

else if (counter == 4) {

Serial.println(“motor On”);

Serial.println(“40%”);

lcd.setcursor(1,0);

lcd.print(“motor On”);

lcd.setcursor(1,1);

lcd.print(“40%”);

analogwrit­e(motor, 102);

}

For counter value 6, 60% power is 153.

else if (counter == 6) {

Serial.println(“motor On”);

Serial.println(“60%”);

lcd.setcursor(1,0);

lcd.print(“motor On”);

lcd.setcursor(1,1);

lcd.print(“60%”); analogwrit­e(motor, 153);

}

For counter value 8 we set the speed to 204.

else if (counter == 8) {

Serial.println(“motor On”);

Serial.println(“80%”);

lcd.setcursor(1,0);

lcd.print(“motor On”);

lcd.setcursor(1,1);

lcd.print(“80%”);

analogwrit­e(motor, 204);

}

Lastly if the value of the counter variable is 10, we set the power of the motor to 100%, which is 255.

else if (counter == 10) {

Serial.println(“motor On”);

Serial.println(“100%”);

lcd.setcursor(1,0);

lcd.print(“motor On”);

lcd.setcursor(1,1);

lcd.print(“100%”);

analogwrit­e(motor, 255);

}

The last part of this long series of conditiona­l tests is a simple else condition. This is a catch-all condition that requires no logic for comparison. If no other comparison­s are made, the else condition must be true. If this happens the motor is turned off using a value of 0, and the LCD screen is cleared.

else {

analogwrit­e(motor, 0);

lcd.clear();

}

}

The very last line of code updates the value stored in the alaststate variable so that it matches the value stored in astate. So now the last state and current state of the A pin match.

alaststate = astate; // Updates the previous state of

the outputa with the current state

}

Save the code to your Raspberry Pi with your Arduino connected go to the Tools menu, and ensure that the correct board, and port are selected for the Arduino. When ready click on Sketch > Upload to send the code to the Arduino. In a few moments the board will reset and the LCD screen will show the instructio­ns for use. We can also open the serial monitor, found in the Tools > Serial Monitor menu. In the serial monitor we can see the exact state of the rotary encoder and the power setting for the motor.

Our project is complete, and we can now manually control the speed of a motor using the rotary encoder. Adding extra motors is as simple as defining another pin for the motor, and then adding a few lines to control that pin at the same time as the original motor pin. We have accomplish­ed so much with very basic Arduino code, thanks to a great community of libraries and support.

 ??  ?? An I2C backpack is a much better solution to connecting all 16 wires needed for the LCD screen to work.
An I2C backpack is a much better solution to connecting all 16 wires needed for the LCD screen to work.
 ??  ?? The LCD screen is a simple and effective output device. We get all of the informatio­n that we need to run the project.
The LCD screen is a simple and effective output device. We get all of the informatio­n that we need to run the project.
 ??  ??
 ??  ?? A rotary encoder is used for input, while an LCD screen shows the speed at which a motor is turning.
A rotary encoder is used for input, while an LCD screen shows the speed at which a motor is turning.
 ??  ?? The circuit is simple, but there are lots of wires. Take your time and trace each connection. If necessary, connect only one device, then test before moving on.
The circuit is simple, but there are lots of wires. Take your time and trace each connection. If necessary, connect only one device, then test before moving on.
 ??  ?? When running the code, open the Serial Monitor Tools > Serial Monitor to see the live output from the Arduino. This is useful for debug purposes.
When running the code, open the Serial Monitor Tools > Serial Monitor to see the live output from the Arduino. This is useful for debug purposes.
 ??  ?? Managing libraries of pre-written code is so much easier with later Arduino IDE releases. Now we have a graphical tool to install and manage the software libraries available in the Arduino community.
Managing libraries of pre-written code is so much easier with later Arduino IDE releases. Now we have a graphical tool to install and manage the software libraries available in the Arduino community.

Newspapers in English

Newspapers from Australia