Witam !
Jest to mój pierwszy projekt opublikowany na Majsterkowo.pl , a więc proszę o wyrozumiałość. Jakiś czas temu zainteresowałem się elektroniką. Postawiłem na Arduino, ponieważ jest łatwe w oprogramowaniu, a także dostępne jest wiele bibliotek i przykładów. Po pewnym czasie, kiedy “nauczyłem” się programować, postanowiłem stworzyć jakiś projekt. Przeglądając internet znalazłem ciekawą rzecz, jaką jest “Useless Box”. Po zrozumieniu działania urządzenia wziąłem się do roboty.
Potrzebne rzeczy:
2x Serwo TowerPro MG-90s
1x Pakiet LiPol 7,4 V (równie dobrze można użyć koszyka zwykłych akumulatorków AA)
1x Przetwornica Step-Down (ja mam jakąś z Ebay’a za 1$)
1x Przełącznik dwupozycyjny
1x Opornik 10 kOhm
2x Opornik 1 kOhm
1x Buzzer
1x Jakieś pudełko
Oto schemat konstrukcji:
Sterowane przez Arduino serwa mają otwierać pudełko oraz przełączać przycisk. Czujnikiem wyzwalającym ruch serw jest przełączenie przycisku.W moim pudełku przewidziane są dwa serwa: jedno do otwierania pudełka, a drugie do przełączania przycisku. Do zasilenia ich wykorzystałem przetwornicę step-down ustawioną na 6 V. Oprócz serw w tym pudełko można też zauważyć buzzer. W razie rozładowania baterii zaczyna on piszczeć. Jest to bardzo przydatne, kiedy zasilamy jakiś układ z Li – Pola, ponieważ jego napięcie nie może spaść poniżej pewnej granicy. Oto cały kod pudełka:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
#include <Servo.h> Servo lapa; //ramię przełączające przycisk Servo drzwi; int przycisk = 7; //przycisk podłączamy do pinu 7 int buzzer = 11; //buzzer podłączamy do pinu 11 int volt = 0; //pomiar napięcia na pinie A0 int posL = 0; int posD = 0; int seq = 1; int licznik = 0; void setup() { lapa.attach(9); //serwo z ramieniem na pinie 9 drzwi.attach(10); //serwo otwierające drzwiczki na pinie 10 pinMode(przycisk, INPUT); pinMode(buzzer, OUTPUT); drzwi.write(35); //ustawienie startowej pozycji serwa(trzeba dopasować we własnej konstrukcji) lapa.write(20); delay(1000); } void loop() { int stan = digitalRead(przycisk); //zczyt stanu przycisku volt = analogRead(A0); //zczyt napiecia na akumulatorze if (volt <= 720) { tone (buzzer, 2000, 500); delay(1000); } if (stan == HIGH) { if (seq <= 1)Sekwencja1(); if (seq == 2)Sekwencja2(); if (seq == 3)Sekwencja3(); if (seq == 4)Sekwencja4(); if (seq == 5)Sekwencja5(); if (seq >= 6)Sekwencja6(); seq++; if (seq > 6)seq = int (random(0,7)); licznik = 0; } else if (stan == LOW) { lapa.write(20); drzwi.write(35); licznik++; if (licznik > 1000){ drzwi.write(20); delay(100); drzwi.write(32); delay(100); drzwi.write(20); delay(100); drzwi.write(32); delay(100); drzwi.write(20); delay(100); drzwi.write(32); delay(100); drzwi.write(35); delay(10); if (licznik >=1001) licznik = 0; } } delay(10); } void Sekwencja1() { for (posD = 35; posD >= 1; posD -= 1) { drzwi.write(posD); delay(15); } for (posL = 20; posL <= 150; posL += 1) { lapa.write(posL); delay(20); } delay(500); for (posL = 150; posL >= 20; posL -= 3) { lapa.write(posL); delay(5); } for (posD = 1; posD <= 35; posD += 3) { drzwi.write(posD); delay(5); } } void Sekwencja2() { delay(500); for (posD = 35; posD >= 1; posD -= 3) { drzwi.write(posD); delay(5); } for (posL = 20; posL <= 150; posL += 3) { lapa.write(posL); delay(5); } delay(500); lapa.write(140); delay(15); lapa.write(150); delay(15); for (posL = 150; posL >= 20; posL -= 3) { lapa.write(posL); delay(5); } for (posD = 1; posD <= 35; posD += 3) { drzwi.write(posD); delay(5); } } void Sekwencja3() { drzwi.write(10); delay(200); drzwi.write(35); delay(25); for (posD = 35; posD >= 1; posD -= 1) { drzwi.write(posD); delay(5); } for (posL = 20; posL <= 120; posL += 1) { lapa.write(posL); delay(15); } lapa.write(150); delay(500); for (posL = 150; posL >= 20; posL -= 3) { lapa.write(posL); delay(5); } for (posD = 1; posD <= 35; posD += 1) { drzwi.write(posD); delay(5); } } void Sekwencja4() { for (posD = 35; posD >= 1; posD -= 1) { drzwi.write(posD); delay(10); } for (posL = 20; posL <= 140; posL += 1) { lapa.write(posL); delay(10); } for (posL = 140; posL >= 20; posL -= 1) { lapa.write(posL); delay(10); } for (posD = 1; posD <= 35; posD += 1) { drzwi.write(posD); delay(10); } delay(1000); drzwi.write(1); delay(60); for (posL = 20; posL <= 150; posL += 4) { lapa.write(posL); delay(8); } delay(500); for (posL = 150; posL >= 20; posL -= 4) { lapa.write(posL); delay(8); } for (posD = 1; posD <= 35; posD += 1) { drzwi.write(posD); delay(10); } } void Sekwencja5() { for (posD = 35; posD >= 1; posD -= 3) { drzwi.write(posD); delay(5); } for (posL = 20; posL <= 130; posL += 3) { lapa.write(posL); delay(5); } for (posL = 130; posL <= 150; posL += 1) { lapa.write(posL); delay(100); } delay(500); for (posL = 150; posL >= 20; posL -= 3) { lapa.write(posL); delay(5); } for (posD = 1; posD <= 7; posD += 1) { drzwi.write(posD); delay(50); } for (posD = 7; posD <= 35; posD += 3) { drzwi.write(posD); delay(5); } } void Sekwencja6(){ for (posD = 35; posD >= 1; posD -= 3) { drzwi.write(posD); delay(5); } for (posL = 20; posL <= 150; posL += 3) { lapa.write(posL); delay(5); } lapa.write(125); delay(100); lapa.write(150); delay(100); lapa.write(125); delay(100); lapa.write(150); delay(100); lapa.write(125); delay(100); lapa.write(150); delay(100); for (posL = 150; posL >= 20; posL -= 2) { lapa.write(posL); delay(5); } drzwi.write(35); delay(80); } |
Zdaję sobie sprawę z tego, że kod ten można prawdopodobnie optymalizować jednak kiedy robiłem ten projekt nie miałem na to czasu, a teraz już mi na tym nie zależy. Teraz wytłumaczę trochę kod.
Sekwencje działania pudełka następują kolejno po sobie. Odpowiada za to ta część kodu.
1 2 3 4 5 6 7 8 9 |
if (seq <= 1)Sekwencja1(); if (seq == 2)Sekwencja2(); if (seq == 3)Sekwencja3(); if (seq == 4)Sekwencja4(); if (seq == 5)Sekwencja5(); if (seq >= 6)Sekwencja6(); seq++; if (seq > 6)seq = int (random(0,7)); licznik = 0; |
Po zakończeniu każdej sekwencji “seq” się zwiększa, a więc przy następnym przełączeniu włączy się już następna sekwencja. Kiedy już wszystkie zostaną uruchomione sekwencja jest wybierana losowo.
Ta część odpowiada za pomiar napięcia i działanie buzzera. W tym przypadku jeśli napięcie spadnie poniżej 7 V, to buzzer zaczyna piszczeć:
1 2 3 4 5 |
volt = analogRead(A0); //zczyt napiecia na akumulatorze if (volt <= 720) { tone (buzzer, 2000, 500); delay(1000); } |
Ta natomiast odpowiada za to, że jeśli przez dziesięć sekund ( licznik = 1000) przełącznik pozostanie w pozycji startowej, to drzwiczki pudełka stukają. Po każdym przełączeniu przycisku oraz po stuknięciu drzwiczkami, licznik ponownie rozpoczyna naliczać 10 sekund:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
else if (stan == LOW) { lapa.write(20); drzwi.write(35); licznik++; if (licznik > 1000){ drzwi.write(20); delay(100); drzwi.write(32); delay(100); drzwi.write(20); delay(100); drzwi.write(32); delay(100); drzwi.write(20); delay(100); drzwi.write(32); delay(100); drzwi.write(35); delay(10); if (licznik >=1001) licznik = 0; } } delay(10); |
Oto filmik przedstawiający działanie mojego “Bezużytecznego pudełka”, filmik nie jest najnowszy, jednak od tego czasu nic się nie zmieniło:
W moim pudełko przewidziane jest 6 sekwencji oraz jedna funkcja dodatkowa (stukanie), jednak każdy może dopasować ich ilość według własnego uznania. Mam nadzieję, że mój projekt wam się spodoba i pozytywnie ocenicie mój projekt. Na ewentualne pytania lub problemy związane z moim pudełkiem odpowiadam w komentarzach.
Na koniec przedstawiam kilka zdjęć:
Zajefajne! Widziałem już różne wersje bezużytecznego pudełka, ale ta jest najlepsza. Na początku myślałem, że to kolejny projekt, w którym niepotrzebnie wykorzystano mikrokontroler, który można by było zastąpić kilkoma elementami dyskretnymi, ale na szczęście myliłem się – Arduino pozwala na wykonywanie różnych interesujących sekwencji. Oczywiście na Atmedze zaprogramowanej w C też by się udało i byłoby bardziej profesjonalnie. Jak jest z poborem mocy na czuwaniu? Nie wiem, czy w Arduino jest taka możliwość, ale ogólnie w Atmedze są różne tryby uśpienia, dzięki czemu można ograniczyć prąd do mikroamperów. Sprawdzanie stanu przełącznika za pomocą if-a w nieskończonej pętli nie jest chyba zbyt energooszczędne – z tego, co wiem, lepiej wykorzystać przerwanie.
Pobór prądu w stanie czuwania wynosi ok. 50 mA.
Minus jest tego taki, że musi być osobny wyłącznik do wyłączenia całego układu. W przypadku standardowego pudełka na ne555 wajcha jest od razu wyłącznikiem.
Niekoniecznie – można tak zaprogramować mikrokontoler, żeby przechodził w tryb oszczędzania energii po przełączeniu przełącznika i ewentualnym wykonaniu sekwencji “niecierpliwienia się” pokazanej na filmiku :) . Mógłby poruszać klapką raz lub kilka razy co jakiś czas od ostatniego przełączenia, a potem wyłączyć zegar i inne zbędne podzespoły. W pilotach od telewizorów nie montuje się wyłączników zasilania, bo działają w podobny sposób, a prąd pobierany z baterii podczas uśpienia jest zaniedbywalnie mały w porównaniu z tym podczas pracy. Gdyby pilot był rzadko używany, to prędzej minąłby termin ważności baterii niż uległyby rozładowaniu.
witam, sam zrobiłem kiedyś podobne urządzenie, tak samo z podobnymi bajerami, tylko że było to na atmedze8, pchać płytkę za 100pln w taki projekt to grzech, a atmega kosztuje 5 pln
ps, foto
oraz elektronika, jeżeli będą osoby zainteresowane to i kod się zajdzie :)
Dlaczego zastosowałeś zewnętrzny kwarc? Atmega8 ma wbudowany rezonator RC, który powinien wystarczyć do tego zastosowania.
rozdzielczość pwm, na taktowaniu 8mhz ciężko było mi uzyskać odpowiednią częstotliwość pwm i w efekcie serwa szarpały,
Ciekawy sposób na użycie stabilizatora SMD ;)
znów ja, nie można edytować więc jedno pod drugim, moja płytka była wzorowana na tej z tej strony, wprowadziłem tylko kilka poprawek, autor w tym projekcie użył atmega328 i pisał program w arduino, nie ukrywam że bazowałem na jego projekcie, jednak 60% kodu uległo zmianie, może to zainspiruje innych majsterkowiczów :)
http://www.lamja.com/?p=451
Bardzo fajnie to wygląda :) Dzięki za wpis :)
Pomysł znany, ale warto go przypomnieć….super
Staranne wykonanie, ciekawy pomysł – spróbujemy go wykonać z synem. Pozdrawiam
Co do przechodzenia w stan uśpienia, był o tym doskonały wpis na majsterkowie to był chyba marudnik do kwiatów. Ja zastanawiam się po co pakiet 7,4V i step down nie lepiej jedno ogniwo i step UP, albo wogóle do całości arduino mini na 8mhz z ogniwa a zasilanie serw tylko przez przetwornicę w momencie włączenia, przetwornica włączana tranzystorem.
Generalnie filmik rozbawił mnie na ocenę :)
Witam serdecznie.
Posiadam na stanie w domu Arduino Uno. Czy może on zastąpić Leonardo?
Zauwazylem ze na schemacie przycisk jest podlaczony do SDA a buzer do pinu 7 w kodzie przycisk podłączamy do pinu 7, buzzer podłączamy do pinu 11.
Witam,
Jeżeli jest jakaś chociaż najmniejsza szans , żeby komuś takie gotowe pudełko odkupić, to byłabym niezwykle szczęśliwa.
Bardzo mi na tym zależy, dobrze zapłacę ;p
Pozdrawiam!
Właśnie robie. Jak zadziała jak trzeba to pani zrobie.
Witam! Jestem jestem zainteresowany kupnem “bezużytecznego pudełka”. Proszę o kontakt.