Skocz do zawartości
BuxBleed

Sterowanie silnikami krokowymi przez BlueTooth z użyciem żyroskopu w telefonie

Pomocna odpowiedź

Cześć, mam problem z obmyśleniem algorytmu sterowania różnicowego do silników krokowych opartych na sterowniku DRV8825. Chodzi o to żeby korzystając z aplikacji, na androida wykorzystującej żyroskop i akcelerometr w telefonie sterować robotem. Apkę napiszę w android studio w języku Java, bo tak chyba jest najłatwiej.

Jak w ogóle zabrać się za coś takiego ? Póki co to wiem jak ruszać robotem do przodu i do tyłu :/

Udostępnij ten post


Link to post
Share on other sites

Rozbij to sobie na mniejsze zadania. Zapomnij na razie o bluetooth, telefonie i akcelerometrach i skoncentruj się na sterowaniu samym robotem — a najpierw samym silnikiem.

Skoro potrafisz ruszać robotem do przodu i do tyłu, to wnioskuję, że kod poruszający tymi silnikami krokowymi z zadanymi szybkościami już masz? Jeśli tak, to nie obchodzi cię już jaki tam jest sterownik dokładnie, od tego momentu operujesz już tylko na szybkościach.

Znasz wymiary swojego robota, więc łatwo możesz policzyć o ile musi się przesunąć jedno koło względem drugiego, żeby robot obrócił się o dany kąt. Droga przejechana zależy od szybkości i czasu — chyba pamiętasz z fizyki? No to powinieneś móc łatwo policzyć z jakimi prędkościami i przez jaki czas te koła muszą się obracać żeby wykonać zadany skręt. Znasz do tego prędkość środka pojazdu, więc z łatwością możesz uzyskać zadany promień skrętu przy danej prędkości — to jest prosta trygonometria.

Jak już będziesz mieć to ogarnięte, to możesz wymyślić jak w swojej aplikacji na telefonie obliczać te dwie wartości na podstawie tego jak sobie wymyśliłeś to sterowanie. Wysyłasz to do robota, robot cały czas czeka na nowe wartości i ustawia prędkości silników zgodnie z nimi.

Udostępnij ten post


Link to post
Share on other sites

No nie do końca, tak to wygląda. Po pierwsze bardzo bym chciał żeby środek ciężkości pokrywał się ze środkiem geometrycznym robota ale z przyczyn konstrukcyjnych jest to nie możliwe.

Powiedziałbym że jest najbardziej jak tylko się da, można oczywiście obciążyć go dodatkowymi obciążnikami aby tak było.

Czyli rozumiem że jak steruje sobie silnikami krokowymi o rozdzielczości 200 kroków, na driverze jest ustawiona rozdzielczoścć 1/32 kroku czyli najmniejszy kąt o jaki może obrócić się koło wynosi 360/(200*32) = 0,05625 stopnia. Promień koła wynosi 40mm czyli ze wzoru na długość łuku koła liczę sobie że przy zadanym kroku podanie jednego impulsu przesuwa robota o 0,03925mm.

Czas podawania impulsu mogę sobie obrać dowolny podając go w funkcji delay() i z niego sobie jakoś wyliczam tą prędkość. Wszystkie obliczenia zakładają, że silnik nie gubi kroków.

I potem staram się jakoś to przełożyć na sam kod tak żeby robot robił to co chce tak ?

Udostępnij ten post


Link to post
Share on other sites

Tak. Przy czym środek ciężkości jest nieistotny — w twoim przypadku liczy się środek pomiędzy dwoma napędzanymi kołami.

Udostępnij ten post


Link to post
Share on other sites

No okej opanowałem trochę popisałem i policzyłem.

Udało mi się sterować robotem za pomocą pewnego rodzaju komend:

Znak 'f' lub 'F' Forward - robot jedzie do przodu o ileś tam centymetrów

Znak 'b' lub 'B' Backwards - robot jedzie do tyłu o ileś tam centymetrów

Znak 'r' lub 'R' Right - robot obraca się w prawo, w miejscu o 90 stopni

Znak 'l' lub 'L' Left- robot obraca się w lewo, w miejscu o 90 stopni

Znak 'o' lub 'O' obrót, literka r od rotate była zajęta - robot obraca się o 180 stopni

No i podając przez terminal ciąg znaków dajmy na to "fbflro" robot wykonuje zadaną sekwencję ruchów.

Dalej nie wiem co zrobić żeby to sterowanie nie było takie "sztywne" i umożliwiało bardziej swobodną kontrole nad robotem.

Udostępnij ten post


Link to post
Share on other sites

Zrób sobie dwie zmienne globalne: prędkość i promień skrętu (albo po prostu prędkości tych dwóch silników), i zrób tak, żeby robot jechał cały czas według ich wartości. Teraz periodycznie sprawdzaj komendy, jedna do zmiany prędkości, druga do zmiany promienia skrętu.

Udostępnij ten post


Link to post
Share on other sites

