Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję

Kurs budowy robotów – #9 – ekspander I/O, serwo

Roboty 11.03.2017 Damian (Treker)

Zbliżamy się do końca kursu budowy robotów, pora omówić więc pozostałe możliwości naszego shieldu, które będą przydatne podczas dalszego rozbudowywania robotów!

Zajmiemy się ekspanderem pinów oraz złączem dla serwomechanizmu modelarskiego. 

Nawigacja serii artykułów:
« poprzednia częśćnastępna część »

Kup zestaw elementów i zacznij naukę w praktyce! Przejdź do strony dystrybutora »

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!

Przykładowy, dodatkowy projekt – ruchomy czujnik odległości.

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.

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

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.

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.

Podłączenie przewodów od serwa.

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:

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.

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

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.

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.

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:

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:

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

Zestaw elementów do budowy robota

Gwarancja pomocy na forum dla osób, które kupią poniższy zestaw!

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!


Kup w Botlandzie »

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!

Ekspander MCP2308.

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.

Wyprowadzenia ekspandera portów.

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:

Podłączenie czujnika do dodatkowego wejścia.

Program musi oczywiście zaczynać się od dołączenia biblioteki oraz zadeklarowania układu:

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:

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:

Działanie programu w praktyce widoczne jest na poniższych zdjęciach:

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.

Podłączenie diod do ekspandera.

Przykładowy program włączający diody podłączone do tych pinów będzie wyglądał następująco:

Działanie programu w praktyce widoczne jest poniżej:

Miganie diodami na dodatkowych pinach.

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!

Kup zestaw elementów i zacznij naukę w praktyce! Przejdź do strony dystrybutora »

Autor kursu: Damian (Treker) Szymański

Powiadomienia o nowych, darmowych artykułach!

Załączniki

Komentarze

__ROBI__

13:03, 12.03.2017

#1

Mój pierwszy wpis, więc chciałbym się przywitać. Dzień dobry :)

Pytanie które nie daje mi spokoju, czy do ekspandera można w jakiś sposób podłączyć omawiany w rozdziale czujnik odległości lub serwo.

W przypadku serwa, nie jestem pewien w jaki sposób przekazać pin z ekspadera do np. servo.attach(x). Najlepiej byłoby : serwo.attach(expander.... no właśnie co ?

Dzięki za kursy, są świetne i inspirują :)

deshipu

13:37, 12.03.2017

#2

__ROBI__ napisał/a:

Pytanie które nie daje mi spokoju, czy do ekspandera można w jakiś sposób podłączyć omawiany w rozdziale czujnik odległości lub serwo.

W przypadku serwa, nie jestem pewien w jaki sposób przekazać pin z ekspadera do np. servo.attach(x). Najlepiej byłoby : serwo.attach(expander.... no właśnie co ?

Da się, ale nie będziesz mógł używać do tego standardowej biblioteki, bo ona zakłada użycie "lokalnych" nóżek. Istnieją natomiast (lub można samemu napisać) biblioteki, które pozawalają na sterowanie takim serwem czy czujnikiem przez ekspander.

Istnieją także dedykowane "ekspandery" specjalnie do serw, którym tylko mówisz które serwo w jakiej pozycji ma się znaleźć, a one już same się martwią generowanie odpowiedniego sygnału, bez konieczności angażowania w to twojego mikrokontrolera -- przykładem takiego sterownika serw jest na przykład to: https://www.adafruit.com/product/815

Treker
Autor wpisu
Administrator

13:45, 12.03.2017

#3

__ROBI__, tak jak napisał już deshipu, da się, tylko akurat do serw może to być mało opłacalne rozwiązanie. Opisywany ekspander to proste piny I/O idealnie do czujników cyfrowych, diod, przycisków etc. Serwomechanizmy potrzebują sygnału PWM, który tutaj musiałbyś generować programowo. Do takiego zastosowania można znaleźć inne, dedykowane układy, które odciążają główny kontroler.

__ROBI__

16:40, 12.03.2017

#4

Dzięki za pomoc :)

Fakt, całkiem zapomniałem o PWM - biblioteka servo zdaje się rozwiązuje to programowo i dlatego też o tym nie pomyślałem ;)

wgląda na to że najlepszym rozwiązaniem jest przełączenie wszystkiego co się da do expandera: czujniki podczerwieni, przełączniki, włącznik i wszystko to co wymaga odczytu/ustawienia konkretnego stanu (HIGH/LOW).

