Project source code at GitHub: samd21-lora-gps
I’ve been doing some LoRa projects lately in order to learn as much as I can about this exciting new radio technology (see this LoRa mesh networking project and this LoRa weather station). ATmega328-based Moteino modules work great for a lot of projects, but I wanted a LoRa node with more processing power, more memory, and an onboard GPS receiver. The ATmega328 is just too constrained with memory — I’ve outgrown it. I really wanted a LoRa board with an ARM Cortex microcontroller like the SAMD21. This is the microcontroller used on the Arduino Zero. So, my ideal board is a SAMD21 with LoRa radio module and GPS receiver, all programmable with the Arduino IDE.
But, where is such a board? I could not find one so I decided to design and make one myself.
Microchip/Atmel makes a SAMD21 chip and there are several variants. Most designs use the ‘G’ variant, but I wanted to use the simpler ‘E’ variant because it comes in a TQFP-32 package that I can very easily solder in my reflow oven without any trouble, or even by hand if I have to.
The GPS module is a cheap Quectel L80 with a MTK3339 chipset. It is easy to use but the backup power circuit requires a charging circuit, so I don’t have battery backup for quick startup. I mainly chose this module because it has big soldering pads with 2.54mm spacing for easier prototyping.
The LoRa radio module is a HopeRF module soldered to the bottom of the board.
Here is the schematic and image of the board design. The Eagle files are in the hardware directory of the samd21-lora-gps GitHub repo.
Burning a Bootloader
To make this board work with Arduino, I had to burn the Arduino bootloader onto the chip using an Atmel-ICE programmer. My board has 5 test points on the bottom for this purpose. The Atmel-ICE needs connections for VTG (3.3V), SWDIO, SWCLK, RESET, and GND. The board has to be powered over USB during the programming procedure. In the Arduino IDE, I selected Tools->Board = Arduino/Genuino Zero (Programming Port), Tools->Programmer = Atmel-ICE, and then just clicked Tools->Burn Bootloader. In a few seconds, my board had a bootloader and is now programmable as an Arduino Zero!
Programming the Board
I was careful in my design to allow this board to be used as an ordinary Arduino Zero even though it uses a different variant of the SAMD21 chip. The downside of this is that the default SPI pins defined for the Arduino Zero board use pins that are not present in the ‘E’ variant of the SAMD21. Luckily the design of the Arduino system is flexible enough that we can define a different SPI interface on different pins. There is a great article by Adafruit on this topic but it may be pretty hard to understand. The bottom line is that by using these lines in your Arduino sketch:
SPIClass SPI1(&sercom1, 12, 13, 11, SPI_PAD_0_SCK_1, SERCOM_RX_PAD_3); pinPeripheral(11, PIO_SERCOM); pinPeripheral(12, PIO_SERCOM); pinPeripheral(13, PIO_SERCOM);
You can now use interface SPI1 to communicate with the LoRa module. I wrote a simple test sketch that reads the GPS module and broadcasts the GPS coordinates on the radio every 15 seconds. See the samd21-lora-gps GitHub repo.
This test code uses the RadioHead library to control the LoRa radio. The RadioHead library is flexible so I was able to use the SPI1 interface by defining a couple of new files, RHHardwareSPI1.[cpp,h].