Servo ramie
Arduino

Przywitaj się z Arduino

Pośród wielu urządzeń, które możemy zbudować w oparciu o serwomechanizmy dziś przyjrzymy się tej konstrukcji przypominającej ramię robota. Konstrukcja zwiera 6 serwomechanizmów, przez co daje możliwość praktycznie dowolnego ustawienia ramienia w przestrzeni. Zbudowanie i oprogramowanie całości to niewątpliwie niezła zabawa. Ale zacznijmy od początku….

Sterowanie serwomechanizmem wydaje się dość złożone, a ramieniem zawierającym ich kilka może odstraszać. Z pomocą przychodzą nam jednak dostępne w środowisku Arduino biblioteki, które umożliwiają proste ustawienie każdego dołączonego serwomechanizmu na żądaną pozycję.

Jak podłączyć serwo?

Klasyczny serwomechanizm ma 3 przewody. Dwa z nich służą do zasilania (czerwony [+] oraz czarny [-]) a żółty do sterowania położeniem.

Zdjęcie przykładowego serwomechanizmu z wyprowadzonymi 3 przewodami

Taki mechanizm nie daje możliwości odczytania aktualnej pozycji serwomechanizmu, to jest urządzenie wykonawcze. Brak możliwości odczytania położenia powoduje problem przy starcie układu, gdyż po włączeniu zasilania będzie ono dążyć do pozycji początkowej, wykonując przy tym bardzo gwałtowny ruch. Zjawisko to zaobserwujemy również uruchamiając nasze robotyczne ramię, więc przed włączeniem zasilania najlepiej je wyprostować i takie położenie założyć w kodzie jako pozycję początkową.

Zasilanie (przewody czerwony i czarny) podłączamy bezpośrednio do źródła napięcia o dużej wydajności (np. akumulator lub zasilacz laboratoryjny). Wydajność źródła zasilania dobieramy zależnie od parametrów użytych serwomechanizmów, dla omawianego ramienia to min 3A. Przewód sterowania (żółty) oraz równolegle masę (czarny) dołączamy do Arduino. Po stronie Arduino do sterowania każdym z serwomechanizmów wykorzystujemy wybrany PIN PWM. Analogicznie, do pozostałych PINów w Arduino podłączamy pozostałe serwomechanizmy i możemy przystąpić do pisania kodu.

Sterowanie PWM

Sterowanie odbywa się przez generowanie sygnału PWM, który w zależności od czasu jego wypełnienia wskazuje na pożądanie położenie serwomechanizmu. Sygnał powinien mieć częstotliwość ok 50Hz.

PWM

Źródło grafiki: Wikipedia

Sygnał PWM sterownika RC do serwemechanizmu.

Zmiany w sygnale PWM widoczne na oscyloskopie.

Powyżej widoczny jest sygnał sterujący serwomechanizmem i jego zmiana po zmianie wychylenia drążka w pilocie RC.

Piszemy kod

Wykorzystujemy tu bibliotekę Servo.h, która zapewnia generowanie sygnału sterującego PWM. Sterowanie odbywa się przez wywoływanie funkcji, napisanej z użyciem wspomnianej biblioteki.

setServoPosition(int servoNumber, int targetAngle, int speed), w której parametry to:

  • servoNumber- numer serwomechanizmu (1-6)
  • targetAngle – zadane ustawienie – kąt (0-180)
  • speed – szybkość ruchu

Nasze ramie będzie wykonywać powtarzający się ruch, dlatego szereg wywołań tej funkcji znajduje się w pętli.

#include <Servo.h>

Servo servos[6]; // Tablica serwomechanizmów
int servoPins[6] = {2, 3, 4, 5, 6, 7}; // Numery pinów, do których są podłączone serwomechanizmy

void setup() {
  for (int i = 0; i < 6; i++) {
    servos[i].attach(servoPins[i]);
  }
  // id_servo (1-6 liczone od dołu), angle (0-180), speed (1 szybko, 30 wolno)
  setServoPosition(1, 175, 10); // obrót do pozycji początkowej
  setServoPosition(2, 90, 10); 
  setServoPosition(3, 90, 10); 
  setServoPosition(4, 90, 10); 
  setServoPosition(5, 80, 10); 
  setServoPosition(6, 90, 10); // szczypce otwarte

}

void loop() {
  setServoPosition(6, 90, 20); //szczypce otwarte

  setServoPosition(4, 180, 20); 
  setServoPosition(2, 75, 20); 
  setServoPosition(3, 45, 20); 
  setServoPosition(6, 150, 20); //szczypce zamkniete
  
  setServoPosition(3, 90, 20); 
  setServoPosition(2, 90, 20); 
  setServoPosition(1, 90, 30); //obrot

  setServoPosition(4, 180, 20); 
  setServoPosition(3, 45, 20); 
  setServoPosition(2, 75, 20); 
  setServoPosition(6, 90, 20); //szczypce otwarte

  setServoPosition(2, 90, 20); 
  setServoPosition(3, 90, 20); 
  setServoPosition(4, 90, 20); 
  setServoPosition(1, 175, 30); //obrot  
  delay(1000);  
}


void setServoPosition(int servoNumber, int targetAngle, int speed) {
  if (servoNumber >= 1 && servoNumber <= 6) {
    Servo servo = servos[servoNumber - 1];
    int currentAngle = servo.read();
    
    if (currentAngle < targetAngle) {
      for (int angle = currentAngle; angle <= targetAngle; angle++) {
        servo.write(angle);
        delay(speed);
      }
    } else if (currentAngle > targetAngle) {
      for (int angle = currentAngle; angle >= targetAngle; angle--) {
        servo.write(angle);
        delay(speed);
      }
    }
  }
}

Efekt działania programu możemy zaobserwować na filmie:

Pomysły na rozbudowę

Przedstawiony kod to jedynie przykład. Rozwiązanie można rozbudować np. o poniższe pomysły:

  • czujnik obecności podnoszonego przedmiotu i uruchamianie ruchu po jego wykryciu
  • dodanie drugiego kosza i umieszczanie przedmiotu naprzemiennie w 2 koszach
  • dodanie czujnika ultradźwiękowego do wyszukania podnoszonego przedmiotu wokoło ramienia
  • pokazywanie przez ramię różnych gestów
  • wykonywanie przez ramię innych czynności np. wciskanie przełącznika włączającego oświetlenie

Podsumowując. Robotyczne ramię ma bardzo duże walory edukacyjne. Uczy programowania, mechaniki i elektroniki. Złożenie ramienia wymaga cierpliwości i precyzji, konieczne jest samodzielne zbudowanie podestu a śrubki wymagają zabezpieczenia ich przed odkręcaniem np. klejem. Niewątpliwie ramię może stanowić element wielu ciekawych pomysłów i być wstępem do zabawy z większymi projektami związanymi z robotyką.

Udanej zabawy!