• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Próbuje napisać kod strikte do łódki zanentowej
#1
Mam już mnóstwo kodu i  już pływa, ale mam problem pływaniem w lini prostej.
Używam starego APM jako bazy ardurower średnio się sprawdza do tego celu.
Na razie używam samego GPS i kompasu, bez żyroskopu bo go wcale nie rozumiem..
Chciał bym się dowiedzieć czy kod wygląda dobrze dla łódki...

Kod:
#include "HMC5883L.h"
#include "ReadEprom.h"
#include <Wire.h>


void HMC5883L_Init() {
 
  Wire.begin(); 

  Wire.beginTransmission(HMC5883L_ADDRESS);
  Wire.write(0x00); // Rejestr konfiguracji A
  Wire.write(0x70); // 8 pomiarów na średnią, 15Hz(0x70) lub 30Hz(0x78)
  Wire.endTransmission();

  Wire.beginTransmission(HMC5883L_ADDRESS);
  Wire.write(0x01); // Rejestr konfiguracji B
  Wire.write(0x20); // Ustawienie wzmocnienia 40
  Wire.endTransmission();

  Wire.beginTransmission(HMC5883L_ADDRESS);
  Wire.write(0x02); // Rejestr trybu
  Wire.write(0x00); // Tryb ciągłego pomiaru
  Wire.endTransmission();
  Wire.requestFrom(HMC5883L_ADDRESS, 6);
}

// Zmienne globalne
float offsetX = 56.50, offsetY = -215.00, offsetZ = 0.0;
float declinationAngle = 5.0;
float rotationAngle = 90.0;
float heading = 0;
bool isUpsideDown = false;  // Domyślnie czujnik jest w normalnej orientacji
float x;
float y;

unsigned long os_czas_kom = 0;
bool AwariaKom = false;


void readRawData(int16_t &x, int16_t &y, int16_t &z) {
 
  // Ustaw wskaźnik na pierwszy rejestr danych (0x03)
  Wire.beginTransmission(HMC5883L_ADDRESS);
  Wire.write(0x03);
  Wire.endTransmission();
 
  Wire.requestFrom(HMC5883L_ADDRESS, 6);
  if (Wire.available() == 6) {
    x = (Wire.read() << 8) | Wire.read();
    z = (Wire.read() << 8) | Wire.read();
    y = (Wire.read() << 8) | Wire.read();

    os_czas_kom = millis();
    AwariaKom = false;
    }
}


unsigned long lastReadTime = 0; // Zmienna globalna

void Read_HMC5883L() {

  if (millis() - lastReadTime > 70) {  // Odczyt co 70 ms
 
  int16_t rawX, rawY, rawZ;
  readRawData(rawX, rawY, rawZ);

  if (isUpsideDown) { 
    rawY =  -rawY;
    x = rawX - offsetX;
    y = rawY + offsetY;
  }else{
  x = rawX - offsetX;
  y = rawY - offsetY;
  }


  heading = atan2(y, x) * 180.0 / M_PI;
  heading += declinationAngle;
  heading += rotationAngle;

  if (heading < 0) heading += 360.0;
  if (heading >= 360) heading -= 360.0;


    if (millis() - os_czas_kom > 3000){
    heading = 0;
    AwariaKom = true;
    }

    lastReadTime = millis();  // Aktualizacja czasu odczytu
    }
}

