So far we have looked at control structures, variables and functions, etc. In the second entry of this course, we looked at how to communicate via serial port. Today we´re going to look at it in more detail. As well as using the serial port to debug our program and find out information, we will also give commands to our ZUM BT 328, or any Arduino board, using the serial monitor. For example, this allows us to send a vector to our robot indicating the direction and speed it should move at. We will also learn how to do this with an analogue signal using the Arduino PWN pins, which we will use to change the colour of the RBG LED. The PWM function of Arduino boards enables us to generate an analogue signal using digital signals. To find out more about it, you can visit the PWM reference page.
List of materials
- ZUM BT-328 controller board or one compatible with Arduino.
- Breadboard (or test board or protoboard).
- RBG LED, common cathode in this case.
- Cable jumper.
Electrical connections
On using a breadboard, if we are starting a project or the project is small, it might not matter, but if it keeps increasing in size, it´s important to use coloured cables to make it easier to understand the circuit visually. By using the RGB LED we can make the connections easier, for example, by using a red cable for the pin that controls the red colour of the RGB LED. We usually use a red cable for the live wires of the circuit and a black or brown cable for earth or GND (ground). The LED module we are using in this example includes resistors to limit the current in the module itself, but if the one you are using doesn´t have any, make sure that you connect a resistor for each colour to avoid burning the LED. This diagram provides an example of how you can connect an LED without integrated resistors:
With this project, we will connect the RGB LED and the ZUM BT-328 board as follows:
ZUM BT-328 | LED RGB |
GND | GND |
6 | R |
5 | G |
3 | B |
The code
As usual, we will start by declaring the variables of the pins:
1 |
int redPin = 6, greenPin = 5, bluePin = 3; |
We will also declare some variables that we will be using throughout the sketch:
1 2 3 |
int delayLed = 10; // The time that passes between each change of LED (ms) // Variables that store the last colour of each LED int red_old = 0, green_old = 0, blue_old = 0; |
In the delayLed variable, we store the time that passes in milliseconds during the transition between one LED value and the next. We recommend using a very low value, as a delay is used to make the transition smoother. As a result, we need to bear in mind that the greater the value, the longer it will take to make the transition, for example, for the value of 10 ms, the transition from black to white, or from (0,0,0) to (255,255,255), takes 7.6 seconds to complete. The same transition with 5 ms takes 3.8 seconds to complete. Now we will use the setup function to start our program:
1 2 3 4 5 6 7 8 9 10 11 |
void setup() { // Starting the serial port. Serial.begin(9600); // We mark the pins used as output. pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.println("Ready!"); } |
We start the serial port at setup and we will use it for communicating between Arduino and the computer. We also set the different pins used for each colour as output. Within the loop, we can find different methods that we haven´t seen until now; parseInt and constrain. The parseInt method is used together with the Serial with the Serial.parseInt(); command. It searches for data received via the serial port on the next chain of whole numbers until it finds a comma. You can view the reference page here. The constrain function is used to “restrict” a value to a range between two other values. This means that if the value is between the range of A-B, it will take its value. If lower, it will take the value of A or if it is higher, it will take the value of B. You can view the reference page here. The code for the loop is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
void setup() { // Starting the serial port. Serial.begin(9600); // We mark the pins used as output. pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.println("Ready!"); } void loop() { // If information is available in the serial port we will use it: while (Serial.available() > 0) { int red = 0, green = 0, blue = 0; // search for the next valid chain of whole numbers and // assign the value converted to a whole number to the corresponding variable red = Serial.parseInt(); // search again. green = Serial.parseInt(); // search again: blue = Serial.parseInt(); // search for the end of line character. Tell the program that the entering of data has been finished. // If you use the Arduino IDE or another IDE that allows the format to be included // of the new line on sending data via the serial monitor, delete the comment // from line 33 and comment on line 34. // if (Serial.read() == '\n'){ if (Serial.read() == '*'){ // Using constrain, we make sure that the value is within the PWM range // For common anode LEDS use, for example, for red: red = 255 - constrain(red, 0, 255); red = constrain(red, 0, 255); green = constrain(green, 0, 255); blue = constrain(blue, 0, 255); // print the three numbers in one string as hexadecimal: Serial.print(red, HEX); Serial.print(green, HEX); Serial.println(blue, HEX); // We change the colour of the RGB LED fade(redPin, red, red_old); fade(greenPin, green, green_old); fade(bluePin, blue, blue_old); Serial.println("Colour changed"); // We store the data of the previous colours. red_old = red; green_old = green; blue_old = blue; } } } |
Within the loop, we can see that fade is called, a function that we have created which allows us to smoothly change the LED from the present colour to the new colour. The fade function is defined after the loop, as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void fade(int pin, int newValue, int aktValue) { // This function changes each colour from the current value to the next // We can distinguish between two cases: // 1 - The new value is higher than the current value, so we need to increase it // 2 - The new value is lower than the current value, so we need to reduce it if (newValue < aktValue) { for (int i = aktValue; i <= newValue; i++) { analogWrite(pin, i); delay(delayLed); } } else if (newValue > aktValue) { for (int i = aktValue; i >= newValue; i--) { analogWrite(pin, i); delay(delayLed); } } } |
- In this function we can distinguish between two cases:
- The next value is higher than the current value, so we need to increase the value of the LED.
- The next value is lower than the current value, so we need to reduce the value of the LED.
A command that we haven´t seen until now also appears in this function, analogWrite, which uses the PWM (pulse width modulation) capacities of our board. The PWM simulates an analogue signal using discrete pulsations from a digital signal. You can find more information on the PWM reference page.