Vse radovedne glave si lahko preberete kako Moodiy deluje. Poglejte kaj so njegovi sestavni deli in kako so povezani med sabo. Vabljeni, da se prijavite na 404 delavnice ali si priskrbite dodatno opremo, da spremenite delovanje svojega Moodiy, se pri tem urite v programiranju in ga nadgradite še bolj po vaši zamisli.

Kako Moodiy deluje?

Moodiy-jevo vezje je sestaljeno iz RGB svetleče diode, ki je preko uporov povezana z mikročipom ATtiny85. Mikročip kontrolira delovanje svetleče diode. Nanj smo naložili programsko kodo. To so nekakšna navodila, po katerih mikročip regulira pretok napetosti na svetleči diodi. Ta navodila so zapisana tako, da dioda v vsakem krogu izmenja vse mavrične barve. To so kombinacije rdeče, zelene in modre svetlobe, ki gorijo samostojno ali v paru, vsaka tako, da je povsem prižgana ali pa, da utripa z različnimi frekvencami. Utripa se vprašamo? Za ta trik boste izvedeli spodaj v poglavju “Moodiy koda”, lahko pa utripanje vidite, če zelo pozorno od strani pogledate ali lažje, če snemate s kamero.

Elementi Moodiy vezja

RGB svetleča dioda

Svetleča dioda ali angleško Light Emitting Diode (LED) je polprevodniški elektronski element in deluje zaradi pojava elektroluminiscence. Poenostavljeno se zgodi to, da ko elektroni prehajajo čez strukturo svetleče diode, pri tem oddajajo fotone, svetlobo. Barva svetlobe, ki jo oddajajo svetleče diode, je odvisna od tega iz katerih materialov je dioda zgrajena.

V Moodiy uporabljamo RGB svetlečo diodo. RGB je oznaka za “Red”, “Green” in “Blue” ali slovensko rdeča, zelena in modra. Zgradba te diode je takšna, da lahko oddaja vse te tri barve svetlobe. To so osnovne barve svetlobe in z njimi lahko zmešamo še vse ostale, ki jih zaznamo z našimi očmi in vidimo z možgani. Zato naš Moodiy lahko deluje tako, da spreminja barve v celotnem mavričnem spektru.

Upor

Je eden izmed najpomembnejših in najpogosteje uporabljenih elektrotehničnih elementov. Uporabljamo ga za omejitev električnega toka. Zakaj je to pomembno? Če bi do našega porabnika, prišlo preveliko toka, bi se lahko poškodoval ali hitreje skvaril.

Upore običajno poznamo v obliki majhnih valjev iz razičnih materialov, poslikanimi z barvnimi črticami. Te črtice označujejo karakteristike upora, njegovo upornost in toleranco. Zelo pomembno je, da za delovanje našega vezja, izberemo upor s pravšnjo upornostjo.

Baterija z ohišjem

Naša naprava ne bo delovala, če nanjo ne priklučimo vira napetosti oziroma vira energije. Moodiy ne potrebuje veliko za svoje delovanje. Deluje na gumbno baterijo s 3,3 volti napetosti. Na vezju se nahaja okroglo ohišje, ki ima na sebi dva kontakta, enega za pozitivni in drugega za negativni pol baterije.

Stikalo

Stikalo našo napravo prižge ali ugasne. Z njim sklenemo ali prekinemo električni krog.

Čip ATtiny85

ATtiny85, ta mali hrošček, je mikročip ali bolje, mikrokontroler. To je mikrovezje. Podobno je celotnemu Moodiy vezju, le da je bistveno manjše in, da je sestavljeno iz drugih elementov. Videli bi ga, če bi odprli črno škatlico, njegovo ohišje.

