Kyneo Utilities

Introduction

In this tutorial we will show how to program some aditional utilities for the the Kyneo: Battery voltage reading, IMU sensors speed test and a test bench.

Battery voltage and temperature description

The Kyneo board is powered by a Lithium-Ion battery, this battery has a maximum voltage of 4.2 V and a minimum of 3V, since the relation between the battery’s charge and it’s voltage is known, this is a way of knowing the state of charge of the cell.

The temperature is measured by the barometer, and it is measured on the board, this might or might not match the ambient temperature.

The following program prints the voltage and temperature through the serial port.

Example Sketch Code – Voltage and Temperature

/**************************************************************************************************
 * Kyneo Voltage and Temperature Example
 * 
 * This sketch will show the board temperature as well as the battery voltage through the Serial 
 * monitor
 * 
 * 
 * Created by GEKO Navsat S.L. for Kyneo V2.0 board
 * 
 * This example is free software, given under a GPL3 license
 * 
 * KYNEO is a product designed by GEKO Navsat S.L. in Europe http://www.gekonavsat.com
 * For further information, visit: http://kyneo.eu/
 * 
 *************************************************************************************************/
#include <KyneoBoard.h>                                 //GekoNavsat libraries
#include <FreeIMU.h>
#include <KyneoUtils.h>

KyneoUtils util;                                        //Object definition
FreeIMU kyneoIMU;

int LoopRate = 3000;  //milliseconds                 //Variable definition


void setup()
{
  Serial.begin(9600);                                                        //Initialization
  
  util.battInit();
  Wire.begin();
  kyneoIMU.init();

  delay(100);
  Serial.println("Setup done");
  delay(100);
  Serial.println("Remember to connect the battery \n");

  util.battLevel(); //first unreal read
}


void loop()
{
  Serial.print("Battery level (mV): ");
  Serial.println(util.battLevel());                                          //Data adquisition and display
  Serial.print("Board Temperature (Cº): ");
  Serial.print(kyneoIMU.baro.getTemperature(MS561101BA_OSR_4096), 1); 
  Serial.println("\n");
  
  delay(LoopRate);
}

IMU Speed Test

The following sketch performs a speed test of three operations: reading the sensor, calibrate the sensors, and sensor fusion. Three complex operations that are measured in milliseconds.

Example Sketch Code – IMU Speed Test

/**************************************************************************************************
 * Kyneo IMU speed test example
 * 
 * This sketch will perform a speed test of the sensor reading runtime, it will show the reading
 * time of the IMU, sensor calibration and sensor fusion
 * 
 * Created by GEKO Navsat S.L. for Kyneo V2.0 board
 * 
 * This example is free software, given under a GPL3 license
 * 
 * KYNEO is a product designed by GEKO Navsat S.L. in Europe http://www.gekonavsat.com
 * For further information, visit: http://kyneo.eu/
 * 
 *************************************************************************************************/
#include <KyneoBoard.h>                                    // GekoNavsat libraries
#include <FreeIMU.h>

FreeIMU kyneoIMU;                                          // Object definition

int LoopRate = 5000;  //milliseconds                       // Variable definition
int raw[11]; 
char str[512];
float val[9], q[4];
unsigned long start, stop;


void setup() { 
  
  Serial.begin(9600);                                      // Initial setup
  Serial.println("Kyneo IMU velocity test");
  
  Wire.begin();
  kyneoIMU.init();

  Serial.println("Setup done\n");
}

void loop() {
  
  Serial.println("Testing RAW reading speed:");
  start = micros();
  for(int i=0; i<1000; i++) {                              // Getting values
    kyneoIMU.getRawValues(raw);
  }
  stop = micros();
  Serial.print("--> result: ");
  Serial.print((stop - start) / 1024);
  Serial.print(" microseconds -- ");
  Serial.print(((stop - start) / 1024.0) / 1000.0);        // Write values
  Serial.println(" milliseconds");
  
  
  Serial.println("Testing CALIBRATED reading speed");
  start = micros();
  for(int i=0; i<1024; i++) {
    kyneoIMU.getValues(val);
  }
  stop = micros();
  Serial.print("--> result: ");
  Serial.print((stop - start) / 1024);
  Serial.print(" microseconds --");
  Serial.print(((stop - start) / 1024.0) / 1000.0);
  Serial.println(" milliseconds");
  
  
  Serial.println("Testing SENSOR FUSION speed:");
  start = micros();
  for(int i=0; i<1024; i++) {
    kyneoIMU.getQ(q);
  }
  stop = micros();
  Serial.print("--> result: ");
  Serial.print((stop - start) / 1024);
  Serial.print(" microseconds -- ");
  Serial.print(((stop - start) / 1024.0) / 1000.0);
  Serial.println(" milliseconds");
  
  Serial.println("Test finished, it will be performed again");
  Serial.println("----");
  
  delay(LoopRate);
}