void calibrateXY() {
  int16_t rawX, rawY, rawZ;
  int16_t minX = 32767, minY = 32767, maxX = -32768, maxY = -32768;
  char userInput;

  // Zapytaj użytkownika o potwierdzenie rozpoczęcia kalibracji
  Serial.println(F("Czy chcesz rozpoczac kalibracje kompasu(T/N)"));
  Serial.println(F("Naciskajac 'T' masz 5s do obracania lodka"));
 
  // Czekaj na odpowiedź użytkownika
  while (true) {
    if (Serial.available() > 0) {
      userInput = Serial.read();  // Odczytanie odpowiedzi użytkownika
      if (userInput == 'T') {  // Jeżeli odpowiedź to 't' (tak)
        Serial.println(F("Rozpoczynam kalibracje..."));
        break;  // Kontynuuj kalibrację
      } else if (userInput == 'N') {  // Jeżeli odpowiedź to 'n' (nie)
        Serial.println(F("Kalibracja anulowana."));
        return;  // Zakończ funkcję, kalibracja nie zostanie wykonana
      }
    }
  }
  delay(5000);
  Serial.println(F("Obracaj lodka przez 10s"));
 
 
  // Zbieranie danych przez 10 sekund
  for (int i = 0; i < 5000; i++) {  // 5000 próbek w 10 sekund
    readRawData(rawX, rawY, rawZ);

    // Szukaj minimum i maksimum dla obu osi X i Y
    if (rawX < minX) minX = rawX;
    if (rawX > maxX) maxX = rawX;
    if (rawY < minY) minY = rawY;
    if (rawY > maxY) maxY = rawY;

    delay(2);  // opóźnienia dla większej liczby próbek
  }

  // Obliczanie ofsetów na podstawie minimalnych i maksymalnych wartości
  offsetX = (maxX + minX) / 2.0;
  offsetY = (maxY + minY) / 2.0;

  // Zapisz ofsety do pamięci eprom i wyswietl
  SaveOfsetCompas();
  delay(10);
  Serial.print(F("Ofset X: "));
  Serial.println(offsetX);
  Serial.print(F("Ofset Y: "));
  Serial.println(offsetY);

  // Kalibracja zakończona
  Serial.println(F("Kalibracja zakonczona"));
}


// Funkcja do zmiany deklinacji przez UART z potwierdzeniem
void changeDeclinationAngle() {
  // Wyświetlanie obecnej wartości deklinacji
  Serial.print(F("Aktualna deklinacja: "));
  Serial.println(declinationAngle);
 
  Serial.println(F("Czy chcesz zmienic wartosc deklinacji? (T/N)"));
  Serial.println(F("www.magnetic-declination.com"));
 
  char userInput;
  while (true) {
    if (Serial.available() > 0) {
      userInput = Serial.read();  // Odczytanie odpowiedzi użytkownika
      if (userInput == 'T') {  // Jeżeli odpowiedź to 't' (tak)
        Serial.println(F("Podaj nowa wartosc deklinacji:"));
        break;  // Kontynuuj zmianę deklinacji
      } else if (userInput == 'N') {  // Jeżeli odpowiedź to 'n' (nie)
        Serial.println(F("Zmiana deklinacji anulowana."));
        return;  // Zakończ funkcję, nie zmieniaj deklinacji
      }
    }
  }
 
 
  // Oczekiwanie na wprowadzenie nowej wartości deklinacji
  while (true) {
    if (Serial.available() > 0) {
      String input = Serial.readStringUntil('\n');  // Odczytanie wejścia użytkownika
      input.trim();  // Usuń zbędne białe znaki

      // Sprawdź, czy wprowadzenie jest liczbą
      float newDeclination = input.toFloat();
      if (newDeclination != 0.0 || input == "0") {
        declinationAngle = newDeclination;  // Ustaw nową deklinację
        SaveDeclinationCompas();
        delay(10);
        Serial.print(F("Nowa deklinacja: "));
        Serial.println(declinationAngle);
        break;
      } else {
        Serial.println(F(""));
      }
    }
  }
}

