Wikis > Developer Resources

Print Friendly, PDF & Email


Software used for development

Developer Image

The developer image is available to registered developers and comes as an Ubuntu 14.04 installation with all required toolchains and IDEs for both Firmware and Hostsoftware development. It was created using Oracle virtualbox 4.3.28 and exported as a OVA file.

It can be run with Oracle Virtualbox, which is available for Windows, Mac OS X and Linux:

Download site for Oracle VirtualBox

Alternatively, it can also be run with VMWare Playerm which is available for Windows and Linux:

Download site for VM Ware Player

Axiamote Firmware

The Axiamote Firmware is written in C++, makes use of the Free Rtos Operating System (v.4.7.0) and is compiled with the CodeSourcery Lite Toolchain.

Free Rtos Homepage

Code Sourcery Workbench Lite Home Page



The Hostwaftware is written in C++ against the Qt – Library 5.4 using the bundled IDE Qt Creator.
The code provided compiles for Android, Windows, Linux x86 and Linux for Raspberry Pi.

Hardware Mechanic

The mechanical parts are designed in FreeCad, version 0.15, which can be installed  from the Freecad developer PPA:

Hardware Electronics

The Electronics, that is schematic and layout are developed using Altium Designer version 4.3.17.
These files  are only available to registered developers.

Developer Image Documentation

User customization


Login with
User: axiamodeveloper
Password: AxiamoDev

Git configuration

Run the following lines in a terminal to set your username and email address to be used in git:

git config --global "Your Name"
git config --global

Create a new ssh key to be used to authenticate against git:
ssh-keygen -t rsa -C "MyName_Axiamo_Key"

Accept default settings (empty passphrase and storge in .ssh folder)

Folder structure


All Toolchains are installed under


Source Code Organization

The source code is organized under

Firmware IDE

To develop Axiamote Firmware, the Eclipse Juno IDE is used. It is started from launcher icon or from terminal:

Start JLINK Debugger


Axiamote in Debug Dock

Place the Axiamote in the debug dock. Make sure the JLink Adapter is plugged and mapped to the VM.

The JLink GDB Server acts as a bridge between the eclipse IDE and the JLink JTAG Debugger used to deploy firmware to the Axiamote and for debugging. Start the Jlink debug server from terminal with jlgdb_power_on .

The alternative script jlgdb_power_unlock is used to unlock an Axiamote which was programmed with a debug-locking bootloader before.

Start debugging on Axiamote


Axiamote debugging started

With the Axiamote in the debug station and the Jlink debugger started, open the Eclipse Firmware IDE and choose the matching launch configuration (e.g  ‘Axiamote Debug’) from the Debug menu. After the programm was transfered, Execution will stop at the first line and allow for debugging.


Hostsoftware IDE

As the IDE for the Hostsoftwrae (Linux, Android, Raspberry, Windows)  Qt Creator is used. It is started from Launcher icon or with qtcreator from terminal.
The Qt project file for the Axiamo Hostsoftware is found under /home/axiamodeveloper/Documents/AxiamoRepo/Host/Axiamo/

The selection for which Target (Linux x86 / Android / Linux Raspberry PI) the software is built is made by choosing the right Kit. The software is built in “shadow build” mode, which means a seperate build directory is created for each environment, so serveral different builds can co-exist.

Select Deployment Target

Select Deployment Target

Deploying to Linux

Starting the software on x86 Linux (in the VM itself) is achieved by selecting the Kit “Desktop Qt 5.4.1 GCC 64 bit). After build, no further steps are required, the software launches locally.

Deploying to android

Plug an android device on USB and map it to the VM. Make sure USB-Debugging is enabled on the android device. Test for connectivity in Debug mode by calling adb devices in a terminal:

axiamodeveloper@AxiamoUbunutuVM:~$ adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached
e022d807 device


Deploying to Raspberry PI

Basically deploying to a Raspberry is done by selecting the “RaspberryKit” from the build kit selection menu, transfer of the file and starting the process on the raspberry is handled by Qt Creator. However we need to establish connectivity beforehand:

1)  Find the IP Adress of the raspberry PI (it is easiest to connect it to a screen, login, and check the IP with ifconfig, or apply a fixed IP, depending on your setup).

2) Establish an ssh connection, accepting the ECDSA key fingerprint if you connect for the first time.

