• 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
opoznienie przy odczycie z czujnika time of flight
#1
Z gory przepraszam za brak polskich czcionek.
Do rzeczy:

W moim urzadzeniu - miniaturowy pojazd na kolach, mam zamontowany czujnik odleglosci - time of flight VL53LOX oraz bardzo wrazliwy - linowy czujnik pola magnetycznego a3503, ktory ma odczytywac sile magnesow neodymowych 0.5cmx1cm ulozonych pod pojazdem - w trakcie jazdy, oraz rozpoznawac rotacje magnesu w kole (rpm). 
Wszystko z osobna dziala ok ale razem to juz nie dziala. Po wielu testach doszedlem iz
problem w tym ze odczyt z czujnika odleglosci VL53LOX  trwa 33 millis, jest to na tyle dlugo ze gdy pojazd poruszajacy sie z predkoscia okolo 10-15km/h przejezdza nad magnesem, czujnik halla ma zbyt duze lagi i nie odbiera pola magnetyczneg, bo przewaznie czeka jeszcze na odczyt z czujnika odleglosci, to samo tyczy sie magnesu w kole - za duze lagi, nie moge okreslic czy kolo wogule sie kreci. W kodzie do odczytu odleglosci uzylem obu metod:
(sensor.readRangeSingleMillimeters())
i
sensor.startContinuous();
(powyzsze komendy zajmuja min 24/34mils do momentu gdzie kod idzie dalej)
czujnik jest standardowo podlaczony do pinow a4 a5 do arduino mini pro 5 volt.

Odnosnie kodu, uzywalem roznych kodow, tych z przykladow i zmodyfikowanych, roznych bibliotek VL53L0X.h, Adafruit, czas odczytu nigdy nie schodzi ponizej 34-24mils.

Czy istnieje jakas mozliwosc zeby wyeliminowac te poznienie lub dokonywac odczytow w trakcie jazdy pojzadu pomimo tych poznien?
 
Odpowiedź
#2
Jeśli nie da się skrócić czasu odczytu informacji z czujnika, może spróbuj zmienić kod - kolejność odczytu informacji z czujników.
Możesz też poczytać o wątkach, ale ponieważ atmega328p jest malutkim procesorkiem, nie wiem, na ile to będzie skuteczne. Sam nie używałem wątków w Arduino (choć wiem, że to możliwe), ale jestem ciekaw, czy sobie poradzi.
 
Odpowiedź
#3
(31-01-2018, 12:54)krn78 napisał(a): Jeśli nie da się skrócić czasu odczytu informacji z czujnika, może spróbuj zmienić kod - kolejność odczytu informacji z czujników.
Możesz też poczytać o wątkach, ale ponieważ atmega328p jest malutkim procesorkiem, nie wiem, na ile to będzie skuteczne. Sam nie używałem wątków w Arduino (choć wiem, że to możliwe), ale jestem ciekaw, czy sobie poradzi.

zmaiana kolejnosci nic nie da bo opoznienie nadal bedzie takie samo, z tymi watkami poczytam ale sprawdzalem inne czujniki odleglosci np.ultrasoniczne i kiedy maja tzw, out of time tez maja pozonienie wiec jak wszyscy do okola sobie z tym radza, w takim razie w zasadzie kazdy robotyk powienien sie zetknac z tym problemem. Ciezki orzech.
 