hmm, można by się pokusić o podpięcie pinów sterujących kierunkiem silnika do expandera, a PWM kontrolować z płytki, zawsze to cztery piny zaoszczędzone ;)

Muszę to sprawdzić.

Dzięki jeszcze raz

Treker
Autor wpisu
Administrator

16:58, 12.03.2017

#5

__ROBI__ napisał/a:

hmm, można by się pokusić o podpięcie pinów sterujących kierunkiem silnika do expandera, a PWM kontrolować z płytki, zawsze to cztery piny zaoszczędzone

To już zależy od konkretnego mostka. Akurat ten, który jest na shieldzie wymaga tylko 2 pinów zwykłych i 2 PWM.

Więc dodawanie ekspandera dla samego mostka nie miałaby sensu :)

__ROBI__

17:06, 12.03.2017

#6

do silników wykorzystuję : Pololu TB6612FNG mam tam trzy piny na silnik ( dwa kierunek, jeden PWM ).

ciekawe, na pewno trzeba poeksperymentować ;)

Dzięki za pomoc i wskazówki :)

leepa79

13:01, 13.03.2017

#7

I jak zwykle mój 'poszukiwacz'

#include "Adafruit_MCP23008.h" //Dodanie biblioteki

Adafruit_MCP23008 ekspander; //Deklaracja "ekspandera"

//Biblioteka od serwomechanizmu

#include <Servo.h>

Servo serwo;

#define SERWO_PIN 11

//Piny silnikow

#define L_PWM 5

#define L_DIR 4

#define R_PWM 6

#define R_DIR 9

#define PWM_MAX 165

//Piny krancowek

#define L_SIDE_SENSOR A2

#define R_SIDE_SENSOR A0

#define BUZZER 10 //Pin buzzera

//Pin czujnika swiatla

#define LIGHT_SENSOR A1

//Piny od czujnika odleglosci

#define trigPin 7

#define echoPin 8

void setup() {

ekspander.begin(); //Rozpoczęcie komunikacji na domyslnym adresie 0x20

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

//Konfiguracja pinow od czujnikow

pinMode(L_SIDE_SENSOR, INPUT_PULLUP);

pinMode(R_SIDE_SENSOR, INPUT_PULLUP);

//Serwo do pinu 11

serwo.attach(SERWO_PIN);

//Serwo na pozycje srodkowa 90 (bo zakres 0-180)

serwo.write(90);

//Deklaracja pinów jako wyjscia

ekspander.pinMode(0, OUTPUT);

ekspander.pinMode(1, OUTPUT);

ekspander.pinMode(2, OUTPUT);

ekspander.pinMode(3, OUTPUT);

//Wylaczenie oswietlenia

ekspander.digitalWrite(0, 0);

ekspander.digitalWrite(1, 0);

ekspander.digitalWrite(2, 0);

ekspander.digitalWrite(3, 0);

}

void loop() {

//Zapalenie swiatel

int odczyt = analogRead(LIGHT_SENSOR);

if(odczyt < 950){

ekspander.digitalWrite(0, LOW);

ekspander.digitalWrite(1, LOW);

ekspander.digitalWrite(2, LOW);

ekspander.digitalWrite(3, LOW);

delay(100);

}else{

ekspander.digitalWrite(0, HIGH);

ekspander.digitalWrite(1, HIGH);

ekspander.digitalWrite(2, HIGH);

ekspander.digitalWrite(3, HIGH);

delay(100);

}

//Krancowki

if (digitalRead(L_SIDE_SENSOR) == LOW) {

//Jesli przeszkoda po lewej stronie

//Jedz do tylu i w prawo

leftMotor(-40);

rightMotor(-40);

digitalWrite(BUZZER, 1);

delay(700);

leftMotor(50);

rightMotor(10);

digitalWrite(BUZZER, 0);

delay(800);

//Koniec warunku wracamy do jazdy prosto

}

if (digitalRead(R_SIDE_SENSOR) == LOW){

//Jesli przeszkoda po prawej stronie

//Jedz do tylu w lewo

leftMotor(-40);

rightMotor(-40);

digitalWrite(BUZZER, 1);

delay(700);

leftMotor(10);

rightMotor(50);

digitalWrite(BUZZER, 0);

delay(800);

//Koniec warunku wracamy do jazdy prosto

}

//Czy wykryto przeszkode w zakresie 0-35 cm

if (zmierzOdleglosc() > 35) {

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() > 35) {

//Jesli jest pusto

leftMotor(40);

rightMotor(-40);

delay(350); //Obracaj w prawo przez 350 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() > 35) {

//Jesli jest pusto

leftMotor(-40);

rightMotor(40);

delay(350); //Obracaj w lewo przez 350 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

}

Do oświetlenia wykorzystane czujniki z fotorezystorami z kursu.

Treker
Autor wpisu
Administrator

14:42, 13.03.2017

#8

leepa79, no i super :) Jak przymocowałeś czujnik do serwa?

