Close

Vaše projekty: Projekt „Bombona“

Arduino Letadlo

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.

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.

Armstrong - Arduino Ovladač Raketoplánu
Armstrong – Arduino Ovladač Raketoplánu

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.

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.

Historie experimentování - Od 555 po Android
Historie experimentování – Od 555 po Android

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.

První "úspěšně" vyleptaný pokus
První „úspěšně“ vyleptaný pokus

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!

Zbyšek Voda

6 Comments on “Vaše projekty: Projekt „Bombona“

Profilový obrázek
Kamilh
2.5.2016 at 23:28

Hm, 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 :)

Profilový obrázek
Ardu2do
7.5.2016 at 13:55

Cí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.

Profilový obrázek
LuBoss
2.5.2016 at 10:03

Pará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í ;-)

Profilový obrázek
Jiří Patera
1.5.2016 at 11:50

Hezký „životní příběh“! A líbí se mi řada zajímavých odkazů a dobrých tipů ve stylu „jak na to“.

Profilový obrázek
Jiří
1.5.2016 at 11:25

Dobrá 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.

Profilový obrázek
Tomáš
25.4.2016 at 21:33

Napsat komentář

shares