Recently I bought a Feather M0 RFM69 Packet Radio (this one), and setting up a hello world radio transmitter-receiver turned out to be more difficult than I expected. Mainly, because none of the examples worked out of the box. So, this is my hello world example. Maybe it’ll help someone in the same situation.
For the most part I followed Adafruit’s tutorial instructions (here), I even downloaded the RadioHead library from the link they provide. The only thing I did different was using a slightly modified version of an example in the RadioHead library (the one downloaded from Adafruit’s link). In particular, the rf69_reliable_datagram examples. Those examples did not work at first either, but then based on Adafruit’s example I changed the driver declaration line:
RH_RF69 driver(8, 3); //RH_RF69 driver;
then set the frequency:
and voila, it worked.
Also, there are two more things that I don’t know if they matter or not, but just in case: a) I used Arduino IDE v1.6.4 (from Adafruit’s link here) because I could not manage to make any example compile after installing the ArduinoSAMDboards and Adafruit SAMDboards on the newest IDE; and b) I ended up Arduino SAMD boards version 1.6.6, and Adafruit SAMD boards version 1.0.4 (I do not recall exactly why I have these versions. I was so frustrated that it wouldn’t work, so when it finally worked yesterday late at night, I told myself my Arduino was haunted and left it untouched. Most likely they work with different versions).
Recently I attempted to use an Adafruit PowerBoost 500C to power a small MCU-based mobile robot. Specifically, I wanted it to:
Supply 5v to the system out of a 3.7v LiPo battery.
Charge the battery like if it was a smartphone
Shut power down when wheels get stuck, and
Trigger an interrupt software when battery is low.
It is this last which gave me some problems. Documentation states the Low battery (LB) pin goes to ground when the battery voltage drops below 3.2v. That sounds just fine, except that there are many things that can make the battery voltage drop briefly below 3.2v, specially as it gets closer to the “low battery” point. In this specific case, even though the battery was “decently” charged, motors running would make the LB pin flicker between High and Low, thus generating a train of false interrupts. As the battery continued to discharge, the flickering continued and the Low LED in the PowerBoost board became brighter. I suspect the duty-cycle of the flickering (so to speak) increased. (I might be wrong on this, a quick look in the oscilloscope would dissipate doubts, but who has time for that). From this explanation, the solution is simple: a low-pass filter. One just needs to adjust the cut-off frequency to let only the low-battery flickering pass, and not those generated by the motors when the battery is still charged.
Low-pass filter solution
My first solution was to filter the flickering in software, and it worked fine. The problem was that no matter what the MCU was getting interrupted no less than 15 times in a second when charged. My second solution was to use a RC filter, with the RC filter I was able to reduce the number of false interrupts to around 1 to 2 per second when charged. (I’m not an expert on this matters, and I’m guessing with the right RC values, the flickering can be entirely removed. Either way, 1 to 2 times per second was good enough for me, and I did not have capacitors of other values at hand.) Then I simply filtered the 1 to 2 false interrupts using the built-in de-bounce filter in the SAM4S and an old trick used for de-bouncing buttons by checking ,waiting, and checking again (a bunch of nested if statements and delays)… after that no more false interrupts.
It’s really just one resistor and a capacitor. I used a 1 uF capacitor and 22 kohms resistor. This tutorial shows more information about it. It even shows the cut-off frequency equation to find the right values for R and C.
Recently I was in need to get two separate UARTS from the SAM4S Xpro board. It took me a while, but I finally figured out how to use the USART1 with interrupts; and since I already had working code for UART1, I decided to post examples for both.
UART1 is exposed in pins 13 and 14 in EXT3, and also in the Debug USB port. It requires the UART – Univ. Async Rec/Trans (driver) ASF module. For this example I’m using the code from here, without any modification.
USART1 is exposed in pins 13 and 14 in EXT1 and EXT2. It requires the USART – Univ. Synch Async Rec/Trans (driver) ASF module. Other modules that may be using it must be removed, or else you get a USART1_Handler redefined error. Most of the code for this example is from the ASF documentation, but it was missing a configuration step of USART1 pins. Also it had what it seemed to be a mistake; in the call to usart_init_rs232, I replaced sysclk_get_main_hz() for sysclk_get_peripheral_hz(), and that fixed it. The working code is in the downloads.
I recently acquired an Atmel BNO055 Xplained Pro board, which features a 9-axis absolute orientation sensor, or at least that is the part I’m interested in. Then I found that the ASF does not provide BNo055 support for the SAM4S. Luckily, it does for the SAM E70. So I adapted the SAM E70 drivers to work with the SAM4S, and surprisingly it worked without any issues.
Note that the drivers in the ASF are a port from the ones provided by Bochs (BNO055 chip manufacturer).
In the downloads you will find an Atmel Studio 7 solution. The /ASF/ThirdParty/bno055 folder contains the driver’s source code, and /config/conf_bno055.h is the configuration file. It is tested for ASFv3.34.1.
The downloads also include three examples. motion_example.c demonstrates how to configure the sensor in low power mode. That is, when no motion is detected the sensor’s MCU goes to sleep, and, when it detects movement (while sleeping), it wakes up and interrupts the main MCU (SAM4S in this case). orientation_example.c configures the sensor in normal mode (no interrupts) and reads orientation values. Lastly, motion_and_orientation.c is a combination of the two, and demonstrate how to read the sensor only when it is awake.
Reading other output data
Like I mentioned above, I was not interested in anything other than orientation values, but it is possible to query the sensor for other fused and non-fused data (e.g. raw accelerometer data). I have not test them, but the SAM E70 example was using these:
This is the second version of a MAC Interface (based on Xbee S1 Radios) for the SAM4S Xplained Pro. More than Xbee drivers, or an Xbee library, it is an actual IEEE 802.15.4 MAC interface. I call it interface, because the entire MAC functionality is handled in hardware from within the Xbee. I simply wrote drivers for the Xbee, and added a MAC and message abstractions.
Setting up the radio
Using the XCTU utility make the following changes to the Xbee S1 radio:
Reset to factory settings (to avoid any parameter being set to a value that might prevent communication),
Set the baud rate to match RADIO_SPEED_RATE in mac_config.h
Change to API mode
Write changes and verify.
Then plug the radio’s Rx, Tx, Vcc and Gnd pins to the SAM4S Xpro board. Because the software uses USART1 you will need to use Rx (Pin 13), Tx (Pin 14), Gnd (Pin 19), and Vcc (Pin 20) in either EXT1 or EXT2. Alternatively, if you have an IO1 XPlained Pro, you could use the pins labeled Rx, Tx, Gnd, and VTG in the IO1 board. (Not sure why these pins? See here or check the SAM4s Xpro User Guide.)
There are three demos. One demonstrating unicast messages, and one demonstrating the use of RSSI. The unicasting demo consists of two nodes. Both send a 1-byte asynchronous message to each other approximately every half a second. Whenever a message is received, they toggle their respective LEDs. Likewise, the RSSI demo consists of two nodes. They both blink their LEDs depending on the RSSI of the last message received.
This is a bare-metal implementation, so do not access the radio concurrently! Meaning, do not access the radio from interrupt handlers (that includes msg_received and ack_received). This is because the radio is a shared resource. Some radio functions (e.g. radio_read_address) span two operations: asking something to the radio, and then receiving a response. You don’t want to use the radio in between. Or say execution is in msg_received, which is executed from the USART1 interrupt handler. Then you ask for radio_read_address which will send data to the radio and then busy-wait until it receives a response. Because execution is already in the USART1 Handler it’ll deadlock. In other words, odd things may occur. So don’t!
To port to a different platform rewriting of xbee_cpu and xbee_uart modules should suffice. All data types used are stdint. h types (e.g. uint8_t).
Source code’s license is GPL (see source code).
In this second version some functionality is NOT IMPLEMENTED. Namely,
Networking-, security- and sleeping-related radio functions (e.g. node discover, sleep mode) .
64-bit MAC address support
Verification of checksum when receiving API frames, as well as doing something when the checksum is wrong.
Verification of status (OK Status) in received responses to Xbee commands
Support for duplicate frames (maybe). The IEEE 802.15.4 standards defines a sequence number as part of the MAC header, to filter duplicate frames. This suggests this is all handled internally by the Xbee. Yet the Xbee has a MAC mode available to eliminate duplicate frames, hence suggesting otherwise.
Processing of Modem Status frames. Though, with the current functionality, modem status frames are never sent by the Xbee (see data_received_callback in xbee.c).
Tested with ASF v3.34.1 (it should compile for newer versions of the ASF with none or minimal changes).
Source code alone and as an Atmel Studio solution.