Intro
Blinking an LED is the hello world of hardware. When you can blink an LED, you can pretty much control anything. Turning an LED on and off is the same as turning on a relay, transistor, or any other interface circuitry. That means that turning an LED on and off is the equivalent of turning on and off things like an air conditioning unit, a heater, or pretty much anything. From a software point of view, it’s the same. The main difference is the interface hardware.
In this tutorial, we will be doing a slight variation on the standard blink application by remotely turning on and off an LED wirelessly. In the previous tutorial, we used a broadcast address to send data to the receiver. In this one, we will use a unicast address to turn on and off their LEDs. You should also see that you can easily extend this to multiple devices to control their LEDs just by adding unicast addresses to the packets you transmit. Let’s get started.
Hardware
The hardware we’ll be using is the same hardware as we used in the first tutorial. We’ll be using the FreakUSB 900 and the Freakduino 900. In this case, the FreakUSB will be the transmitter and the Freakduino 900 will be the receiver. This is also known as an actuator network as opposed to a sensor network since data will be originating from the main computer and controlling other devices.
Tx Code
For the Tx code, we’ll be setting an address for our transmitter. We actually don’t really need it, but it will come in handy later on. You actually just need to set the address once on your nodes and they will be saved in nonvolatile memory. The address won’t change from that point on until you set the address again in your code.
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 | #include "chibi.h" #define DEST_ADDR 3 #define PAYLOAD_SIZE 100 #define DELAY_TIME 300 byte buf[PAYLOAD_SIZE]; void setup() { chibiInit(); buf[0] = 0; } void loop() { if (buf[0] == 0) { buf[0] = 1; } else { buf[0] = 0; } chibiTx(DEST_ADDR, buf, 1); delay(DELAY_TIME); } |
You might be starting to see some similarities on the transmit side now if you went through the previous tutorial. The first thing we do is bring in the chibiArduino library by declaring
#include “chibi.h”
We added more #define statements here because it cleans up our code and makes it more readable. We added a define for the destination address, source address, and payload size. By having the defines here, we can change them any time just by changing the define. That way, we won’t have to comb through our code and change the value everywhere when we want a different payload size or address. In this code, it’s not so much of a problem, but as code gets larger, it really helps to keep the code clean and organized.
We also declared our byte buffer which will hold our transmit data and set it to the payload size. If you read further on in the code, you’ll see we only use 1 byte of the byte buffer. You can technically adjust the payload size define to 1 byte because of this. I’m just using 100 bytes because its the max payload size and I don’t have to think about what size I’ll be using in the code.
In the setup, I initialize the chibiArduino stack and then set the first byte of the data buffer to 0.
All the work is being done in the loop code. In this code, we’re toggling the first byte of the data buffer between 0 and 1. You can actually simplify that code immensely by using the following statement:
buf[0] ^= 1;
That would xor the value which also toggles it between 0 and 1, but to make it readable, it’s probably best to keep it a bit verbose. We have plenty of code space anyways so it’s not a huge issue to have larger statements. The first byte of the data buffer is all we’re going to send and it will be used to control the LED on the far end. When it’s a 1, the LED will turn on, when it’s a 0, it will turn off.
Once we have the value we want, we transmit it using the chibiTx function. In this case, we’re sending it out to a unicast address as opposed to the previous tutorial where we sent it out to a broadcast address. For a broadcast address, any device within listening range will receive the packet. For a unicast address, only the specific device will receive the packet. All other devices will automatically filter out the packet and they won’t receive it.
Finally, we add a bit of delay so it won’t blink so fast that we can’t see it.
Rx Code
Before we get into the Rx code, we need to add the LED to the freakduino board. We’ll be using pin 9 for the LED so we’ll want to connect an LED with the short leg going into pin 9 and the long leg going to GND. This is actually a bit of a hack because we usually need to add a current limiting resistor to the LED. However in this case, we’re driving the LED directly off the Arduino microcontroller’s pin (pin 9) which can only source up to 30 mA. This is about how much current an LED needs to operate so its still within the safe zone. If however, the pins could source up to 100 mA, then we’d probably need to add the resistor or risk burning out the LED. In general, its not recommended to wire up an LED like this, but in this very, very special case, it should be okay.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include "chibi.h" #define MY_ADDR 3 #define PAYLOAD_SIZE 100 #define LED_PIN 9 byte buf[PAYLOAD_SIZE]; void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); chibiInit(); chibiSetShortAddr(MY_ADDR); } void loop() { if (chibiDataRcvd() == true) { byte len = chibiGetData(buf); if (len == 0) return; digitalWrite(LED_PIN, buf[0]); } } |
The Rx code follows the same format for receiving data. Similar to the Tx side, we need to bring in the chibiArduino stack by using #include “chibi.h”. After that, we add a couple of #defines for the main parameters our code will be using. In this case, the node address is set to 3 which is the destination address we used in the transmitter. We are also setting the led pin here. I actually chose pin 9 because it also happens to be a PWM pin. That way, it’s easier to use it to fade or dim the LED later on.
We then declare the byte buffer which will hold our received data.
In the setup, we need to initialize the LED and the chibiArduino stack. To initialize the LED, we use the pinMode() function and set the LED to an output. We then also write a 0 to the pin so it will turn the LED off initially. After initializing the chibiArduino stack, we also set the short address for the device. The protocol we’re using is IEEE 802.15.4 which contains two types of addresses: the 64-bit long address and the 16-bit short address. The short address is kind of like the nickname and it will need to be unique for the particular network. The 64-bit long address is designed to be globally unique so only one device would have that address in the whole world. In this case, we’re just going to set the short address since to 3 which is a unique address to our network.
In the loop code, we test to see if we received any data into the device by calling the function chibiDataRcvd(). If it returns true, that means data has arrived and we can process it. If data has arrived, we call the chibiGetData() function and pass in our byte buffer. That function will return the length or amount of bytes of data we received. The next thing we want to do is check to see if the length is 0. If it is, then that signals a duplicate packet which means that it’s a packet that we’ve already received. This usually happens at the periphery of reception where the transmitter doesn’t receive our acknowledge and resends data to us. In this case, we just discard it.
Once we have valid data, we write the value of the first byte to the LED pin. This should be the toggling value and it should blink our LED. Voila!
Application
There are actually two applications that can immediately use this code from Wireless Blink. The first is as a simple device to check for dead spots when you’re doing a site survey. I use this quite often where I send a stream of data to wirelessly blink an LED. The receiver is battery powered and will blink the LED. As the transmitter puts out the signal to blink the LED, I can then walk around with the receiver and see how far I can receive signal and where dead spots might be. You can tell when you’re hitting the limits of signal reception because the LED starts blinking erratically as it loses some of the packets. Your eye is quite perceptive with patterns and so when you see the rhythm of the LED starts becoming less constant, you know you’re hitting reception limits. You can see me doing something similar as I’m testing out where the signal boundaries are for a farm that I’m helping to instrument with wireless sensor devices. I’m transmitting from a set position in the farm near where we would position a 3G bridge from the local sensor network to the larger internet. From that point, I want to see how much of the farm area we can cover with signal, especially because the terrain is extremely hilly.
Another application of wireless blink actually helped me create another full product line called Illuminado. It’s actually quite strange that one of my most successful projects is essentially a specialized application of wireless blink. It started with me discussing with some dancers about triggering EL wire on and off wirelessly to music back in 2012.
They would choreograph their movements to the music and also to the lighting configurations. We worked on the project together and the basic core of the application was this code from wireless blink. On the receivers, I would wait for wireless signals to come in that would trigger the receiver to turn on different pins. Over time, I would also start integrating other effects like fading the lights on and off, but the basic crux of it is waiting for some signals to come in and then turning things on and off based on those signals.
On the transmitter side, I had the basic transmitter code but had to incorporate a little bit more functionality to bridge an off-the-shelf application and translate the signals it sends out to signals that the receiver can understand. However once the translation was done, it was basically sending packets out to each receiver and telling it which pins to turn on and off.
If you enjoyed this tutorial and are curious to learn more about wireless, please show your support by checking out the FreakLabs shop. All the boards used in this tutorial can be purchased here . Thank so much!