LightTracker-1.0/lora-asset-tracker-tx/lora-asset-tracker-tx.ino

832 wiersze
25 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <RadioLib.h>
#include <avr/dtostrf.h>
#include <Adafruit_BMP085.h>
#include "SparkFun_Ublox_Arduino_Library.h"
#include "SparkFunLIS3DH.h"
#include <SPI.h>
#include <MemoryFree.h>;
#include <Adafruit_SSD1306.h>
// SX1262 LoRa Module has the following connections:
// NSS pin: 8
// DIO1 pin: 3
// NRST pin: 9
// BUSY pin: 2
SX1262 lora = new Module(8, 3, 9, 2);
#define BattPin A5
#define GpsPwr 12
#define GpsON digitalWrite(GpsPwr, LOW);
#define GpsOFF digitalWrite(GpsPwr, HIGH);
SFE_UBLOX_GPS myGPS;
Adafruit_BMP085 bmp;
LIS3DH myIMU; //Default constructor is I2C, addr 0x19.
#define SSD1306_WHITE 1 ///< Draw 'on' pixels
//#define DEVMODE // Development mode. Uncomment to enable for debugging.
boolean airborne = false; //if you want to put the tracker on a airborne device, set this variable true;
//*********** General Settings ***********//
uint16_t trackerID = 1234; //change this and set a random unique trackerID to avoid conflicts if you have multiple trackers.
uint16_t loRaTXinterval=60; //time interval (seconds) between two beacons (TX). This value is updated (increased) based on your LoRa Region settings and duty cycle.
uint8_t measurementSystem = 0; //0 for metric (meters, km, Celcius, etc.), 1 for imperial (feet, mile, Fahrenheit,etc.)
float battMin=2.7;// min volts to run.
//*********** LoRa Settings ***********//
//following TX settings should be same on the reciever module,
//otherwise RX module can not recieve LoRa packets.
boolean loRaEnabled = true;
//Following frequencies were chosen arbitrarily; and should be same on the reciever (RX) module.
//If necessary, users can select the appropriate channels according to their country regulations.
float loraFrequency = 865.2; //EU863-870
//float loraFrequency = 907.4; //US902-928
int8_t outputPower = 16; //dBm (max outputPower is 16 dBm for EU868, AS923, KR920, RU864)
//int8_t outputPower = 22; //dBm (max outputPower is 30 dBm for US915, AU915, IN865 but device limit is 22 dBm)
float loraBandWith = 125.0f; //do not change this, 125kHz is optimum for default payload size. //https://avbentem.github.io/airtime-calculator/
uint8_t spreadingFactor = 8; ////do not change this, SF8 is optimum for default payload size. https://www.thethingsnetwork.org/docs/lorawan/spreading-factors/
uint8_t codingRate = 5; //do not change this
uint8_t syncWord = 0x12; //(private network)
uint16_t preambleLength = 8; //do not change this
int8_t lowDataRateOptimization = 0; //do not change this
float dutyCyle = 0.01; //https://www.thethingsnetwork.org/docs/lorawan/duty-cycle.html
int8_t loRaWANHeaderSize = 0; // aka overhead size, 13 for LoRAWAN, 0 for LoRa
int explcttHdr = 0; //1 for LoRaWAN, 0 for LoRa
int8_t CRC = 1; //do not change this
//latitude,longtitude,altitude,sattelite,speed,bearing,voltage,temp,pressure,etc. / 22 packets x 4 = 88 bytes
typedef union {
float f[22]; // Assigning fVal.f will also populate fVal.bytes;
unsigned char bytes[4]; // Both fVal.f and fVal.bytes share the same 4 bytes of memory.
} floatArr2Val;
floatArr2Val telemetry;
//********** GPS (uBlox) Settings ****************//
uint8_t navigationFrequencyGPS = 10; //1-10. Set the number of GPS nav solutions sent per second. 10 is max and provide 10 GPS data per second.
#define defaultMaxWait 100 //do not change this. Overriding UBlox default setting (1100) to fetch data faster from GPS module via I2C
#define getPVTmaxWait 100 //do not change this. Overriding UBlox default setting (1100) to fetch data faster from GPS module via I2C
//********** OLED Display Settings ****************//
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int displayPageID = 1;
int displayInterval = 5;
uint32_t last_display_refreshed = -10000;
//*********** Temp Veriables ***********//
boolean gpsFixed = false;
int txCount = 1; //do not change this. counting LoRa TX messages...
uint32_t last_packet_send = -60000; //do not change this. Last LoRa packet sent time
float maxAltitude = 0; //do not change this.
float minPressure = 101325; //do not change this.
float accelGX = 0;
float accelGY = 0;
float accelGZ = 0;
float minGX = 0;
float maxGX = 0;
float minGY = 0;
float maxGY = 0;
float minGZ = 0;
float maxGZ = 0;
float tempAltitude = 0;
float tempSpeed = 0;
float tempTemperature = 0;
float tempLatitude = 0;
float tempLongitude = 0;
float tempSats = 0;
float tempHeading = 0;
float tempVoltage = 0;
float tempPressure = 0;
static char tempUnit[2] = ""; //C or F
static char speedUnit[7] = ""; //km/h or mph (mile per hour)
static char altUnit[5] = ""; //meters or feet
static char distUnit[5] = ""; //km or mile
static char measureSystem[10] = ""; //Metric or Imperial
void setup() {
pinMode(A1,INPUT_PULLUP);
if(digitalRead(A1)==LOW) while(1);
delay(5000);
pinMode(GpsPwr, OUTPUT);
GpsON;
SerialUSB.begin(115200);
// Wait up to 5 seconds for serial to be opened, to allow catching
// startup messages on native USB boards (that do not reset when
// serial is opened).
unsigned long start = millis();
while (millis() - start < 5000 && !SerialUSB);
SerialUSB.println();
SerialUSB.println(F("Starting"));
SerialUSB.println();
SerialUSB.println(F("LoRa setup initiating.."));
setupLoRa();
printLoRaSettings();
SerialUSB.println(F("GPS setup initiating..(NO GPS fix yet)"));
setupGPS_BMP();
delay(2000);
if(airborne){
SerialUSB.println(F("Airborne mode initiated..."));
setupUBloxDynamicModel(); // Set the dynamic model to DYN_MODEL_AIRBORNE4g
}
SerialUSB.println(F("Accelerometer setup initiating.."));
setupAccel();
//OLED Display
setupDisplay();
freeMem();
printDisplay(4);
delay(7000);
}
void loop() {
if (readBatt() > battMin) {
if (myGPS.getPVT() && (myGPS.getFixType() !=0) && (myGPS.getSIV() > 3)) {
if(!gpsFixed){
SerialUSB.println(F("GPS Fixed..."));
gpsFixed = true;
}
}
#if defined(DEVMODE)
printGPSData();
#endif
updateTelemetry();
getAccelerometerData();
//update display
if (millis() - last_display_refreshed > (displayInterval * 1000)) {
printDisplay(displayPageID);
last_display_refreshed = millis();
++displayPageID;
if(displayPageID == 3) {
displayPageID = 1;
}
}
if(loRaEnabled) {
if (millis() - last_packet_send > (loRaTXinterval * 1000)) {
printDisplay(3);
sendLoraPacket();
printLoRaSettings();
last_packet_send = millis();
if(loraFrequency >= 863.f && loraFrequency <= 870.f){
calculateTransmitInterval();
}
delay(1000);
printDisplay(2);
last_display_refreshed = millis();
SerialUSB.print(F("Next TX is "));
SerialUSB.print(loRaTXinterval);
SerialUSB.println(F(" seconds later."));
freeMem();
}
}
} else {
SerialUSB.println(F("Voltage is too low, please check your battery..."));
}
}
void printDisplay(int pageID){
display.clearDisplay();
display.setCursor(0, 0);
switch(pageID) {
case 1:
static char fixMessage[10] = "";
if(myGPS.getFixType() !=0){
sprintf(fixMessage, "%s", "Fixed");
} else {
sprintf(fixMessage, "%s", "Not Fixed");
}
display.println("");
display.print("GPS Fix : ");display.println(fixMessage);
display.print("GPS Sats: ");display.println((int)tempSats);
display.print("Lat : ");display.println(tempLatitude);
display.print("Long : ");display.println(tempLongitude);
display.print("Altitude: ");display.print((int)tempAltitude);display.println(altUnit);
display.print("Speed : ");display.print((int)tempSpeed);display.println(speedUnit);
break;
case 2:
display.println("");
display.print("Battery :");display.print(tempVoltage); display.println("V");
display.print("Temp :");display.print(tempTemperature);display.println(tempUnit);
display.print("Pressure:");display.print(tempPressure); display.println("hPa");
display.print("TX Count:");display.println(txCount-1);
display.print("Next TX :");display.print(loRaTXinterval - ((millis() - last_packet_send)/1000)); display.println(" secs left");
break;
case 3:
display.println("");
display.println("");
display.println("LoRa Pckt Sending...");
display.println("");
break;
case 4:
display.println("");
display.print("Freq : ");display.print(loraFrequency);display.println("mHz");
display.print("SF : ");display.println(spreadingFactor);
display.print("Bandwith: ");display.print(loraBandWith);display.println("kHz");
display.print("Power : ");display.print(outputPower);display.println("dBm");
display.print("PcktSize: ");display.print(sizeof(telemetry));display.println(" bytes");
display.print("Measure : ");display.println(measureSystem);
break;
default:
SerialUSB.println("default");
break;
}
display.display();
}
void setupDisplay(){
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
SerialUSB.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
if(measurementSystem == 0){ //Metric
//meters
sprintf(altUnit, "%s", " m");
//km/hour
sprintf(speedUnit, "%s", " km/h");
//Celsius
sprintf(tempUnit, "%s", "C");
//km
sprintf(distUnit, "%s", " km");
//Metric
sprintf(measureSystem, "%s", "Metric");
} else { //Imperial
//feet
sprintf(altUnit, "%s", " ft");
//mile/hour
sprintf(speedUnit, "%s", " mph");
//Fahrenheit
sprintf(tempUnit, "%s", "F");
//mile
sprintf(distUnit, "%s", " mi");
//Imperial
sprintf(measureSystem, "%s", "Imperial");
}
}
void setupAccel() {
//********** Acceloremeter (LSM303DLHC) Settings **************//
myIMU.settings.adcEnabled = 1;
myIMU.settings.accelSampleRate = 400; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
myIMU.settings.accelRange = 16; //Max G force readable. Can be: 2, 4, 8, 16
myIMU.settings.xAccelEnabled = 1;
myIMU.settings.yAccelEnabled = 1;
myIMU.settings.zAccelEnabled = 1;
//Call .begin() to configure the IMU
myIMU.begin();
delay(100);
}
void getAccelerometerData(){
accelGX = myIMU.readFloatAccelX();
accelGY = myIMU.readFloatAccelY();
accelGZ = myIMU.readFloatAccelZ();
if (accelGX < minGX) {
minGX = accelGX;
} else if (accelGX > maxGX) {
maxGX = accelGX;
}
if (accelGY < minGY) {
minGY = accelGY;
} else if (accelGY > maxGY) {
maxGY = accelGY;
}
if (accelGZ < minGZ) {
minGZ = accelGZ;
} else if (accelGZ > maxGZ) {
maxGZ = accelGZ;
}
}
// Same functionality as Arduino's standard map function, except using floats
float mapf(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void sendLoraPacket(){
SerialUSB.print(F("[SX1262] LoRa Radio Module Transmitting packet ... "));
int state = lora.transmit(telemetry.bytes,sizeof(telemetry));
if (state == ERR_NONE) {
// the packet was successfully transmitted
SerialUSB.println(F("success!"));
// print measured data rate
SerialUSB.print(F("[SX1262] Datarate:\t"));
SerialUSB.print(lora.getDataRate());
SerialUSB.println(F(" bps"));
} else if (state == ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 256 bytes
SerialUSB.println(F("too long!"));
} else if (state == ERR_TX_TIMEOUT) {
// timeout occured while transmitting packet
SerialUSB.println(F("timeout!"));
} else {
// some other error occurred
SerialUSB.print(F("failed, code "));
SerialUSB.println(state);
}
lora.sleep();
txCount++;
}
void updateTelemetry() {
if(measurementSystem == 0){ //Metric
//meters
tempAltitude = myGPS.getAltitude() / 1000.f;
//km/hour
tempSpeed = myGPS.getGroundSpeed() * 0.0036f;
//Celsius
tempTemperature = bmp.readTemperature();
} else { //Imperial
//feet
tempAltitude = (myGPS.getAltitude() * 3.2808399) / 1000.f;
//mile/hour
tempSpeed = myGPS.getGroundSpeed() * 0.00223694f;
//Fahrenheit
tempTemperature = (bmp.readTemperature() * 1.8f) + 32;
}
tempLatitude = myGPS.getLatitude() / 10000000.f;
tempLongitude = myGPS.getLongitude() / 10000000.f;
tempSats = myGPS.getSIV();
if ((tempSats > 4) && (tempAltitude > maxAltitude)) {
maxAltitude = tempAltitude;
}
tempHeading = myGPS.getHeading() / 100000;
tempVoltage = readBatt();
tempPressure = bmp.readPressure() / 100.0;
if (tempPressure < minPressure) {
minPressure = tempPressure;
}
//prepare data for LoRa communcation...
if(loRaEnabled) {
telemetry.f[0] = tempLatitude;
telemetry.f[1] = tempLongitude;
telemetry.f[2] = tempAltitude;
telemetry.f[3] = tempSats;
telemetry.f[4] = tempHeading;
telemetry.f[5] = tempSpeed;
telemetry.f[6] = tempVoltage;
telemetry.f[7] = tempTemperature;
telemetry.f[8] = tempPressure;
telemetry.f[9] = accelGX;
telemetry.f[10] = accelGY;
telemetry.f[11] = accelGZ;
telemetry.f[12] = minGX;
telemetry.f[13] = maxGX;
telemetry.f[14] = minGY;
telemetry.f[15] = maxGY;
telemetry.f[16] = minGZ;
telemetry.f[17] = maxGZ;
telemetry.f[18] = maxAltitude;
telemetry.f[19] = minPressure;
telemetry.f[20] = txCount;
telemetry.f[21] = trackerID;
}
#if defined(DEVMODE)
SerialUSB.println(F(""));
SerialUSB.print(F("Batt: "));
SerialUSB.print(tempVoltage);
SerialUSB.print(F(" Temp: "));
SerialUSB.print(tempTemperature);
SerialUSB.print(F(" Press: "));
SerialUSB.print(tempPressure);
SerialUSB.print(F(" GX: "));
SerialUSB.print(accelGX);
SerialUSB.print(F(" GY: "));
SerialUSB.print(accelGY);
SerialUSB.print(F(" GZ: "));
SerialUSB.println(accelGZ);
#endif
/**
#if defined(DEVMODE)
SerialUSB.println(F("----"));
SerialUSB.print(F("lat :"));
SerialUSB.println(telemetry.f[0]);
SerialUSB.print(F("long :"));
SerialUSB.println(telemetry.f[1]);
SerialUSB.print(F("alt :"));
SerialUSB.println(telemetry.f[2]);
SerialUSB.print(F("sats :"));
SerialUSB.println(telemetry.f[3]);
SerialUSB.print(F("course:"));
SerialUSB.println(telemetry.f[4]);
SerialUSB.print(F("speed :"));
SerialUSB.println(telemetry.f[5]);
SerialUSB.print(F("batt :"));
SerialUSB.println(telemetry.f[6]);
SerialUSB.print(F("temp :"));
SerialUSB.println(telemetry.f[7]);
SerialUSB.print(F("press :"));
SerialUSB.println(telemetry.f[8]);
SerialUSB.print(F("scaledGX :"));
SerialUSB.println(telemetry.f[9]);
SerialUSB.print(F("scaledGY :"));
SerialUSB.println(telemetry.f[10]);
SerialUSB.print(F("scaledGZ :"));
SerialUSB.println(telemetry.f[11]);
SerialUSB.print(F("minScaledGX :"));
SerialUSB.println(telemetry.f[12]);
SerialUSB.print(F("maxScaledGX :"));
SerialUSB.println(telemetry.f[13]);
SerialUSB.print(F("minScaledGY :"));
SerialUSB.println(telemetry.f[14]);
SerialUSB.print(F("maxScaledGY :"));
SerialUSB.println(telemetry.f[15]);
SerialUSB.print(F("minScaledGZ :"));
SerialUSB.println(telemetry.f[16]);
SerialUSB.print(F("maxScaledGZ :"));
SerialUSB.println(telemetry.f[17]);
SerialUSB.print(F("maxAltitude :"));
SerialUSB.println(telemetry.f[18]);
SerialUSB.print(F("minPressure :"));
SerialUSB.println(telemetry.f[19]);
SerialUSB.print(F("txCount :"));
SerialUSB.println(telemetry.f[20]);
SerialUSB.print(F("trackerID :"));
SerialUSB.println((int)telemetry.f[21]);
SerialUSB.println(F("----"));
#endif
*/
}
void setupLoRa() {
// initialize SX1262 with default settings
SerialUSB.print(F("[SX1262] Initializing ... "));
int state = lora.begin();
if (state == ERR_NONE) {
SerialUSB.println(F("success!"));
} else {
SerialUSB.print(F("failed, code "));
SerialUSB.println(state);
while (true);
}
if (lora.setFrequency(loraFrequency,true) == ERR_INVALID_FREQUENCY) {
SerialUSB.println(F("Selected frequency is invalid for this module!"));
while (true);
}
// set bandwidth to 1250 kHz
if (lora.setBandwidth(loraBandWith) == ERR_INVALID_BANDWIDTH) {
SerialUSB.println(F("Selected bandwidth is invalid for this module!"));
while (true);
}
// set spreading factor to 10
if (lora.setSpreadingFactor(spreadingFactor) == ERR_INVALID_SPREADING_FACTOR) {
SerialUSB.println(F("Selected spreading factor is invalid for this module!"));
while (true);
}
// set coding rate to 5
if (lora.setCodingRate(codingRate) == ERR_INVALID_CODING_RATE) {
SerialUSB.println(F("Selected coding rate is invalid for this module!"));
while (true);
}
// set LoRaWAN sync word to 0x34
if (lora.setSyncWord(syncWord) != ERR_NONE) {
SerialUSB.println(F("Unable to set sync word!"));
while (true);
}
// set over current protection limit to 140 mA (accepted range is 45 - 240 mA)
if (lora.setCurrentLimit(140) == ERR_INVALID_CURRENT_LIMIT) {
Serial.println(F("Selected current limit is invalid for this module!"));
while (true);
}
// set output power to outputPower dBm (accepted range is -17, 22 dBm)
if (lora.setOutputPower(outputPower) == ERR_INVALID_OUTPUT_POWER) {
SerialUSB.println(F("Selected output power is invalid for this module!"));
while (true);
}
// set LoRa preamble length to 8 symbols (accepted range is 0 - 65535)
if (lora.setPreambleLength(preambleLength) == ERR_INVALID_PREAMBLE_LENGTH) {
SerialUSB.println(F("Selected preamble length is invalid for this module!"));
while (true);
}
// enable CRC
if (lora.setCRC(CRC) == ERR_INVALID_CRC_CONFIGURATION) {
SerialUSB.println(F("Selected CRC is invalid for this module!"));
while (true);
}
SerialUSB.println(F("All settings succesfully changed!"));
}
float readBatt() {
float R1 = 560000.0; // 560K
float R2 = 100000.0; // 100K
float value = 0.0f;
do {
value =analogRead(BattPin);
value +=analogRead(BattPin);
value +=analogRead(BattPin);
value = value / 3.0f;
value = (value * 3.3) / 1024.0f;
value = value / (R2/(R1+R2));
} while (value > 20.0);
return value ;
}
void printLoRaSettings(){
SerialUSB.println(F("-------------------------------LoRa Settings-----------------------------------------"));
SerialUSB.print(F("Freq: "));
SerialUSB.print(loraFrequency);
SerialUSB.print(F("mHz, Bandwith: "));
SerialUSB.print(loraBandWith);
SerialUSB.print(F("kHz, SF: "));
SerialUSB.print(spreadingFactor);
SerialUSB.print(F(", Power: "));
SerialUSB.print(outputPower);
SerialUSB.print(F("dBm, Payload Size: "));
SerialUSB.print(sizeof(telemetry));
SerialUSB.println(F(" bytes"));
SerialUSB.println(F("------------------------------------------------------------------------------------"));
}
//Every radio device must be compliant with the regulated duty cycle limits. This applies to both nodes and gateways.
//In practice, this means that you should program your nodes in such a way, that they stay within the limits.
//The easiest way to do this, is to calculate how much airtime each message consumes using one of the many
//airtime calculators and use that information to choose a good transmit interval (duty cycle). https://www.thethingsnetwork.org/docs/lorawan/duty-cycle.html
//Following function checks and enforce duty cycle limits based on your LoRa settings so you can not break the law.
void calculateTransmitInterval(){
if(spreadingFactor>= 11){
lowDataRateOptimization = 1;
}
if (loraFrequency >=868.7 && loraFrequency <=869.2) {
dutyCyle = 0.001;
} else if (loraFrequency >=869.4 && loraFrequency <=869.65) {
dutyCyle = 0.1;
} else {
dutyCyle = 0.01;
}
float symbolDuration = pow(2, spreadingFactor) / (loraBandWith * 1000.f);
float a = (8 * (sizeof(telemetry) + loRaWANHeaderSize)) - (4 * spreadingFactor) + 28 + (16 * CRC) - (20 * (1-explcttHdr));
float b = 4 * (spreadingFactor - (2 * lowDataRateOptimization));
int nbrSymbols = ceil(a/b) * codingRate;
if (nbrSymbols < 0){
nbrSymbols = 0;
}
nbrSymbols += 8;
float preambuleDuration = (preambleLength + 4.25f) * symbolDuration;
float payloadDuration = nbrSymbols * symbolDuration;
float packetDuration = (preambuleDuration + payloadDuration) / dutyCyle;
if (loRaTXinterval < (int)packetDuration) {
#if defined(DEVMODE)
SerialUSB.print(F("Updating "));
SerialUSB.print(F("loRaTXinterval= "));
SerialUSB.print(loRaTXinterval);
SerialUSB.print(F(" to loRaTXinterval= "));
SerialUSB.print((int)packetDuration);
SerialUSB.println(F(" seconds..."));
#endif
loRaTXinterval = (int)(packetDuration);
}
}
void setupGPS_BMP() {
GpsON;
delay(100);
Wire.begin();
bmp.begin();
Wire.setClock(400000);
if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
{
SerialUSB.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
while (1)
;
}
// do not overload the buffer system from the GPS, disable UART output
myGPS.setUART1Output(0); //Disable the UART1 port output
myGPS.setUART2Output(0); //Disable Set the UART2 port output
myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
//myGPS.enableDebugging(); //Enable debug messages over Serial (default)
myGPS.setNavigationFrequency(navigationFrequencyGPS);//Sadece roket için 10 yapalım. //Set output to 10 times a second
byte rate = myGPS.getNavigationFrequency(); //Get the update rate of this module
//SerialUSB.print("Current GPS update rate:");
//SerialUSB.println(rate);
myGPS.saveConfiguration(); //Save the current settings to flash and BBR
}
void setupUBloxDynamicModel() {
// If we are going to change the dynamic platform model, let's do it here.
// Possible values are:
// PORTABLE, STATIONARY, PEDESTRIAN, AUTOMOTIVE, SEA, AIRBORNE1g, AIRBORNE2g, AIRBORNE4g, WRIST, BIKE
//DYN_MODEL_AIRBORNE4g model increases ublox max. altitude limit from 12.000 meters to 50.000 meters.
if (myGPS.setDynamicModel(DYN_MODEL_AIRBORNE4g) == false) // Set the dynamic model to DYN_MODEL_AIRBORNE4g
{
SerialUSB.println(F("***!!! Warning: setDynamicModel failed !!!***"));
}
else
{
SerialUSB.print(F("Dynamic platform model changed successfully! : "));
SerialUSB.println(myGPS.getDynamicModel());
}
}
void freeMem() {
#if defined(DEVMODE)
SerialUSB.print(F("Free RAM: ")); SerialUSB.print(freeMemory(), DEC); SerialUSB.println(F(" byte"));
#endif
}
void printGPSData()
{
// Calling getPVT returns true if there actually is a fresh navigation solution available.
SerialUSB.println(F(""));
byte fixType = myGPS.getFixType();
SerialUSB.print(F("FixType: "));
SerialUSB.print(fixType);
long latitude = myGPS.getLatitude();
float flat = myGPS.getLatitude() / 10000000.f;
SerialUSB.print(F(" Lat: "));
SerialUSB.print(latitude);
SerialUSB.print(F(" - "));
SerialUSB.print(flat);
long longitude = myGPS.getLongitude();
float flong = myGPS.getLongitude() / 10000000.f;
SerialUSB.print(F(" Long: "));
SerialUSB.print(longitude);
SerialUSB.print(F(" - "));
SerialUSB.print(flong);
float altitude = myGPS.getAltitude() / 1000;
SerialUSB.print(F(" Alt: "));
SerialUSB.print(altitude);
SerialUSB.print(F(" (m)"));
int SIV = myGPS.getSIV();
SerialUSB.print(F(" SIV: "));
SerialUSB.print(SIV);
float speed = myGPS.getGroundSpeed() * 0.0036f;
SerialUSB.print(F(" Speed: "));
SerialUSB.print(speed);
SerialUSB.print(F(" (km/h)"));
long heading = myGPS.getHeading() / 100000;
SerialUSB.print(F(" Heading: "));
SerialUSB.print(heading);
SerialUSB.print(F(" (degrees )"));
SerialUSB.print(" ");
SerialUSB.print(myGPS.getYear());
SerialUSB.print("-");
SerialUSB.print(myGPS.getMonth());
SerialUSB.print("-");
SerialUSB.print(myGPS.getDay());
SerialUSB.print(" ");
SerialUSB.print(myGPS.getHour());
SerialUSB.print(":");
SerialUSB.print(myGPS.getMinute());
SerialUSB.print(":");
SerialUSB.print(myGPS.getSecond());
SerialUSB.print(":");
SerialUSB.print(myGPS.getMillisecond());
SerialUSB.println();
delay(1000);
}