Skocz do zawartości

ESP32 sterowanie obiektem 3D poprzez żyroskop L3GD20H


arek1996

Pomocna odpowiedź

Cześć,

Próbuje zmusić żyroskop L3GD20H podłączony pod ESP32 do rotowania obiektu 3D np w Unity. 

Udało mi się osiągnąć taki efekt: 

EFEKT

Niestety nie mogę tego okiełznać, szybkość obracania żyroskopem wpływa na rotowanie obiektu, nie jest to jednoznaczne. Czy to żyroskop nie jest dość dokładny? a może ja coś robię nie tak i są sposoby żeby to jakoś sensowniej obsługiwać, a ja coś robię nie tak? Ktoś może z tego korzystał i ma jakieś rady? Czy ten żyroskop pokazuje różnice między aktualnym a poprzednim stanem? Czy utrzymuje ten stan jakiś czas powodując że obiekt za bardzo się rotuje? I nie do końca rozumiem czym jest ten zakres pomiarowy: ±245 °/s, ±500 °/s lub ±2000 °/s.

Link to żyroskopu: Link

Podsyłam aktualny kod, który daje efekt jak na filmiku: 

Arduino:

#include <Wire.h>
#include <L3G.h>

L3G gyro;

void setup() {
  Serial.begin(9600);
  Wire.begin();

  if (!gyro.init(L3G::device_D20H, L3G::sa0_auto ))
  {
    Serial.println("Failed to autodetect gyro type!");
    while (1);
  }

  gyro.enableDefault();
  gyro.writeReg(L3G::CTRL_REG1, 0x6F);
}

void loop() {
  gyro.read();

  Serial.println("{\"x\":" + String(gyro.g.x / 250.0f) + ", \"y\":" + String(gyro.g.y / 250.0f) + ", \"z\":" + String(gyro.g.z / 250.0f) + "}");
}

UNITY:

using UnityEngine;
using System.IO.Ports;

public class SerialRead : MonoBehaviour
{
    private SerialPort sp;

    void Start()
    {
        string the_com = "";

        foreach (string mysps in SerialPort.GetPortNames())
        {
            Debug.Log(mysps);
            if (mysps != "COM1") 
            { 
                the_com = mysps; 
                break; 
            }
        }

        sp = new SerialPort("\\\\.\\" + the_com, 9600);

        if (!sp.IsOpen)
        {
            sp.Open();
            sp.ReadTimeout = 100;
            sp.Handshake = Handshake.None;
        }
    }

    void Update()
    {
        if (!sp.IsOpen)
        {
            sp.Open();
        }
        else
        {
            var gyro = JsonUtility.FromJson<Gyro>(sp.ReadLine());
            gameObject.transform.Rotate(gyro.GetGyroRotation() * Time.deltaTime);
        }

    }
}

 

Link do komentarza
Share on other sites

30 minut temu, arek1996 napisał:

Czy ten żyroskop pokazuje różnice między aktualnym a poprzednim stanem?

Żyroskop podaje stan aktualny.

30 minut temu, arek1996 napisał:

Czy utrzymuje ten stan jakiś czas powodując że obiekt za bardzo się rotuje? I nie do końca rozumiem czym jest ten zakres pomiarowy: ±245 °/s, ±500 °/s lub ±2000

Żyroskop mierzy prędkość kątową, a to jest zakres prędkości określający dokładność pomiaru. Im mniejszy zakres tym większa czułość.

By uzyskać kąt musisz dodać do swojej pętli wskaźnik czasu danej iteracji oraz sumować kąt i jego przesyłać do Unity. Wyjaśnienie tego zagadnienia jest dość skomplikowane, ale w skrócie: czas między iteracjami pętli nie jest jednakowy, mimo, że na taki wygląda. Dodatkowo ufanie sterownikom Windowsa w kwestii idealnego czasu odbioru danych w idealnych odstępach czasu... Bezcenne... xD Nawet Linux z RT Kernel'em potrafi mieć z tym problemy, chociaż zostały one bardzo mocno zniwelowane, a taki złom jak Windows, który ma miliard zbędnych procesów potrafi czasem przesunąć odbiór danych o parę ms, które robi się krytyczne po pewnym czasie. Zacznij liczyć aktualny kąt żyroskopu w loop() na ESP (patrz filmik niżej), a powinno działać kilkanaście razy lepiej.

Dodatkowo dochodzi problem tzw. "angle walk" - żyroskop nie jest urządzeniem idealnym i zawsze będzie miał jakiś odczyt, który będzie oscylował w okolicy zera, ale nie będzie zerem.

P.S. stosowanie żyroskopu bez akcelerometru to masochistyczne podejście. I zwiększ baudrate... 9600bit/s to dość mało jak na komunikację w czasie rzeczywistym.

Edytowano przez H1M4W4R1
  • Lubię! 2
Link do komentarza
Share on other sites

51 minut temu, H1M4W4R1 napisał:

Żyroskop podaje stan aktualny.

Żyroskop mierzy prędkość kątową, a to jest zakres prędkości określający dokładność pomiaru. Im mniejszy zakres tym większa czułość.

By uzyskać kąt musisz dodać do swojej pętli wskaźnik czasu danej iteracji oraz sumować kąt i jego przesyłać do Unity. Wyjaśnienie tego zagadnienia jest dość skomplikowane, ale w skrócie: czas między iteracjami pętli nie jest jednakowy, mimo, że na taki wygląda. Dodatkowo ufanie sterownikom Windowsa w kwestii idealnego czasu odbioru danych w idealnych odstępach czasu... Bezcenne... xD Nawet Linux z RT Kernel'em potrafi mieć z tym problemy, chociaż zostały one bardzo mocno zniwelowane, a taki złom jak Windows, który ma miliard zbędnych procesów potrafi czasem przesunąć odbiór danych o parę ms, które robi się krytyczne po pewnym czasie. Zacznij liczyć aktualny kąt żyroskopu w loop() na ESP (patrz filmik niżej), a powinno działać kilkanaście razy lepiej.

Dodatkowo dochodzi problem tzw. "angle walk" - żyroskop nie jest urządzeniem idealnym i zawsze będzie miał jakiś odczyt, który będzie oscylował w okolicy zera, ale nie będzie zerem.

P.S. stosowanie żyroskopu bez akcelerometru to masochistyczne podejście. I zwiększ baudrate... 9600bit/s to dość mało jak na komunikację w czasie rzeczywistym.

Bardzo dziękuje za odpowiedź, na pewno skorzystam. Rozumiem że na ESP32 mam mieć własny wector który oblicza aktualny kąt i podawać to do Unity, wtedy opóźnienia nie będą mieć znaczenia? 
A jest jakiś sposób żeby "angle walk" wyeliminować? Z tego co patrzyłem to na Y potrafi on wynieść nawet do 1° jak żyroskop stoi nietknięty,  więc cube będzie się polowi obracać... 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

14 minut temu, arek1996 napisał:

Przeanalizowałem ten kod i wynika z tego że bez akcelerometru nie da się wyeliminować "angle walk".

Możesz go zredukować za pomocą uśredniania wyników z n pomiarów, ale wtedy zmniejszasz częstotliwość, a zarazem drobne ruchy nie będą wykryte.

  • 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.