Skocz do zawartości

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
  • 2 tygodnie później...

Aktualnie troszkę ciężko z czasem, ale wykonuję aplikacje na PC w celu zadawania wartości poszczególnym członom PID + przygotowanie pod sterowanie .... będę informował jak wykonam ten krok 😉

  • 4 miesiące później...
(edytowany)

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

Będę dociekliwy i upierdliwy 😋. Skąd wiesz ze jest taka częstotliwość? Jakie taktowanie procka? Czy robiłeś te pomiary na analizatorze stanow logicznych? 

  • Lubię! 1
(edytowany)

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

Jak sprawdzasz? Sorry muszę być pewny że robisz to dobrze. Te czasy sa bardzo ważne, musze miec 200%pewności. Nie napisałeś taktowania. Pamietaj ze float obciąża atmege. Konkretnie odpowiadaj 😄

  • Lubię! 1
(edytowany)

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

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

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