Ta mikrokontroler lahko uporabimo za izdelavo različnih naprav. Tudi Moodiy je naprava, naprava za oddajanje barvne svetlobe. ATtiny85 ima 8 nogic in vsaka je namenjena določeni uporabi. Na te nogice povežemo elemente, ki jih potrebujemo za delovanje naprave po naši zamisli. Čisto vsega, kar bi si želeli, ne moremo povezati na mikrokontroler. Uporabimo lahko elemente, ki so zanj primerni, tiste, ki jih zmore upravljati. Obstajajo številni elementi, ki so za to primerni, različni senzorji in aktuatorji. Senzorji so tisti elementi, ki zaznavajo, nekaj sprejemajo iz okolja, aktuatorji pa tisti, ki izvajajo neko akcijo, oddajajo v okolje. Poznamo na primer senzor, ki zaznava svetlobo ali pa vlago, primer aktuatorja pa bi bil motor ali svetleča dioda.

Elemente za delovanje naše naprave, moramo pravilno povezati z mikrokontrolerjem. Pri tem si pomagamo s podatki in načrti, ki jih dobimo pri proizvajalcu mikrokontrolerja. Zato, da bo mikrokontroler upravljal z elementi tako kot si želimo, moramo zanj napisati programsko kodo, torej navodila po katerih bo deloval.

Tiskano vezje

Naše elemente ali komponente v vezju, povežemo med sabo tako, da jih spojimo in ustvarimo med njimi povezave. To lahko storimo s postopkom spajkanja tako, da jih spojimo kar enega na drugega, lahko si pomagamo z žicam, lahko vzamemo tudi ploščice v katere jih vstavimo skozi vnaprej pripravljene luknjice. Najbolj učinkovito pa je izdelati tiskano vezje!

Tiskano vezje je plošča, na kateri so posamezni elementi povezani med sabo preko povezav, ki se nahajajo v tej plošči. Vezje sprva narišemo v primernem računalniškem programu in ga nato izdelamo. Lahko ga izdelamo sami ali pa pošljemo svoj načrt podjetju, ki se ukvarja prav z izdelavo vezij.

Moodiy koda

Preden napišemo svojo programsko kodo, se vprašamo, kaj želimo, da naša RGB svetleča dioda počne? Mi želimo, da izmenja vse mavrične barve!

Kako pa sploh dobimo vse mavrične barve? Imamo tri osnovne barve svetlobe, rdečo, zeleno in modro. Če te barve svetlobe mešamo med sabo, dobimo vse ostale.

Ugotovimo, da če zmešamo rdečo in zeleno, dobimo rumeno, če zmešamo rdečo in modro dobimo magento, to je odtenek rožnate in, če zmešamo zeleno in modro, dobimo cian, to je odtenek modre ali modro-zelene.

Zato, da bo naša RGB svetleča dioda spreminjala barve tako, da se bodo prelivale med sabo, moramo počasi dodajati ali odvzemati barvo. Pričnimo z rdečo in modro. Prižgemo rdečo, nato pa v vsakem koraku malo bolj prižgemo modro, dokler nista obe povsem prižgani in vidimo magento. Nato pričnemo rdečo v vsakem koraku malo bolj ugašati, dokler ne gori samo še modra. Zdaj pričnemo vedno bolj prižigati zeleno, dokler povsem ne gorita tako modra, kot tudi zelena in vidimo cian. Zeleno pričnemo postopno ugašati, dokler ne gori samo zelena, nato pa pričnemo postopno prižigati rdečo, dokler ne gorita tako zelena, kot tudi rdeča in vidimo rumeno. Zeleno pričnemo počasi ugašati, dokler ne gori samo rdeča in tako pridemo na začetek svojega barvnega zaporedja.

Sedaj pa poglejmo, kako je potrebno zapisati programsko kodo, da bo RGB svetleča dioda res počela to, kar želimo. Ugotovimo, da je RGB svetleča dioda digitalna komponenta. To pomeni, da ima lahko samo dve vrednosti, 0 in 1. Lahko jo prižgemo ali ugasnemo, ne moremo je prižgati samo malo, kot bi to lahko storili z analogno komponento. Zato tukaj uporabimo trik, ki smo ga omenili že prej. Diodo lahko prižigamo in ugašamo zelo hitro, kar z našimi očmi ne zaznamo. Dioda pravzaprav utripa, a mi vidimo kot, da gori z neko jakostjo. Pojav zaradi katerega je to mogoče, se imenuje vztrajnost vida.