Ładne oświetlenie robota - chyba jeden z dodatkowych modułów, nad którym pracujemy Ci się spodoba ;)

leepa79

16:03, 13.03.2017

#9

Czujnik najszybszym sposobem - klej na gorąco :)

No i oczywiście czekam na dodatkowe moduły - widziałem, że shield już w sprzedaży.

Pesjar

13:21, 23.03.2017

#10

Chciałbym połączyć program sterowania pilotem z ostatnim programem sterowania za pośrednictwem czujnika odległości.

Po skopiowaniu wszystkich elementów z programu obsługi czujnika, których niema w programie obsługi pilotem, przed void loop(), weryfikacja przebiega pozytywnie. Jednak po wklejeniu pod void loop() po ostatnim

Case….

…..

break;

case 56:

Całość programu obsługi czujnika po void loop()

break;

weryfikacja wykazuje błąd.

Całość programu :

#include <RC5.h>

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

//Piny od czujnika odleglosci

#define trigPin 7

#define echoPin 8

#define BUZZER 10

#define LED 13

#define TSOP_PIN 3

RC5 rc5(TSOP_PIN); //Informacja o podłączeniu odbiornika TSOP

byte address;

byte command;

byte toggle;

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

pinMode(LED, OUTPUT);

digitalWrite(LED, 0); //Wylaczenie diody

//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);

Serial.begin(9600);

}

void loop() {

if (rc5.read(&toggle, &address, &command)){

switch(command) {

case 2: //Do przodu

leftMotor(40);

rightMotor(40);

break;

case 8: //Do tyłu

leftMotor(-40);

rightMotor(-40);

break;

case 5: //STOP

stopMotors();

break;

case 4: //Obrót w lewo

leftMotor(-30);

rightMotor(30);

break;

case 6: //Obrót w prawo

leftMotor(30);

rightMotor(-30);

break;

case 12:

digitalWrite(BUZZER, 1);

delay(500);

digitalWrite(BUZZER, 0);

break;

case 56:

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

}

break;

}

}

}

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

}

Gdzie popełniam błąd.

Jak zapisać po „case 56:” polecenie aby program samoczynnie wykonywał jazdę na podstawie wskazań czujnika.

Treker
Autor wpisu
Administrator

15:10, 23.03.2017

#11

Pesjar, proszę sprawdzić, gdzie i jak zadeklarowano funkcję leftMotor, rightMotor. Z tego, co widzę są one umieszczone w programie podwójnie. Raz na końcu programu (poprawnie) oraz drugi raz wewnątrz switch...case, co jest błędem. Nie można deklarować funkcji wewnątrz konstrukcji warunkowej switch. Tym bardziej nie można deklarować ich dwa razy ;) Informacje na temat pisania własnych funkcji (i miejsca na ich umieszczanie) zostały opisane w kursie podstaw Arduino: Kurs Arduino – #9 – Czujnik odległości HC-SR04, funkcje

Pesjar

16:40, 23.03.2017

#12

Jestem kompletnym laikiem w programowaniu.

Wyciełem powtarzające się funkcję leftMotor, rightMotor i stopMotors.

Jednak w dalszym ciągu weryfikacja wkazuje błąd.

Co zrobić dalej?

Program pomkorekcie:

#include <RC5.h>

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

//Piny od czujnika odleglosci

#define trigPin 7

#define echoPin 8

#define BUZZER 10

#define LED 13

#define TSOP_PIN 3

RC5 rc5(TSOP_PIN); //Informacja o podłączeniu odbiornika TSOP

byte address;

byte command;

byte toggle;

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

pinMode(LED, OUTPUT);

digitalWrite(LED, 0); //Wylaczenie diody

//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);

Serial.begin(9600);

}

