Hi, I am a new programmer. I have a String called tempMessage which contains longitude and latitude, which are constantly changing.
in my code, I do
longitude = tempMessage.toDouble();
Say that tempMessage is 34.134408, longitude is only 34.13,
if its -117.707238, it becomes 117.71, loosing the sign.
How do I convert to preserve as many decimals as possible from the string to the double?
If it is a char array using atof, then how do I record bytes one at a time, add to the char array, and then convert the char array?
my full processing code is:
void parseMessage(char rxPacket[], int16_t rxSize, int16_t rssi){
Serial.printf("\r\nreceived packet \"%s\" with rssi %d , length %d\r\n",rxPacket,rssi,rxSize);
int numCommas = 0;
String tempMessage;
String val;
for(int i = 0; i <= rxSize; i++){
val = String(rxPacket[i]);
if(val == ","){
switch(numCommas){
case 0:
//int hour
rGpsData.gps_hour = tempMessage.toInt();
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 1:
//int minute
rGpsData.gps_minute = tempMessage.toInt();
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 2:
//int second
rGpsData.gps_second = tempMessage.toInt();
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 3:
//int sats
rGpsData.satellitesConnected = tempMessage.toInt();
Serial.print("rGpsData.satellitesConnected"); Serial.println(rGpsData.satellitesConnected);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 4:
//float lat
rGpsData.latitude = tempMessage.toDouble();
//rGpsData.latitude = tempMessage.toFloat(); // atof(tempMessage)
Serial.print("rGpsData.latitude"); Serial.println(rGpsData.latitude);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 5:
//float long
rGpsData.longitude = tempMessage.toDouble();
//rGpsData.longitude = tempMessage.toFloat();
Serial.print("rGpsData.longitude"); Serial.println(rGpsData.longitude);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 6:
//double altitudeM
rGpsData.altitudeM = tempMessage.toDouble();
//rGpsData.altitudeM = tempMessage.toFloat();
Serial.print("rGpsData.altitude"); Serial.println(rGpsData.altitudeM);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print(" tM: "); Serial.println(tempMessage);
break;
case 7:
//bool valid
if(tempMessage == "1"){
rGpsData.valid = true;
}
else if (tempMessage == "0"){
rGpsData.valid = false;
}
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 8:
Serial.println("8 commas");
Serial.print("8 nC: "); Serial.print(numCommas);
Serial.print("8 tM: "); Serial.println(tempMessage);
break;
}
//Serial.print(" == nC: "); Serial.print(numCommas);
//Serial.print(" == tM: "); Serial.println(tempMessage);
tempMessage = "";
numCommas++;
}
else if(val == "|"){
if(rxPacket[i-1] == '1'){
rGpsData.valid = true;
}
else if (rxPacket[i-1] == '0'){
rGpsData.valid = false;
}
Serial.print("Valid: "); Serial.println(rGpsData.valid);
break;
}
else{
tempMessage += val;
}
}
}
example output:
received packet "19,11,28,9,34.134408,-117.707238,196.40,1|" with rssi -29 , length 42
rGpsData.satellitesConnected9
C tM: 9
rGpsData.latitude34.13
C tM: 34.134408
rGpsData.longitude-117.71
C tM: -117.707238
rGpsData.altitude196.40
tM: 196.40
Valid: 1
Tm is the temprory message, while the value show is what I'm writing it to.
(I just used C to show that it was an output from inside the case statement)
rGpsData is a struct with all the data inside, I want to write to update that data so that I can use it later, but constantly be updating it so that it is accurate.
My actual full code is here, just in case you want to look through for how I'm getting the message and using it and suggest a better way
/*
parse data coming in and assign it to rdata stuffs on every recieve cycle.
*/
#include "Arduino.h"
#include <Wire.h>
#include "LoRaWan_APP.h"
#include "GPS_Air530.h"
#include "HT_SSD1306Wire.h"
SSD1306Wire screen(0x3c, 500000, SDA, SCL, GEOMETRY_128_64, GPIO10 ); // addr , freq , i2c group , resolution , rst
Air530Class Gps;
#ifndef LoraWan_RGB
#define LoraWan_RGB 0
#endif
#define RF_FREQUENCY 915000000 // Hz
#define TX_OUTPUT_POWER 14 // dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7..SF12]
#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 50 // Define the payload size here
char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];
static RadioEvents_t RadioEvents;
int16_t txNumber;
int16_t rssi,rxSize;
struct recieveData{
double latitude;
double longitude;
double altitudeM;
double signalQuality;
int locationAge;
double speedKmph;
double courseDeg;
int satellitesConnected;
int gps_year;
int gps_day;
int gps_month;
int gps_hour;
int gps_minute;
int gps_second;
int gps_centisecond;
bool valid;
//year, day, month, hour, minute, second, centisecond, lat, lng, alt.meters, sats, hdop (quality), age, coursedeg, speedkmph
};
recieveData rGpsData;
struct selfData{
double latitude;
double longitude;
double altitudeM;
double signalQuality;
int locationAge;
double speedKmph;
double courseDeg;
int satellitesConnected;
int gps_year;
int gps_day;
int gps_month;
int gps_hour;
int gps_minute;
int gps_second;
int gps_centisecond;
bool valid;
};
selfData sGpsData;
uint32_t gpsTimer = 0;
uint32_t displayInformationTimer = 0;
int timer1000 = 1000;
void VextON(void){
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
}
void VextOFF(void) {//Vext default OFF
pinMode(Vext,OUTPUT);
digitalWrite(Vext, HIGH);
}
void displayInformation();
void setup() {
Serial.begin(115200);
VextON();
Gps.begin(9600);
Gps.setmode(MODE_GPS);
rssi=0;
RadioEvents.RxDone = OnRxDone;
Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
screen.init();
screen.clear();
screen.display();
screen.setTextAlignment(TEXT_ALIGN_CENTER);
screen.setFont(ArialMT_Plain_10);
screen.drawString(screen.width()/2,screen.height()/2,"gps comms 2 RX");
screen.display();
delay(1000);
screen.clear();
Serial.println("into RX mode");
}
void loop(){
Radio.Rx( 0 );
delay(500);
Radio.IrqProcess( );
displayInformation();
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ){
rssi=rssi;
rxSize=size;
memcpy(rxpacket, payload, size );
rxpacket[size]='\0';
//turnOnRGB(COLOR_RECEIVED,0);
Radio.Sleep( );
parseMessage(rxpacket,rxSize, rssi);
}
void parseMessage(char rxPacket[], int16_t rxSize, int16_t rssi){
Serial.printf("\r\nreceived packet \"%s\" with rssi %d , length %d\r\n",rxPacket,rssi,rxSize);
int numCommas = 0;
String tempMessage;
String val;
for(int i = 0; i <= rxSize; i++){
val = String(rxPacket[i]);
if(val == ","){
switch(numCommas){
case 0:
//int hour
rGpsData.gps_hour = tempMessage.toInt();
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 1:
//int minute
rGpsData.gps_minute = tempMessage.toInt();
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 2:
//int second
rGpsData.gps_second = tempMessage.toInt();
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 3:
//int sats
rGpsData.satellitesConnected = tempMessage.toInt();
Serial.print("rGpsData.satellitesConnected"); Serial.println(rGpsData.satellitesConnected);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 4:
//float lat
rGpsData.latitude = tempMessage.toDouble();
//rGpsData.latitude = tempMessage.toFloat(); // atof(tempMessage)
Serial.print("rGpsData.latitude"); Serial.println(rGpsData.latitude);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 5:
//float long
rGpsData.longitude = tempMessage.toDouble();
//rGpsData.longitude = tempMessage.toFloat();
Serial.print("rGpsData.longitude"); Serial.println(rGpsData.longitude);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 6:
//double altitudeM
rGpsData.altitudeM = tempMessage.toDouble();
//rGpsData.altitudeM = tempMessage.toFloat();
Serial.print("rGpsData.altitude"); Serial.println(rGpsData.altitudeM);
//Serial.print("CnC: "); Serial.print(numCommas);
Serial.print(" tM: "); Serial.println(tempMessage);
break;
case 7:
//bool valid
if(tempMessage == "1"){
rGpsData.valid = true;
}
else if (tempMessage == "0"){
rGpsData.valid = false;
}
//Serial.print("CnC: "); Serial.print(numCommas);
//Serial.print("C tM: "); Serial.println(tempMessage);
break;
case 8:
Serial.println("8 commas");
Serial.print("8 nC: "); Serial.print(numCommas);
Serial.print("8 tM: "); Serial.println(tempMessage);
break;
}
//Serial.print(" == nC: "); Serial.print(numCommas);
//Serial.print(" == tM: "); Serial.println(tempMessage);
tempMessage = "";
numCommas++;
}
else if(val == "|"){
if(rxPacket[i-1] == '1'){
rGpsData.valid = true;
}
else if (rxPacket[i-1] == '0'){
rGpsData.valid = false;
}
Serial.print("Valid: "); Serial.println(rGpsData.valid);
break;
}
else{
tempMessage += val;
}
}
}
void displayInformation(){
if(millis() - displayInformationTimer >= timer1000){
updateSelfInfo();
Serial.println("========================");
String lineString;
screen.clear();
screen.setFont(ArialMT_Plain_10);
screen.setTextAlignment(TEXT_ALIGN_LEFT);
//recieved data
if(rGpsData.valid == true){
lineString = "R long " + String(long(rGpsData.longitude)) + " d " + String(rGpsData.gps_day) + "/" + String(rGpsData.gps_month) + "/" + String(rGpsData.gps_year);
screen.drawString(0, 0,lineString);
Serial.println(lineString);
lineString = " R lat " + String(long(rGpsData.latitude)) + " alt " + String(rGpsData.altitudeM) + " t " + String(rGpsData.gps_hour) + ":" + String(rGpsData.gps_minute) + ":" + String(rGpsData.gps_second);
screen.drawString(0, 16,lineString);
Serial.println(lineString);
}
else if(rGpsData.valid == false){
screen.setFont(ArialMT_Plain_16);
screen.setTextAlignment(TEXT_ALIGN_CENTER);
lineString = "Recieved INVALID";
screen.drawString(0, 0,lineString);
Serial.println(lineString);
}
//self data
if(sGpsData.valid == true){
lineString = "S long " + String(long(sGpsData.longitude)) + " d " + String(sGpsData.gps_day) + "/" + String(sGpsData.gps_month) + "/" + String(sGpsData.gps_year);
screen.drawString(0, 32,lineString);
Serial.println(lineString);
lineString = "lat " + String(long(sGpsData.latitude)) + " alt " + String(sGpsData.altitudeM) + " t " + String(sGpsData.gps_hour) + ":" + String(sGpsData.gps_minute) + ":" + String(sGpsData.gps_second);
screen.drawString(0, 48,lineString);
Serial.println(lineString);
}
else if(sGpsData.valid == false){
screen.setFont(ArialMT_Plain_16);
screen.setTextAlignment(TEXT_ALIGN_CENTER);
lineString = "SELF INVALID";
screen.drawString(0, 32,lineString);
Serial.println(lineString);
}
screen.display();
Serial.println("========================");
}
}
void updateSelfInfo(){
readGps();
/*//DEBUG PRINTS FOR LOOP
Serial.print("day: "); Serial.println(data.gps_day);
Serial.print("month: ");Serial.println(data.gps_month);
Serial.print("gps_year: "); Serial.println(data.gps_year);
Serial.print("hour: "); Serial.println(data.gps_hour);
Serial.print("gps_minute: "); Serial.println(data.gps_minute);
Serial.print("gps_second: "); Serial.println(data.gps_second);
Serial.print("gps_centisecond: "); Serial.println(data.gps_centisecond);
Serial.print("latitude: "); Serial.println(data.latitude);
Serial.print("longitude: "); Serial.println(data.longitude);
Serial.print("altitudeM: "); Serial.println(data.altitudeM);
Serial.print("satellites: "); Serial.println(data.satellitesConnected;);
Serial.print("signalQuality: "); Serial.println(data.signalQuality);
Serial.print("locationAge: "); Serial.println(data.locationAge);
Serial.print("courseDeg: "); Serial.println(data.courseDeg);
Serial.print("speedKmph: "); Serial.println(data.speedKmph);
Serial.println(">>>>>>>>>>>>>>>>>>....................");
delay(1000);
*/
if (Gps.date.isValid()){
sGpsData.valid = true;
sGpsData.gps_day = Gps.date.day();
sGpsData.gps_month = Gps.date.month();
sGpsData.gps_year = Gps.date.year();
}
else{
sGpsData.valid = false;
Serial.print("INVALID++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
if (Gps.time.isValid()){
sGpsData.valid = true;
sGpsData.gps_hour = Gps.time.hour();
sGpsData.gps_minute = Gps.time.minute();
sGpsData.gps_second = Gps.time.second();
sGpsData.gps_centisecond = Gps.time.centisecond();
}
else{
sGpsData.valid = false;
Serial.print(" INVALID++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
rGpsData.latitude = Gps.location.lat();
rGpsData.longitude = Gps.location.lng();
rGpsData.altitudeM = Gps.altitude.meters();
/*//debug prints
Serial.print("LAT: ");
Serial.print(Gps.location.lat(),6);
Serial.print(", LON: ");
Serial.print(Gps.location.lng(),6);
Serial.print(", ALT: ");
Serial.print(Gps.altitude.meters());
*/
rGpsData.satellitesConnected = Gps.satellites.value();
rGpsData.signalQuality = Gps.hdop.hdop();
rGpsData.locationAge = Gps.location.age();
rGpsData.courseDeg = Gps.course.deg();
rGpsData.speedKmph = Gps.speed.kmph();
/*// debug prints
Serial.println();
Serial.print("SATS: ");
Serial.print(Gps.satellites.value());
Serial.print(", HDOP: ");
Serial.print(Gps.hdop.hdop());
Serial.print(", AGE: ");
Serial.print(Gps.location.age());
Serial.print(", COURSE: ");
Serial.print(Gps.course.deg());
Serial.print(", SPEED: ");
Serial.println(Gps.speed.kmph());
Serial.println();*/
}
void readGps(){
if(millis() - gpsTimer > timer1000){
while(Gps.available() > 0){
Gps.encode(Gps.read());
}
gpsTimer = millis();
}
if (millis() > 5000 && Gps.charsProcessed() < 10)
{
sGpsData.valid = false;
Serial.println("No GPS detected: check wiring.");
while(true);
}
}