axiamodeveloper@AxiamoUbunutuVM:~$ ssh pi@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is c1:4e:93:31:07:0b:b7:f4:14:78:12:0a:f4:d8:30:e9.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.

3) Adapt IP-Adress in Qt Creator.
In QtCreator, open “Tools,Options,Devices”, Add a new “Generic Linux Device” or adapt the Existing one. Enter the IP-Adress you’ve found before.


IP address settings for Raspberry PI in QtCreator

4) Select device in Raspberry Kit

In QtCreator, open “Tools,Options,Build&Run,Kits,RaspberryKit”, select the device you adapted or created before.

Select Raspberry Device to deploy to

Select Raspberry Device to deploy to

5) Transfer the Qt library files to your raspberry. You can do this by burning the raspberry PI image mounted on the development machine to the SD card, or by using rsync for the transfer:

On the developer machine, run:

rsync -rav /mnt/rasp-pi-rootfs/opt/qt5/ pi@<raspberrPiAddress>:/home/pi/qt5/

Open as ssh connection to your raspberry:
ssh pi@<raspberrPiAddress>

On the raspberry, move the Libs to the correct location.
sudo mv qt5 /opt/
and then set the LD_LIBRARY_PATH in your .bashrc script :
echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/opt/qt5/lib/" >> .bashrc

Finally, reboot the raspberry.
You only need to run these steps for the first time deplyoment to your raspberry, once done you can simplay deploy by hitting the run button from QtCreator.

Software documentation

Axiamote Firmware

Operating system

Axiamote Firmware is based on the Real Time Operating System FreeRtos.

Please refer to the Online API  for usage of the RTOS classes.

The version currently in use is: V7.4.0

Measurement Allocation Table (MAT)

The MAT contains an index of start and stop adresses of Measurements in Flash.

A MAT entry is started when enabling record flag and  finished when disabling the record feature.
The complete MAT (first page in flash) can be read with

<msg>1<GetFlashPage> 00 00 01 00 </msg>


MAT entry structure

Length: 18 Bytes

8 Bytes 4 Bytes 4 Bytes 2 Bytes
measurementID startAddress endAddress CRC16

Byte order of values is MSB to LSB


EF CD AB 89 67 45 23 01 00 03 00 00 00 03 00 03 07 F8


  • 8 Bytes 01 23 45 67 89 AB CD EF

start address:

  • 1 Byte LUN: 00
  • 2 Bytes Block: 00 03
  • 1 Byte Page: 00

end address:

  • 1 Byte LUN: 00
  • 2 Bytes Block: 00 03
  • 1 Byte Page: 03


  • 2 Bytes F8 07

start address points to the page where the measurement’s header is located. measurement data begins at page 1.
end address points to the last page containing data.

Message Protocol


Gets the stored Mahony Gain.

<msg>1<SndMahonyGain>03 04</msg>


Sets the Mahony Gain to a custom value and stores it in settings.

The first byte is the numerator and the second byte is the denumerator

<msg>1<SetMahonyGain>03 04</msg>


Gets the stored Madgwick Gain.

<msg>1<SndMadgwickGain>03 04</msg>


Sets the Madgwick Gain to a custom value and stores it in settings.

The first byte is the numerator and the second byte is the denumerator

<msg>1<SetMadgwickGain>03 04</msg>


Calibrates the Accelerometer and Gyroscope offsets to zero and stores them in settings.

Be sure to put the sensor on a horizontal surface and do not move it while calibrating!



Gets the stored Accelerometer and Gyroscope offsets.

<msg>1<SndCalData>AA AA AA 0D 00 00 00 00 00 0D 00 00</msg>


Sets the Accelerometer and Gyroscope offsets to custom values and stores them in settings.

First 6 Bytes are Accelerometer offsets from XA_H to ZA_L

Second 6 Bytes are Gyroscope offsets from XG_H to ZG_L

<msg>1<SetCalData>AA AA AA 0D 00 00 00 00 00 0D 00 00</msg>


Deletes a specific block of the flash memory. Our flash has:

  • 2 LUNs (DIEs)
  • 4096 blocks per LUN
  • 64 pages per block

32bit value:

  • 1 Byte LUN (00).
  • 2 Bytes block number (00 01)
  • 1 Byte *ignored* page number (00)
<msg>1<DeleteBlock>00 00 01 00</msg>


