Kursy • Poradniki • Inspirujące DIY • Forum
Zgodnie z zapowiedzią, artykuł ten jest dodatkiem do kursu (pierwotnie miało go nie być), więc wyjątkowo użyję tutaj również elementów spoza zestawu. Dodatkowe podzespoły były omawiane w kursie podstaw Arduino. Wszyscy, którzy mają zestaw do tamtej serii (oraz kilka przewodów połączeniowych) będą mogli wykonać opisywane projekty!
Lekturę polecam również osobom, które nie mają tych dodatkowych elementów,
zawsze warto poznać możliwości rozbudowy robota!
Dodatek 1: Sterowanie serwomechanizmem
Nasz shield wyposażony jest w układ DRV, który pozwala sterować dwoma silnikami DC. Oprócz tego możemy podłączyć do niego jeszcze jeden napęd - serwomechanizm modelarski. Działanie serw opisane zostało już podczas kursu podstaw programowania Arduino (odcinek 5).
W skrócie mówiąc napędy te pozwalają na precyzyjne ruchy w zakresie 0-180º.
Najczęściej serwomechanizmy zasila się z około 5V. Każdy silnik (czyli również serwo) pobiera stosunkowo duży prąd, który może zakłócać działanie elektroniki. Dlatego absolutnie nie można zasilać serwomechanizmu z "5V", które znajduje się na pinach Arduino.
Dla bezpieczeństwa układu na pokładzie shieldu znajduje się dodatkowy stabilizator napięcia, który odpowiedzialny jest wyłącznie za zasilanie napędu podłączonego do złącza SERVO. Zastosowany układ to LM1117 w obudowie SOT223, który może dostarczyć do 800mA prądu. Wartość ta będzie wystarczająca dla większości serwomechanizmów typu micro.
Podczas dalszej części artykułu wykorzystałem serwomechanizm modelarski typu micro, który był częścią zestawu do kursu podstaw programowania Arduino. Napęd ten będzie idealnie pasował do otworu przygotowanego w przedniej części podwozia.
Najpierw należy przełożyć przewód,
a dopiero później (pod mały kątem) cały napęd.
- Najpierw przewód pod małym kątem.
- Serwo na miejscu.
Następnie trzeba przymocować napęd do podstawy. Można to zrobić na kilka sposób. Najprościej za pomocą gumki (jak na zdjęciu poniżej). Druga opcja to wykorzystanie małych wkrętów dołączanych z serwomechanizmami - można je wkręcić w sklejkę.
- Mocowanie za pomocą gumki.
- Mocowanie za pomocą małych wkrętów.
Jeśli powyższe rozwiązania się nie sprawdzą, to warto poszukać małych śrubek z nakrętkami M2, które pozwolą przykręcić serwo do podstawy - będzie to najmocniejsze połączenie.
- Śrubki M2.
- Nakrętki M2 od spodu.
Gdy serwo będzie zamocowane wystarczy podłączyć je do gniazda SERVO. Przewód jest na tyle długi, że spokojnie można poprowadzić go pod spodem robota. We wtyczce znajdziemy najczęściej przewody w następujących kolorach
- Czarny/brązowy - podłączamy do G (GND)
- Czerwony - podłączamy do Vcc
- Pomarańczowy/żółty - podłączamy do wyprowadzenia opisanego jako PWM.
Gdy serwo jest gotowe możemy przejść do napisania programu testowego. Ograniczę się tutaj do wklejenia gotowego programu. Osoby, które nie miały wcześniej styczności z serwami odsyłam do kursu podstaw Arduino. Program testowy, który zmienia pozycję serwa wygląda następująco:
//Biblioteka od serwomechanizmu
#include <Servo.h>
Servo serwo;
#define SERWO_PIN 11
void setup() {
//Serwo do pinu 11
serwo.attach(SERWO_PIN);
}
void loop() {
int i = 0;
//Obroty serwa w pętli co 1 stopień
for (i = 0; i < 180; i++){
serwo.write(i); //Zmien pozycje
delay(10); //Opoznienie dla lepszego efektu
}
}
Działanie kodu w praktyce:
Serwo z przodu robota przydaje się w wielu przypadkach. Można przykładowo zamontować tam czujniki lub mocne diody, którymi pojazd będzie oświetlał swoje otoczenie. Łącząc elementy z kursu Arduino można stworzyć ruchomy czujnik skanujący otoczenie - tym właśnie się zajmiemy!
Ruchomy czujnik skanujący otoczenie
Naszym sensorem odległości będzie popularny czujnik ultradźwiękowy HC-SR04, który został dokładnie opisany w #9 części kursu Arduino. Jeśli nie mamy pod ręką żadnego mocowania do tego czujnika, to można poradzić sobie na dwa sposoby.
Pierwszym z nich jest przytwierdzenie orczyka serwomechanizmu do czujnika za pomocą gumek. Rozwiązanie to jest najmniej inwazyjne, ale może być zbyt delikatne. Druga opcja to odrobina kleju na gorąco (tzw. hotglue).
Niezależnie od wybranej metody trzeba uważać, aby orczyk serwomechanizmu nie znalazł się po tej samej stronie czujnika, co złącza. Poprawny sposób montażu widoczny jest na poniższych zdjęciach.
- Mocowanie za pomocą gumki.
- Mocowanie za pomocą kleju.
Kolejny krok, to podłączenie czujnika. Aby mógł on obracać się swobodnie proponuję przewody poprowadzić swobodnie górą robota. Czujnik można podłączyć do dowolnych pinów. Idealnie sprawdzi się tutaj listwa na shieldzie opisana jako DIGITAL (obok przycisku).
Połączenie użyte w dalszej części artykułu to:
- Vcc z czujnika → 5V
- GND z czujnika → GND
- ECHO z czujnika → pin D8
- TRIG z czujnika → pin D7
- Podłączenie do płytki.
- Podłączenie do czujnika.
Program obsługi czujnika
Zadaniem programu będzie mądre unikać przeszkód. Pojazd powinien jechać do przodu, aż napotka przeszkodę. W tym momencie serwomechanizm obróci czujnik w lewo/prawo i sprawdzi, z której strony jest pusto. Następnie robot obróci się w daną stronę i dalej będzie jechał prosto.
Zacznijmy od szkieletu programu, który zawiera wszystkie niezbędne deklaracje. Funkcje, które są odpowiedzialne za sterowanie silnikami oraz funkcję, która zwraca odległość od przeszkody.
Funkcja zwracająca odległość od przeszkody została
skopiowana z #9 części kursu podstaw Arduino.
//Biblioteka od serwomechanizmu
#include <Servo.h>
Servo serwo;
#define SERWO_PIN 11
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 165
#define BUZZER 10
//Piny od czujnika odleglosci
#define trigPin 7
#define echoPin 8
void setup() {
//Konfiguracja pinow od mostka H
pinMode(L_DIR, OUTPUT);
pinMode(R_DIR, OUTPUT);
pinMode(L_PWM, OUTPUT);
pinMode(R_PWM, OUTPUT);
//Konfiguracja pozostalych elementow
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, 0); //Wylaczenie buzzera
//Czujnik odleglosci
pinMode(trigPin, OUTPUT); //Pin, do którego podłączymy trig jako wyjście
pinMode(echoPin, INPUT); //a echo, jako wejście
//Serwo do pinu 11
serwo.attach(SERWO_PIN);
//Serwo na pozycje srodkowa 90 (bo zakres 0-180)
serwo.write(90);
}
void loop() {
}
int zmierzOdleglosc() {
long czas, dystans;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
czas = pulseIn(echoPin, HIGH);
dystans = czas / 58;
return dystans;
}
void leftMotor(int V) {
if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(L_DIR, 0); //Kierunek: do przodu
analogWrite(L_PWM, V); //Ustawienie predkosci
} else {
V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(L_DIR, 1); //Kierunek: do tyłu
analogWrite(L_PWM, V); //Ustawienie predkosci
}
}
void rightMotor(int V) {
if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(R_DIR, 0); //Kierunek: do przodu
analogWrite(R_PWM, V); //Ustawienie predkosci
} else {
V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(R_DIR, 1); //Kierunek: do tyłu
analogWrite(R_PWM, V); //Ustawienie predkosci
}
}
void stopMotors() {
analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}
Teraz możemy zacząć uzupełniać program. Aby artykuł był czytelniejszy będę teraz pokazywał jedynie zawartość pętli loop. Cały program (wraz z powyższymi funkcjami) wkleję na samym końcu, aby nikt nie miał żadnych wątpliwości, co do jego formy.
Zaczynamy od warunku, który sprawdza, czy przed robotem jest przeszkoda. Jeśli jej nie ma, to chcemy jechać do przodu.
void loop() {
//Czy wykryto przeszkode w zakresie 0-40 cm
if (zmierzOdleglosc() > 40) {
leftMotor(40); //Jesli nie, to jedz prosto
rightMotor(40);
} else {
//Jesli przeszkoda
}
//Opoznienie 100ms, ponieważ nie ma potrzeby sprawdzać przeszkod czesciej
delay(100);
}
Teraz skupmy się na przypadku, gdy przeszkoda jest wykryta. Najlepiej wtedy zatrzymać robota oraz skierować czujnik w prawo. Następnie proponuje zatrzymać całość np. na 800 ms, aby wszelkie drgania w robocie ustały (mogłoby to fałszować pomiary czujnika).
Serwo z czujnikiem obracamy do pozycji 20, a nie 0, ponieważ
w skrajnym położeniu sensor mógłby wykrywać koło robota jako przeszkodę!
Następnie sprawdzamy, czy po prawej stronie robota jest pusto. Jeśli tak, to obracamy pojazd:
void loop() {
//Czy wykryto przeszkode w zakresie 0-40 cm
if (zmierzOdleglosc() > 40) {
leftMotor(40); //Jesli nie, to jedz prosto
rightMotor(40);
} else {
//Jesli przeszkoda
stopMotors(); //Zatrzymaj robota
serwo.write(20); //Skrec czujnikiem w prawo
delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
//Sprawdz, czy po prawej stronie jest przeszkoda
if (zmierzOdleglosc() > 40) {
//Jesli jest pusto
leftMotor(40);
rightMotor(-40);
delay(400); //Obracaj w prawo przez 400 ms
} else {
//Jeśli po prawej jest przeszkoda
}
}
//Opoznienie 100ms, ponieważ nie ma potrzeby sprawdzać przeszkod czesciej
delay(100);
}
Jeśli po prawej stronie jest przeszkoda, to czujnik obracamy w lewo (do pozycji 160) i ponownie sprawdzamy otoczenie robota. Jeśli jest pusto, to skręcamy właśnie tam.
Jeśli czujnik wykryje przeszkodę oznacza to, że robot jest w potrzasku (przeszkoda z przodu, po lewej i po prawej). Wtedy można np. zacząć cofać. Aby nie rozbudowywać zbytnio przykładu ograniczę się tutaj do wydania dźwięku za pomocą buzzera, co będzie nam sygnalizowało utknięcie robota.
Na sam koniec warunku sprawdzającego obecność przeszkód po bokach trzeba koniecznie wyprostować czujnik tak, aby znów spoglądał do przodu. Cały program wygląda następująco:
//Biblioteka od serwomechanizmu
#include <Servo.h>
Servo serwo;
#define SERWO_PIN 11
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 165
#define BUZZER 10
//Piny od czujnika odleglosci
#define trigPin 7
#define echoPin 8
void setup() {
//Konfiguracja pinow od mostka H
pinMode(L_DIR, OUTPUT);
pinMode(R_DIR, OUTPUT);
pinMode(L_PWM, OUTPUT);
pinMode(R_PWM, OUTPUT);
//Konfiguracja pozostalych elementow
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, 0); //Wylaczenie buzzera
//Czujnik odleglosci
pinMode(trigPin, OUTPUT); //Pin, do którego podłączymy trig jako wyjście
pinMode(echoPin, INPUT); //a echo, jako wejście
//Serwo do pinu 11
serwo.attach(SERWO_PIN);
//Serwo na pozycje srodkowa 90 (bo zakres 0-180)
serwo.write(90);
}
void loop() {
//Czy wykryto przeszkode w zakresie 0-40 cm
if (zmierzOdleglosc() > 40) {
leftMotor(40); //Jesli nie, to jedz prosto
rightMotor(40);
} else {
//Jesli przeszkoda
stopMotors(); //Zatrzymaj robota
serwo.write(20); //Skrec czujnikiem w prawo
delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
//Sprawdz, czy po prawej stronie jest przeszkoda
if (zmierzOdleglosc() > 40) {
//Jesli jest pusto
leftMotor(40);
rightMotor(-40);
delay(400); //Obracaj w prawo przez 400 ms
} else {
//Jeśli po prawej jest przeszkoda
serwo.write(160); //Obroc czujnik w lewo
delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
//Sprawdz, czy po lowej stronie jest przeszkoda
if (zmierzOdleglosc() > 40) {
//Jesli jest pusto
leftMotor(-40);
rightMotor(40);
delay(400); //Obracaj w lewo przez 400 ms
} else {
//Jesli z przodu, z lewej i prawej jest przeszkoda
digitalWrite(BUZZER, 1);
delay(500);
digitalWrite(BUZZER, 0);
//Daj sygnal buzzerem
}
}
//Po sprawdzeniu przeszkod po bokach
//Ustaw czujnik prosto
serwo.write(90);
}
//Opoznienie 100ms, ponieważ nie ma potrzeby sprawdzać przeszkod czesciej
delay(100);
}
int zmierzOdleglosc() {
long czas, dystans;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
czas = pulseIn(echoPin, HIGH);
dystans = czas / 58;
return dystans;
}
void leftMotor(int V) {
if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(L_DIR, 0); //Kierunek: do przodu
analogWrite(L_PWM, V); //Ustawienie predkosci
} else {
V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(L_DIR, 1); //Kierunek: do tyłu
analogWrite(L_PWM, V); //Ustawienie predkosci
}
}
void rightMotor(int V) {
if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(R_DIR, 0); //Kierunek: do przodu
analogWrite(R_PWM, V); //Ustawienie predkosci
} else {
V = abs(V); //Funkcja abs() zwroci wartosc V bez znaku
V = map(V, 0, 100, 0, PWM_MAX);
digitalWrite(R_DIR, 1); //Kierunek: do tyłu
analogWrite(R_PWM, V); //Ustawienie predkosci
}
}
void stopMotors() {
analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}
Zachowanie robota w praktyce widoczne jest na poniższym wideo:
To tylko jedno zastosowanie serwomechanizmu. Na pewno każdy z Was znajdzie jeszcze wiele zadań dla tego dodatku. Tymczasem pora sprawdzić ostatnią funkcjonalność naszej płytki!
Dodatek 2: ekspander pinów
Ilość pinów dostępnych w Arduino jest ograniczona. Na szczęście jeśli zabraknie wolnych wyjść nie trzeba dodawać do projektu kolejnego kontrolera. Wtedy bardzo przydają się ekspandery pinów.
Układy te komunikują się z mikrokontrolerem za pomocą jednego z popularnych interfejsów komunikacyjnych (najczęściej I2C) i pozwalają dodać do Arduino kilka kolejnych wejść/wyjść.
Gotowe zestawy do kursów Forbota
Komplet elementów Gwarancja pomocy Wysyłka w 24h
Części pozwalające wykonać ćwiczenia z kursu budowy robotów dostępne są w formie gotowych zestawów! W komplecie znajdują się elementy mechaniczne (w tym koła i silniki), baterie oraz shield!
Zamów w Botland.com.pl »Układ MCP2308
Na pokładzie naszego shielda znajduje się układ MCP2308, który komunikuje się z Arduino za pomocą interfejsu I2C wyprowadzonego na pinach A4 oraz A5. Aby komunikacja przebiegała poprawnie piny te muszą zostać podciągnięte do dodatniej szyny zasilania przez rezystory.
Odpowiednie rezystory są już przylutowane na płytce!
Układ posiada 20 wyprowadzeń, ich dokładny opis znaleźć można w dokumentacji układu. Jednak na ten moment najważniejsze są piny:
- 1-2, dzięki którym układ komunikuje się z Arduino
- 3-5, piny adresowe (w naszym wypadku zwarte do masy) ustalają adres pod jakim będziemy komunikować się z ekspanderem. W naszej konfiguracji z układem będzie można "rozmawiać" pod adresem 0x20 (zapis szesnastkowy)
- 12-19, piny, które będą służyły za dodatkowe, uniwersalne wejścia/wyjścia.
Układ został umieszczony w lewym górnym rogu shieldu, a jego wyprowadzenia umieszczone są na krawędzi płytki. Gdyby zaszła potrzeba w przyszłości podłączenia innego układu, który korzysta z komunikacji przez I2C, to w tym celu należy skorzystać ze złącza opisanego jako I2C (na prawo od układu MCP2308).
Biblioteka do obsługi ekspandera
Do pracy z układem MCP2308 polecam bibliotekę udostępnianą przez firmę Adafruit. Wszystkie pliki dostępne są na GitHubie. Na tym etapie kursu każdy powinien już wiedzieć jak samodzielnie zainstalować bibliotekę (jeśli nie, to zalecam powrót do poprzednich artykułów).
Zanim pójdziesz dalej upewnij się, że biblioteka do MCP2308
została pomyślnie zainstalowana!
Dodatkowe wejścia
Zacznijmy od wykorzystania dodatkowych pinów w roli wejść. Na początek wystarczy podłączyć do ekspandera jeden z czujników krańcowych. Jedno z wyprowadzeń podłączamy do pinu nr 0, a drugie do masy. Przykładowe podłączenie widoczne jest na poniższym zdjęciu:
Program musi oczywiście zaczynać się od dołączenia biblioteki oraz zadeklarowania układu:
#include "Adafruit_MCP23008.h" //Dodanie biblioteki
Adafruit_MCP23008 ekspander; //Deklaracja "ekspandera"
void setup() {
ekspander.begin(); //Rozpoczęcie komunikacji na domyslnym adresie 0x20
}
void loop() {
}
Biblioteka domyślnie przyjmuje, że ekspander jest skonfigurowany do pracy pod adresem 0x20 dlatego nie musimy go podawać. W innych bibliotekach może być inaczej, trzeba o tym pamiętać, ponieważ błędny adres układu to najczęstsza przyczyna problemów w komunikacji przez I2C.
W kolejnym kroku za pomocą znajomo brzmiącego polecenia ekspander.pinMode() możliwe jest ustalenie kierunku pracy wybranego pinu. Niestety funkcja ta pozwala jedynie określić, czy pin ma działać jako wejście/wyjście. Dla nas ważne jest, aby włączyć również dodatkowo wewnętrzne podciągnięcie wejścia (przez rezystor) do dodatniej szyny zasilania. Dlatego musimy skorzystać z drugiego polecenia ekspander.pullUp().
Uzupełniona funkcja setup() będzie wyglądać następująco:
#include "Adafruit_MCP23008.h" //Dodanie biblioteki
Adafruit_MCP23008 ekspander; //Deklaracja "ekspandera"
void setup() {
ekspander.begin(); //Rozpoczęcie komunikacji na domyslnym adresie 0x20
//Konfiguracja pinu 0 ekspandera jako wejscie
ekspander.pinMode(0, INPUT);
//Wlaczenie wewnetrznego podciagniecia do dodatniej szyny zasilania
ekspander.pullUp(0, HIGH);
//Konfiguracja pinu 13 Arduino jako wyjscie (dla diody)
pinMode(13, OUTPUT);
}
void loop() {
}
Teraz w pętli loop() możemy sprawdzić czy ekspander działa poprawnie. Najprościej będzie, gdy stan czujnika (wciśnięty/puszczony) będziemy sygnalizować za pomocą diody podłączonej do pinu Arduino nr 13. Sprawdzenia stanu wejścia dokonamy za pomocą ekspander.digitalRead().
Cały program będzie wyglądał więc następująco:
#include "Adafruit_MCP23008.h" //Dodanie biblioteki
Adafruit_MCP23008 ekspander; //Deklaracja "ekspandera"
void setup() {
ekspander.begin(); //Rozpoczęcie komunikacji na domyslnym adresie 0x20
//Konfiguracja pinu 0 ekspandera jako wejscie
ekspander.pinMode(0, INPUT);
//Wlaczenie wewnetrznego podciagniecia do dodatniej szyny zasilania
ekspander.pullUp(0, HIGH);
//Konfiguracja pinu 13 Arduino jako wyjscie (dla diody)
pinMode(13, OUTPUT);
}
void loop() {
if (ekspander.digitalRead(0) == LOW) { //Jesli przycisk wcisniety
digitalWrite(13, HIGH); //Wlacz diode
} else { //Jesli nie
digitalWrite(13, LOW); //Wylacz diode
}
}
Działanie programu w praktyce widoczne jest na poniższych zdjęciach:
- Czujnik wciśnięty dioda (obok buzzera) świeci.
- Czujnik puszczony dioda nie świeci.
Dodatkowe wyjścia
Analogicznie możemy wykorzystać piny ekspandera w roli uniwersalnych wyjść cyfrowych. Dla testu do pinów ekspandera nr 0-3 podłączyłem 4 diody. W tym celu wykorzystałem LEDy, płytkę stykową oraz rezystory.
Przykładowy program włączający diody podłączone do tych pinów będzie wyglądał następująco:
#include "Adafruit_MCP23008.h" //Dodanie biblioteki
Adafruit_MCP23008 ekspander; //Deklaracja "ekspandera"
void setup() {
ekspander.begin(); //Rozpoczęcie komunikacji na domyslnym adresie 0x20
//Deklaracja pinów jako wyjscia
ekspander.pinMode(0, OUTPUT);
ekspander.pinMode(1, OUTPUT);
ekspander.pinMode(2, OUTPUT);
ekspander.pinMode(3, OUTPUT);
}
void loop() {
int i = 0;
//Wlaczanie kolejnych diod
for (i = 0; i <= 3; i++) {
ekspander.digitalWrite(i, HIGH);
delay(200);
}
//Wylaczanie kolejnych diod
for (i = 3; i >= 0; i--) {
ekspander.digitalWrite(i, LOW);
delay(200);
}
}
Działanie programu w praktyce widoczne jest poniżej:
Reasumując, ekspander pozwala nam szybko dodać do układu dodatkowe piny. Trzeba jednak pamiętać podczas programowania, aby rozróżniać ich numerację! Czym innym będzie pin nr 0 z Arduino, a czym innym pin nr 0 z ekspandera.
Oczywiście powyższe programy, to jedynie proste przykłady. Do ekspandera można podłączyć wiele różnych peryferiów. Dla testu proponuję np. podłączyć do niego dwa mechaniczne czujniki przeszkód (krańcówki) i napisać jeszcze raz program prostego omijania przeszkód. Dokładnie tak, jak robiliśmy to w #5 części kursu budowy robotów.
Podsumowanie
Teraz nasz shield nie skrywa już żadnych tajemnic! W poprzednich artykułach omówione zostały wszystkie peryferia, które są w niego wbudowane. Na pewno nie jeden raz zaskoczycie mnie swoją kreatywnością i rozbudujecie robota o zupełnie nowe funkcje! Koniecznie dajcie znać w komentarzach, jeśli uda Wam się dodać do niego coś ciekawego.
W kolejnym artykule będzie krótkie podsumowanie kursu. Zdradzę część planów na przyszłość. Zarówno podwozie robota, jak i shield pojawią się jeszcze w wielu artykułach na Forbocie!
Nawigacja kursu
Autor kursu: Damian (Treker) Szymański
Załączniki
Powiązane wpisy
arduino, ekspander, kurs, kursBudowyRobotow, serwo, serwomechanizm
Trwa ładowanie komentarzy...