This is the first video in the FreakLabs Wireless Communications with Arduino and the chibiArduino library series. Although Hello World might seem like a trivial application, in the case of wireless, it plays a critical role. There are many things that can go wrong in wireless so being able to transmit “hello world” means that the transmitter is working, the communications channel is okay, and the receiver can successfully receive your packet. In other words, it means your system is working from end-to-end.
In this tutorial, I’ll be walking you through the complete set up of the hardware, transmitter, and receiver. I then show how you can use your hello world application as a tool to do a site survey and log the signal strength at various areas. This is an invaluable tool to know where to position your transmitters and receivers and where you might need to bolster the signal. If you prefer to read the tutorial, the text follows the video.
Timeline
- 00:08 – Introduction
- 00:35 – Hardware Description
- 00:52 – Transmitter Introduction
- 01:49 – Transmitter Code
- 05:21 – Receiver Introduction
- 06:14 – Receiver Code
- 09:57 – Practical Application – Walkaround Site Survey
- 11:43 – Conclusion
Introduction
Welcome to the first of the FreakLabs chibiArduino Wireless Tutorial Video Series. These tutorials are designed to get you up and running quickly to transmit data wirelessly with Arduino using the FreakLabs chibiArduino library and the Freakduino platform. The purpose of this first tutorial, “Wireless Hello World”, is to make sure our hardware is okay, that we can establish communications from the transmitter to receiver, and that the complete hardware chain is working from computer to transmitter to receiver to computer. Hello World can sometimes be thought of as trivial but it’s one of the most important things you can do as sanity check to make sure the hardware is working properly.
Hardware
The hardware we will be using for this tutorial is the Freakduino 900 and the FreakUSB 900 boards by FreakLabs. The Freakduino 900 is an Arduino compatible board that integrates a wireless 900 MHz radio as well as battery circuitry for a complete standalone wireless solution. The FreakUSB is a compact, Arduino compatible USB dongle that integrates a 900 MHz wireless radio and is designed to interface directly to a computer or a computing device such as a Raspberry Pi. The combination of these two devices will be used in this tutorial to transmit data from the standalone device and receive data into the computer.
Transmit Code
Before we get into the code, it’s probably best to discuss a bit about the functions from the chibiArduino library that we’ll be using. The first thing we’ll be doing is bringing in the chibiArduino library and if you have the library installed correctly, you should just need to type in the following:
1 | #include "chibi.h" |
The chibiArduino library operates on byte arrays so to send data, we have to load it into a byte array to transmit it. The maximum payload of the chibiArduino stack is 100 bytes so I typically use a byte array of length 100 bytes, although this can change as needed. Sometimes you only need 10 bytes or even 1 byte.
1 | byte data[100]; |
Before you use the chibiArduino stack, you have to initialize it. This requires the use of the chibiInit() function in the setup code.
1 | chibiInit(); |
And finally, to transmit data, you have to call the chibiTx function which has the following format:
1 2 3 4 5 6 7 8 9 | status = chibiTx(addr, data, length); /* status: CHB_SUCCESS = 0, CHB_SUCCESS_DATA_PENDING = 1, CHB_CHANNEL_ACCESS_FAILURE = 3, CHB_NO_ACK = 5, CHB_INVALID = 7 */ |
You can see that the chibiTx function will return a status. You can choose to ignore it, but it comes in quite handy if you want to know if the data was successfully transmitted. The remote side will send an acknowledgement (ACK) if it receives the data. A neat thing about the hardware is that it will retry a transmission until it exhausts the number of retries set in the registers. The default is three retries but that can be set in the chibiUsrCfg.h file. If the retries are exhausted and still no ACK has come back, then you will get a status of CHB_NO_ACK and can decide how you want to handle the transmission failure. This functionality is extremely useful to improve the reliability of the transmissions.
Here is the complete transmit side of the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include "chibi.h" #define DEST_ADDR 0xFFFF //broadcast address byte msg[] = "Hello Wireless World"; byte buf[100]; void setup() { chibiInit(); } void loop() { chibiTx(DEST_ADDR, msg, sizeof(msg)); delay(300); } |
In the transmit code, the first thing we did was bring in the chibiArduino library using the #include directive. After that, we defined our destination address (#define DEST_ADDR …) which sets an alias for 0xFFFF. The reason we use 0xFFFF is because it’s the default broadcast address in the protocol that we’re using. We’re using IEEE 802.15.4 which is a wireless sensor network specific protocol. Other protocols such as Zigbee and Thread are built on top of it. Within the protocol, 0xFFFF is defined as an address that all devices will listen to. Even if our device’s address is 3, if a packet comes in with a destination address of 0xFFFF, it will make it through the hardware filters and our device will receive it. Normally we’ll use unicast addresses like 3, but in this case, we’ll use the broadcast address since it’s slightly simpler and we don’t have to worry about managing source and destination addresses so much.
In the setup() function, we just call one function which is chibiInit(). This will intialize the complete protocol stack and get it ready to transmit and receive data. After that, we get into the loop function and call the chibiTx(…) function. In this function, we have to pass the destination address, byte array that we want to send, and the length of the byte array we’re sending. In this case, we use the sizeof() function to automagically calculate the length we want to transmit. Finally, the delay of 300 milliseconds is just so we don’t pound the receiver and airwaves with transmissions.
Receive Code
The receive side of the code is slightly more complex than the transmit side. There’s actually a two-step process to receiving data. The first step is to see if any data has come into our device. We can do this by calling:
1 2 | rcvd = chibiDataRcvd(); rcvd: boolean value. true if data has been received, else false |
If data has been received, then we pass a byte array into our chibiGetData function:
1 2 3 4 | byte buf[100]; len = chibiGetData(buf); // len: length in bytes returned by the chibiGetData function. // This is the number of bytes we received |
And in this code, we’ll also get the RSSI or Received Signal Strength Indicator. This is the signal strength of the received packet and is an indicator of the link quality between the transmitter and receiver. We want this to be as high as possible and definitely nonzero.
1 | rssi = chibiGetRSSI(); |
With that said, here’s our complete receive 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 27 | #include "chibi.h" byte buf[100]; void setup() { Serial.begin(57600); chibiInit(); } void loop() { if (chibiDataRcvd() == true) { byte len, rssi; len = chibiGetData(buf); rssi = chibiGetRSSI(); if (len == 0) return; // print out message and RSSI here Serial.print((char *)buf); Serial.print(", RSSI: "); Serial.println(rssi); } } |
In the above code, the first part is pretty much the same as the transmit code. We pull in the chibiArduino library using the #include directive. We then declare our byte array.
In the setup function, we initialize the serial port as well as the chibiArduino library since we’ll be printing data out to the display.
In the loop function, we perform our two step receive process. The first step checks to see if data is received using our chibiDataRcvd() function. If that returns true, then we retrieve the data using the chibiGetData() function. We also get the signal strength. The next line is quite interesting: “if (len == 0) return;” . In wireless, it’s possible to get duplicate packets. This usually occurs at the boundaries of reception where the remote device receives data and then sends an ACK. The transmitter doesn’t receive the ACK though and retries the transmission. The receiver then gets a packet that’s a duplicate of the previously received packet. The software automatically checks for this case and if it happens, it returns a length of 0. In our code, we check to see if the length is 0. In this case, we don’t want to process the duplicate packet and so we just discard it and exit the loop. The final lines mainly print out our “Hello World” message and the RSSI.
Real World Application
The RSSI is actually an extremely useful piece of information because now, this software not only functions as a “Hello World” application, but can also assist in doing site surveys. I actually used the previous code to test out the link conditions at hackerfarm earlier today. We are setting up sensors to quantify specific parameters of our farm and want to accumulate the data at hackerfarm. Then we can set up a dashboard as well was timestamp and store the data inside a database. Hackerfarm is approximately 1 km away from the farm plot (FarmLab) however that 1km is deceptive since it’s the worst possible terrain for wireless communications. There is a large hill in between, multiple houses, stone walls, and there is absolutely no line of sight. The attenuation is horrible.
Actually, I was a bit skeptical that I’d be able to get communication all the way out there because of the crazy attenuation we’d be getting so I set up site survey from Hackerfarm to FarmLab. I planted an 18 dBi antenna at Hackerfarm transmitting with the exact same transmit code shown above. I then loaded the receiver code into another device and walked out to FarmLab to check on the signal strength numbers. Lo and behold, there is quite a decent connection between Hackerfarm and FarmLab and even with the attenuation, we have enough margin for a reliable connection. If we bump up the number of automatic retries to something like 10 and monitor the transmit status to see if the data made it through, we should be able to set up fairly reliable communications between Hackerfarm and FarmLab. Farm dashboard, here we come 🙂
That’s the end of this tutorial. If you’re interested in the hardware used in this tutorial, you can find it at the FreakLabs shop:
For the site survey, I used the 900 MHz long range boards. These ones have additional amplifiers on the front end to boost the range:
[page_title text=”Support FreakLabs”]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!