Skocz do zawartości
Komentator

Kurs Arduino - #5 - PWM, serwomechanizmy, biblioteki

Pomocna odpowiedź

22 godziny temu, Treker napisał:

Dla pewności - chodzi Ci o zmianę położenia serwa o mniej niż "41" jednostek, a nie o ustawienie serwa na pozycji z zakresu 0-41?

Tak, jak zmieniam położenie serwa o mniej niż 41 jednostek to zachowuje się dziwnie. W zakresie 0-41 niby działa, ale przy poniższym programie rusza się tylko w obie strony o niecałe 20 stopni. Usłyszałem również, że z czasem zaczyna wydawać coraz to różne dźwięki podczas pracy.. Tak jakby się męczył?

void loop() 
{  
 serwomechanizm.write(60);
 delay(2000); 
 serwomechanizm.write(20);
 delay(2000);
}

 

Udostępnij ten post


Link to post
Share on other sites

Sprawdź dla pewności czy taki sam problem występuje trochę "dalej" tzn. spróbuj np. zmienić pozycję ze 100 na 120. Jeśli tak będzie to widocznie trafiło Ci się serwo z jakąś dziwną wadą fabryczną (jeszcze takiej tutaj nikt nie zgłaszał), zgłoś wtedy reklamację w Botlandzie 😉

Udostępnij ten post


Link to post
Share on other sites

Aha no i teraz jak znowu zacząłem go używać to zakres maksymalnego wychylenia się zmniejszył. Przy pierwszym użyciu (wczoraj)  gdy podawałem mu 180 obracał się o jakieś 170, a teraz względem jakiegoś tam wybranego zera gdy podam mu 180 przemieszcza się tylko o około 135 stopni.

Jak rozkazuje mu zmienić 0 -> 100 -> 120 to dostaje 0 -> 70 -> 90 (około). Bardzo możliwe, że wada fabryczna.

 

Udostępnij ten post


Link to post
Share on other sites

Moje serwo nie może wychylić się maksymalnie do 180 stopni, ani przy automatycznym naliczaniu do 180, ani nawet jeśli ręcznie wpiszę tą wartość. Jakaś wada konstrukcyjna? 

Tą pozycję którą zaznaczyłem strzałką serwo uznaje za 180 st. i wraca do pozycji zerowej.

IMG_20191006_100107.jpg InkedIMG_20191006_100117_LI.jpg

Udostępnij ten post


Link to post
Share on other sites

@husadam5 tak właściwie te 180* jest trochę umowne (szczególnie w przypadku małych napędów tego typu). Serwa głównie działają w trochę mniejszym zakresie, ale większość dochodzi do 180*. Są jednak takie egzemplarze, które w związku z ułożeniem potencjometru/zębatek nie osiągają tak szerokiego zakresu ruchów, ale nie nazwałbym tego wadą konstrukcyjną. Jeśli chcesz wykorzystywać serwomechanizm w zastosowaniu, które wymaga pełnych 180* to możesz napisać do sklepu z prośbą o wymianę. Jeśli nie jest to dla Ciebie kluczowe to możesz śmiało korzystać z tego serwa, bo powinno działać poprawnie 🙂

Udostępnij ten post


Link to post
Share on other sites

Witam,