Reads out a specific page out of the flash memory. 32bit value:

  • 1 Byte LUN (00)
  • 2 Bytes block number (00 01)
  • 1 Byte page number (00)
<msg>1<GetFlashPage>00 00 01 00</msg>
<msg>1<SndFlashPage>XX XX XX XX XX ...</msg>


Adds a recording track to a specifc device:

  • 8 Bytes devices serial number (24 4E 79 01 51 5F 58 13)
  • 2 Bytes track ID (01 11)
  • 2 Bytes downsampling factor (00 00)
  • 1 Byte track width in Bytes (02)
  • 1 Byte configuration index to use (00) configs defined in driver class
<msg>1<AddTrack>24 4E 79 01 51 5F 58 13 01 11 00 00 02 00</msg>

Driver IDs:

DRIVER_MPU9150 = 0x0100, Invensense MPU9150 or MPU9250

DRIVER_MS5611 = 0x0200, Pressure Sensor on Hardware 3.1

DRIVER_GPIO = 0x0300, GPIOs present on Hardware 3.1 and 4.0

DRIVER_LIS331 = 0x0400, Large Scale Accelerometer present on DECA board for 4.0

DRIVER_DSP = 0x8000 DSP Algorithms

TrackID(Hex)                  Track

TRACK_MPU9150_ACC_X    = DRIVER_MPU9150 | 0x0010,

TRACK_MPU9150_ACC_Y    = DRIVER_MPU9150 | 0x0011,

TRACK_MPU9150_ACC_Z    = DRIVER_MPU9150 | 0x0012,

TRACK_MPU9150_GYR_X    = DRIVER_MPU9150 | 0x0020,

TRACK_MPU9150_GYR_Y    = DRIVER_MPU9150 | 0x0021,

TRACK_MPU9150_GYR_Z    = DRIVER_MPU9150 | 0x0022,

TRACK_MPU9150_MAG_X    = DRIVER_MPU9150 | 0x0030,

TRACK_MPU9150_MAG_Y    = DRIVER_MPU9150 | 0x0031,

TRACK_MPU9150_MAG_Z    = DRIVER_MPU9150 | 0x0032,

TRACK_MPU9150_FUS_6AXIS_RAW    = DRIVER_MPU9150 | 0x0040,

TRACK_MPU9150_FUS_MADGWICK    = DRIVER_MPU9150 | 0x0041,

TRACK_MPU9150_FUS_MAHONY    = DRIVER_MPU9150 | 0x0042,

TRACK_MS5611_PRESS    = DRIVER_MS5611 | 0x0010,

TRACK_MS5611_TEMP    = DRIVER_MS5611   | 0x0011,

TRACK_MS5611_ASL    = DRIVER_MS5611   | 0x0012,








TRACK_LIS331_ACC_X    = DRIVER_LIS331 | 0x0010,

TRACK_LIS331_ACC_Y = DRIVER_LIS331 | 0x0011,

TRACK_LIS331_ACC_Z = DRIVER_LIS331 | 0x0012

Config Indexes

LIS331: TrackID 041X

Config Index DEC Config Index HEX DataRate Range Range
0 0x00 1000Hz +/-100g
1 0x01 1000Hz +/-200g
2 0x02 1000Hz +/-400g
3 0x03 400Hz +/-100g
4 0x04 400Hz +/-200g
5 0x05 400Hz +/-400g
6 0x06 100Hz +/-100g
7 0x07 100Hz +/-200g
8 0x08 100Hz +/-400g
9 0x09 50Hz +/-100g
10 0x0A 50Hz +/-200g
11 0x0B 50Hz +/-400g


Resets the device tracks defined in device’s settings



Sets the device’s base measurement frequency in Hz as a 16bit value.

All tracks are recorded with that frequency unless they have a downsampling factor specified.

Below 100Hz is selected.

<msg>1<SetBaseFreq>00 64</msg>


Sets all the device’s features in one command. 64bit value.

<msg>1<SetFeatures>00 00 00 00 00 00 00 00</msg>

index  hex feature

0 0x00 Power meter enable

1 0x01 Garmin HR enable

2 0x02 Sensor test enable

3 0x03 Livestream LPM enable

4 0x04 Livestream USB enable

5 0x05 Livestream BT enable

6 0x06 Record enable

7 0x07 Status push enable

8 0x08 (not yet used)

9 0x09 ANT network enable