void changeRotationAngle() {
  // Wyświetlanie obecnej wartości kąta obrotu
  Serial.println(F(""));
  Serial.print(F("Aktualny kat obrotu: "));
  Serial.print(rotationAngle);
  Serial.println(F("°"));
  Serial.println(F(""));
 
  Serial.println(F("Wybierz opcje zmiany kata obrotu:"));
  Serial.println(F("1.Ustaw kat 0°"));
  Serial.println(F("2.Ustaw kat 90° (wew APM)"));
  Serial.println(F("3.Ustaw kat 180°"));
  Serial.println(F("4.Ustaw kat 270°"));
  Serial.println(F("5.Wprowadz dowolny kat (1-359°)"));
  Serial.println(F("0.Powrot"));

  while (true) {
    if (Serial.available() > 0) {
      char userInput = Serial.read();  // Odczytanie wyboru użytkownika

      // Usuń znaki końca linii z bufora
      if (userInput == '\n' || userInput == '\r') {
        continue;
      }
     
      switch (userInput) {
        case '1':
          rotationAngle = 0;
          SaveRotationCompas();
          Serial.println(F("Kat obrotu ustawiony na 0°."));
          return;  // Wyjście z funkcji
        case '2':
          rotationAngle = 90;
          SaveRotationCompas();
          Serial.println(F("Kat obrotu ustawiony na 90°."));
          return;  // Wyjście z funkcji
        case '3':
          rotationAngle = 180;
          SaveRotationCompas();
          Serial.println(F("Kat obrotu ustawiony na 180°."));
          return;  // Wyjście z funkcji
        case '4':
          rotationAngle = 270;
          SaveRotationCompas();
          Serial.println(F("Kat obrotu ustawiony na 270°."));
          return;  // Wyjście z funkcji
        case '5':

        Serial.println(F(""));
        Serial.println(F("Podaj nową wartosc kata obrotu (1-359°)"));
       
while (true) {
    if (Serial.available() > 0) {
      String input = Serial.readStringUntil('\n');  // Odczytanie wejścia użytkownika
      input.trim();  // Usuń zbędne białe znaki

      // Sprawdź, czy wprowadzenie jest liczbą
      float newRotationAngle = input.toFloat();
      // Sprawdzamy, czy kąt mieści się w zakresie 1-359
      if (newRotationAngle >= 1.0 && newRotationAngle <= 359.0) {
        rotationAngle = newRotationAngle;  // Ustaw nowy kąt obrotu
        SaveRotationCompas();
        delay(10);
        Serial.print(F("Nowy kat obrotu: "));
        Serial.print(rotationAngle);
        Serial.println(F("°"));
        return;  // Zakończ funkcję
      }
    }
  }
        return;
        case '0':
          return;  // Wyjście z funkcji

      }
    }
  }
}

void changeOrientation() {
  Serial.print(F("Aktualna pozycja: "));
  if (isUpsideDown) { 
  Serial.println(F("do gory nogami"));
  }else{
  Serial.println(F("normalna"));
  }
  Serial.println(F("Wybierz orientacje kompasu:"));
  Serial.println(F("1.Normalna orientacja(wew APM)"));
  Serial.println(F("2.Czujnik wlutowany do gory nogami"));
  Serial.println(F("0.Powrot"));

  while (true) {
    if (Serial.available() > 0) {
      char userInput = Serial.read();  // Odczytanie wyboru użytkownika

      // Usuń znaki końca linii z bufora
      if (userInput == '\n' || userInput == '\r') {
        continue;
      }
     
      switch (userInput) {
        case '1':
          isUpsideDown = false;  // Normalna orientacja
          SaveUpSideCompas();
          Serial.println(F("Czujnik ustawiony w normalnej orientacji."));
          return;
        case '2':
          isUpsideDown = true;  // Odwrócona orientacja
          SaveUpSideCompas();
          Serial.println(F("Czujnik ustawiony do gory nogami."));
          return;
        case '0':
          return;  // Wyjście z funkcji
      }
    }
  }
}

 
 
 
i
Kod:
#ifndef HMC5883L_H
#define HMC5883L_H
#include <Arduino.h>

// Adres czujnika HMC5883L
#define HMC5883L_ADDRESS 0x1E

void HMC5883L_Init();    //INICJALIZACJA

extern float heading;    //DANE KOMPAU
extern bool  AwariaKom;  //AWARIA KOMPASU

extern float offsetX;
extern float offsetY;
extern float offsetZ;

extern float declinationAngle;
extern float rotationAngle;
extern bool  isUpsideDown;

// FUNKCJE
void calibrateXY();
void Read_HMC5883L();
void changeDeclinationAngle();
void changeRotationAngle();
void changeOrientation();

#endif

Może by ktoś chętny co nie co poprawił lub podpowiedział....Sprawdził i utwierdził by mnie czy to działa prawidłowo.      Bo niby wskazania są ale nie wiem czy wystarczająco dokładne.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości