Skocz do zawartości

ESP32 sterowanie obiektem 3D poprzez żyroskop L3GD20H


Pomocna odpowiedź

Napisano

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);
        }

    }
}

 

(edytowany)
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
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ć... 

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

Są takie, które są projektowane tak, żeby dryft był jak najmniejszy (cena), ale wyeliminować się nie da pewnie z racji sposobu działania. Ja np. na Androidzie, dryft zamodelowałem wielomianem i go odejmowałem od surowych danych z żyroskopu.

  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...