10 0x0A HR enable

11 0x0B LED on record enable

12 0x0C LED on sampling enable

13 0x0D LED on ANT enable

14 0x0E LED on BT enable

15 0x0F LED Identify mode enable

16 0x10 Record on time enable

17 0x11 Record on disconnect enable

18 0x12 Record on ANT enable

19 0x13 BT always on enable

20 0x14 BT on powerup enable

21 0x15 BT on pushbutton enable


Sets one device feature. 16bit value.

Format is [index] [enable]. Below the identify mode is activated

<msg>1<SetFeature>0F 01</msg>


Sets the device’s color used in Identification mode as 32bit value.

Format is [XX] [RR] [GG] [BB]. Below the color is set to red.

<msg>1<SetDeviceColor>00 FF 00 00</msg>


Sets the device time as 32bit UNIX time.

<msg>1<SetTime>00 00 00 0D</msg>


Gets the device time as 32bit UNIX time.

<msg>1<SndTime>00 00 00 0D</msg>


Gets the device firmware 16bit value.




Gets the device state (IDLE or SAMPLING) as 8bit value.



Gets the device’s battery voltage as 16bit value in millivolts.

<msg>1<SndBatVoltage>10 04</msg>


Gets the device’s charging state (0x01=charging or 0x00=not charging) as 8bit value.



Gets the charging current of the device in [mA] as 8bit value. Normally a value between 0 and 50 [mA].



Gets the device’s HW test results as 16bit value. Each tested peripheral sets an indexed flag if it passes power on self test. Currently the following peripherals are supported:

  • Motion Sensor MPU9150: BIT3
  • Pressure Sensor MS5611: BIT1
  • Flash MT29F: BIT0


Gets the device’s active settings as a 128bit value:

  • 8 Bytes serial number
  • 4 Bytes UNIX time
  • 2 Bytes firmware version
  • 6 Bytes ANT ID
  • 8 Bytes Measurement ID
  • 4 Bytes Record start time
  • 4 Bytes record end time
  • 2 Bytes battery voltage
  • 1 Byte charging state
  • 1 Byte current top state
<msg>1<SndSetings>24 4E 79 01 51 5F 58 13 00 00 03 3F 01 03 00 00 00 00 00 00 11 22 33 44 55 66 77 88 00 00 00 00 00 00 00 00 00 00 00 00</msg>


Gets the device’s unique serial number as 64bit value.

<msg>1<SndSerial>24 4E 79 01 51 5F 58 13</msg>

GetRecStart / GetRecEnd

Gets the defined start/end time for recording as 32bit UNIX time.

<msg>1<SndRecStart>01 02 03 04</msg>

SetRecStart / SetRecEnd

Gets the defined start/end time for recording as 32bit UNIX time.

<msg>1<SetRecStart>01 02 03 04</msg>


Gets the device’s 64bit measurement ID.

<msg>1<SndMeasID>01 02 03 04 01 02 03 04</msg>


Gets the device’s 64bit measurement ID.



Track Concept

By ‘sensor node’ we mean the complete device (with sensor, cpu  etc ….), by ‘sensor’ one physical sensor such as accelerometer, pressure and etc.
The sensors nodes are configured in terms of what data to record / stream, in what precision and how fast with the concept of a track setup. The track setup can only be changed when the sensors are idle (not sampling). The setup can be stored to the flash memory and gets loaded on power up. If the track setup is changed but not stored, the changed setup is used until the device gets rebooted.

Track definition

A track definition contains:

  • Track ID (2 Bytes)
    • The sensor the track belongs to (1 Byte)
    • The sensor axis   (1 Byte)
  • Downsampling factor (2 Bytes)
  • Track visibility (1 Byte)
  • Configuration index (1 Byte)

Track ID

Identifies what Sensor / Axis to sample. The tracks from physical sensors are documented in “Standard Tracks.” Custom algorithms get their own ID in the range of 0x8000 – 0x80FF.

 Downsampling factor

All Tracks have a common data rate, which is the data rate configured for the sensor node.

By use of the downsampling factor, a single track can be sampled and stored / streamed slower than the  common data rate.

fsTrack = fsCommon / (DownSamplingFactor + 1)


Track Visibility

Value Meaning

1 Visible; Track get sampled and stored / streamed

0 Invisible; Track gets sampled (for use in algorithms), but not
stored / streamed

