Skocz do zawartości
Komentator

Kurs Arduino - #5 - PWM, serwomechanizmy, biblioteki

Pomocna odpowiedź

MrauMrauChan, witam na forum 🙂 Czy używasz serwomechanizmu z naszego zestawu? Pytam, ponieważ nie widzę, abyś miał zarejestrowany zestaw do tego kursu. Wygląda na to, że posiadasz inną wersję silnika, niż ta, która jest opisana w kursie. Jeśli pochodzi ona z zestawu, to zgłoś się do Botlandu w celu wymiany 🙂

Udostępnij ten post


Link to post
Share on other sites

Przedstawiam mój projekt z wykorzystaniem serwomechanizmu. Wiem, że nie działa idealnie ale być może oda mi się to niedługo zmienić, jak tylko poznam tajniki regulatora PID od strony programowej. Chociaż w tym programie można dopatrzyć się członu proporcjonalnego i różniczkującego.

Zadaniem poniższego projektu jest przywracanie kulki łożyska toczącej się po torze do pozycji okołośrodkowej. Do konstrukcji projektu wykorzystano zamiennik Arduino R3 Uno oraz serwomechanizm MG995.

Zasada działania:

Kulka łożyska toczy się po torze wykonanym z profilu aluminiowego i ścieżki rezystancyjnej pozyskanej ze złomu przetwornika rezystancyjnego 10kΩ. Do końcówek ścieżki rezystancyjnej przyłożono napięcie zasialania Arduino zaś przewód zamocowany do profilu wyprowadzono na wyjscie ADC mikrokontrolera .

Koniecznym było zastosowanie filtra RC ponieważ ze względu na niewielką powierzchnię styku kulki i toru oraz chropowatość powierzchni kulka często traciła kontakt z podłożem co skutkowało pojawieniem się zakłóceń. Dodatkowo filtr programowy wygładza zakłócenia spowodowane drganiami pochodzącymi od działającego serwomechanizmu.

Zmiany dzielnika napięcia określają położenie kulki na torze. Odpowiednie wychylenie ramienia serwomechanizmu uzależnione jest od akutalnego położenia kulki.

Wartości oraz przedziały wartości dla zmiennych:
 

pozycja; // Wychylenie ramienia serwomechanizmu w stopniach w momencie zatrzymania się kulki.

int i; // Zmienna służąca do przełączania trybów pracy stabilizatora:

//0= tryb pracy

//1= poziomowanie ręczne

//ZMIENNE DOTYCZĄCE POMIARU NAPIĘCIA--------------------------------------------------------------------------------

int wartosc_dzielnika_bez_filtru; // Wartość dzielnika napięcia zmieniająca się wraz z ruchem kulki po torze.

int poziomowanie_reczne; // Zmienna służąca do ręcznego ustawienia zmiennej pozycja; // Różnica napięć w momencie wyhamowania kulki.

int tlumienie; // Parametr dodawany do zmiennej pozycja_hamowania. Pozwala na sprawniejsze wyhamowanie kulki w czasie powrotu do pozycji okołosrodkowej.

int delta_przedzial_wartosc_srodkowa; // Przyrost zmiennej przedzial_wartosci_srodkowej. Pozwala na sprawniejsze wyhamowanie kulki w czasie powrotu do pozycji okołosrodkowej.

void setup()

