Vaše projekty: Projekt „Bombona“
V rámci soutěže ke 4000 fanouškům na naší FB stránce se sešlo spoustu zajímavých projektů. To nás namotivovalo k tomu zde vytvořit rubriku Vaše projekty. Víme totiž, že je super mít možnost nechat se inspirovat od ostatních. Jako první Vám přinášíme článek o projektu, který nám poslal Jan Hons Šuškleb. S ním také vyhrál první cenu.
Vše začalo asi před rokem. Začal jsem na zelené louce a prošlapával si cestu neznámým terénem. Vlastně, abych si ověřil využitelnost internetu jako čistě vzdělávacího média a co vše a jakým způsobem je využitelné. Proto jsem projekt paojal širším způsobem. Vyzkoušel 3D tisk, naučil se základy programování a rozšířil si obzory.
Pokud by měl někdo obdobný zájem si vše vyzkoušet, pokusím se celý proces sumarizovat v tomtlo článku.
Procesy, které je možné zvládnout pomocí návodů na youtube a obdobných serverech:
- výroba, kompletace, rozchození a naučení se létání s RC modelem, 🙂
- RC simulátor Phoenix,
- Google Sketchup – pro 3D tisk,
- Netfabb – finish 3D tisku (vystřelovací mechanismus bomby),
- Visual Studio s pluginem Micro (programování Arduina),
- Arduino language,
- pájení a práce s SMD technologií,
- návrh obvodu a simulace obvodu,
- Eagle (pro návrh PCB tištěného spoje),
- domácí výroba PCB,
- zdokonalení se v anglickém jazyce
- a nějaké další dovednosti jako soustružení, sváření, řízení auta, odhánění dětí od nedodělané práce atd.
Každý z těchto procesů je pro začátečníka poměrně náročný a cesta k úspěchu, byť jen částečnému, je plná mnohdy zoufalých pokusů a omylů a vyžaduje nesmírnou trpělivost. Odměnou je ale báječný pocit, že je to alespoň částečně možné ve zcela amatérských podmínkách, bez předchozích znalostí či dovedností, a každá takto nově nabitá zkušenost pootvírá dveře do krásných zákoutí technologické říše divů.
V následujícím představení projektu upozadím procesy přímo nesouvisející s Arduinem a pouze bych k tomu podotknul, že naučit se létat pro mne bylo nejtěžší dovedností, kterou je třeba navíc zcela v mozku zautomatizovat. Proto bych doporučil, z úplného kraje, pár dnů potrénovat se simulátorem a až potom se pustit do rozsekávaní modelů na louce. Každý podle svého gusta. Já jsem samozřejmě začal na louce a až s hromádkou kuliček z EPP jsem pořídil simulátor.
Pájení, výroba PCB, 3D tisk už jsou přeci jen méně adrenalinové záležitosti a dají se zmáknout v klidu, po nocích, z křesla u počítače. Nejprve jsem vyzkoušel Arduino IDE, ale po pár nocích hraní si s template projekty mne přestalo bavit bílé prostředí a u složitějšího kódu nemožnost skrývání stromů kódu a nějak jsem intuitivně tušil, že to jde určitě i jinak a třeba třídění proměnných a automatické doplňování kódu by taky bodlo. Proto jsem sjel tutoriály od Microsoftu: Jak na Visual Studio, a naučil se tak základy.
Bylo třeba doinstalovat Plugin Micro. Vše v předcházejícím návodu.
Obsah článku:
Armstrong
Prvním projektem se stal Armstrong: blikač-pípač- generátor kostky-přehazovač blikacích sekvencí a tak podobně. Doplněno o MP3 přehrávač se tak ze staré krabice na špendlíky stal na několik dnů raketoplán. Děti si s tím chvilku vyhrály, hlavně si to pomohly sestrojit a několikrát letěly za gaučem na Mars i na měsíc.
Poté jsem sestrojil pípač s rf modulem a nakrmil ho upraveným kódem – odsud: https://www.arduino.cc/en/tutorial/melody.
int speakerPin = 17; int length = 25; // the number of notes char notes[] = "CaaggeecCaaggeecoeeee"; // a space represents a rest int beats[] = { 4, 2, 2, 2, 2, 1, 3, 4, 4, 2, 2, 2, 2, 1, 3, 4, 2, 1, 1, 1, 1, 2, }; int tempo = 150; void playTone(int tone, int duration) { for (long i = 0; i < duration * 1000L; i += tone * 2) { digitalWrite(speakerPin, HIGH); digitalWrite(13, HIGH); delayMicroseconds(tone); digitalWrite(speakerPin, LOW); digitalWrite(13, LOW); delayMicroseconds(tone); } } void playNote(char note, int duration) { char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'o' }; int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 0 }; // play the tone corresponding to the note name for (int i = 0; i < 8; i++) { if (names[i] == note) { playTone(tones[i], duration); } } } void setup() { pinMode(speakerPin, OUTPUT); pinMode(13, OUTPUT); } void loop() { for (int i = 0; i < length; i++) { if (notes[i] == ' ') { delay(beats[i] * tempo); // rest } else { playNote(notes[i], beats[i] * tempo); } // pause between notes delay(tempo / 2); } for (int i = 0; i < 5; i++) { digitalWrite(13, HIGH); delay(50); digitalWrite(13, LOW); delay(100); } delay(250); }
Konstrukce je obdobná jako RF vysílač odsud. Má pin ATAD a ten se spojí s Arduino vstupovýstupem a napájení s malou LiPol baterkou. To je celé. Více viz zde.
Následovaly mé chabé pokusy s testováním senzorů, ale posléze jsem přišel na to, že existují již hotová kompletní řešení pro všechny senzory, co jsem si půjčil, a že mne to vlastně nebaví. Chtěl jsem dětem sestrojit robota, ale pak jsem jej našel na Aliexpresu hotového, a tak jsem Arduino odložil do šuplíku na neurčito, přemýšlel o koupi hotových řešení a přišlo první zoufalství. Vše již stejně bylo, je a bude uděláno v Číně, proč objevovat Ameriku, když to stačí objednat.
- Našel jsem tedy profesionální RF odpovídač TBeacon
- Letadlo i s odhazováním bomby
- Profi nasvícení letadla
- Kompletní autopilot
Takže, kdo se s tím vším nechce otravovat a projekt se mu líbí, může si to koupit vše hotové. A Amos Komenský ať se jde zahrabat a dá si oběd v čínském bistru pod bustou pana prezidenta. Vše letělo do kouta, zaprášený ovladač od televize dostal nové baterky a po příchodu z práce jsem se opět resetoval u televize.
Jenže jednoho večera mě tak děsně namíchli s neustálým vymýváním mozku, že ovladač letěl z okna, kutil ve mně se vzepřel a já opět vytáhl Arduino ze šuplíku. Chtěl jsem udělat něco zvláštnějšího a pustit se trošku víc do bastlení, a tak jsem si pořídil řiditelné ledky WS2812B (1, 2).
Jenže NeoPixel kód, teď už vím, že se tomu říká „knihovna“, se mi nelíbil, a tak jsem se naučil používat knihovny a github: https://visualstudio.github.com/. A začal experimentovat s geniální knihovnou FASTLED (G+ komunita).
A zase mě to chytlo. A světlo světa spatřil tento light box:
Video Lightbox
Co umí: spoustu sekvencí, zpomalování, zrychlování a přibral jsem další skill a sice řízení z PC přes serial port. A naučil se psát si primitivní aplikace.
Poznámka pro ty, co s tím třeba ještě nezačali… Byly stavy, kdy jsem mlátil hlavou o klávesnici a naprosto zoufale nechápal, proč to nejede, kde zas chybí nebo přebývá středník a proč programátoři nejsou lidi. A tak jsem objevil komunitu a zjistil, že lidé kolem Arduina jsou poměrně sdílní nadšenci ochotní pomoct a tu a tam se podělit o radu.
A pak už to šlo samo.
Kecám.
Ne nešlo.
Neo se ze mě přes noc nestal, ale osvojil jsem si cyklus neustálého hledání informací v referenčním manuálu, v knihách, fórech a tutoriálech, tedy návodech. Po nějaké době se mi začal jevit kód z internetu jasnější a srozumitelnější a pochopil jsem, že jsou tak asi dva druhy kodérů. Geniální čuňata a shovívaví průvodci neméně tak geniální. A pak taky tak něco mezi a jak kdy.
Čuňáckým kódem nemá vůbec smysl se zabývat a prase, aby se v tom vyznalo. Shovívavý průvodce má kód popsaný, někdy i krásně upravený, a občas je radost se v tom hrabat a člověk se ledacos naučí. A když se k tomu po měsíci vrátí, tak do toho zas nemusí čučet od začátku. To jen tak na okraj, pokud někdo dočetl až sem, čemuž se upřímně divím a v tom případě mi to dělá radost.
if here == ažsem potom radost = nějaká hodnota
Pomohlo mi psát si kód takto a až pak jej začít strkat do závorek, středníků a dalších celků. Následovala miniaturizace a s tím spojený přechod na pro mé účely zcela vyhovující „platformu“ Attiny a začal jsem experimentovat s čipy Attiny45 a Attiny85 dle tohoto návodu. Tím jsem potunil bedničku Armstrong, a uvolnil si tak Arduino UNO na další pokusy.
Na jakékoli druhy blikání a na časování nenáročné operace je to podle mě úplně skvělé. Zde je krásně vidět, kolik pinů má který čip k dispozici, a kódování jsem nijak upravovat nemusel.
A na řadu přišel první FSM. A potřeba multitaskingu a Interrupts a další krásné záhady Arduina. A knihovnička s čudlíkem a knihovnička na servo a první robot na světě. Bohužel nemám dokumentaci, jednalo se o pár pokusů se servama a motorkem. A na řadu přišla potřeba výroby prvního tišťáku. A naprosto frustrující a zničující učení se programu EAGL na kreslení tišťáků.
Pokud někdo začíná, nedělejte stejnou tvrdohlavou chybu jako já a nezačínejte s EAGLEM. Je to mocný nástroj, ale vůbec žádný sluha. Intuitivnost naprosto nulová a to co jsem se před pár měsíci naučil ve sketchupu kvůli 3D tisku, tak v Eaglu jde naprosto proti tomu. Vývojáři toho programu patrně nejsou lidi, ale nějaký druh umělé inteligence. Zlomit ten program mi dalo opravdu děsnou práci. Na druhou stranu v ničem jiném bych už teď nechtěl dělat, protože toho svede opravdu hodně a skvěle. Ale pro začátečníka je to děs. Jistě existují i lehčí programy, na druhou stranu tento je v základu pro domácí kutění zdarma a dá se v něm udělat úplně naprosto vše kolem návrhů elektroniky.
Googloval jsem pojem leptání fotocestou. A postupoval podle návodu z těchto stránek mlab.cz. S tím, že PCB jsem koupil už s fotovrstvou.
Bombona
Nakonec tedy spíš konečně přišel čas, kdy jsem pocítil potřebu si kód nějak graficky nakreslit, protože jsem se ztrácel v logice, co ze kterého stavu se má pokračovat kam. Můj požadavek na 2CH dvoukanálové ovládání je následující.
- 1CH (GEARS) z recievru letadla ovládá serva podvozku a s tím rozsvěcuje i přistávací světla (přistávací sekvenci)
- 2CH (FLAPS) při 1/3 signálu mění sekvence blikání a bomb drop, při plném signálu vysouvá klapky přes zpomalovač.
sekvence blikání:
- OFF ( Arduino ve sleep modu spotřeba teoretických 6uA, praktických úplně jinde a to teď ladím)
- ALARM (vše bliká při vybité baterce) – under construction
- STANDARD
- TAXI (při pojíždění po runway)
- BLUE (upozornění před vypuštěním bomby nebo možnost skoku do STD režimu)
- BOMB DROP
Z toho vyplývá, že jsem začal tvořit jakési stavy nějakého vnitřního stroje a nemohl jsem se v tom vyznat, co má po čem následovat. A tak jsem objevil krásný online nástroj GLIFFY, ve kterém se dají jednotlivé stavy krásně rozkreslit, nebo třeba i jen myšlenková mapa. A kód se pak dá navrhovat snadněji.
A pak už jsem se pustil do finálního programování vlastního blikače a odhazovače. Požadované funkce:
- Blikání s digitálními ledkami WS2812B
- Blikání s normálními ledkami
- Ovládání serva
- Ovládání dvěma RC kanály – jeden na vysouvání podvozku, ten rozsvítí přistávací sekvenci, druhý na odhazování bomby, vysouvání klapek a přepínání sekvence blikání.
- Přepínání dotykovým spínačem (když je ero na zemi a pro testování)
- Přepínání do režimu nízké spotřeby a vypnutí komplet.
- Monitorování napětí baterky.
- A příprava na spolupráci s Ardupilotem. (to jsem zatím neimplementoval)
Přikládám i ukázkový kód, ale opatrně s tím, protože jsem tam pomazal hlavičky odkud jsem to polepil, a tak by se autoři oněch řádků mohli čepýřit. Nějak jsem jaksi vůbec nepočítal, že bych to někdy někam dával, ale kamarádovi se to líbilo a přesvědčil mne, tak se s vámi o to dělím!
Zatím jsem nestudoval ty licence a ochrany autorství a takové věci, ale budu se do toho muset brzo pustit. Zde tedy ukázka amatérského kódu. Varuji ale profíky a hnidopichy – „z tohodle vás asi trefí šlak!“ Ale co?! Já mám radost, že to funguje!!! A o to podle mě jde především.
Můj amatérský kód:
/* Name: Navlights_2016_susu_Duben_v9.ino Created: 3/29/2016 7:57:36 PM Author: Já + půl internetu docela by mně bodlo, kdyby mně nějaký dobrák vysvětlil jak se to tady s tou hlavičkou dělá. */ #include "FastLED.h" #include "Button.h" #include "PinChangeInt.h" #include "Servo.h" #define NUM_LEDS 2 #define LED_DT 5 #define LED_TYPE WS2812B #define COLOR_ORDER GRB #define FRAMES_PER_SECOND 100 //*********************_POWERSLEEEP___************************************ #include "LowPower.h" const int wakeUpPin = 2; ///*********END___INTEGERS POWER SLEEP____******************************************** //uint8_t max_bright = 255; struct CRGB leds[NUM_LEDS]; int ledMode; // Starting mode is typically 0. Use 99 if no controls available. ###### CHANGE ME ######### int maxMode; int lastMode; int multiswitch; // Pushbutton pin definition const int buttonled = 11; //LED in power button já si to prostě občas popisuju anglicky protože mně pak kolegové nečeši rozumí při pomoci int buttonState = 0; int lastButtonState = 0; #define BUTTON_PIN 2 // Digital pin used for debounced pushbutton #define PULLUP true #define INVERT true #define DEBOUNCE_MS 10 #define BLINK_INTERVAL 100 #define LONG_PRESS 3000 Button myBtn(BUTTON_PIN, PULLUP, INVERT, DEBOUNCE_MS); // Declare the button enum { ONOFF, TO_BLINK, BLINK, TO_ONOFF }; uint8_t buttonSTATE; //The current state machine state boolean buttonledState; //The current LED status unsigned long ms; //The current time from millis() unsigned long msLast; // Generic variables uint8_t thisdelay = 0; // Standard delay uint8_t thishue = 0; // Standard hue uint8_t thissat = 255; // Standard saturation int thisbright = 0; // Standard brightness uint8_t thisfade = 224; // Standard fade rate bool thisdir = 0; // Standard direction //___INTEGERS RECIEVER BUS____******************************************** int Gear; int Flaps; int alarmmode = 0; boolean Offmode; //RC swicth ints boolean Smode; boolean Tmode; boolean LLmode; boolean Amode; byte Amodecount; //___INTEGERS SERVO BUS____******************************************** #define GEAR_IN_PIN 4 #define FLAPS_IN_PIN 3 // #define GEAR_OUT_PIN 12 #define FLAPS_OUT_PIN 10 //Bomb Servo servoGEAR; Servo servoFLAPS; #define GEAR_FLAG 2 // These bit flags are set in bUpdateFlagsShared to indicate which #define FLAPS_FLAG 4 // channels have new signals volatile uint8_t bUpdateFlagsShared; volatile uint16_t unGEARInShared; volatile uint16_t unFLAPSInShared; uint32_t ulGEARStart; uint32_t ulFLAPSStart; //___INTEGERS TAIL STROBO FLASHERU____******************************************** const int ledx = 7; int stateONOFF = LOW; int ledx_ONOFF = 1500; //pause time unsigned long currentMillis = 0; unsigned long previousONOFF_Millis = 0; boolean blink = false; unsigned long currentstrobo = 0; unsigned long previousstrobo = 0; long OnTime = 70; //on step long OffTime = 140; //off step int ledState = LOW; int nmbrcount = 4; int pocitani = 0; //____WING__INTEGERS_______******************************************************* //const int ledwing = 8; int stateONOFF_wing = LOW; int ledx_ONOFF_wing = 1500; //pause time unsigned long currentMillis_wing = 0; unsigned long previousONOFF_Millis_wing = 0; boolean blink_wing = false; unsigned long currentstrobo_wing = 0; unsigned long previousstrobo_wing = 0; long OnTime_wing = 60; //on step long OffTime_wing = 180; //off step int ledState_wing = LOW; int nmbrcount_wing = 4; int pocitani_wing = 0; //______Beacon____*************************************************** int beacon1 = 6; // the PWM pin the LED is attached to boolean beac01 = false; uint8_t xbeacon = 0; byte xbeaconval = 0; //______Landning____*************************************************** const int LLled = 13; boolean ONOFFland = false; int LLledState; void setup() { //Serial.begin(9600); delay(500); digitalWrite(buttonled, HIGH); servoFLAPS.writeMicroseconds(1800); //pinMode(wakeUpPin, INPUT); //sleep wakeup pinMode(buttonled, OUTPUT); //Button Led pinMode(ledx, OUTPUT); // Tail led. v ocase pinMode(beacon1, OUTPUT); // Analog1 - Beacon led. MAJAK A0 pinMode(LLled, OUTPUT); // Landing led. v křídlech LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS); //ws2812 v křídlech //FastLED.setBrightness(max_bright); // set_max_power_in_volts_and_milliamps(5, 1000); // UNDER CONSTRUCTION change_mode(ledMode, 0); // Initialize the first sequence //********************____RC_READ___************** // servoGEAR.attach(GEAR_OUT_PIN); servoFLAPS.attach(FLAPS_OUT_PIN); PCintPort::attachInterrupt(GEAR_IN_PIN, calcGEAR, CHANGE); PCintPort::attachInterrupt(FLAPS_IN_PIN, calcFLAPS, CHANGE); xbeaconval = 0; //majak initializace 0 } void loop() { detachInterrupt(0); ms = millis(); //show_at_max_brightness_for_power(); RCread(); RCswitch(); readbutton(); change_mode(ledMode, 0); // Strobe, don't set it. } void change_mode(int newMode, int mc) { // mc stands for 'Mode Change', where mc = 0 is strobe the routine, while mc = 1 is change the routine maxMode = 6; if (mc) Beacon(false); // Set this OFF as default if (mc) Landing(false); if (mc) fill_solid(leds, NUM_LEDS, CRGB(0, 0, 0)); // Clean up the array for the first time through. Don't show display though, so you may have a smooth transition. switch (newMode) { // First time through a new mode, so let's initialize the variables for a given display. case 0: if (mc) { thisdelay = 20; } Off(); break; // All off, not animated. case 1: if (mc) { thisdelay = 20; } Beacon(true); TailONOFF(1700, 5); Sinusovac2(); break; // Standart Strobo2(0xff, 0xff, 0xff, 2, 70, 75); case 2: if (mc) { thisdelay = 20; } Landing(true); Beacon(true); TailONOFF(1000, 3); Sinusovac(); break; //Landing {thisdelay=20;} SinusovacPIN(); case 3: if (mc) { thisdelay = 20; } SinusovacLR(); TailONOFF(3500, 2); break; //Standby TAXI Landing case 4: if (mc) { thisdelay = 20; } Beacon(true); TailONOFF(500, 4); Wingstrob(800, 3); break; // Full Strobo - ALARM Strobo1(0xff, 0xff, 0xff, 5, 70, 75); case 5: if (mc) { thisdelay = 20; } Drop(); {fill_solid(leds, NUM_LEDS, CRGB(0, 0, 255)); LEDS.show(); } LEDS.show(); break; // BLUE on, not animated. case 6: if (mc) { thisdelay = 20; } Beacon(true); break; //beacon } // switch newMode ledMode = newMode; lastMode = ledMode; } // change_mode() //---------------------- WINGS - křídla - ws2812 --------------------------------------------- void Standby() { /* leds[0] = CRGB::Red; leds[1] = CRGB::Green; LEDS.show(); */ } void Wingwhite() { leds[0] = CRGB::White; leds[1] = CRGB::White; LEDS.show(); } void Wingblack() { leds[0] = CRGB::Black; leds[1] = CRGB::Black; LEDS.show(); } void Wingstrob(int ledx_ONOFF_wing, int kolikrat_wing) { currentMillis_wing = millis(); currentstrobo_wing = millis(); if (currentMillis - previousONOFF_Millis_wing >= ledx_ONOFF_wing) { blink_wing = !blink_wing; previousONOFF_Millis_wing += ledx_ONOFF_wing; } if ((blink_wing == true) && (stateONOFF_wing == LOW)) { stateONOFF_wing = HIGH; Wingstrobo(); } else { stateONOFF_wing = LOW; } nmbrcount_wing = kolikrat_wing; Pocitadlo_wing(); } void Wingstrobo() { if ((ledState_wing == HIGH) && (currentstrobo_wing - previousstrobo_wing >= OnTime_wing)) { ledState_wing = LOW; previousstrobo_wing = currentstrobo_wing; // digitalWrite(ledwing, ledState); Wingblack(); } else if ((ledState_wing == LOW) && (stateONOFF_wing == HIGH) && (currentstrobo_wing - previousstrobo_wing >= OffTime_wing)) { ledState_wing = HIGH; previousstrobo_wing = currentstrobo_wing; // digitalWrite(ledwing, ledState); Wingwhite(); pocitani_wing = pocitani_wing + 1; } } void Pocitadlo_wing() { if ((pocitani_wing >= nmbrcount_wing) && (blink_wing == true)) { pocitani_wing = 0; blink_wing = false; // digitalWrite(ledwing, LOW); Wingblack(); } stateONOFF_wing = LOW; } //----------------------Sinusovac WS2812B --------------------------------------------- void Sinusovac() { uint8_t xsin = beatsin8(25, 0, 255); // beatsin16(BPM,min,max); leds[0] = CRGB(xsin, 0, 0); leds[1] = CRGB(0, xsin, 0); LEDS.show(); } // konec sinusovace //----------------------Sinusovac LEFT/RIGHT WS2812B --------------------------------------------- void SinusovacLR() { uint8_t xsinlr = beatsin8(22, 0, 255); // beatsin16(BPM,min,max); leds[0] = CRGB(xsinlr, 0, 0); byte z = 255 - xsinlr; leds[1] = CRGB(0, z, 0); LEDS.show(); } // konec sinusovace //----------------------Sinusovac2 WS2812B --------------------------------------------- void Sinusovac2() { uint8_t xsin2 = beatsin8(29, 0, 255); // beatsin16(BPM,min,max); leds[0] = CRGB(xsin2, 0, 0); leds[1] = CRGB(0, xsin2, 0); LEDS.show(); if (xsin2 <= 7) { Wingwhite(); } if (xsin2 <= 5) { Wingblack(); } if (xsin2 <= 3) { Wingwhite(); } if (xsin2 <= 1) { Wingblack(); } } // konec sinusovace //**************************___TAIL STROBO FLASH___**********************************************************************// ///* void TailONOFF(int ledx_ONOFF, int kolikrat) { currentMillis = millis(); currentstrobo = millis(); if (currentMillis - previousONOFF_Millis >= ledx_ONOFF) { blink = !blink; previousONOFF_Millis += ledx_ONOFF; } if ((blink == true) && (stateONOFF == LOW)) { stateONOFF = HIGH; Tailstrobo(); } else { stateONOFF = LOW; } nmbrcount = kolikrat; Pocitadlo(); } void Tailstrobo() { if ((ledState == HIGH) && (currentstrobo - previousstrobo >= OnTime)) { ledState = LOW; previousstrobo = currentstrobo; digitalWrite(ledx, ledState); } else if ((ledState == LOW) && (stateONOFF == HIGH) && (currentstrobo - previousstrobo >= OffTime)) { ledState = HIGH; previousstrobo = currentstrobo; digitalWrite(ledx, ledState); pocitani = pocitani + 1; } } void Pocitadlo() { if ((pocitani >= nmbrcount) && (blink == true)) { pocitani = 0; blink = false; digitalWrite(ledx, LOW); } stateONOFF = LOW; } //*/ /* void TailONOFF(int casovac, int defpocitac) { uint8_t zapvyp; zapvyp = beat8(25, 0); if (zapvyp < 140) { uint8_t blik; blik = beat8(230, 0); if (blik >= 230)ledState = HIGH; else ledState = LOW; } else { ledState = LOW; } digitalWrite(ledx, ledState); } */ //KONEC **************************************************************************************************************** //----------------------Sinusovac pin BEACON--------------------------------------------- void Beacon(boolean beac01) { if (beac01 == true) { uint8_t xbeaconval = beatsin8(9, 0, 255, 0, 0); //xbeacon = cubicwave8(xbeaconval); xbeacon = quadwave8(xbeaconval); analogWrite(beacon1, xbeacon); } else analogWrite(beacon1, 0); } // konec sinusovace //----------------------Landning --------------------------------------------- void Landing(boolean ONOFFland) { if (ONOFFland == true) { LLledState = HIGH; } else { LLledState = LOW; } digitalWrite(LLled, LLledState); } // konec landing //----------------------All PINS OFF--------------------------------------------- void Off() { Offmode = true; digitalWrite(ledx, LOW); digitalWrite(LLled, LOW); analogWrite(beacon1, 0); fill_solid(leds, NUM_LEDS, CRGB(0, 0, 0)); LEDS.show(); } void Sleep() { Off(); attachInterrupt(0, wakeUp, LOW); LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); } //---------------------- Utility Functions --------------------------------------------- void wakeUp() { // Just a handler for the pin interrupt. } int wrap(int step) { if (step < 0) return NUM_LEDS + step; if (step > NUM_LEDS - 1) return step - NUM_LEDS; return step; } // wrap() void fill_solid_HSV(uint8_t ahue, uint8_t asat, uint8_t abright) { // Set all LED's to an HSV value. for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV(ahue, asat, abright); } } // fill_solid_HSV() void setPixel(int Pixel, byte red, byte green, byte blue) { leds[Pixel].r = red; leds[Pixel].g = green; leds[Pixel].b = blue; } void readbutton() { // Read the button and increase the mode myBtn.read(); if (myBtn.wasPressed()) { switchLED(); } if (myBtn.wasReleased()) { switchLED(); ledMode = ledMode >= maxMode ? 0 : ledMode + 1; // Reset to 0 only during a mode change change_mode(ledMode, 1); } if (myBtn.pressedFor(3000)) { switchLED(); digitalWrite(buttonled, LOW); ledMode = 255; change_mode(ledMode, 1); Sleep(); } } // readbutton() //*******************BUTTON signal LED**************************** void switchLED() { msLast = ms; //record the last switch time buttonledState = !buttonledState; digitalWrite(buttonled, buttonledState); } //Switch the LED on and off every BLINK_INETERVAL milliseconds. void fastBlink() { if (ms - msLast >= BLINK_INTERVAL) switchLED(); } //*******************RC Reciever functions**************************** void RCswitch() { if (Offmode == true) { Smode = true; //OFF mode Tmode = true; LLmode = true; Smode = true; Offmode = !Offmode; } else { if (Gear == 0 & Flaps == 0) { if (Smode == false) { change_mode(1, 1); // 1 STANDART Smode = true; } Tmode = false; Amode = false; LLmode = false; servoFLAPS.writeMicroseconds(1800); if (Amodecount > 2) { Amodecount = 0; } } if (Gear == 1 & Flaps == 0) { if (Tmode == false) { change_mode(3, 1); // 3 TAXI Tmode = true; } Smode = false; LLmode = false; Amode = false; } if (Gear == 1 & Flaps == 1) { if (LLmode == false) { change_mode(2, 1); // 2 LL LLmode = true; } Tmode = false; Smode = false; Amode = false; servoFLAPS.writeMicroseconds(1800); if (Amodecount > 2) { Amodecount = 0; } } if (Gear == 0 & Flaps == 1) { if (Amode == false) { switch (Amodecount) { case 0: if (1) change_mode(4, 1); break; //ALARM case 1: if (2) change_mode(5, 1); break; // BombDROP BLUE LIGHT case 2: if (3) change_mode(6, 1); break; // Beacon } Amodecount++; Amode = true; Serial.println(Amodecount); } Tmode = false; LLmode = false; Smode = false; } } //Serial.println(Smode); } //****************SERVO Functions***************************** void Drop() { servoFLAPS.writeMicroseconds(800); } void RCread() { // create local variables to hold a local copies of the channel inputs // these are declared static so that thier values will be retained // between calls to loop. static uint16_t unGEARIn; static uint16_t unFLAPSIn; // local copy of update flags static uint8_t bUpdateFlags; // check shared update flags to see if any channels have a new signal if (bUpdateFlagsShared) { noInterrupts(); // turn interrupts off quickly while we take local copies of the shared variables // take a local copy of which channels were updated in case we need to use this in the rest of loop bUpdateFlags = bUpdateFlagsShared; // in the current code, the shared values are always populated // so we could copy them without testing the flags // however in the future this could change, so lets // only copy when the flags tell us we can. if (bUpdateFlags & GEAR_FLAG) { unGEARIn = unGEARInShared; } if (bUpdateFlags & FLAPS_FLAG) { unFLAPSIn = unFLAPSInShared; } // clear shared copy of updated flags as we have already taken the updates // we still have a local copy if we need to use it in bUpdateFlags bUpdateFlagsShared = 0; interrupts(); // we have local copies of the inputs, so now we can turn interrupts back on // as soon as interrupts are back on, we can no longer use the shared copies, the interrupt // service routines own these and could update them at any time. During the update, the // shared copies may contain junk. Luckily we have our local copies to work with 🙂 } // do any processing from here onwards // only use the local values unFLAPSIn, unThrottleIn and unGEARIn, the shared // variables unFLAPSInShared, unThrottleInShared, unGEARInShared are always owned by // the interrupt routines and should not be used in loop // the following code provides simple pass through // this is a good initial test, the Arduino will pass through // receiver input as if the Arduino is not there. // This should be used to confirm the circuit and power // before attempting any custom processing in a project. // we are checking to see if the channel value has changed, this is indicated // by the flags. For the simple pass through we don't really need this check, // but for a more complex project where a new signal requires significant processing // this allows us to only calculate new values when we have new inputs, rather than // on every cycle. if (bUpdateFlags & GEAR_FLAG) { if (servoGEAR.readMicroseconds() != unGEARIn) { servoGEAR.writeMicroseconds(unGEARIn); } } if (bUpdateFlags & FLAPS_FLAG) { if (servoFLAPS.readMicroseconds() != unFLAPSIn) { } } bUpdateFlags = 0; /* int printme; int printmenew = unFLAPSIn; if (printmenew != printme) Serial.print("\t"); Serial.println (printmenew); // display if it changed printme= printmenew; */ if (unFLAPSIn > 1000 && unFLAPSIn < 1700) { Flaps = 1; //Serial.print("\t"); //Serial.println("Flaps 1"); } if (unFLAPSIn > 1800 && unFLAPSIn < 2100) { Flaps = 0; //Serial.print("\t"); //Serial.println("Flaps 0"); } if (unGEARIn > 1000 && unGEARIn < 1400) { Gear = 1; //Serial.print("\t"); //Serial.print("\t"); //Serial.println("Gear 0"); } if (unGEARIn > 1500 && unGEARIn < 2100) { Gear = 0; //Serial.print("\t"); //Serial.print("\t"); //Serial.println("Gear 1"); } /* if (unFLAPSIn < 100 && unGEARIn < 100) { ledMode = 5; change_mode(ledMode, 1); } */ } void calcGEAR() { if (digitalRead(GEAR_IN_PIN) == HIGH) { ulGEARStart = micros(); } else { unGEARInShared = (uint16_t)(micros() - ulGEARStart); bUpdateFlagsShared |= GEAR_FLAG; } } void calcFLAPS() { if (digitalRead(FLAPS_IN_PIN) == HIGH) { ulFLAPSStart = micros(); } else { unFLAPSInShared = (uint16_t)(micros() - ulFLAPSStart); bUpdateFlagsShared |= FLAPS_FLAG; } }
No a protože je dobré vědět kdy skončit, přikládám video toho mála, co mám zdokumentované, a přeji všem nadšeným bastlířům, i skutečným profesionálům, ať je nadšení neopustí a ta práce s Arduinem ať se stane nejen vaším osobním rozvojem, ale třeba i uměleckou tvorbou.
S pozdravem
J.H.Šuškleb
Janovi za projekt moc děkujeme a přejeme hodně úspěchů. Máte projekt, se kterým se chcete pochlubit? Napište na zbysek@bastlirna.hwkitchen.cz!
- Sledovač slunce s Arduinem - 23.3.2022
- Programovatelný kytarový pedál s Arduinem - 26.2.2020
- Arduino infračervený teploměr vytištěný na 3D tiskárně - 11.2.2020
6 Comments on “Vaše projekty: Projekt „Bombona“”
Napsat komentář
Pro přidávání komentářů se musíte nejdříve přihlásit.
Kamilh
2.5.2016 at 23:28Hm, abych pravdu rekl, jako modelar pouzivam klasicky volny kanal pro servo pumovnice a nadaval bych do era dalsi vahu ( shield, baterie a pod.) O to vic bonbonu se vejde. Trochu mi uchazi smysl projektu. Cilem bylo aby si deti odpovidacem odhodili bonbony kdy ony chteji? Cili trebas i kdyz nejni ero nad hlavou 🙂
Ardu2do
7.5.2016 at 13:55Cílem je RF „hon na lišku“
A něco se naučit.
Někam to spadne a pomcí vysílačky se hledá kam.
Dle popisu volny kanal na odhoz bomby neni k dispozici.
5ch klapky
6ch podvozek
Takže kombinaci tech dvou se uvolni 7me servo pro padak.
LuBoss
2.5.2016 at 10:03Paráda.
Ale přeci jenom jsem u videa až do konce čekal, zda uvidím to nejzajímavější – odhození pumy. To mi tak trošičku chybí 😉
Jiří Patera
1.5.2016 at 11:50Hezký „životní příběh“! A líbí se mi řada zajímavých odkazů a dobrých tipů ve stylu „jak na to“.
Jiří
1.5.2016 at 11:25Dobrá inspirace pro modeláře, ale ne všichni modeláři ovládají Arduino tak dokonale. Pokud by tento program měl sloužit jako návod postrádám:
1. seznam komponentů
2. zapojení pinů k Arduinu (ne každý je schopný z program toto vyčíst)
3.odkazy na použité knihovny (odkud se dají stáhnout)
4.připojení příjmače k Arduinu
Sám se už delší dobu o Arduino zajímám a tak vím jak jsou začátky těžké. Využívám volně šiřitelní programy a upravuji si je pro vlastní potřebu. Problémy dělá hledání použitých knihoven. Ne všichni autoři programů dávají na ně odkazy. Troufám si říct že hodě z nás co používáme Arduino jako inspiraci neovládá programování a využívá již hotové programy, případně je upravuje. Vymýšlet něco co už někdo vymyslel je ztráta času. Právě srozumitelné programy pomohou rozšířit řadu těch co se začnou o Arduino zajímat. Pro modeláře vyšla řada návodů v loňském ročníku RC revue. Autorovi tohoto článku přeji další úspěchy a pokud své další nápady bude zveřejňovat ať myslí na ty méně zručné v Arduinu.
Tomáš
25.4.2016 at 21:33Tak to je opravdu cool!