Če si narišemo graf, kot je ta spodaj, vidimo, da zato, da bo naša barva diode svetila bolj šibko, malo manj, jo moramo prižgati za zelo kratek čas in ugasniti za daljši čas ter to ponavljati z zelo hitrim izmenjevanjem. Ker mi teh hitrih sprememb ne vidimo, nam zgleda kot, da barva sveti samo bolj šibko.

Koda - kako smo jo zapisali?

Najprej si poglejmo glavno zanko z imenom loop() v kateri ugašamo in prižigamo različne barve naše RGB svetleče diode. Vsebina zanke je zapisana znotraj dveh zavitih oklepajev, ukazi pa se izvajajo eden za drugim po vrsticah dokler ne pridemo do konca. Potem izvajanje ukazov nadaljujemo na vrhu zanke. Ta postopek se ponavlja vse dokler fizično ne izklopimo vezja, zato rečemo da se zanka ponavlja v neskončnost.

Sedaj pa poglejmo kaj se dogaja znotraj glavne zanke. Najprej kličemo ukaz oz. funkcijo postopno_priziganje(), kjer moramo določiti katero barvo želimo postopno prižigati in hitrost prižiganja. Pri barvi lahko izbiramo med vrednostmi modra, rdeca in zelena. Hitrost priziganja pa dolocimo z vrednostjo cas2. Kako in kje so vrednosti nastavljene bo prikazano v nadaljevanju.


void loop() {

  postopno_priziganje(modra, cas2);
 
  postopno_ugasanje(rdeca, cas2);

  postopno_priziganje(zelena, cas2);
 
  postopno_ugasanje(modra, cas2);

  postopno_priziganje(rdeca, cas2);
 
  postopno_ugasanje(zelena, cas2);

  if (ze_dovolj_prizgan(prvi_cas, max_cas)) {
    ugasni_se();
  }
}

Ko smo do konca prižgali modro barvo dobimo mešanico modre in rdeče, ki je bila že predhodno prižgana. Sedaj rabimo ugasniti rdečo barvo. To storimo s funkcijo postopno_ugasanje(), kjer ponovno definiramo barvo (rdeca) in hitrost ugasanja (cas2). Postopek prižiganja in ugašanja barv ponavljamo dokler ne uporabimo vseh možnih kombinacij modre, zelene in rdeče. 

Včasih se zgodi, da pozabimo ugasniti vezje, zato na koncu zanke preverimo, če svetleča dioda gori že več kot 5 ur. To preverimo s pogojnim stavkom if(), kjer s funkcijo ze_dovolj_prizgan() preverimo ali je svetleča dioda prižgano več kot max_cas. V tem primeru ugasnemo vse barve s funkcijo 

Postopno prižiganje

void postopno_priziganje (int barva, int cas2){
  int cas1 = 0;
  while(cas1 < cas2){
      digitalWrite(barva, HIGH);
      delayMicroseconds(cas1);
      digitalWrite(barva,LOW);
      delayMicroseconds(cas2-cas1);
    cas1++; 
  }
  digitalWrite(barva,HIGH);
  delay(cas_vmes);
}
Funkcije ali bolj preprosto ukaze moramo definirati predno jih lahko uporabimo v glavni zanki. Kot pri glavni zanki najprej določimo tip funkcije void kar pomeni, da funkcija ne vrne nobene vrednosti, ko se izvede. Zadolžena je le, da postopno prižge željeno barvo in nič drugega. Najprej nastavimo vrednost cas1 na nič, da ga bomo lahko primerjali z vhodno vrednostjo cas2. Potem ponavljamo vsebino zanke while() vse dokler je cas1 < cas2. Znotraj zanke prižigamo in ugašamo določeno barvo z ukazom digitalWrite(), pri čemer HIGH pomeni prižgano, LOW pa ugasnjeno. S spreminjanjem časovnega zamika med prižgano in ugasnjeno barvo določamo svetlost določene barve. Zamik določamo z ukazom delayMicroseconds(). Ves čas se vrednost cas1 povečuje in ko preseže vrednost cas2 dokončno prižgemo željeno barvo. Ukaz delay(cas_vmes) uporabimo, zato da se barve ne menjavajo prehitro.

