hi, i am on a project that calculate travelled distance. firstly i had a standing error. in other word device thought that i am travelling while i was standing still because of gps uncertinity. i fixed it by adding minimum 30 meters threshold. but now my device calculates approximately %6 less then actual travelled distance. is there any way to lower this error? or is it natural. i am waiting for your comment. thank you.
i am using arduino nano
neo 7m gps module
gps antenna
satellite count generally above 7
related part of my gps distance
//distance measurement
currentMillis=millis();
if(currentMillis - previousMillis >= 2000){ //calculate disance one in every 2 sec
distance = TinyGPS::distance_between(flat, flon, slat, slon);
distance=300;
if(distance>30){
slat=flat;
slon=flon;
sum_distance1=sum_distance1+distance;
if (taksimetrepressed==1) sum_distance3=sum_distance3+distance; //taksimetre pressed but passenger didnt sit
if (sensor1>350 || sensor2>350 || sensor3>350 || sensor4>350 || ((millis()-previousMillis6)<6000) ) { // anlık kesilme önlemesi
sum_distance2=sum_distance2+sum_distance3+distance;
taksimetrepressed=0;
sum_distance3=0;
//kısa mesafe uzun mesafe
sum_distance4=sum_distance4+distance;
}
Serial.print("sum_distance1: "); Serial.println(sum_distance1);
Serial.print("sum_distance2: "); Serial.println(sum_distance2);
Serial.print("sum_distance3: "); Serial.println(sum_distance3);
}
Serial.print("distance "); Serial.println(distance);
previousMillis=currentMillis;
}
all my code,
#include <SoftwareSerial.h>
#include <TinyGPS.h>
TinyGPS gps;
SoftwareSerial ss(3, 4);
//distance
float slat=39;
float slon=27;
unsigned long age=0;
unsigned long sum_distance1;
unsigned long sum_distance2;
unsigned long sum_distance3; //taksimetre basıldıktan sonra müsteri oturuncaya kadar geçen süre
unsigned long sum_distance4; //uzun yolcu kısa yolcu sayar
int distance=0;
//kısa mesafe uzun mesefe
int kyolcu=0;
int uyolcu=0;
//timer
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis3=0; //save distance
unsigned long previousMillis4=0; //secure gps cable
unsigned long previousMillis5=0; // taksimetre sıfırlama
unsigned long previousMillis6=0; //uzun yolcu kısa yolcu sayar
//--sensors and taksimetre
#define sensor1pin A0
#define sensor2pin A1
#define sensor3pin A2
#define sensor4pin A3
int sensor1;
int sensor2;
int sensor3;
int sensor4;
#define taksimetrepin 2
bool taksimetrepressed=0;
#include "U8glib.h"
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);
//--------------RFID
#include <SPI.h> //SPI kütüphanemizi tanımlıyoruz.
#include <MFRC522.h>
int RST_PIN = 9; //RC522 modülü reset pinini tanımlıyoruz.
int SS_PIN = 10;
MFRC522 rfid(SS_PIN, RST_PIN); //RC522 modülü ayarlarını yapıyoruz.
byte ID[4] = {145, 90, 212, 38}; //Yetkili kart ID'sini tanımlıyoruz.
byte ID2[4] = {243, 98, 199, 22};
bool yetkili=0;
//------plaka
#define up A6
#define down 5
#define left 6
#define right 7
#define enter 8
bool upval=0;
bool downval=0;
bool leftval=0;
bool rightval=0;
bool enterval=0;
char Letters[34]={"ABCDEFGHIJKLMNOPRSTUVYZ 1234567890"};
char plaka[11]="";
int plaka_position=0;
int letter_position=0;
//record
#include <EEPROM.h>
int address = 0;
byte value;
//-----eeprom val
//150,160 long sum dist
//0-11 plaka
//100,101,102 ref year
//--Geçerlilik süresi----
unsigned long refyymmdd;
char urunKodu[11]="1111111111";
int urunKodu_position=0;
//*****************************************************
//****************************************************
void setup()
{
Serial.begin(115200);
ss.begin(9600);
//sensors and taksimetre
pinMode(sensor1pin,INPUT);
pinMode(sensor2pin,INPUT);
pinMode(sensor3pin,INPUT);
pinMode(sensor4pin,INPUT);
pinMode(taksimetrepin,INPUT);
attachInterrupt(digitalPinToInterrupt(taksimetrepin), ISR2, FALLING);
//---plaka
pinMode(up,INPUT);
pinMode(down,INPUT);
pinMode(left,INPUT);
pinMode(right,INPUT);
pinMode(enter,INPUT);
for (int i=0;i<10;i++){
plaka[i] = EEPROM.read(i);
}
//opening screen
u8g.firstPage();
do {
draw1();
} while (u8g.nextPage() );
delay(2000);
//----yetkilendirme
SPI.begin();
rfid.PCD_Init();
while(1){
u8g.firstPage();
do {
draw2();
} while (u8g.nextPage() );
delay(100);
authorization();
if(yetkili==1) break;
}
yetkili=0; // inorder to unauthorize
//--plakagirilmesi
while(1){
plakaGir();
if (enterval==1) break;
}
//---geçerlilik süresi
int yy=EEPROM.read(100);
int mm=EEPROM.read(101);
int dd=EEPROM.read(102);
refyymmdd=long(yy)*10000+long(mm)*100+dd;
Serial.print("refyymmdd: ");Serial.println(refyymmdd);
//reading distances from eeprom
EEPROM.get(150,sum_distance1);
EEPROM.get(160,sum_distance2);
//gps bağlanma beklemesi
int counter=0;
while(1){
smartdelay(1000);
gps.f_get_position(&slat, &slon, &age);
Serial.print("slat: "); Serial.println(slat,6);
Serial.print("slon: "); Serial.println(slon,6);
if(slat>1 && slat<100) break;
u8g.firstPage();
do {
u8g.setFont(u8g_font_profont12);
u8g.setPrintPos(0, 10);
u8g.print("GPS Sinyali Araniyor");
u8g.setPrintPos(counter*3, 25);
u8g.print("*");
} while (u8g.nextPage() );
delay(2000);
counter++;
if (counter>45) counter=0;
}
}
//******************************************************
//******************************************************
void loop()
{
Serial.println("--------------------");
//GPS informations
smartdelay(1000);
uint8_t sat =gps.satellites();
Serial.print("sat: "); Serial.println(sat);
float flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon, &age);
Serial.print("flat: "); Serial.println(flat,6);
Serial.print("flon: "); Serial.println(flon,6);
Serial.print("slat: "); Serial.println(slat,6);
Serial.print("slon: "); Serial.println(slon,6);
float spd=gps.f_speed_kmph();
int intspd=spd;
Serial.print("spd "); Serial.println(spd);
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age2;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age2);
hour+=3;if(hour>=24)hour-=24;
//gps get date time
unsigned long date, time;
gps.get_datetime(&date, &time, &age);
Serial.print("Date(ddmmyy): "); Serial.print(date); Serial.print(" Time(hhmmsscc): ");
Serial.print(time);
Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
//CheckDate
checkDate(date);
//-----------------------------------------------------------------
// sensordeğeri okuma
readSensors();
if( (millis()-previousMillis5) > 1200000) { //taksimetre time interval
taksimetrepressed=0;
sum_distance3=0;
}
if (sensor1>350 || sensor2>350 || sensor3>350 || sensor4>350 ) {
taksimetrepressed=0;
previousMillis6=millis(); //kısa/uzun
}
//distance measurement
currentMillis=millis();
if(currentMillis - previousMillis >= 2000){ //calculate disance one in every 2 sec
distance = TinyGPS::distance_between(flat, flon, slat, slon);
distance=300;
if(distance>30){
slat=flat;
slon=flon;
sum_distance1=sum_distance1+distance;
if (taksimetrepressed==1) sum_distance3=sum_distance3+distance; //taksimetre pressed but passenger didnt sit
if (sensor1>350 || sensor2>350 || sensor3>350 || sensor4>350 || ((millis()-previousMillis6)<6000) ) { // anlık kesilme önlemesi
sum_distance2=sum_distance2+sum_distance3+distance;
taksimetrepressed=0;
sum_distance3=0;
//kısa mesafe uzun mesafe
sum_distance4=sum_distance4+distance;
}
Serial.print("sum_distance1: "); Serial.println(sum_distance1);
Serial.print("sum_distance2: "); Serial.println(sum_distance2);
Serial.print("sum_distance3: "); Serial.println(sum_distance3);
}
Serial.print("distance "); Serial.println(distance);
previousMillis=currentMillis;
}
//kısa mesafe uzun mesafe
if ( sensor1<350 && sensor2<350 && sensor3<350 && sensor4<350 && ( (millis()-previousMillis6)>20000) ){
if (sum_distance4>250 && sum_distance4<2000){
kyolcu++;
sum_distance4=0;
}
if (sum_distance4>=2000){
uyolcu++;
sum_distance4=0;
}
sum_distance4=0;
}
//print oled
u8g.firstPage();
do {
u8g.setFont(u8g_font_profont12);
u8g.setPrintPos(0, 64);
u8g.print("Uzun: ");
u8g.print(uyolcu);
u8g.setPrintPos(64, 64);
u8g.print("Kisa: ");
u8g.print(kyolcu);
u8g.setPrintPos(0, 55);
u8g.print("Son:");
u8g.print(sum_distance4);
u8g.setPrintPos(0, 10);
if(hour<10) u8g.print("0"+String(hour));
else u8g.print(hour);
u8g.setPrintPos(10, 10);
u8g.print(":");
u8g.setPrintPos(16, 10);
if(minute<10) u8g.print("0"+String(minute));
else u8g.print(minute);
u8g.setDefaultForegroundColor();
u8g.drawBox(60, 0, 64, 11);
u8g.setDefaultBackgroundColor();
u8g.setPrintPos(64, 10);
u8g.print(plaka);
u8g.setDefaultForegroundColor();
u8g.setPrintPos(0, 25);
u8g.print("Top:"); u8g.print(sum_distance1/1000);
u8g.setPrintPos(64, 25);
u8g.print("Dolu:"); u8g.print(sum_distance2/1);
if (sensor1>350 || sensor2>350 || sensor3>350 || sensor4>350){
u8g.setPrintPos(120, 25);
u8g.print("+");
}
//hız
u8g.drawFrame(0,29,60,14);
u8g.setPrintPos(4, 40);
u8g.print("HIZ: ");
u8g.print(intspd);
//sil sum distance
u8g.setPrintPos(84, 40);
u8g.print(sum_distance1);
;
//sensör verisi
u8g.setPrintPos(64, 55);
u8g.print("Durak:");
u8g.print(sum_distance3);
if(taksimetrepressed==1){
u8g.setPrintPos(120, 55);
u8g.print("+");
}
else {u8g.setPrintPos(120, 55); u8g.print(" "); }
} while (u8g.nextPage() );
delay(10);
//KM sıfırlama
zeroizeDistance();
//Save Distance
if ((currentMillis-previousMillis3)>900000){
previousMillis3=currentMillis;
saveDistance();
}
//security GPS cable is Not Connected
if (sat>=3)previousMillis4=millis();
if (sat<3 && millis()-previousMillis4>1200000){
Serial.print("GPS bağlantısı kesildi: ");
yetkili=0;
while(1){
u8g.firstPage();
do {
u8g.setFont(u8g_font_profont12);
u8g.setPrintPos(0, 10);
u8g.print("GPS Baglantisi");
u8g.setPrintPos(0, 25);
u8g.print("Koptu!");
u8g.setPrintPos(0, 40);
} while (u8g.nextPage() );
delay(1000);
u8g.firstPage();
do {
draw2();
} while (u8g.nextPage() );
delay(500);
authorization();
if(yetkili==1) break;
}
}
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
void authorization(){
yetkili=0;
if ( ! rfid.PICC_IsNewCardPresent()){ //Yeni kartın okunmasını bekliyoruz.
delay(200);
return;
}
if ( ! rfid.PICC_ReadCardSerial()) //Kart okunmadığı zaman bekliyoruz.
return;
if ((rfid.uid.uidByte[0] == ID[0] && //Okunan kart ID'si ile ID değişkenini karşılaştırıyoruz.
rfid.uid.uidByte[1] == ID[1] &&
rfid.uid.uidByte[2] == ID[2] &&
rfid.uid.uidByte[3] == ID[3] ) ||
(rfid.uid.uidByte[0] == ID2[0] && //Okunan kart ID'si ile ID değişkenini karşılaştırıyoruz.
rfid.uid.uidByte[1] == ID2[1] &&
rfid.uid.uidByte[2] == ID2[2] &&
rfid.uid.uidByte[3] == ID2[3] ) ){
Serial.println("cihaz acilıyor...");
ekranaYazdir();
yetkili=1;
}
else{ //Yetkisiz girişte içerideki komutlar çalıştırılır.
Serial.println("Yetkisiz Kart");
ekranaYazdir();
yetkili=0;
u8g.firstPage();
do {
drawYetkisizKart();
} while( u8g.nextPage() );
delay(1500);
}
rfid.PICC_HaltA();
}
void ekranaYazdir(){
Serial.print("ID Numarasi: ");
for(int sayac = 0; sayac < 4; sayac++){
Serial.print(rfid.uid.uidByte[sayac]);
Serial.print(" ");
}
Serial.println("");
}
//-----draw section-----------------------
void draw1(void){
u8g.setFont(u8g_font_profont12);
u8g.setPrintPos(0, 10);
u8g.print("Mesafe Olcer");
u8g.setPrintPos(0, 25);
u8g.print("v5");
u8g.setPrintPos(0, 40);
}
void draw2(void){
u8g.setFont(u8g_font_profont12);
u8g.setPrintPos(0, 10);
u8g.print("Lutfen Yetki Kartini");
u8g.setPrintPos(0, 25);
u8g.print("Okutunuz!");
u8g.setPrintPos(0, 40);
}
void drawYetkisizKart(void){
u8g.setFont(u8g_font_profont12);
u8g.setPrintPos(0, 10);
u8g.print("!!!Gecersiz kart!!!");
u8g.setPrintPos(0, 25);
u8g.print("Lutfen Yetkili Karti");
u8g.setPrintPos(0, 40);
u8g.print("Okutun!");
}
//----------------------
void plakaGir(){
int analogupval; //sometimes analog pin lowers 800 so it result low
analogupval=analogRead(up);
if (analogupval>10) upval=1;
else upval=0;
downval=digitalRead(down);
leftval=digitalRead(left);
rightval=digitalRead(right);
enterval=digitalRead(enter);
/*
Serial.println("---------");
Serial.print("up: ");Serial.println(upval);
Serial.print("down: ");Serial.println(downval);
Serial.print("left: ");Serial.println(leftval);
Serial.print("right: ");Serial.println(rightval);
Serial.print("enter: ");Serial.println(enterval);
Serial.print("plaka: ");Serial.println(plaka);
Serial.print("plaka_position: ");Serial.println(plaka_position);
Serial.print("letter_position: ");Serial.println(letter_position);
Serial.print("letter: ");Serial.println(Letters[letter_position]);
*/
if( upval==1){
letter_position++;
if(letter_position>33)letter_position=0;
plaka[plaka_position]=Letters[letter_position];
EEPROM.update(plaka_position,Letters[letter_position]);
}
if(downval==1){
letter_position--;
if(letter_position<0)letter_position=33;
plaka[plaka_position]=Letters[letter_position];
EEPROM.update(plaka_position,Letters[letter_position]);
}
if( rightval==1){
plaka_position++;
if(plaka_position>9)plaka_position=0;
for (int i=0; i<35; i++) {
if (plaka[plaka_position] == Letters[i]) {
letter_position = i;
break;
}
}
}
if(leftval==1){
plaka_position--;
if(plaka_position<0)plaka_position=9;
for (int i=0; i<35; i++) {
if (plaka[plaka_position] == Letters[i]) {
letter_position = i;
break;
}
}
}
//print oled
u8g.firstPage();
do {
uint8_t i, h;
u8g_uint_t w, d;
u8g.setFont(u8g_font_6x13);
u8g.setFontRefHeightText();
u8g.setFontPosTop();
h = u8g.getFontAscent()-u8g.getFontDescent();
w = u8g.getWidth();
u8g.setPrintPos(0, 10);
u8g.print("Plakayi Giriniz");
u8g.setPrintPos(0, 25);
for ( i = 0; i < 10; i++ ) {
u8g.setDefaultForegroundColor();
if ( i == plaka_position ) {
u8g.drawBox(i*6, 25, 6, h);
u8g.setDefaultBackgroundColor();
}
u8g.print(plaka[i]);
}
u8g.setDefaultForegroundColor();
u8g.setPrintPos(plaka_position*6, 40);
u8g.print(Letters[letter_position]);
}
while (u8g.nextPage() );
delay(20);
}
void checkDate(unsigned long date){
long reverseDate= date/10000; // dd
reverseDate += (date/100) % 100*100; // mm
reverseDate += (date % 100) *10000; // yy
if (reverseDate>refyymmdd){
uptadeDate();
return;
}
}
void uptadeDate(){
while(1){
upval=digitalRead(up);
downval=digitalRead(down);
leftval=digitalRead(left);
rightval=digitalRead(right);
enterval=digitalRead(enter);
if( upval==1){
letter_position++;
if(letter_position>33)letter_position=0;
urunKodu[urunKodu_position]=Letters[letter_position];
}
if(downval==1){
letter_position--;
if(letter_position<0)letter_position=33;
urunKodu[urunKodu_position]=Letters[letter_position];
}
if( rightval==1){
urunKodu_position++;
if(urunKodu_position>9)urunKodu_position=0;
for (int i=0; i<35; i++) {
if (urunKodu[urunKodu_position] == Letters[i]) {
letter_position = i;
break;
}
}
}
if(leftval==1){
urunKodu_position--;
if(urunKodu_position<0)urunKodu_position=9;
for (int i=0; i<35; i++) {
if (urunKodu[urunKodu_position] == Letters[i]) {
letter_position = i;
break;
}
}
}
//print oled
u8g.firstPage();
do {
uint8_t i, h;
u8g_uint_t w, d;
u8g.setFont(u8g_font_6x13);
u8g.setFontRefHeightText();
u8g.setFontPosTop();
h = u8g.getFontAscent()-u8g.getFontDescent();
w = u8g.getWidth();
u8g.setPrintPos(0, 10);
u8g.print("Kullanim Suresi doldu");
u8g.setPrintPos(0, 25);
u8g.print("Lutfen Kodu Giriniz");
u8g.setPrintPos(0, 40);
for ( i = 0; i < 10; i++ ) {
u8g.setDefaultForegroundColor();
if ( i == urunKodu_position ) {
u8g.drawBox(i*6, 40, 6, h);
u8g.setDefaultBackgroundColor();
}
u8g.print(urunKodu[i]);
}
u8g.setDefaultForegroundColor();
u8g.setPrintPos(urunKodu_position*6, 55);
u8g.print(Letters[letter_position]);
}
while (u8g.nextPage() );
delay(10);
Serial.print("urunkodu");Serial.println(urunKodu);
if(enterval==1){
if(String(urunKodu)=="2111111111"){
refyymmdd=240625;
EEPROM.put(100,24);
EEPROM.put(101,06);
EEPROM.put(102,25);
Serial.println("Dogru kod girildi");
return;
}
if(String(urunKodu)=="311111111"){
refyymmdd=250626;
EEPROM.put(100,25);
EEPROM.put(101,06);
EEPROM.put(102,26);
Serial.println("Dogru kod girildi");
return;
}
if(String(urunKodu)=="411111111"){
refyymmdd=260627;
EEPROM.put(100,26);
EEPROM.put(101,06);
EEPROM.put(102,27);
Serial.println("Dogru kod girildi");
return;
}
}
}
}
void zeroizeDistance(){
enterval=digitalRead(enter);
if (enterval==1){
u8g.firstPage();
do {
draw2();
} while (u8g.nextPage() );
delay(100);
unsigned long previousMillis2 = millis();
while(millis()-previousMillis2<20000){ //after 10 sec exit this mode
authorization();
if (yetkili==1){
sum_distance1=0;
sum_distance2=0;
EEPROM.put(150,sum_distance1);
EEPROM.put(160,sum_distance2);
uyolcu=0;
kyolcu=0;
break;
}
}
}
}
void saveDistance(){
unsigned long sum_distance1_v2;
unsigned long sum_distance2_v2;
EEPROM.get(150,sum_distance1_v2);
EEPROM.get(160,sum_distance2_v2);
//to protect eeprom lifecycle write values if only they changes.
//EEPROM.update is not working cuz they are long.
if (sum_distance1>sum_distance1_v2) EEPROM.put(150,sum_distance1);
if (sum_distance2>sum_distance2_v2) EEPROM.put(160,sum_distance2);
}
void readSensors(){
sensor1=analogRead(sensor1pin);
sensor2=analogRead(sensor2pin);
sensor3=analogRead(sensor3pin);
sensor4=analogRead(sensor4pin);
Serial.print("sensors: "); Serial.println(sensor1);Serial.println(sensor2);Serial.println(sensor3);Serial.println(sensor4);
// sensor bağlantısı kesilme emniyeti
if (sensor1<10 ||sensor2<10 || sensor3<10 || sensor4<10){
Serial.print("Sensor bağlantısı kesildi sensor: ");
yetkili=0;
while(1){
u8g.firstPage();
do {
u8g.setFont(u8g_font_profont12);
u8g.setPrintPos(0, 10);
u8g.print("Sensor Baglantisi");
u8g.setPrintPos(0, 25);
u8g.print("Koptu!");
u8g.setPrintPos(0, 40);
} while (u8g.nextPage() );
delay(1000);
u8g.firstPage();
do {
draw2();
} while (u8g.nextPage() );
delay(500);
authorization();
if(yetkili==1) break;
}
}
}
void ISR2(){
taksimetrepressed=1;
Serial.println("-----ISR*******------------------------");
previousMillis5=millis();
taksimetrepressed=1;
sum_distance3=0;
}