Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

FlightGear

Input from a pushbutton

A simple scenario: Arduino "talks" to FlightGear

Let's play with FlightGear and Arduino now! We want Arduino to interact with Flightgear, we'll make it send data over a serial connection so that it will make FlightGear do something accordingly.

As a first example we will make Arduino read a digital input (a push button) and send its status over the virtual serial connection to the PC. FlightGear will listen to that very same virtual com port, read the value and update its property tree accordingly.

Arduino will keep sending those values and Flightgear will keep reading them and updating its own status.


Virtual COM Ports

Let's point a few details out first. When you attach Arduino to your PC with a USB cable the OS will treat it as a Virtual Serial Port, that means the PC will "talk" to Arduino thinking it's connected to a serial port even it's a USB connection instead.

That makes things easy to us since a serial connection is easy to handle and FlightGear provides a framework for that.

There's a little caveat for Windows users having their Arduino board recognized as a COM21 port (or any other high numbered com port, i.e. everything over COM9). You have to name it \\.\COM21 when talking to FlightGear, don't try calling it simply COM21, Flightgear will fail talking to it.


Wiring Arduino and the Input Sensor

That's pretty basic stuff to any Arduino user. I'll be quick with that.

Connect a push button as you normally would. One pin goes to a digital input (that's pin7 here), the same pin is connected to a 10KOhm resistor; the other pin goes to +5V. The resistor is then connected to GND.

That way Arduino knows the button is pushed when pin7 senses a +5V signal on it, otherwise it senses the GND through the 10KOhm resistor. Hence we have a 1 or a 0 on pin7.

Check this Playground example if you want to know more about this basic schematics: http://arduino.cc/en/Tutorial/DigitalReadSerial


Coding Arduino

That's basic stuff too. Copy this code inside the Arduino IDE; compile it and upload it to your Arduino board.

  1. /*
  2.   FGFS Pushbutton Input
  3.   Reads a digital input on pin 7, prints the result
  4.   to the serial port
  5.  
  6.   This example code is in the public domain.
  7.  */
  8.  
  9. void setup() {
  10.   Serial.begin(9600);
  11.   pinMode(7, INPUT);
  12. }
  13.  
  14. void loop() {
  15.   int sensorValue = digitalRead(7);
  16.   Serial.println(sensorValue);
  17. }

We are setting the serial communication speed at 9600bps here, it's a commonly supported speed over any serial communication. Not very fast but fast enough. We could crank it up in the future when higher data transfer rates will be usefull. As of now, it's enough.

The sketch is reading Arduino's pin7 digital input, if it's HIGH it prints a 1 (one) char over the serial line, if it's LOW it sends a 0 (zero) char over it.

Open up the Serial Monitor and check what happens while pushing and releasing the button.


Making FlightGear listen to the serial input

Now that Arduino is pumping data over the serial port, we have to make FlightGear listen to that.

Let's say our Arduino appears to the OS as COM21. I am using Windows here, so please forgive me if I use this convention for naming serial ports and I'm not being generic enough to provide specifics for other OSes; Linux users will have their serial ports named something like /dev/tty01 (or similar). Other OSes ... I don't know.

We will call it \\.\COM21 when talking to FlightGear, that's the way it wants them to be named. That's not necessary with COM1-9 (because Windows provides aliases to those Device Names) but it's mandatory with COM ports over 9 (for which there are no aliases). That's according to the Win32 Device Namespace convention. Check this document for further details: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx

Making FlightGear listen to a serial port is simple as adding a command line option to the executable before running it. The command line option looks like this:
fgfs.exe --generic=serial,in,30,\\.\COM21,9600,Arduino_GearDown_SerialInput

This very long command line option tells FlightGear a few things: that it has to listen to a serial input communication, it has to check 30 times per second for incoming data, it has to listen on port \\.\COM21 which is set at 9600bps and it has to use the Arduino_GearDown_SerialInput.xml file to decipher this communication.

If you use FGRUN (the Windows FlightGear Wizard) you may fill a bunch of input fields inside the Input/Output section of the Advanced Options instead of manually writing this very long option. It will be much more simple and you will not get it wrong.

Well, that's almost all of it. We only miss something now, we mentioned it earlier, it's the Protocol File, it's the glue that binds the two worlds together. We still have to write down the previous mentioned Arduino_GearDown_SerialInput.xml file. It describes how data will arrive to FlightGear and how it has to treat them. Keep on reading.


Writing an Input Protocol File

Writing a protocol file is needed to make FlightGear know what incoming data to consider and how to use them.

FlightGear stores protocol files inside its FlightGear/data/Protocol directory. Btw, I strongly invite you to read the README.protocol file.

FlightGear treats data arriving in blocks, every block has a predefined amount of chunks. Each chunk defines a property to be written in its property tree. Everytime new data arrives through the serial connection, FlightGear will update its own property tree with the new values.

Each block ends when a line_separator has been read, each chunk is separated by the following one with a var_separator.

In this simple example we have a single data chunk to read, FlightGear is expected to update only a single attribute in its property tree. We will update the /controls/gear/gear-down property only. In a more complex scenario we will have more chunks arriving all at once in a single block, they will be separated by some special character (or an entire word), Flightgear calls that a "Variable Separator" (var_separator). Every block will terminate with a "Line Separator" (line_separator).

The following protocol file defines incoming data as being made by a single field, only one chunk is defined, the one called GearDown. Flightgear will expect to receive boolean values (0 or 1) and will update the property /controls/gear/gear-down in its tree with that value. Every line will be terminated with a carriage return (remember the code: Serial.println(sensorValue)). The var_separator will result being useless since there are no multiple attributes to read.

<?xml version="1.0"?>
<PropertyList>
 <generic>
  <input>

   <line_separator>carriagereturn</line_separator>
   <var_separator>,</var_separator>

   <chunk>
    <name>GearDown</name>
    <node>/controls/gear/gear-down</node>
    <type>bool</type>
   </chunk>

 </input>
 </generic>
</PropertyList>

Simply copy this code into a text file and save it in FlightGear's protocols directory with the name Arduino_GearDown_SerialInput.xml .


Starting FlightGear

Now everything is ready go. Arduino is running the code and sending zeroes and ones over the serial connection, FlightGear's protocol file has been saved and FlightGear's command line option has been entered.

Now start FlightGear as usual and check what happens when you push the button connected to Arduino.


Side notes

Create the custom protocol file before running the FlightGear Wizard otherwise it will not display the newly created protocol file in its list. That's because it scans the protocol directory only when it starts up. In this case, simply close the wizard and start it again so that it scans the protocol directory with the new files inside.

Don't run FlightGear when Arduino's Ide Serial Monitor is open. That won't work. The Serial Monitor will lock the serial port and FlightGear will not be able to listen to it.
If you do, FlightGear will fail with the following error message:

Error opening device: \\.\COM21
Error opening channel communication layer.
I/O Channel config failed.