Ja akurat operowałem na impulsach, policzyłem sobie że 1 impuls to 0.03925 mm drogi pokonanej przez robota i obrót o ok 0.02 stopnia względem drugiego koła. I teraz sobie operuje na tych wartościach.

Zbocze narastające podaje na silnik co 0.1ms i to jest stałą wartością.

Udostępnij ten post


Link to post
Share on other sites

Po wielu dniach ciężkiej walki ogarnąłem mniej więcej ten problem. Steruje robotem za pomocą akcelerometru w telefonie, napisałem do tego aplikację w App Inventorze.

Robot działa na silnikach krokowych sterowanych układem DRV8825

Mam jednak problem w odpowiednim odczytywaniu danych z akcelerometru. Pokręciłem sobie swoim telefonem w w każdy możliwy sposób i rozpisałem przedziały wartości jakie przyjmują odpowiednio współrzędne xyz po poszczególnych rotacjach.

No i nie działa 😥

Robot reaguje na odczyt z akcelerometru no ale, świruje, zachowuje się nieprzewidywalnie i czasami w ogóle nie reaguje :/

Kod robota:


#define L_DIR 2 
#define R_DIR 3
#define L_STEP 9
#define R_STEP 8      //definicje pinów STEP i DIR na sterowniku DRV8825


void forward();
void backwards();
void right();
void left();


void setup()
{ 
 Serial.begin(9600);
 pinMode(L_STEP, OUTPUT);  
 pinMode(R_STEP, OUTPUT);
 digitalWrite(L_STEP,LOW);
 digitalWrite(R_STEP,LOW);
 digitalWrite(L_DIR,LOW);
 digitalWrite(R_DIR,HIGH);
 delay(1);
} 

void forward()
{
 digitalWrite(L_DIR,LOW);
 digitalWrite(R_DIR,HIGH);
 for(int i = 0 ; i<500; i++)
 {
   delayMicroseconds(50);
   digitalWrite(L_STEP,LOW);     // sterowanie obydwoma silnikami poprzez podanie im impulsu co 500us
   digitalWrite(R_STEP,LOW);
   delayMicroseconds(50);
   digitalWrite(L_STEP,HIGH);
   digitalWrite(R_STEP,HIGH);
 }
 return;
}

void backwards()
{
 digitalWrite(L_DIR,HIGH);
 digitalWrite(R_DIR,LOW);
 for(int i = 0 ; i<500; i++)
 {
   delayMicroseconds(50);
   digitalWrite(L_STEP,LOW);     // sterowanie obydwoma silnikami poprzez podanie im impulsu co 500us
   digitalWrite(R_STEP,LOW);
   delayMicroseconds(50);
   digitalWrite(L_STEP,HIGH);
   digitalWrite(R_STEP,HIGH);
 }
 return;
}
void left()
{
 digitalWrite(L_DIR,HIGH);
 digitalWrite(R_DIR,HIGH);
 for(int i = 0 ; i<500; i++)
 {
   delayMicroseconds(50);
   digitalWrite(L_STEP,LOW);
   digitalWrite(R_STEP,LOW);
   delayMicroseconds(50);
   digitalWrite(L_STEP,HIGH);
   digitalWrite(R_STEP,HIGH);
 }
 return;
}

void right()
{
 digitalWrite(L_DIR,LOW);
 digitalWrite(R_DIR,LOW);
 for(int i = 0 ; i<500; i++)
 {
   delayMicroseconds(50);
   digitalWrite(L_STEP,LOW);
   digitalWrite(R_STEP,LOW);
   delayMicroseconds(50);
   digitalWrite(L_STEP,HIGH);
   digitalWrite(R_STEP,HIGH);
 }
 return;
}


void loop() 
{ 
  if (Serial.available()>0)      
 {
   char data;
   data = (char)Serial.read(); 
   switch(data)
   {
     case 'w':
       forward();
       break;
     case 's':
       backwards();
       break;  
     case 'l':
       left();
       break;  
     case 'r':
       right();
       break;    
   }
 }
} 

Schemat programu:

Udostępnij ten post


Link to post
Share on other sites

Trudno mi jest odpowiedzieć na problem opisany jako "świruje". Może możesz jakoś podejrzeć co do tego robota rzeczywiście wysyłasz?

Udostępnij ten post


Link to post
Share on other sites

W tym pierwszym dużym ifie masz

... get zAccel >=1 and get zAccel >= 9

Czy na pewno tak to ma wyglądać? Jeśli tak, to porównywanie z 1 możesz usunąć.

Udostępnij ten post


Link to post
Share on other sites

Tak, masz rację powinno to wyglądać z>= 1 && z <= 9. Po tej poprawce robot zdaje się poruszać mniej chaotycznie, jednak jest to wciąż dalekie od perfekcji.

No mógłbym w zasadzie wypisywać to co wysyłam poniżej w jakimś TextBoxie i go aktualizować co jakiś czas używając Timera, albo też robot mógłby przesyłać informację zwrotną wysyłając natychmiast to co otrzymał.

Udostępnij ten post


Link to post
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...