void loop() {

if (rc5.read(&toggle, &address, &command)){

switch(command) {

case 2: //Do przodu

leftMotor(40);

rightMotor(40);

break;

case 8: //Do tyłu

leftMotor(-40);

rightMotor(-40);

break;

case 5: //STOP

stopMotors();

break;

case 4: //Obrót w lewo

leftMotor(-30);

rightMotor(30);

break;

case 6: //Obrót w prawo

leftMotor(30);

rightMotor(-30);

break;

case 12:

digitalWrite(BUZZER, 1);

delay(500);

digitalWrite(BUZZER, 0);

break;

case 56:

//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;

}

break;

}

}

}

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

}

Treker
Autor wpisu
Administrator

17:27, 23.03.2017

#13

Pesjar, radziłbym na spokojnie przeanalizować poprzednie kursy Arduino, bazowanie na wklejaniu "gotowców" generuje więcej problemów niż dobrego ;) Tak jak pisałem, wewnątrz instrukcji switch nie można deklarować żadnych funkcji. Nadal jest tam deklaracja funkcji zmierzOdleglosc(), która powinna znaleźć się tam gdzie pozostałe funkcje (na końcu).

Proszę pamiętać, aby kody umieszczać wewnątrz tag'ów [code] - tym razem poprawię już ręcznie :)

leepa79

18:25, 23.03.2017

#14

Pesjar, W środowisku Arduino jest fajny 'trik' - jak klikniesz za nawiasem klamrowym to zobaczysz wyżej taki prostokąt i już wiesz gdzie się zaczyna i kończy dany blok.

Bardzo pomocne na etapie działania 'kopiuj --> wklej' ;)

Sam jestem początkującym i też mi się zdarza tak działać...Co do Twojego kodu to na początku skasowałbym wszystko od 'case 56:' do ostatniego nawiasu klamrowego przed 'void leftMotor'. Przed 'void leftMotor' Powinny Ci zastać trzy nawiasy i zobacz czego każdy dotyczy (metodą z obrazka powyżej). Potem wróć do lekcji o odbiorniku IR (RC5) i ekspander I/O, serwo i zobacz jak to tam wyglądało (wskazówka - int zmierzOdleglosc() nie siedzi w void loop() ). Dla własnej nauki poprawiłem Twój kod, ale oczywiście nie zabiorę Ci tej przyjemności w zabawie i nie podam go na forum.

A u mnie kod na takim etapie:

#include "Adafruit_MCP23008.h" //Dodanie biblioteki

Adafruit_MCP23008 ekspander; //Deklaracja "ekspandera"

//adrs biblioteki https://github.com/adafruit/Adafruit-MCP23008-library

//Biblioteka od serwomechanizmu

#include <Servo.h>

Servo serwo;

#define SERWO_PIN 11

//Piny silnikow

#define L_PWM 5

#define L_DIR 4

#define R_PWM 6

#define R_DIR 9

#define PWM_MAX 165

//Piny krancowek

#define L_SIDE_SENSOR A2

#define R_SIDE_SENSOR A0

#define BUZZER 10 //Pin buzzera

//Pin czujnika swiatla

#define LIGHT_SENSOR A1

//Piny od czujnika odleglosci

#define trigPin 7

#define echoPin 8

//Oswietlenie miganie

const int ledPin1 = 1;

const int ledPin2 = 0;

int stan = LOW;

unsigned long previousMillis = 0;

const long interval = 500;

void setup() {

ekspander.begin(); //Rozpoczęcie komunikacji na domyslnym adresie 0x20

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

//Konfiguracja pinow od czujnikow

pinMode(L_SIDE_SENSOR, INPUT_PULLUP);

pinMode(R_SIDE_SENSOR, INPUT_PULLUP);

//Serwo do pinu 11

serwo.attach(SERWO_PIN);

//Serwo na pozycje srodkowa 90 (bo zakres 0-180)

serwo.write(90);

//Deklaracja pinów jako wyjscia (oswietlenie)

ekspander.pinMode(2, OUTPUT);

ekspander.pinMode(3, OUTPUT);

pinMode(ledPin1, OUTPUT);

pinMode(ledPin2, OUTPUT);

//Wylaczenie oswietlenia

digitalWrite(ledPin1, LOW);

digitalWrite(ledPin2, LOW);

ekspander.digitalWrite(2, 0);

ekspander.digitalWrite(3, 0);

}

