Skocz do zawartości

Monitor lotu na Arduino i GPS


Rak_Rakoski

Pomocna odpowiedź

Chcę wykonać moduł monitora (Loggera) służący do zapisu parametrów lotu pod czas oblotów samolotów rc, wykorzystując Arduino UNO, moduł gps neo-6m i bibliotekę TinyGps++. Napisałem kod który podaje błędne odczyty wysokości i chyba też prędkości, chcę mierzyć wysokość od miejsca startu. Moja lokalizacja jest na wysokości ok. 41m n.p.m. Gps pokazuje mi wysokość ok. 90m n.p.m. Ale nie mogę uzyskać poprawnego pomiaru wysokości. W sieci nie znalazłem informacji na temat poprawności mojego kodu. Proszę o pomoc w zakresie poprawności kodu lub ewentualne inne rozwiązanie tego problemu.

#include <SPI.h>
#include <Wire.h>
#include <SD.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

const byte address[1][8] PROGMEM = {0x28};

OneWire oneWire(A1);
DallasTemperature sensors(&oneWire);

File Dane;

static const int RXPin = 9, TXPin = 10;
static const uint32_t GPSBaud = 9600;


// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

unsigned long aktualnyCzas = 0;
unsigned long zapamietanyCzas = 0;
unsigned long roznicaCzasu = 0;

unsigned long aktualnyCzas1 = 0;
unsigned long zapamietanyCzas1 = 0;
unsigned long roznicaCzasu1 = 0;

int S = 0;
int M = 0;
int H = 0;
int i = 0;
int z = 0;
String RTY = "";

float tempMax = 0;
float wys_npmMax = 0;
float wysMax = 0;
float wys = 0;
float baza = 0;
float predMax = 0;
void setup() 
{
  
  ss.begin(GPSBaud);
  

  SD.begin(4);
  pinMode(7, OUTPUT); // Dioda informująca o zapisywaniu na kartę
  pinMode(A2, OUTPUT); // Dioda informująca o zlapaniu pozycji
  sensors.begin();
  digitalWrite(A2, LOW);
}

void loop() 
{
  while (ss.available() > 0)
    if (gps.encode(ss.read()))
    
  char sz[32];
  float temp = sensors.getTempCByIndex(0); // Temperatura
  double wysnpm = gps.altitude.meters(); // Wysokosć
  double pred = gps.speed.kmph(); // Prędkość
  double X = gps.location.lat();
  double Y = gps.location.lng();
  sensors.requestTemperatures();

  if (z == 0 && gps.date.isValid() && gps.time.isValid())
  {
    Dane = SD.open("Dane.txt", FILE_WRITE);
    printDateTime(gps.date, gps.time);
    Dane.println("Czas lotu (HH:MM:SS); Prędkość (Kmh); Wysokość (m); temperatura silnika (*C);");
    Dane.close();
    z++; 
  }
  
  //Złożenie pakietu informacji do zapisu na sd
  RTY = String(H) + ":" + String(M) + ":" + String(S) + "; " + pred + "; " + wys + "; " + temp + ";           " + baza + ";  " + wysnpm + ";     " + X + ";       " + Y + ";";
  
  
  
  aktualnyCzas = millis();
  roznicaCzasu = aktualnyCzas - zapamietanyCzas;
  
  aktualnyCzas1 = millis();
  roznicaCzasu1 = aktualnyCzas1 - zapamietanyCzas1;
  
  if (gps.altitude.isValid() && i == 0)
  {
    digitalWrite(A2, HIGH);
    baza = wysnpm;
    i++;
  }
  if (gps.altitude.isValid())
  {
  wys = wysnpm - baza;
  }
  
  //Jeśli różnica wynosi ponad sekundę
  if (roznicaCzasu >= 1000UL && gps.altitude.isValid()) 
  {
    zapamietanyCzas = aktualnyCzas;
    S = S + 1;
    if (S > 59)
    {
     S = 0;
     M = M + 1;
    }
    if (M > 59)
    {
     M = 0;
     H = H + 1;
    }
     
  }
 smartDelay(1000);

 
  if (roznicaCzasu1 >= 1000UL && gps.altitude.isValid()) 
  {
    zapamietanyCzas1 = aktualnyCzas1;
    digitalWrite(7, HIGH);
    Dane = SD.open("Dane.txt", FILE_WRITE);
    
  Dane.println(RTY);
  Dane.close();
  digitalWrite(7, LOW);
  }
  
}
static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
    Dane.print(sz);
  }
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Dane.println(sz);
  }
}
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

Log zapisany na karcie:

Cytat