Postopno ugašanje

Podobno kot pri prižiganju tudi tukaj v zanki while() prižigamo in ugašamo željeno barvo dokler cas1 ne preseže cas2. Razlika tukaj je le ta, da na koncu barvo ugasnemo z ukazom digitalWrite(barva,LOW) in znotraj while() zanke nekoliko drugače določamo časovne zamike. Poskusite najti kakšna je razlika med trenutno in prejšnjo while() zanko.
void postopno_ugasanje(int barva, int cas2){
  int cas1 = 0;
  while(cas1 < cas2){
      digitalWrite(barva, HIGH);
      delayMicroseconds(cas2-cas1);
      digitalWrite(barva,LOW);
      delayMicroseconds(cas1);
    cas1++;
  }
  digitalWrite(barva,LOW);
  delay(cas_vmes);
}

Koliko časa še?

bool ze_dovolj_prizgan (unsigned long prvi_cas, unsigned long max_cas){
  return millis() - prvi_cas > max_cas;
}
S funkcijo ze_dovolj_prizgan() preverimo, če je presežen največji dovoljeni čas delovanja oz. max_cas. Pred imenom te funkcije ni besede void temveč bool, kar pomeni da nam funkcija vrne nek odgovor, ki je lahko 0 ali 1. V funkciji je bistvena vrednost prvi_cas pove kdaj smo prižgali vezje. Čas se v vezju šteje v milisekundah in do trenutnega časa lahko vedno dostopamo z ukazom millis(). Če želimo ugotoviti koliko časa vezje že deluje moramo od trenutnega časa millis() odšteti prvi_cas. Sedaj rabimo samo še preveriti

Ugasni se

void ugasni_se(){
  digitalWrite(rdeca, LOW);
  digitalWrite(zelena, LOW);
  digitalWrite(modra, LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();  
  sleep_mode(); 
}

Celotna koda

#include <avr/sleep.h>
  
int rdeca = 2;
int zelena = 1;
int modra = 0;

int cas1 = 0;
int cas2 = 4000;
int cas_vmes = 1000;

unsigned long prvi_cas = millis();
unsigned long max_cas = 5ul * 60ul * 60ul * 1000ul;

void setup() {
  pinMode(rdeca, OUTPUT);
  pinMode(zelena, OUTPUT);
  pinMode(modra, OUTPUT);
  digitalWrite(rdeca,HIGH);
}

void postopno_priziganje (int barva, int cas2){
  int cas1 = 0;
  while(cas1 < cas2){
      digitalWrite(barva, HIGH);
      delayMicroseconds(cas1);
      digitalWrite(barva,LOW);
      delayMicroseconds(cas2-cas1);
    cas1++; 
  }
  digitalWrite(barva,HIGH);
  delay(cas_vmes);
}

void postopno_ugasanje(int barva, int cas2){
  int cas1 = 0;
  while(cas1 < cas2){
      digitalWrite(barva, HIGH);
      delayMicroseconds(cas2-cas1);
      digitalWrite(barva,LOW);
      delayMicroseconds(cas1);
    cas1++;
  }
  digitalWrite(barva,LOW);
  delay(cas_vmes);
}

bool ze_dovolj_prizgan (unsigned long prvi_cas, unsigned long max_cas){
  return millis() - prvi_cas > max_cas;
}

void ugasni_se(){
  digitalWrite(rdeca, LOW);
  digitalWrite(zelena, LOW);
  digitalWrite(modra, LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();  
  sleep_mode(); 
}

void loop() {
  postopno_priziganje(modra, cas2);
  postopno_ugasanje(rdeca, cas2);
  postopno_priziganje(zelena, cas2);
  postopno_ugasanje(modra, cas2);
  postopno_priziganje(rdeca, cas2);
  postopno_ugasanje(zelena, cas2);
  if (ze_dovolj_prizgan(prvi_cas, max_cas)) {
    ugasni_se();
  }
}