Sygnalizator czyli jak wykorzystać przycisk
Weekend parę tygodni temu od samego początku zapowiadał się deszczowo. Znaczyło to, że z moją trójką dzieci będziemy cały dzień w domu. Jest to pewnego rodzaju wyzwanie – jak to przeżyć bez nadszarpniętych nerwów :)
Jako że mój syn (3 i pół roku) jest na etapie rozjeżdżania dywanu na wszystkie strony z wykorzystaniem samochodów i pociągów wszelkiego rodzaju, zrodził się na szybko pomysł gnalizatora, jak został w mowie 3 latka ochrzczony…
Pół godziny i udało się zrobić coś takiego. Miałem nadzieję, że będzie wzbudzał zainteresowanie przez kolejne pół godziny, a okazało się, że przez następnych kilka dni stanowił niezbędny element torów przeszkód powstających na dywanie.
Jak to działa?
Najpierw literatura – idea była taka, żeby powstał prosty sygnalizator, zmieniający swój stan przez przyciśnięcie przycisku.
Diodę czerwoną podłączamy do cyfrowego wyjścia nr 3, zieloną do cyfrowego wyjścia 2 a przycisk do cyfrowego wejścia nr 4.
Schemat:
Kod:
int buttonPin = 4; int LED = HIGH; int greenPin = 02; // LED connected to digital pin 13 int redPin = 03; int infraPin = 0; int val = LOW; int prev = LOW; #define ST_OFF 0 #define ST_ON 1 #define ST_PULSE 2 int status = ST_OFF; //początkowa konfiguracja void setup() { pinMode(greenPin, OUTPUT); // sets the digital pin as output pinMode(redPin, OUTPUT); // sets the digital pin as output pinMode(buttonPin, INPUT); // ustawienie pinu jako wejscie Serial.begin(57600); digitalWrite(redPin,HIGH); digitalWrite(greenPin,HIGH); } void display_status() { int static pulse = LOW; int static count = 5; switch (status) { case ST_OFF: off(redPin); on(greenPin); break; case ST_ON: on(redPin); off(greenPin); break; case ST_PULSE: off(redPin); digitalWrite(greenPin, pulse); pulse = !pulse; delay(400); count--; if (count==0) { status=ST_ON; count=5; } } } void next_status() { switch (status) { case ST_OFF: status = ST_PULSE; break; case ST_ON: status = ST_OFF; break; case ST_PULSE: break; } } void on( int pin) { digitalWrite(pin,HIGH); } void off( int pin) { digitalWrite(pin,LOW); } void loop() { val = digitalRead(buttonPin); if (val == HIGH && prev == LOW) { next_status(); } prev = val; display_status(); delay(50); }
Sygnalizator może być w trzech stanach – wyłączony (ST_OFF, świeci zielone), włączony (ST_ON, świeci czerwone) i pulsujący (ST_PULSE, miga zielone).
W głównej pętli sprawdzamy czy nie został wciśnięty przycisk. Jeżeli tak, to przejdź do następnego stanu (next_status
) z wyjątkiem ST_PULSE, w którym uparcie pozostaje. Dzięki temu naciśnięcie przycisku podczas migania, nie powoduje przeskoku do następnego stanu.
Następnie wyświetlany jest stan odpowiadający bieżącemu statusowi (display_status
). Tutaj jest realizowane miganie, oraz po odbębnieniu odpowiedniej liczby cykli, zmieniany stan na ST_ON, czyli – czerwone.
display_status
mogłoby być źródłem problemów, gdyby był to bardziej złożony układ. Dodaje swoje opóźnienie w ST_PULSE (delay(400)
), zmienia stan – proszenie się o kłopoty. Ale w tak prostym układzie – może być.
Co nowego?
Nowym elementem, którego nie używaliśmy we wcześniejszych przykładach jest tutaj przełącznik. Prosty przycisk którego naciśnięcie ma wykryć Arduino.
Potencjalna pułapka – po co tam jest rezystor? Czemu nie tak:
Otóż, w momencie, w którym przycisk jest wyciśnięty, nie ma problemu, wejście cyfrowe jest zwarte do zasilania i jest w stanie wysokim. Jednak po jego zwarciu z masą wejście napięcie zasilania też zostaje zwarte do masy, co powoduje niekontrolowany przepływ prądu. Może to uszkodzić układ zasilający (tutaj to kawałek Arduino).
Gdyby zrezygnować z napięcia zasilania, trzeba sobie zdawać sprawę, że gdy przycisk nie jest wciśnięty, wówczas wejście cyfrowe zostaje zawieszone w powietrzu i nie mamy najmniejszej gwarancji co zostanie odczytane przez Arduino. Może to być stan niski lub wysoki (i będzie się zmieniać losowo). Podłączenie napięcia +5V (przez rezystor) pozwala na unikniecie takiej niejednoznaczności i mieć pewność, że nie zniszczymy układu.
A może uda się tutaj zamieścić tutorial/instrukcję pokazującą jak zastosować Arduino do sterowania samochodem RC z poziomu komputera… mam tutaj na myśli coś w stylu …Computer-Controlled R/C Car with Camera
http://blogs.msdn.com/coding4fun/archive/2007/01/22/1507304.aspx
Czekam z niecierpliwością!
Oczywiści że można by :) Ja niestety na razie nie mam materiału na taki tutorial, ale może znajdzie się wśród czytelników. Jeżeli ktokolwiek ma swój projekt, którym chciałby się pochwalić to zapraszam, chętnie go opublikuje.
Mogę tylko teoretyzować, gdyż takiej aparatury nie wykonywałem. Ale to chyba można zrobić dość łatwo. W wielu sklepach są nadajniki i odbiorniki o częstotliwości 433 MHz. Kosztują kilkanaście PLN, ale mają zasięg kilkuset metrów. Wymagają jedynie zasilania i sygnału z szeregowego wyjścia (np pin 1 w Arduino). Wadą ich jest to, że są dość proste i podatne na zakłócenia. Można też nabyć bardziej skomplikowane moduły XBee w cenie kilkunastu $ (popularne w takich zastosowaniach).
Zabawa polega na tym, by jeden z modułów podłączyć do PC, a drugi do Arduino. Arduino podłączamy też silniki znajdujące się w modelu poprzez odpowiednie układy w zależności od typu silnika.
Podłączenie XBee – http://www.arduino.cc/playground/Shields/Xbee01
Silnik na prąd stały (napędowy) – http://itp.nyu.edu/physcomp/Labs/DCMotorControl
Serwomechanizm (np do wyznaczania kierunku) – na moim blogu http://sprae.jogger.pl/2009/02/20/terminator-howto/
Z góry nadmieniam, że moje zaawansowanie w dziedzinie elektroniki oceniam jako podstawowe…Jeśli autor tej strony pozwoli, będę kontynuowała temat. Załóżmy, że kupuję tani samochód zdalnie sterowany. Otwieram pilota zdalnego sterowania i widzę obraz taki jak (lub przypuszczam podobny http://www.coding4fun.net/images/ComputerControlledRCCarwithCamera_525E/CIMG02014.jpg. Mechaniczne zamknięcie poszczególnych obwodów powoduje jazdę samochodu w przód, tył, lewo, prawo. Wyprowadzam 6 przewodów jak na rysunku http://www.coding4fun.net/images/ComputerControlledRCCarwithCamera_525E/CIMG02084.jpg . I teraz proszę o wyjaśnienie i podpowiedź – jak podłączyć je do arduino i jak sterować jazdą z poziomu komputera (na przykład klawiszami kierunkowymi). I może jeszcze jedno słowo dlaczego taki projekcik. Uważam, że wykonanie go sprawiłoby większą przyjemność niż np. zakup gotowego http://www.morele.net/rc-mini-car-zdalnie-sterowany-samochodzik-na-usb-05423-204212/. Nie mówiąc już o możliwości rozbudowy kamera, analiza obrazu itp… Później można oczywiście zbudować własny model, o którym wspomina sprae.
Ehhh, AJAX i przypadkowe kliknięcie back…. grrrr
Jeszcze raz, w skrócie ;) – Autor strony pozwala a nawet zachęca. Co najwyżej można się przenieść na forum Arduino http://forum.nettigo.pl/ może będzie wygodniej.
Co do meritum:
Witam serdecznie
Przeanalizowałem artykuł i przykładowy kontroler. Wyjścia podłączone do joysticków kontrolera są kluczowane do masy. Można zaryzykować i spróbować podłączyć je do wyjść „DIGITAL” w Arduino, uaktywniając dany przełącznik zerem logicznym „LOW”.
W artykule byli trochę ostrożniejsi i zastosowali przekaźniki zastępujące przełączniki joystickow. O tym jak można podłączyć przekaźnik przeczytamy tu. http://www.arduino.cc/playground/uploads/Learning/relays.pdf
Myślę że w przypadku tej konkretnej aparatury wystarczyłyby same tranzystory z rezystorami.
Najważniejsze to zanalizować zakupiony nadajnik, tak by zobaczyć co z czym łączą joysticki.
Chętnie pomogę w podłączeniu, tylko potrzeba więcej konkretów.
Witam ponownie,
Znalazłam w internecie schemat:
a) http://www.shaunbowman.com/ProjectMedia/RcCar/more-moreBetterCircuitDiagram.gif
b) http://www.shaunbowman.com/ProjectMedia/RcCar/Car-Inside.JPG
Pytanie: Czy zamiast podłączać układ do LPT mogę podłączyć wszystko w ten sposób do Arduino?
Idea rozwiązania dokładnie taka jak na schemacie z drobnym ale – stan wysoki w porcie szeregowym to 2V (TTL logic level). Arduino na wyjściu cyfrowym daje 5V. Wiec trzeba zrobić dzielnik napięcia – podłączyć w szereg dwa rezystory o tak dobranych wartościach żeby 'pośrodku’ były 2V.
http://pl.wikipedia.org/wiki/Dzielnik_napi%C4%99cia
Ewentualnie dobrać inne tranzystory.
@Joanna: Brawo! Dobrze sobie radzisz. Wg. mnie spokojnie mozesz to wpiac w Arduino..
@Netmaniak: mysle, ze sie mylisz. Lpt to port rownolegly i ma stany ttl, czyli mmoga na nim wystepowac napiecia _od_ 2 do 5 V w stanie wysokim
czy będzie jakiś tutorial jak zmontować płytkę sterującą silnikami?
Chciałbym bardzo. Niestety ale ostatnio inne projekty, nie związane z Arduino pochłaniają mi mnóstwo czasu. Rezultat – względna cisza na tym blogu.
Jednak gdyby ktoś chciał spróbować to mogę zaproponować, że jeżeli zobowiąże się napisać jakiś tutorial (szczegóły do uzgodnienia) mogę pomóc sprzedając części z ekstra rabatem 20%.
Witam,
Chciałem zaproponować drobną optymalizację przedstawionego układu. Otóż Atmega na na wyjściach cyfrowych wewnętrzne pullupy 20k. Domyślnie są nieaktywne, ale można łatwo je włączyć. Po pinMode(buttonPin, INPUT); należly jeszcze zrobić:
digitalWrite(buttonPin, HIGH);
wtedy rezystor pomiędzy +5V a D4 będzie niepotrzebny (przycisk łączymy bezpośrednio pomiędzy gnd i D4).
Pozdrawiam,
Paweł
O nie wiedziałem o tym :)
Faktycznie dużo to upraszcza, warto o tym pamiętać.
Tak mnie naszła taka myśl. Z tego co pamiętam z zajęć na uczelni, to wciśnięcie przycisku powodowało dodatkowe zakłócenia i w efekcie układ mógł odebrać kilka zmian sygnału. Dlatego dodawało się tam jeszcze debouncer. Jak to jest, że ten przedstawiony układ wraz z kodem działa bezproblemowo mimo braku debouncera? :)
Dobre pytanie, ale odpowiedź jest banalnie prosta – delay(50); w loop :) O debouncingu jest w innym miejscu https://starter-kit.nettigo.pl/2011/09/sygnalizator-revisited-czyli-przyciski-i-debouncing/
Jeśli przycisk inicjalizuje czynność funkcję działającą dłużej niż czas drgania to nie trzeba się męczyć :)
Niby proste, a o tym zupełnie nie pomyślałem. Dzięki wielkie za odpowiedź :)