Configuration Index

Chooses the sensor configuration from a predefined set.

TrackID ConfigIndex Meaning

011X 4 16g range, 1kHz internal sampling

012X 4 16g range, 1kHz internal sampling

013X 4 100Hz internal sampling


Standard Tracks

TrackID (Hex) Meaning

0110 MPU9150 Accelerometer X

0111 MPU9150 Accelerometer Y

0112 MPU9150 Accelerometer Z

0120 MPU9150 Gyroscope X

0121 MPU9150 Gyroscope Y

0122 MPU9150 Gyroscope Z

0130 MPU9150 Magnetometer X

0131 MPU9150 Magnetometer Y

0132 MPU9150 Magnetometer Z

0140 MPU9150 DMP Quaternions (6 Axis Fusion)

0141 MPU9150 Fusion Quaternions (9 Axis Fusion)

0142 MPU9150 Fusion Euler Angles (9 Axis Fusion)


Implement Custom Command

To implement a custom command, run through the following steps:


  • Message.h:
    • Adapt constant kNumberOfCommands (increment)
    • Enhance the Enumeration “Type” in with constants for the new command (e.g. kGetSomething, kSndSomething)
  • Message.cpp:
    • Enhance the const Message::Commands fields with the Asci String used for the commands
  • Parser.cpp
    • Enhance the method Parser::ExtractMessage with the appropriate Data extraction for the command,
      implement a new  case in the switch case statement or reuse an existing one. In case the command does not contain parameters, no adaption is needed.
    • Enhance the Method Parser::WriteMessage, add the data response formatting for the command, implement a new case in the switch case statement or reuse an existing one. Add your command even if the answer contains no specific data.
  • CommunicationTask.cpp:
    • Adapt the CommunicationTask::SendMessgage method to forward the new message to the correct Task (e.g. StorageTask or ControlTask)
  • StorageTask.cpp / ControlTask.cpp
    • Handle the new message type in the switch / case block in the run() method of the task:
      • Change message type to matching response
      • Attach data to the message
      • Send the message back

Hardware Documentation



Energy Micro EFM32  Leopard Gecko



Invensense MPU9250


Micron NAND Flash Memory, 8 Gb



Stollmann BlueMod+SR, BT 4.0 & 2.1


Linear LTC3553, USB charger, PowerManager

Sensor Node Interfaces


A sensor node plugged into USB offers a virtual comport over which messages following the protocol in ‘Configuration and Data Stream / Upload protocol’ can be exchanged.

Bluetooth RFCOMM

A sensor node offers a Bluetooth connection over RFCOMM / SPP (SerialPortProtocol).
Once paired and connected, it behaves the same way as the USB – CDC port.


Test Communication with a Terminal

Communication is tested in the easiest way with a Serial Terminal, we recommend HTERM (, a simple and powerful Terminal for all major OS’.

Ubuntu & USB : 

  • Make sure your user is member of the “plugdev” group:
    “sudo usermod -a -G plugdev <YourUserName>”
  • Plug your Device, and wait for it to start
  • You can check on the command line with the command “dmesg” whether the device was recognized correctly, the output should look something like this:
    Product: Axiamote USB
    usb 2-1.3: Manufacturer: Axiamo
    cdc_acm 2-1.3:1.0: This device cannot do calls on its own. It is not a modem.
    ttyACM0: USB ACM device
  • Note the virtual com port that was assigned, on Ubuntu this is typically /dev/ttyACM0

Ubuntu & Bluetooth:

  • Turn on your Axiamote
  • Make sure Bluetooth is enabled on your PC
  • Start the tool “Blueman”, hit “Search”
    AxiamoteBluemanFrom the list of found devices, right click your device and choose “Pair”
  • In case you’re asked to verify a pin, just accept it.
  • Right click the device again and choose “Connect To; SPP”.
    Check for a information like “Serial port connected to /dev/rfcomm0”,
    This is your virtual serial connection over bluetooth

Run Commands in terminal

  • Connect an Axiamote as noted above
  • Start hterm
  • ScreenShotHterm
  • Enter the name of the comport, as found above.
  • Connect, baudrate doesn’t matter since it’s a virtual port
  • Set the “Send on enter” option to “CR-LF”
  • Enter a complete command and hit enter. e.g. “<msg>1<GetSerial></msg>”
  • Check for the response in “Recieved Data”