11/03/2019 11:50:59                 
Czas lotu (HH:MM:SS)     Prędkość (Kmh)     Wysokość (m)     temperatura silnika (*C)    
0:00:00    0    0    20,25                        0,00  0,00
0:00:02    0,54    0    19,88                   90,80  90,70
0:00:05    0,93    -0,9    19,94               90,80  89,90
0:00:08    0,74    -1,6    19,94               90,80  89,10
0:00:11    0    -1,7    19,75                     90,80  89,10
0:00:14    0    -1,5    19,81                     90,80  89,40
0:00:18    0,93    -1,2    19,94                90,80  90,00
0:00:21    2,46    1,8    19,81                 90,80  94,00
0:00:24    9,7    5,3    19,75                   90,80  97,40
0:00:28    32,54    12,9    19,75             90,80  104,60
0:00:31    39,41    14,3    19,69             90,80  105,40
0:00:34    34,71    15,1    19,69             90,80  105,40
0:00:37    22,02    12,7    19,56             90,80  101,70
0:00:41    16,41    8,9    19,5                 90,80  98,10
0:00:45    26,87    1,3    19,31               90,80  95,40
0:00:49    52,08    10,1    19,31             90,80  100,90
0:00:52    52,08    10,1    19,31             90,80  100,90
0:00:55    52,08    10,1    19,25             90,80  97,70
0:00:59    3,02    7,5    19,25                 90,80  97,90
0:01:03    4,7    7,6    19,25                   90,80  99,00
0:01:07    0    8    19,06                         90,80  99,10

 

Link do komentarza
Share on other sites

Długo nikt nic nie napisał więc cos podpowiem. UNO i zasilanie bateryjne to zły pomysł. UNO, które ledwo sobie radzi z obsługa kart SD w trybie 1-bit to kolejny zły pomysł. Może to jest powód, że nikt nie chce pomóc albo to, ze nie pokazałeś schematu elektrycznego jak to wszystko masz podłączone.

Link do komentarza
Share on other sites

A ja myślę, że nie ma co rozkminiać "bateryjności" czy prędkości transmisji z kartą, bo wcale nie tu leży problem. Ani UNO nie jest jakoś specjalnie ułomne - wystarczy rozumieć jak działa jego stabilizator i nie karmić go zbyt wysokim napięciem a straty będą akceptowalnie małe, ani też prędkość karty w trybie 1-bitowym nie jest żadnym ograniczeniem dla loggera GPS, gdzie dane ciekną jak krew z nosa. Kolega @Rak_Rakoskizwyczajnie powinien zapoznać się z narzędziem jakiego używa. GPS nie jest panaceum na wszelkie potrzeby. Owszem, daje informację o pozycji, ale wg swojego własnego układu odniesienia. O ile długość/szerokość są w miarę dokładne (a biorąc pod uwagę zasięg systemu i koszty dzisiejszych odbiorników cywilnych wręcz rewelacyjne), o tyle wysokość jest tam raportowana najsłabiej. Wiąże się to z przyjętą zasadą pracy, ale także ze wspomnianym układem odniesienia. GPS zakłada, że Ziemia jest elipsoidą wg  normy WGS84 i to względem niej odbiornik podaje swoją wysokość. Niestety Ziemia nie chce być tak regularna i ma swoje górki i dołki. Nie myślę tu o górach i dolinach jakie widzimy na poziomnicach map, ale wielkoskalowe odchyłki od przyjętej, regularnej bryły. Z tego powodu - w zależności od miejsca na Ziemi - GPS będzie pokazywał zawyżone lub obniżone odczyty wysokości względem lokalnego zera n.p.m. W tym artykule jest trochę komentarza i mapka odchyłek:

https://xcmag.com/news/gps-versus-barometric-altitude-the-definitive-answer/

Odbiorniki GPS mają wbudowaną elipsoidę WGS84 (i czasem także inne bryły odniesienia do wyboru - w różnych aplikacjach/środowiskach potrzeby i przyzwyczajenia są różne) a co ciekawe niektóre mają nawet wbudowaną mapę właśnie tych wielkoskalowych odchyłek od WGS84, ale nie wszystkie.

Nie analizowałem Twojego kodu, ale nie na pierwszy rzut oka, zgodnie z zasadą brzytwy Ockhama nie doszukiwałbym się w nim błędów. Skoro dostajesz poprawne ramki NMEA i GPS ma "fix", to praktycznie na 100% to działa. A najbardziej oczywiste źródło błędu wysokości widać jak na dłoni. Moim zdaniem wystarczy, byś zapamiętywał uśrednioną z wielu odczytów "zerową" wysokość przy starcie i względem niej zapisywał swoje logi. Możesz też wprowadzić stałą poprawkę do kodu obowiązującą np. dla obszaru Polski, ale wtedy np. wyjazd do Indii może zepsuć wyniki 🙄 Zerowanie wysokości przed startem przeprowadza się standardowo w przypadku używania wysokościomierzy ciśnieniowych po to by uzyskać tzw. AAL (Above Aerodrome Level) i dopóki nie lecisz do Stanów jest to całkiem OK. Swoją drogą polecam barometry jako dodatkowe/uzupełniające w stosunku do GPS źródło informacji o wysokości. Nowoczesne chipy MEMS przy uśrednianych pomiarach (np. do 1Hz) potrafią mieć rozdzielczość 10cm(!) a to zupełnie wystarcza do utrzymania stałej wysokości zawisu czy lotu dronem. Sprawdziłem kiedyś na moich lataczach 😎

Edytowano przez marek1707
literówki..
  • Lubię! 1
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.