Kyneo Test Bench

This program is a testing rig for the Kyneo’s sensors, it will provide a reading from the sensor when asked for it. This might be one of the most useful programs for the board. It can be used as a way to show the boards capabilities but also as a way of testing any of the sensors. This program is controlled by single letter commands, in order for it to work properly we have to set the input to “no line adjustment”.

Example Sketch Code – Kyneo Test Bench

/**************************************************************************************************
 * Kyneo test bench Example
 * 
 * This serves as a test bench in order to check the readings of the boards sensors, the imput
 * commands are the following:
 * 
 * A.- Euler Angles values
 * Q.- Quaternion values
 * R.- Raw IMU sensors data
 * B.- Battery Voltage
 * L.- Blinking LEDs
 * G.- Location and time information
 * N.- Last received NMEA frame
 * 
 * 
 * Created by GEKO Navsat S.L. for Kyneo V2.0 board
 * 
 * This example is free software, given under a GPL3 license
 * 
 * KYNEO is a product designed by GEKO Navsat S.L. in Europe http://www.gekonavsat.com
 * For further information, visit: http://kyneo.eu/
 * 
 *************************************************************************************************/
#include <KyneoBoard.h>                                                           // GekoNavsat libraries
#include <KyneoGNSS.h>
#include <KyneoUtils.h>
#include <FreeIMU.h>

FreeIMU kyneoIMU;                                                                 // Object definition
KyneoGNSS gnss;         
KyneoUtils util;  

int LoopRate = 10;  //milliseconds                                                // Variable definition
int alt;
int gnss_idx = 0, newFrame = 0, options = 0, count = 0;
int headprint = 10, counter = 9, ledFactor = 10;                                  // If you want to read the hidden message, set ledFactor to 1
int raw[9];
float lat, lon;
float att[3],q[4];
char cmd, a;
char frame[100], day[10], hour[10];

void setup()
{
  Serial.begin(9600);
  Serial.print("Setting up... ");

  util.battInit();
  Wire.begin();
  kyneoIMU.init();
  pinMode(GP_LED_0, OUTPUT);
  pinMode(GP_LED_1, OUTPUT);

  Serial1.begin(9600);  // Default baudrate to connect with GNSS module
  delay(100);
  //set rate divider(GPGLL, GPRMC, GPVTG, GPGGA, GPGSA, GPGSV, PMTKCHN). 
  gnss.setNMEAOutput(    0,     1,     0,     1,     0,     0,       0);         // Period of each NMEA message
                                                                          
  Serial.println("done!");
  Serial.println("--------------------------------------------");
  Serial.println("Welcome to the Kyneo testbench by GekoNavsat!");
}