Odpowiedź
#4
Może pokaż kod programu i biblioteki?
A tak teoretyzując, wpisz w google "atmega czas adc", na mikrokontrolery blogspot com znajdziesz artykuł ADC - Ile da się wycisnąć?
Jak z niego wynika szybkość konwersji ADC zależy od przyjętego prescalera ADC.
Ściągnij sobie dokumentację PDF procesora atmega328, zobacz jaki można ustawić wartości, od ADC jest rejestr ADCSRA, a do ustawień prescalera są bity ADPS:
ADCSRA = (1<<ADEN) //Bit 7 - ADEN: ADC Enable (uruchomienie przetwornika)
|(1<<ADFR) //tryb Free run
|(1<<ADIE) //uruchomienie zgłaszania przerwań
|(1<<ADSC) //rozpoczęcie konwersji
|(1<<ADPS1)
|(1<<ADPS2); //ADPS2:1: (ustawienie preskalera) preskaler= 64
Sprawdź jak w bibliotece jest odczytywana wartość ADC. Jeśli tak jak w artykule, to można tam coś podłubać z tym preskalerem. Ustawienia prescalera na 64 lub 32 i obserwowanie czy zmienia coś w Twoim czasie odczytu.
ADCSRA = (1<<ADPS1) | (1<<ADPS2); //dla 64
lub
ADCSRA = (1<<ADPS2) | (1<<ADPS0): //dla 32
Teoretycznie odczytów przy 10bitach może być 15 tysięcy na sekundę, nie wiadomo jednak ile sampli jest na jeden pomiar w używanej bibliotece by wyeliminować przypadkowe wartości, co jeszcze z samplami jest robione przed wypluciem wyniku. Trzeba tam w nich pogrzebać i popatrzeć czy da się przyspieszyć. Może przy każdym wywołaniu pomiaru preskaler jest ustawiany i tam to trzeba zmienić, w bibliotece. Może kosztem dokładności zmniejszyć liczbę próbek lub liczbę bitów.
Jeśli używa się funkcji wbudowanej w Arduino analogRead(), to nie można bawić się ręcznie tymi rejestrami.
Poza tym funkcja analogRead() niby jest wolna, ale jak sprawdziłem można zrobić 128 pomiarów w czasie 14ms na UNO. Spokojnie można zrobić 8 pomiarów i uśrednić w ciągu 1ms, dwa kanały to 2ms. Czyli nie odbiega od maksimum znacząco.
Teraz dochodzimy do sensora VL53LOX. Jest to sensor z komunikacją cyfrową I2C. Można próbować podkręcić magistralę I2C by dane leciały szybciej od sensora do Arduino , ale generalnie problem polega na tym, że biblioteka (którą akurat ja znalazłem) wysyła żądanie pomiaru i czeka na odpowiedź, sprawdza jednocześnie czy upłynął timeout odpowiedzi, który wynosi 500ms. A typowy czas odpowiedzi to właśnie 20-40ms. I tyle program Ci wisi, choć może nawet wisieć te 500 jak czujnik nie będzie miał humoru. Generalnie transmisja I2C jest wolna, a tu jeszcze oczekiwanie na jej rozpoczęcie.
Rozwiązań jest kilka, a co przypasuje to już zależy od Ciebie
1. Szukanie innej biblioteki, która tylko inicjuje pomiar, ustawia przerwanie od I2C (TWI jak to nazywa się w atmedze) i wraca do odczytu po wywołaniu przerwania. Odczyt kilku bajtów powinien zajmować <1ms.
2. Wywoływanie zliczania impulsów RPM w przerwaniu INT0 - INT2 i zliczenie (pewnie tutaj można zastąpić czujnik liniowy na dwustanowy), a wyliczenia RPM i pomiar ADC w przerwaniach timera. Jeśli akurat się trafi na transmisję I2C może to ją zakłócić, ale też na czas samej transmisji można wyłączyć przerwania.
3. Czujnik odległości zmienić na jakiś ADC, jak widać 1 odczyt ADC to 100us, zamiast 30-500ms.
4. Można ewentualnie pobawić się z odczytami w trybie continuous, czy tam nie jest tak, że zakończenie odczytu inicjuje kolejny pomiar i kończy funkcję, tylko jeśli Ty tam wracasz po 1ms to wisisz czekając na zakończenie tego kolejnego pomiaru, zaglądaj po ten odczyt w bezpiecznym odstępie np. 33-40ms, wtedy czas odczytu powinien być tylko tyle ile potrzeba na przesłanie danych I2C, no może będzie starszy o te 7ms. Timeout można wtedy ustawić np. na 2, 4, ale za to wrócić do pomiaru nie po 33ms tylko po kolejnej pętli. Oczywiście bez delay tylko zliczaj sobie millis() i jak minie 40 to wywołanie odczytu. Jak to zadziała to kolejny krok sprawdzenie czy I2C działa na 100kHz, 400kHz, a może da się go bujnąć na 800 i czujnik da radę (na czekanie nie pomoże)?
PS
Sprawdziłbym też czy (w zależności od wersji) masz pin INT lub G (GPIO1), wg dokumentacji jest do generowania przerwania gdy pomiar gotowy do odczytu. Można odpali tryb continuous i sprawdzić czy tam się nie pojawia pik co około 30ms, jeśli tak to odczyt w tym trybie można zrobić w przerwaniu zewnętrznym. Lub jeśli piki z RPM są bardziej istotne ustawić tylko jakąś flagę i wrócić do odczytu w pętli głównej po czym zerować flagę.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#5
Glownie korzystam z bibliotek VL53L0X.h, Wire.h, Adafruit_VL53L0X-master, nie wiem czy wrzucenie ich tu to dobry pomysl, te kody to tasiemce. Obawaiam sie ze z mojego poziomu programowania nie jestem z twoich rad wiele wyciagnac, moje programowanie nie polega na zrozumieniu procesow, magistral itd, a raczej modyfikuje przykladowe kody do swoich potrzeb i bez namacalnego przykladu bedzie ciezko dlatego najbardziej przemawia do mnie opcja nr 1 - ale nie znalazlem biblioteki ktrora by miala obsluge takich przerwan, zreszta bez przykladu nawet nie wiedzial bym jak ja obsluzyc. Opcja nr 3 tez odpada bo obecny czujnik odleglosci wybralem ze wzgeldu na wiele innych niezbednych parametrow - wielkosc, montaz, cena itd. Opcja nr 2 tez brzmi niezle ale bez przykladow mam za mala wiedze.

