Skocz do zawartości

Autonomiczy robot balansujący


lubniewicz

Pomocna odpowiedź

(edytowany)

Jestem już, nie mogłem wcześniej odpisać - obowiązki zawodowe. Robot będzie już stał na ... kołach. Robot będzie trzymał około 0 st. lecz będzie uciekał na boki bo jeszcze nie będzie miał PID prędkości, który będzie zadawał kąt. Pamiętaj, że te nastawy które teraz zrobimy mogę ulec delikatnie zmianie, ponieważ dopiero finalną regulacje zrobi się mając w sumie 3 PID. Więc nie zdziw się jak będziemy musieli jeszcze te nastawy zmienić. Będę mówił w skrócie o poszczególnych członach jako P, I, D. Jak powiem że masz zwiększyć np D to będę miał na myśli zwiększenie "ram_rejestr.p_kd". Proponuje na razie nie zakładać blokady WINDUP. Proponuje jednak aby kontrolować, aby suma błędów nie była za duża. To wyjdzie w regulacji. Ok zaczynamy:

  1. Ustaw kąt zadany na 0st.
  2. Zlikwiduj ograniczenie windup i wyświetlaj po UART jaki masz wynik na całym członie P, I, D oraz suma błędów (osobna dla każdego). Kąta już nie musisz wyświetlać po UART.
  3. Robota postaw pionowo. 
  4. Zwiększaj P aby robot zaczął oscylować w pobliży 0st, mam tutaj na myśli np w granicy od -5st do 5st. Ważne aby oscylował. Trzymaj robota w pionie, dłońmi trzymaj go z tyły i z przodu aby nie pojechał. Robot ma oscylować. Jak będzie oscylował to zmniejsz P tak aby już nie oscylował. To ma być tak na styk. Wiem, że mój opis jest mało dokładny ale lepiej nie umiem tego opisać. Resztę roboty przejmie człon I.
  5. Zwiększaj I aby robot znowu zaczął balansować. Jednocześnie sprawdzaj jaką masz sumę błędu. Nie może być ta wartość za duża. Szczegółowo o tym później napiszę.
  6. Teraz zwiększaj D, aż oscylacje będą mniejsze, krótsze. D można porównać do amortyzatora samochodowego. 
  7. Jak dobrze to ustawisz to robot powinien trzymać około 0 stopni i powoli odjeżdżać w tył lub przód. Mam tutaj na myśli, że może i musi przyspieszać w dany kierunek i ma trzymać około 0st. Nie może oscylować w miejscu ma delikatnie odjeżdżać w tył lub przód.

Jak to zrobisz przejdziemy dalej.   

PS. W żadnym wypadku dane wysłane po UART nie mogą blokować częstotliwości wywołania procesu 10ms. Ja to sprawdzałem na analizatorze stanów logicznych. To jest bardzo ważne. 

Edytowano przez lubniewicz
  • Lubię! 1
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

Witam,

Na wstępie pragnę wszystkich powitać i pogratulować autorowi tego tematu za wykonaną pracę. Trafiłem na ten wątek próbując rozwiązać problem z moim robotem, a raczej upewnić się, że zrobiłem wszytko dobrze.

Aktualnie kończę pracę nad robotem balansującym. W ramach wprowadzenia trochę opiszę konstrukcję i implementację.

Robot napędzany jest silnikami krokowymi + sterowniki A4988. Mikrokrok ustowiony na 1/16. Mikrokontroler - Arduino Leonardo. Do generowania impulsów sterujących wykorzystałem dwa timery sprzętowe 16-bitowe (osobno na każdy silnik). Do sterowania robotem wykorzystałem moduł WiFi ESP8266-E12. Jeśli chodzi o aplikację to na początku próbowałem napisać ją sam, ale z uwagi na ograniczony czas ostatecznie wykorzystałem apkę RoboRemoFree. Robot jest skonfigurowany jako AccessPoint, a komunikacja odbywa się poprzez przesyłanie pakietów UDP. Jeśli chodzi o układ regulacji to zaimplementowałem dwa regulatory w konfiguracji kaskadowej (regulator prędkości i stabilności). Pętla główna programu działa bez użycia opóźnień.

Praktycznie wszystko mam ukończone, ale robot źle znosi nawet niewielkie zakłócenia (lekkie szturchnięcie wyprowadza go z pozycji równowagi). Wykorzystując tylko regulator stabilności robot utrzymuje równowagę w okolicach 0 stopni, ale moim zdaniem rewelacji nie ma. Po dodaniu drugiego regulatora nie radzi sobie wcale. Chciałbym się upewnić, czy jest to tylko kwestia nastaw regulatorów, a nie czasem budowy układu regulacji, czy może czegoś innego?

Dodam jeszcze, że próbując zwiększyć częstotliwość generowania impulsów (prędkość silników) po przekroczeniu pewnej wartości silniki kręcą się w przeciwną stronę. Maksymalna uzyskana prędkość to trochę ponad 1obr/s (jeden obrót, to 3200 kroków), czyli nie ma rewelacji.

Funkcja stworzona do implementacji regulatorów.

float regulatorPID(PID& pid, float zadanaWartosc, float obecnaWartosc, float  deltaT, float kp, float ki, float kd, bool run) {
  
  if (run == false) {	// jesli robot sie przewroci lub nie ma zezwolenia na start
	pid.previousError = 0;	
	pid.errorIntegral = 0; 
  }
  
  pid.error = zadanaWartosc - obecnaWartosc;  
  pid.errorIntegral = pid.errorIntegral + (pid.error * deltaT); // blad czesci calkujacej metoda prostokatow
  pid.errorIntegral = constrain(pid.errorIntegral, -30, 30);  // anti-windup
  pid.errorD = (pid.error - pid.previousError) / deltaT; 
  
  pid.Pout = kp * pid.error;
  pid.Iout = ki * pid.errorIntegral;
  pid.Dout = kd * pid.errorD;

  pid.PIDoutput = pid.Pout + pid.Iout + pid.Dout;
  pid.previousError = pid.error;
  
  return(pid.PIDoutput);
}

  

 

Edytowano przez Borroq
Link do komentarza
Share on other sites

Sprawdzam czas trwania głównej pętli programu. Potem ją przeliczam na okres próbkowania (dt), który wykorzystuję do przekształcenia prędkości kątowej żyroskopu na kąt obrotu (całkowanie) oraz w regulatorach 😉

Procesor to ATmega32U4 -  taktowanie 16MHz

Edytowano przez Borroq
Link do komentarza
Share on other sites

Sprawdzam czas trwania jednego cyklu programu. Za każdym razem wartość ta jest aktualizowana. Na początku pętli głównej obliczam to w ten sposób:

poprzedniCzas = czas;
czas = micros();
czasPetli = czas - poprzedniCzas;
dt = czasPetli / 1000000; // okres probkowania [s]

To moim zdaniem mam dobrze, bo filtr komplementarny działa całkiem nieźle...

Edytowano przez Borroq
Link do komentarza
Share on other sites

A zmienne nie są przepełnione? Ogólnie tutaj jest według mnie zonk. Robisz podstawowy błąd... Zakładasz że dt moze sie zmieniać... Niestety dt musi buc stałe to podstawa. Regulatory ustawiasz pod stale dt. Nie możesz raz ustawic regulator a dt plywa. Według mnie musisz to poprawić, chyba ze chcesz aby to działało tak sobie... Ps. Zmien to. Daj stale dt poprzez zastosowanie timeroe programowych lub sprzętowy. Dobrze ze wyliczas dt ale niestety to musi być stale. 

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