{

Serial.begin(9600); // Zezwolenie na transmisję danych przez UART.

serwo.attach(9); // Przypisanie pinu 9 do serwomechanizmu.

serwo.write(pozycja=pozycja=0;

delta_przedzial_wartosc_srodkowa=0;

}

if((roznica_napiec>przedzial_wartosci_srodkowej)&& przyrost>0) //Kulka przemieszcza się po prawej połowie równi, od środka do prawej.

{

pozycja= map(roznica_napiec,0,max_roznica_napiec,pozycja=roznica_napiec; // Miejsce, w którym kulka zatrzymuje się.

tlumienie=map(roznica_napiec,przedzial_wartosci_srodkowej,max_roznica_napiec,0,16); // Tłumienie zwiększa wychylenie ramienia przy hamowaniu kulki. Im dalej od środka zatrzyma się kulka, tym większe tłumienie.

delta_przedzial_wartosc_srodkowa=map(abs(roznica_napiec_kulka_stop),przedzial_wartosci_srodkowej,max_roznica_napiec,10,50); // Określenie wartości chwilowego poszerzenia przedziału środkowego

pozycja_stop=pozycja; // Położenie ramienia serwomechanizmu w momencie zatrzymania kulki.

serwo.write(pozycja); // Ustawienie nowej pozycji.

}

if((roznica_napiec>przedzial_wartosci_srodkowej)&&przyrost<0) //Kulka przemieszcza się po prawej połowie równi, od prawej do środka.

{

pozycja= map(roznica_napiec,przedzial_wartosci_srodkowej+delta_przedzial_wartosc_srodkowa,roznica_napiec_kulka_stop,pozycja_hamowania-tlumienie,pozycja_stop);

serwo.write(pozycja); // Ustawienie nowej pozycji.

if(roznica_napiec<(przedzial_wartosci_srodkowej+delta_przedzial_wartosc_srodkowa)){serwo.write(pozycja=roznica_napiec; // Miejsce, w którym kulka zatrzymuje się.

tlumienie=map(roznica_napiec,-przedzial_wartosci_srodkowej,-max_roznica_napiec,0,14 ); // Tłumienie zwiększa wychylenie ramienia przy hamowaniu kulki. Im dalej od środka zatrzyma się kulka, tym większe tłumienie.

delta_przedzial_wartosc_srodkowa=map(abs(roznica_napiec_kulka_stop),przedzial_wartosci_srodkowej,max_roznica_napiec,10,50); // Określenie wartości chwilowego poszerzenia przedziału środkowego

pozycja_stop=pozycja; // Położenie ramienia serwomechanizmu w momencie zatrzymania kulki.

serwo.write(pozycja); // Ustawienie nowej pozycji.

}

if((roznica_napiec<-przedzial_wartosci_srodkowej)&&przyrost>0) //Kulka przemieszcza się po lewej połowie równi, od lewej do środka.

{

pozycja= map(roznica_napiec,-przedzial_wartosci_srodkowej-delta_przedzial_wartosc_srodkowa,roznica_napiec_kulka_stop,pozycja_hamowania+tlumienie,pozycja_stop);

serwo.write(pozycja); // Ustawienie nowej pozycji.

if(roznica_napiec>(-przedzial_wartosci_srodkowej-delta_przedzial_wartosc_srodkowa)){serwo.write(pozycja_startowa_serwomechanizmu);};

}

roznica_napiec_poprzednia=roznica_napiec; // Ustawienie aktualnej wartości zmiennej roznica_napiec jako wartości poprzedniej w celu porównania jej z nową wartością w następnym przebiegu programu.

}

void przycisk_wcisniety (void)

{

if (digitalRead(przycisk)==LOW) // Zmiana wartości zmiennej i w wyniku reakcji na naciśnięcie przycisku menu.

{

delay (80); // Filtrowanie "drgania styków" przycisku.

if (digitalRead(przycisk)==LOW)

{i++;

digitalWrite(13,HIGH); // Sygnalizacja wciśniętego przycisku zapaleniem wbudowanego w arduino led

}

if(i==2){i=0;digitalWrite(13,LOW);}

}

}

 

Udostępnij ten post


Link to post
Share on other sites

Samo dodanie #include nie działało u mnie (Arduino IDE 1.8.5). Trzeba było wejść w Sketch -> Include library-> Manage Libraries i zainstalować biblitekę Servo. Można też wspomnieć o tym w artykule.

Udostępnij ten post


Link to post
Share on other sites

noniwoo, dzięki za sugestię sprawdzę temat - do tej pory biblioteka ta była cały czas domyślnie dostępna 🙂

Udostępnij ten post


Link to post
Share on other sites

Jak mam rozumieć to, ze w przypadku ustawienia wypelnienia na minusie dioda też się świeci?

int wypelnienie = 0;
int zmiana = 5;

void setup(){
 pinMode(3, OUTPUT);
 Serial.begin(9600);
}

void loop() {
 wypelnienie = 0;

 while (wypelnienie < 255) {
 wypelnienie = wypelnienie + zmiana;
 analogWrite(3, wypelnienie);
 delay(50);
 Serial.println(wypelnienie);
 }

 while (wypelnienie >= 0) {
 wypelnienie = wypelnienie - zmiana;
 analogWrite(3, wypelnienie);
 delay(50);
 Serial.println(wypelnienie);
 }
}

Napisałem tak program robiąc mały błąd i zdziwiło mnie to, że gdy wypelnienie jest na minusie to dioda też świeci...jak mam to rozumieć? Na pewno nie ma tam napięcia ujemnego gdyż dioda przewodzi w jednym kierunku

Udostępnij ten post


Link to post
Share on other sites

To w ogóle nie jest związane z żadnymi napięciami. Przede wszystkim przeczytaj jak działa funkcja analogWrite():

https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/

i generalnie staraj się korzystać z opisów funkcji z jakich korzystasz w programie.

W takim razie (minęło 5 minut i już przeczytałeś) wiesz, że analogWrite() wypuszcza na pin procesora sygnał prostokątny miotający się między 0 a 5V. Dioda LED zapala się bardzo szybko i tak samo szybko gaśnie, ale Twoje oko tego nie widzi. Uśrednia sobie za to jasność mrugającej bardzo szybko diody i im dłużej ona świeci w stosunku do zgaszenia - tym wydaje się jaśniejsza.

A teraz dlaczego minus także ją zapala? Arytmetyka procesora pracuje na kombinacjach bitów i tylko od naszej umowy zależy jak te kombinacje rozumiemy. W tym szczególnym przypadku zmienna "wypełnienie" ma typ int, czyli jest 16 bitami które reprezentują liczby dziesiętne od -32768 do +32767. Z kolei fnkcja analogWrite() potrzebuje liczby 8-bitowej bez znaku (czyli tylko dodatniej) w zakresie 0 do +255.

Tutaj musisz koniecznie poczytać o tzw. kodzie uzupełnieniowym do 2, np:

http://www.algorytm.edu.pl/systemy-liczbowe/u2.html

Kompilator musiał dokonać konwersji Twojego int-a na to czego potrzebuje funkcja analogWrite() i zrobił to bez Twojego udziału. Niemniej jednak właśnie z takich powodów jak Twój kod warto wiedzieć i rozumieć działanie typów zmiennych i ich wzajemnych relacji czy sposobów konwersji.

I tak przykładowo (możesz to wszystko sprawdzić na kalkulatorze Windows):

- weźmy liczbę -123

- ta wartość przedstawiona jako 16 bitów w kodzie U2 wygląda tak: 1111111110000101 i tak wygląda w pamięci RAMi procesora (gdzie podzielona jest na 8-bitowe bajty: 11111111 i 10000101, ale to nie ma tutaj znaczenia)

- kompilator nie może 16 bitów "wepchnąć" do funkcji biorącej tylko 8 bitów więc obcina te bardziej znaczące zostawiając 10000101

- ta z kolei wartość, interpretowana w analogWrite() jako liczba bez znaku ma wartość dziesiętną 133 i takie wypełnienie (czyli 133/256) dostanie dioda LED.

Czy to jakoś wyjaśnia?

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

Cześć,

Mam pytanie do zadania 5.1

#define led 5

int wypelnienie = 0;                                     
int zmiana = 10;                                       

void setup() {

 pinMode (led, OUTPUT);
 Serial.begin (9600);
}

void loop() {

while (wypelnienie < (255 - zmiana))                                  // gorny zakres wypelnienia musi byc mniejsza o wartosc jednostek wypelnienia (np. 255-10 = 244)
 {                                                                    // jezeli tego nie zrobimy wartosc wypelnienia wyskoczy poza zakres i lampka w trakcie przelaczania miga

   analogWrite (led, wypelnienie);
   wypelnienie = wypelnienie + zmiana;
   Serial.println (wypelnienie);
   delay (25);

 }
  while (wypelnienie > (0 + zmiana))                               // dolny zakres wypelnienia musi byc wiekszy o wartosc wypelnienia (np. 0 + 10 = 10)
   {                                                                 // tak samo jak w gornym zakresie
     analogWrite (led, wypelnienie);
     wypelnienie = wypelnienie -= zmiana;
     Serial.println(wypelnienie);
     delay (25);   
   }
}

Chodzi o to czy mają sens obliczenia w warunkach pętli. Są po to, że jeżeli w wartość wypełnienia wpiszemy wartość dowolną (np. 10) to nie wychodzi z zakresu (0-255 - powoduje to mignięcie LED'a), ale jednak zmniejszam zakres, za to zmiana jasności diody jest płynna.

Udostępnij ten post


Link to post
Share on other sites

ShaneXXII, witam na forum!

Można tak robić. Trzeba tylko uważać, aby przypadkiem nie zrobić sobie jakiejś pułapki (typu warunek, którego nie da się nigdy spełnić itd).

Udostępnij ten post


Link to post
Share on other sites

Witam. Czy istnieje możliwość sterowania serwomechanizmem z wyjścia cyfrowego? Mam na myśli czy podanie 5v na wejście sygnału PWM spowoduje wychylenie serva w jedno skarjne położenie a tym samym umożliwi prostą pracę w trybie on/off?

Udostępnij ten post


Link to post
Share on other sites

@chillforever, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.
47 minut temu, chillforever napisał:

Mam na myśli czy podanie 5v na wejście sygnału PWM spowoduje wychylenie serva w jedno skarjne położenie a tym samym umożliwi prostą pracę w trybie on/off?

Nie, niestety tak to nie działa. Jednak jeśli nie potrzebujesz sterować serwem przez Arduino to możesz sobie zbudować np. prosty sterownik na NE555. Przykład: Kurs elektroniki II – #9 – czujnik przeszkód, sterownik serwa. Jeśli zastąpisz potencjometr z tamtego projektu odpowiednimi rezystorami to uzyskasz efekt, w którym włączenie układu ustawi serwo w konkretnej pozycji 🙂

Udostępnij ten post


Link to post
Share on other sites

Cześć, 

Specjalnie kupiłem zestaw z botlandu pod ten kurs a w nim nie ma dwoch kondenstatorów takiej samej pojemności. 

Nie, mówie, że to jest problem nie do przejścia tylko szkoda, że w tak drogim zestawie nie ma wystarczającej liczby potrzebnych materiałów do przejścia kursu pozdrawiam.

Udostępnij ten post


Link to post
Share on other sites

@grzes003, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.

15 godzin temu, grzes003 napisał:

Specjalnie kupiłem zestaw z botlandu pod ten kurs a w nim nie ma dwoch kondenstatorów takiej samej pojemności. 

Zakładam, że piszesz o kondensatorach podłączanych do stabilizatora? Temat przewijał się już tutaj kilka razy - w skrócie: nie ma potrzeby podpinać tam aż 4 kondensatorów (2 ceramiczne i 2 elektrolityczne). Jeśli dobrze pamiętam, to tutaj pokazany jest schemat w "maksymalnej" wersji, ale w praktyce jak się nie doda tych kondensatorów to wszystko również działa poprawnie. Wystarczy jeden elektrolit i jeden ceramiczny. Sprawdzę ten temat i naniosę poprawkę, aby nie wprowadzało to w błąd. Jeśli będziesz miał problem z działaniem układu to daj mi znać przez prywatną wiadomość - mogę do Ciebie wysłać dodatkowe kondensatory. Nie ma żadnego problemu 🙂

Udostępnij ten post


Link to post
Share on other sites

Witam. Mam taki problem z serwo zakupionym z zestawem startowym (redox s90). Gdy ustawiam na nim wartość 0 to on jakby ciągle pracuje chcąc się przekręcić jeszcze trochę. Natomiast jak ustawiam 180 jest ok, ale w sumie ustawienie pozycji np 175 jest taka sama jak dla 180. Na reszcie pośrednich pracuje dobrze. Przyjmuje pozycję i generalnie jej nie poprawia. Czy to może oznaczać, że servo jest uszkodzony? 

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!

Gość
Dołącz do dyskusji! Kliknij, aby zacząć 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...