void loop() {
  if(options == 0){
    Serial.println();
    Serial.println("Choose one of the following options:");
    Serial.println("    ");
    Serial.println("    H.- Hello");
    Serial.println("    A.- Euler Angles values");
    Serial.println("    Q.- Quaternion values");
    Serial.println("    R.- Raw IMU sensors data");
    Serial.println("    B.- Battery Voltage");
    Serial.println("    L.- Blinking LEDs");
    Serial.println("    G.- Location and time information");
    Serial.println("    N.- Last received NMEA frame");
    Serial.println("    - Send any command to stop");
    Serial.println();
    Serial.println("*commands must be sent with -NO LINE ENDING-");
    Serial.println();
    
    while(!Serial.available());                                                   // Waits for user command
    while(Serial.available()){
      if(count++ == 0)cmd = Serial.read();
    }
    count = 0;
    options = 1;
  }else{

    if(cmd == 'h'|| cmd == 'H') {
      Serial.println("Hello user!");
      
    }else if (cmd == 'a' || cmd == 'A'){
      while(!Serial.available()){
        kyneoIMU.getYawPitchRoll(att);
        Serial.print("Yaw: ");
        Serial.print(att[0]);
        Serial.print(" Pitch: ");
        Serial.print(att[1]);
        Serial.print(" Roll: ");
        Serial.print(att[2]);
        Serial.println("");
      }
      
    }else if (cmd == 'q' || cmd == 'Q'){

      while(!Serial.available()){
        kyneoIMU.getQ(q);
        Serial.print("  q0: ");
        Serial.print(q[0]);
        Serial.print("  q1: ");
        Serial.print(q[1]);
        Serial.print("  q2: ");
        Serial.print(q[2]);
        Serial.print("  q3: ");
        Serial.println(q[3]);
      }
      
    }else if (cmd == 'r' || cmd == 'R'){
      while(!Serial.available()){
        counter++;
        if(counter == 10){                                                      // Prints column titles every 10 lines
          counter = 0;
          Serial.println("acc_x\tacc_y\tacc_z\tgyr_x\tgyr_y\tgyr_z\tmag_x\tmag_y\tmag_z\tTemp\tAlt");  
        }
  
        kyneoIMU.getRawValues(raw);
        Serial.print((float)raw[0]/2048, 2);    // acc_x
        Serial.print("\t");
        Serial.print((float)raw[1]/2048, 2);    // acc_y
        Serial.print("\t");
        Serial.print((float)raw[2]/2048, 2);    // acc_z
        Serial.print("\t");
        Serial.print((float)raw[3]/16.384, 2);  //gyr_x
        Serial.print("\t");
        Serial.print((float)raw[4]/16.384, 2);  //gyr_y
        Serial.print("\t");
        Serial.print((float)raw[5]/16.384, 2);  //gyr_z
        Serial.print("\t");
        Serial.print((float)raw[6]/1.707, 1);   //mag_x
        Serial.print("\t");
        Serial.print((float)raw[7]/1.707, 1);   //mag_y
        Serial.print("\t");
        Serial.print((float)raw[8]/1.707, 1);   //mag_z
        Serial.print("\t");
        Serial.print(kyneoIMU.baro.getTemperature(MS561101BA_OSR_4096), 1);    // Temperature reading
        Serial.print("\t");
        Serial.println(kyneoIMU.getBaroAlt(), 2);   //pres
      }
      
    }else if (cmd == 'b' || cmd == 'B'){
      while(!Serial.available()){
        Serial.print("Battery level (mV): ");
        Serial.println(util.battLevel());
        delay(500);
      }
      
    }else if (cmd == 'g' || cmd == 'G'){
      while(!Serial.available()){
        gnss_idx = gnss.getLatLon(lat, lon);
        if(gnss_idx == 2){
          gnss.getdate(day);
          gnss.gettime(hour);
          alt = gnss.getalt();
      
          Serial.println("--------------------");
          Serial.print("Fecha:    ");
          Serial.println(day);
          Serial.print("Hora:     ");
          Serial.println(hour);
          Serial.print("Latitud:  ");
          Serial.println(lat,6);
          Serial.print("Longitud: ");
          Serial.println(lon,6);
          Serial.print("Altitud:  ");
          Serial.println(alt);
        }else{
          Serial.println("No GNSS information read...");
        }
      }
      
    }else if (cmd == 'n' || cmd == 'N'){
      while(!Serial.available()){
        if(gnss.getSingleNMEA(frame, 100)!=0){
          Serial.print("NMEA received: ");
          Serial.print(frame);
        }else{
          Serial.println("No NMEA frame received");
        }
      }

    }else if (cmd == 'l' || cmd == 'L'){
      while(!Serial.available()){                                          // Blinks some cool morse code 😉
        Serial.println("Blinking LEDs!, (wair for whole message)");
        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_0, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_0, LOW);    // LED0 OFF.
        delay(1500/ledFactor);

        
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(250/ledFactor);
        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(750/ledFactor);

        digitalWrite(GP_LED_1, HIGH);   // LED0 ON.
        delay(750/ledFactor);
        digitalWrite(GP_LED_1, LOW);    // LED0 OFF.
        delay(2000/ledFactor);
      }
      
    }else{
      Serial.println("Command not found");
    }
    while(Serial.available()) a = Serial.read();                               // Serial buffer flushing
    options = 0;
  }
}

Link to software repository

More information about Kyneo go to Kyneo Manual

For all the latest software visit our GitHub page GEKO Navsat Github's examples

Posted in Tutorials.