Rozpocząłem budowę swojego pierwszego projektu, ale muszę wrócić do rozdziału o serwomechanizmach. Zaobserwowałem, że serwo, nawet jeśli ustawię je w stałej pozycji (już w sekcji "setup") przez cały czas "pomrukuje" próbując korygować pozycję (chyba, ruch nie jest widoczny). Czasem, jeśli przyłożę do ramienia bardzo niewielką siłę i "pomogę" mu w ten sposób ustawić położenie docelowe to uspokaja się na kilka minut, po czym znowu wraca do korekt. Moje pytanie jest proste - czy to normalne? Czy można to zignorować? Z pewnością przyspiesza to zużycie baterii ale przypuszczam, że wynika to z zasady działania (utrzymywanie pozycji w zależności od współczynnika wypełnienia sygnału.... Z góry dziękuję za komentarze.

Udostępnij ten post


Link to post
Share on other sites

Spróbuj trochę zwiększyć lub zmniejszyć okres sygnału dla serwa. Ponieważ taktowanie taktowaniu nierówne ze względu na rozrzuty produkcyjne i warunki pracy czasami trzeba kompensować różne odchylenia od normy. Serwa na ogół mają dużą tolerancję dla częstotliwości ale czasami i to za mało. Zdarzały mi się takie przypadki jak Twój i przeważnie pomagała delikatna korekta częstotliwości sygnału.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Na początku pliku Servo.h masz kilka definów, może poeksperymentuj z REFRESH_INTERVAL:

#define Servo_VERSION           2     // software version of this library

#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo  
#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo 
#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
#define REFRESH_INTERVAL    20000     // minumim time to refresh servos in microseconds 

#define SERVOS_PER_TIMER       12     // the maximum number of servos controlled by one timer 
#define MAX_SERVOS   (_Nbr_16timers  * SERVOS_PER_TIMER)

#define INVALID_SERVO         255     // flag indicating an invalid servo index

#if !defined(ARDUINO_ARCH_STM32F4)

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

zadanie domowe 5.5

 

czy da się to zrobić prościej z zachowaniem jeszcze lepszej wydajności dla programu?

 

#include <Servo.h> //biblioteka serwa

Servo serwomechanizm;
int pozycja=0; // pozycja serwa 0-180
int potencjometr=0;


void setup(){
  Serial.begin(9600);
  serwomechanizm.attach(9);//serwo podlaczone do pinu 9
}

void loop(){
  serwomechanizm.write(pozycja);
    potencjometr=analogRead(A1);
 pozycja = map(potencjometr,0,1023,0,180);
    Serial.print(potencjometr);
Serial.print("   ");
  Serial.println(pozycja);
  delay(50);
}

 

Zadanie domowe 5.4

czy da się to zrobić prościej z zachowaniem jeszcze lepszej wydajności dla programu?

#include<Servo.h>

Servo serwo;
int pozycja=0;
String dane=("");
int danee=0;
bool flaga=0;

void setup(){
  Serial.begin(9600);
  serwo.attach(9);
  
}

void loop(){

  danee=dane.toInt(); //konwersja danych na INT

  if (Serial.available()>0){
    
    dane=Serial.readStringUntil('\n');
  }
  
  
  if(danee<=180 && danee>=0){
      serwo.write(danee); // ustawienie serwa na daną cyfrę z zakresu 0-180
  	  flaga=0;
  } else if (flaga==0){
    Serial.println("podaj dane z zakresu 0-180");
    flaga=1;
  }
  
 
  
  delay(50);
}

 

Edytowano przez bakardi92

Udostępnij ten post


Link to post
Share on other sites

@bakardi92 w przypadku pierwszego programu dobrze byłoby dla formalności poprawić kolejność wykonywanych instrukcji. Najpierw odczytujesz wartość z potencjometru i ją mapujesz, a później ustawiasz odpowiednio serwomechanizm. W tej chwili działa to trochę inaczej. W praktyce różnicy raczej nie zobaczysz, ale dobrze byłoby zadbać o logiczny ciąg programu 🙂

W drugim programie analogicznie - też warto popracować nad kolejnością. Do tego zastanów się czy jest sens, aby np. poniższa linijka wykonywała się w każdym obiegu pętli:

danee=dane.toInt(); //konwersja danych na INT

Udostępnij ten post


Link to post
Share on other sites
18 godzin temu, Treker napisał:

@bakardi92 w przypadku pierwszego programu dobrze byłoby dla formalności poprawić kolejność wykonywanych instrukcji. Najpierw odczytujesz wartość z potencjometru i ją mapujesz, a później ustawiasz odpowiednio serwomechanizm. W tej chwili działa to trochę inaczej. W praktyce różnicy raczej nie zobaczysz, ale dobrze byłoby zadbać o logiczny ciąg programu 🙂

W drugim programie analogicznie - też warto popracować nad kolejnością. Do tego zastanów się czy jest sens, aby np. poniższa linijka wykonywała się w każdym obiegu pętli:


danee=dane.toInt(); //konwersja danych na INT

W sumie nie ma sensu, masz rację trzeba by to wrzucić do pętli IF która zbiera dane z portu szeregowego. Dzięki że wspominasz o takich szczegółach. Na pewno przy pisaniu bardziej skomplikowanych programów taki zapis będzie miał już większe znaczenie niż ma teraz, ale warto się uczyć dobrych nawyków programowania jak najszybciej. Jeszcz raz dzięki 🙂

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@bakardi92 powodzenia podczas kolejnych ćwiczeń 🙂

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Witam serdecznie,

Mam pytanie do zadania 5.4. Napisałem taki oto kod:

#include <Servo.h>              //biblioteka do sterowania serwo

Servo serwo;                   //dodanie serwo jako zmiennej servo
String zakres="";
int zakres_int=0;

void setup() {
serwo.attach(10);               //serwo na 10 pinie
Serial.begin(9600);
Serial.println("Podaj o ile stopni przesunąć serwo.");
Serial.println("Możesz wybrać z zakresu 1-180 stopni.");
}

void loop() {
  zakres=Serial.readStringUntil('\n');
  zakres_int=zakres.toInt();


  if (zakres_int>0 && zakres_int<=180){                       //jeśli wpiszemy liczbe 1-180 to serwo
   serwo.write(zakres_int);                                  //powinno się o tyle przesunąć
   Serial.println("Przesuniesz serwo o "+zakres+" stopni.");
   delay(50);
}

  if (zakres_int<0 || zakres_int>180){                       //jeśli wpiszemy inną liczbę to wyświetli napis
   serwo.write(90);
   Serial.println("Zła wartość. Można podać przesunięcie w zakresie 0-180 stopni.");
   delay(50);
}
}

I generalnie wszystko niby działa, ale nie wiem dlaczego przy wpisywaniu kolejnych liczb serwo dziwnie się zachowuje. Np. jeśli wpiszę 50 to odchyli się o ok. 50°, ale jak zaraz po tym wpiszę 60 to odchylenie jest bardzo małe (wątpię, żeby miało nawet 30°). Podobnie, gdy wpiszę 90 to odchyla się tak samo jak wpisałbym 180. I trzecia rzecz- po wpisaniu dwa razy pod rząd tej samej wielkości nie reaguje, tzn. np. przy wpisaniu 80 odchyla się, ale po ponownym wpisaniu 80 już nie reaguje w ogóle. Dopiero po wpisaniu innej wartości się przesuwa. Czy to może być związane z samym serwem (napięcia są ok, pomierzyłem baterię (9V) i napięcie po stabilizatorze (5V), a zasilam serwo z wyjścia Vin. Kondensatory są również na swoim miejscu) ? Czy coś jest nie tak w programie?

Dodam, że używane przeze mnie serwo to to z Botlandu dołączone do zestawu z Arduino (SG-90-micro).

Pozdrawiam serdecznie 🙂

Edytowano przez Scorpo

Udostępnij ten post


Link to post
Share on other sites

No ale przecież funkcja serwo.write(N) nie przesuwa wału serwa "o N stopni" tylko ustawia wał w bezwzględnym położeniu "N stopni". Zatem jeśli każesz mu się ustawić w położeniu 50 to jedzie (gdziekolwiek akurat jest) do 50, potem dajesz 60 to podjeżdża o 10. Jeśli zapodasz 90 to ustawi się mniej więcej w połowie a kolejne 90 już nic nie da, bo przecież serwo już tam stoi. A gdy znowu wpiszesz 50 to wróci na pozycję 50. Tekst wypisywany w println() powinien zatem brzmieć "Przesuwam serwo do pozycji ..." 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Zadanie 5.4

#include <Servo.h>
String odebrane = "";        // przechowuje odczytane dane

Servo serwomech;
int pozycja = 0;             // pozycja serwomechanizmu
void setup()
{
  Serial.begin(9600);       // prędkość łącza
  serwomech.attach(9);      // serwo na pin 9
}

void loop()
{
  Serial.println(" Podaj liczbę od 0 - 180");   //komunikat wysłany do konsoli
  while (Serial.available() == 0) {             //czekaj na wprowadzenie liczb
    delay(50);
  }
  if (Serial.available() > 0) {               // jesli dane wprowadzone to...
    odebrane = Serial.readStringUntil('\n');  // odebrane dane
    pozycja = odebrane.toInt();               // konwertowane do Int
    if (pozycja <= 180) {                     // sprawdzenie czy liczba mieści się w zakresie
      serwomech.write(pozycja);               // przekazanie pozycji dla serwomechanizmu
    } else {
      Serial.println("Liczba nie mieści się w zadanym zakresie");  // komunikat o przekroczeniu zakresu
    }



  }
}

Zadanie 5.5

#include <Servo.h>
	
Servo serwomech;
int pozycja = 0;   // pozycja serwomechanizmu
int odebrane = 0;  // zmienna przechowująca dane z ADC
void setup()
{
  serwomech.attach(9);      // serwo na pin 9
}
	void loop()
{
  odebrane = analogRead(A5);                 // odczytanie wartości napięcia z ADC
  odebrane = map(odebrane, 0, 1023, 0, 180); // przeskalowanie danych
  if (odebrane <= 180) {                     // sprawdzenie zakresu
    serwomech.write(odebrane);               // ustawienie pozycji serwomechanizmu
  }
}
  • Lubię! 1

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