void loop() {

//Zapalenie swiatel

int odczyt = analogRead(LIGHT_SENSOR);

if(odczyt < 950){

digitalWrite(ledPin1, 0);

digitalWrite(ledPin2, 0);

ekspander.digitalWrite(2, LOW);

ekspander.digitalWrite(3, LOW);

delay(100);

}else{

light();

}

//Krancowki

if (digitalRead(L_SIDE_SENSOR) == LOW) {

//Jesli przeszkoda po lewej stronie

//Jedz do tylu i w prawo

leftMotor(-40);

rightMotor(-40);

digitalWrite(BUZZER, 1);

delay(700);

leftMotor(50);

rightMotor(10);

digitalWrite(BUZZER, 0);

delay(800);

//Koniec warunku wracamy do jazdy prosto

}

if (digitalRead(R_SIDE_SENSOR) == LOW){

//Jesli przeszkoda po prawej stronie

//Jedz do tylu w lewo

leftMotor(-40);

rightMotor(-40);

digitalWrite(BUZZER, 1);

delay(700);

leftMotor(10);

rightMotor(50);

digitalWrite(BUZZER, 0);

delay(800);

//Koniec warunku wracamy do jazdy prosto

}

//Czy wykryto przeszkode w zakresie 0-35 cm

if (zmierzOdleglosc() > 35) {

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() > 35) {

//Jesli jest pusto

leftMotor(40);

rightMotor(-40);

delay(350); //Obracaj w prawo przez 350 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() > 35) {

//Jesli jest pusto

leftMotor(-40);

rightMotor(40);

delay(350); //Obracaj w lewo przez 350 ms

} else {

//Jesli z przodu, z lewej i prawej jest przeszkoda

digitalWrite(BUZZER, 1);

delay(500);

digitalWrite(BUZZER, 0);

//Daj sygnal buzzerem

delay(1000);

leftMotor(35); //Obrot w miejscu o 180 st w prawo

rightMotor(-35);

delay(850);

}

}

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

}

void light(){

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (stan == LOW) {

stan = HIGH;

} else {

stan = LOW;

}

digitalWrite(ledPin1, stan);

digitalWrite(ledPin2, !stan);

ekspander.digitalWrite(2, 1);

ekspander.digitalWrite(3, 1);

}

}

Czyli próba zastosowania 'millis' dla migania diod z tyłu i ucieczka w sytuacji gdzie po lewej i po prawej przeszkoda poniżej 35 cm.

Pesjar

8:00, 24.03.2017

#15

Do leepa79

Skorzystam z Twoich rad. Byłbym jednak wdzięczny gdybś przesłał mi poprawiony kod.

Nadminiam że mam prawie 70 lat jestem emerytowanym ekonomistą. Boję się że zaplątam sie i nic z tego nie wyjdzie. Posiadając poprawiony kod porównam z efektami moich poprawek i napewno pozwoli mi to wyłapać błędy.

Jeśli nie chcesz publikowć tego na forum to poniżej podaję swój adres: jaroslawpestka6@gmail.com

Pesjar

9:23, 25.03.2017

#16

Niestety kręcę się w kółko i nic mi nie wychodzi.

Drobne korekty programu sterowania pilotem oraz drobne korekty konstrukcji takie jak: zaprogramowałem klawisze 144, 149, 150, 151, 145 do szybszej jazdy do przodu, po łuku, stop i w tył. Do każdej jazdy wstecz dodałem sygnał buzera. Przy skręcie orczyk obraca czujnik w kierunku skrętu. Do orczyka zamontowałem dwie czerwone diody, Serwo zamontowałem tak aby było wyżej, z obawy by nie wjeżdżał pod meble. Czujniki wykorzystywane przy światłolubie zastosowałem jako przednie lampy.

Czy ktoś nie napisał by takiego programu, którego założenia podaje poniżej, byłbym wdzięczny.

Do programu sterującego pilotem dodać funkcje, która po wciśnięciu przycisku na pilocie ( na przykład klawisz, który po naciśnięciu wysyła wartość 56) uruchamiał by cały program sterowania za pomocą ruchomego czujnika skanującego otoczenie. Następnie po naciśnięciu wcześniej zaprogramowanych przycisków na piloci wracał by do sterowania ręcznego.

[ Dodano: 26-03-2017, 09:28 ]

Zdjęcie mojego robota.

Zobacz wszystkie komentarze (28) na forum

FORBOT Damian Szymański © 2006 - 2017 Zakaz kopiowania treści oraz grafik bez zgody autora. vPRsLH.