Hardware

A simple solution for outdoors localization and basic navigation is an Arduino board, such as the Adafruit Feather nRF52840 Sense with a GPS shield, such as the Adafruit Ultimate GPS FeatherWing. The Sense provides a micro controller, Bluetooth, a 6DoF IMU, and a magnetometer (a LIS3MDL). The FeatherWing provides a GPS.

Assembly

Solder the FeatherWing to the Sense. Add support for the nRF52 to the Arduino IDE. Then, add the board - it’s the Adafruit nRF52840 Sense. The Arduino IDE will probably need to also install the nRF core library (adafruit:nrf52@1.6.1). You should now be able to connect to the board.

Software

Add the following libraries to the Arduino IDE:

  • Adafruit GPS library
  • Adafruit LIS3MDL
  • Adafruit_LSM6DS

Run the sketch provided in /system_hw_test/gps_mag. It yields all the data for tilt compensated magnetic heading, a full AHRS solution (yaw, tilt, roll) and a GPS location, as well as altitude and velocity.

WARNING The direction and AHRS data will be entirely incorrect unless you calibrate your magnetometer, gyro, and accelerator.

Calibration

In the /system_hw_test/gps_mag.ino, see:

/* For calibration, set CALIBRATION to true, run the script, close
the Arduino IDE, close the serial monitor, and open MotionCal.

MotionCal can be downloaded here:

https://github.com/PaulStoffregen/MotionCal

If you do not see your Arduino in MotionCal's serial port 
drop down menu, follow these instructions to compile MotionCal 
for your OS and platform

https://github.com/PaulStoffregen/MotionCal/issues/11#issuecomment-2412937251
*/

bool CALIBRATION = false;

Once you have established your 15 (3+9+3) calibration coefficients (see https://github.com/PaulStoffregen/MotionCal), determine the device string of your sensor (provided in the initial serial debug output), and add your calibration coefficients following the example given in gap_mag.ino:

if (strcmp(DeviceID, "38e4bfd6") == 0) {
	float mh[] = {24.420, -16.87, -3.880}; // in uTesla
	float ms[] = { 0.959,  0.050, -0.038,  \
	               0.050,  1.078,  0.002,  \
	              -0.038,  0.002,  0.970}; 
	float gc[] = { 0.000,  0.020,  0.010}; // in Radians/s
	memcpy(mag_hardiron,  mh, sizeof(mag_hardiron));
	memcpy(mag_softiron,  ms, sizeof(mag_softiron));
	memcpy(gyro_zerorate, gc, sizeof(gyro_zerorate));
} else {
	Serial.println("CAUTION: Magnetometer not calibrated - code will yield garbage - please calibrate your Magnetometer and IMU");
}

WARNING If you use different sensor hardware (and not the nRF52840 Sense with the FeatherWing), you will need to adapt all data flowing from your gyros, accelerators, and magnetometer to (1) have the correct units, (2) follow the correct sign conventions, and (3) accommodate your pcb/sensor geometry as well as how the sensors are mounted relative to your robot. This tends to be extremely tedious and time consuming, so we recommend using the Sense/FeatherWing for which this driver has been developed.

Usage

Once your Sense/FeatherWing is streaming data on the serial line, it can be fed into OM1. See src/inputs/plugins/serial_reader for an example of how to do that.