With the introduction of the Ground Station, I have spent the past couple of days writing the framework that handles the communication between the Ground Station and Autopilot. The previous incarnation of the Ground Station was simply the ground radio connected via USB to the laptop. The code handling the communication would therefore run on the laptop. In the new version, this code now runs on an ARM7 microcontroller. The goal is to have the Ground Station in continuous communication with the Autopilot, updating variables at different rates and storing them locally. The Ground Station software running on the laptop would then simply read these updated values through USB from the ARM7.
With that in mind I set out my goals for the communication framework:
- Object orientated approach using “Command” objects containing the commands and respective data.
- Asynchronous queuing of “Command” object, allowing multiple threads to send commands at the same time.
- Handling of data received from the radio, and associating the response to the correct command.
- Operation using DMA (Direct Memory Access) and interrupts only, saving processor time
This framework will run on both the Autopilot and Ground Station using the RFM DNT900 radios mentioned in previous articles. The DNT900 radios are used in protocol mode which allows the setting of a destination MAC Address and also packet length. On the receiving side, protocol mode provides a distinct header which can be used to pick out the beginning of the packet.
The ARM7 architecture from Atmel has very extensive DMA coverage of all peripherals. The UARTs used to communicate with the radios have Rx and Tx double buffer DMA channels which allow uninterrupted reception or transmission of data without processor intervention. Interrupts are also provided when the buffers are empty (in case of Transmission) or full (In case of Reception).
The picture below shows what’s going on in a high level flowchart (click to enlarge):
To explain what’s going on, I’ll start at the Ground Station. The first thing to note is that commands can be Queued both from the USB interface and also periodically. This allows the Ground Station software to issue commands to the DNT900 via the USB interface (such as read a radio register). Periodical commands will be used for retrieving telemetry from the aircraft or updating control surface positions when required. The command queue will make sure that no collisions take place as new commands are added.
The Tx Empty interrupt is employed to signal when the UART transmitter has finished doing whatever it was doing and is ready to send. The command is then sent through the radio to the Autopilot. On the receiving side, as commands are received, their DNT900 CommandIDs are matched to the commands in the queue to determine their original command. The data is then copied to that particular command object and a status flag is set for that command (If the command was a data Rx/Tx command, a callback function is called).
The reception is achieved completely through the DMA and interrupts. The processor sets the DMA to generate an interrupt when a packet header is received. This packet header contains the length of the total packet. A second interrupt is then set to fire when the entire packet has been received. Therefore each packet is received via 2 Rx interrupts and with minimal processor overhead.
On the Autopilot side, the entire process is repeated with the exception that the Autopilot will only send commands in response to an original inquiry or command from the Ground Station. This “polling” system allows the Ground Station to talk to multiple Autopilots at once without collision. The interrupt and DMA driven system also frees up the processor and simplifies the act of sending a command. You simply create a “Command” object and populate it with data and push it into the FIFO. When a response is received for your command or if it times out, a status byte will be set accordingly on your command object. For periodic commands, a Callback function is called to facilitate the transfer of data from the command to the registers of the Ground Station or Autopilot.
To simplify the operation of the Ground Station, I have also implemented its “Configuration” in the form of registers with an address and category. These registers can then be read/written to from the USB interface to change the configuration of the Ground Station. This configuration includes things such as transmission power and time interval for periodic commands.
At the moment I’m still ironing out some bugs but it’s looking good to go for our flight this weekend. I’m hoping to have the ground station collect some data from the Autopilot while Damien manually flies the plane. Stay tuned!