Part 5 - Serial communication
For this exercise we will be making use of the Libelium xBee shield which allows us to use an xBee radio module for wireless serial communication. xBee modules are based on the ZigBee protocol which is often used in IoT applications. To us they represent an incredibly easy way to set up wireless serial communication with no configuration, but they can also be accessed with configuration tools to do more complicated things like setting up a mesh network of sensors, or a home automation system. On the Leonardo board we can send serial wirelessly just by doing a 'Serial1.print', note the '1', and send our serial message to any other xBee enabled Arduino in the vicinity. This also means when we start serial we need to use 'Serial1.begin(9600)'. We can still use 'Serial.', without the '1', functions like printing for debugging etc.
The circuit:
I have set up a SEND unit which will be broadcasting address and code number combinations, you need to create a RECEIVE function that will listen out for only your address and then use the code number to turn your RGB LED a certain colour. Serial is received into a buffer and can be read a byte at a time so often requires the creation of a string that you add characters to as you read them out of the buffer. In this case we are working with integers and can use the 'Serial.parseInt()' function which simplifies things somewhat. You will see all sorts of ways of working with serial and there are many tutorials available, depending on your application you may want to give each communication a start and end character or look out for a new line to signify the end of the message, but for this exercise we can keep things simple.
The SEND unit code:
/* * The SEND part of our serial communication * via our xBee shield. We are sending numbers * 1 - 10 for the address of the node we want to * speak to and then a code int for the colour * we want them to show. * * * Luke Woodbury 16 Jan 2017 * dotLib.org */ void setup() { //set up serial for the xbee comms Serial1.begin(9600); //set up serial for printing to monitor etc Serial.begin(9600); } void loop() { //use a for loop to create 0 - 9 for (int i=0; i<10; i++){ //...add a 1 to send 1 - 10 Serial1.print(i+1); //Serial.print(i+1); //use the modulo operator to wrap i to 0 - 2 int code = (i%3); //send a space Serial1.print(' '); //Serial.print(' '); //... then send the code Serial1.print(code); //Serial.println(code); //...then another space to stop parseInt waiting Serial1.print(' '); delay(500); } }
We will use the mechanism below to read in our serial message
if (Serial1.available() >= 3) { //use 'parseInt' to set the address variable address = Serial1.parseInt(); code = Serial1.parseInt(); }
- You need to set the address of your node. Use the number on your breadboard, for example:
const int thisNode = 1;
- Use the address value to see if a message is meant for you, if not ignore it
- Use the code to decide which LED to turn on 0 for Red, 1 for Green or 2 for Blue, you can use a switch case statement or an if else statement to do so
- Set a delay of a second and then turn the LED off again
- If you have got it right your LED should light up the same colour every 5 seconds
+ Hint 1
You need to declare pins and variables for the LEDs, the incoming address and code:
//set up the LED variable and the actual pin consts int LED = 1; const int redPin = 10; const int grnPin = 6; const int bluPin = 9; //this will be where we set the number of our node //i.e. the number written on your breadboard const int thisNode = 1; //variables to hold the incoming node address and code int address = 0; int code = 0;
+ Hint 2
You need to start Serial and your LED pins should be set as OUTPUT:
void setup() { //set up the serial data rate Serial1.begin(9600); //set the pin modes pinMode(grnPin, OUTPUT); pinMode(bluPin, OUTPUT); pinMode(redPin, OUTPUT); }
+ Hint 3
The main loop needs to:
- use the mechanism above to parse the incoming integers
- check if the message is addressed to us
- if it is, then set the LED pin to use and set it high
- delay and then turn it off
+ The solution
/* * The RECEIVE part of our serial communication * via our xBee shield. We are receiving numbers * 1 - 10 combined with an int code. * The number is the address of the node we want to * listen out for and the code is the colour we want * to show. * * * Luke Woodbury 13 Jan 2017 * dotLib.org */ //set up the colour variable and the actual pin consts int LED = 0; const int redPin = 10; const int grnPin = 6; const int bluPin = 9; //this will be where we set the number of our node //i.e. the number written on your breadboard const int thisNode = 1; //variables to hold the incoming node address and code int address = 0; int code = 0; void setup() { //set up the serial data rate Serial1.begin(9600); Serial.begin(9600); //set the pin modes so they are bright! pinMode(grnPin, OUTPUT); pinMode(bluPin, OUTPUT); pinMode(redPin, OUTPUT); } void loop() { //if there is something in the serial buffer if (Serial1.available() >= 3) { //use 'parseInt' to set the address/code variable address = Serial1.parseInt(); code = Serial1.parseInt(); //if address matches our node number if(address == thisNode){ //Serial.print(address); //Serial.println(code); //use a switch statement to change the LED pin to light switch(code){ case 0: LED = redPin; break; case 1: LED = grnPin; break; case 2: LED = bluPin; break; } //we could have used an if statement instead of course /*if (code == 0){ LED = redPin; } else if (code == 1){ LED = grnPin; } else{ LED = bluPin; }*/ //turn the LED on and off digitalWrite(LED, HIGH); delay(1000); digitalWrite(LED, LOW); } } }