Moj kod jest b.prosty wylaczajac obsluge sterowanika silnika to sam odizolowany kod na odczyt sily magnesu z halla + odczyt odleglosci wyglada tak:

//---------Motor driver
int enablePin = 9;
int directionPin = 8;
int motordir=0;
int motorpower=250;

//------- Distance sensor
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;

void setup()
{
// ----VL53L0X
Serial.begin(9600);
Wire.begin();

sensor.init();
sensor.setTimeout(500);
sensor.startContinuous();
//-------- Hall sensor
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}

void loop()
{
int distance=(sensor.readRangeContinuousMillimeters()); // tu jest problem przestoj 34mils
//------------------------- Hall Sensor
int val = analogRead(A2);
if (val>510 & val<530){
// tutaj kod kiedy pojazd najedzie na magnes o danej sile
}
/* tutaj prowizoryczny kod do sterowania silnikiem
analogWrite(directionPin, motordir);
analogWrite(enablePin, motorpower);
*/
}

stosujac komendy: sensor.setMeasurementTimingBudget(20000);
w trybie single-shot range jestem wstanie zmniejszyc przerwania do 24mils ale to nadal zbyt wiele.

Czy mogl bys napisac fragment kody zebym mial jakikolwiek punkt zaczepienia. W miedzy czasie pozostaje mi lektora programowania.
 
Odpowiedź
#6
Witam
Przykład jest w szkicu "BlinkWithoutDelay".
Dopisz u siebie:
Kod:
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
unsigned long interval = 40;           // interval at which to blink (milliseconds)

void setup() {

}

void loop() {
  unsigned long currentMillis = millis();
 if (currentMillis - previousMillis >= interval) {
   // save the last time you blinked the LED
   previousMillis = currentMillis;
//tu przenies to co ma być wywolywane w odstepie "interval"ms
int distance=(sensor.readRangeContinuousMillimeters()); // tu jest problem przestoj 34mils
 }
//Reszta Twojej pętli

}

Sprawdz czy to cos zmienia w ogóle, potem możesz sobie szukać kolejnych ms. Możesz się pobawić zmniejszyć interval, zmniejszyć timeout  - wtedy gdy nie było odczytu, tylko funkcja zwróci błąd timeout, ustawiasz interval 1 i wracasz do pomiaru za 1ms, jak się udało kolejnym razem to wracasz do bazowego interval, ale w tym czasie jak coś trzeba zrobić to program nie wisi czekając na wynik. Z wykorzystaniem zliczania millis() po prostu zagląda tu co te ustawione 40ms (interval).
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości