Najprej omenimo, da obstoja nova verzija programskega okolja Arduino in sicer Arduino 1.6.5
Vezje vsebuje RGB LED diodo in barvni senzor TCS 230. Če bo barvni senzor zaznal rdečo barvo, bo svetila rdeča LED dioda, če bo barvni senzor zaznal zeleno barvo, bo svetila zelena LED dioda, če pa bo barvni senzor zaznal modro barvo, bo svetila modra LED dioda.
RGB LED dioda:
Slika 1: RGB LED dioda s skupno katodo (vir: http://www.chromationsystems.com/store/images/5mmRGBLED.png)
RGB LED dioda ima v bistvu tre LED diode v enem ohišju, ki vsebuje štiri priključke. Najdaljši priključek (priključek 3) je skupna katoda in jo povežemo z maso (GND). Ostali trije priključki predstavljajo anode, en priključek za rdečo (priključek 4), drugi za zeleno (priključek 1) in tretji priključek za modro (priključek 2) LED diodo. Za krmiljenje RGB LED diode potrebujemo tri izhodne pine na razvojni plošči Arduino Uno. Anode posameznih LED diod na te pine priključimo preko 470 Ω uporov. Ko RGB LED diodo priključimo na razvojno ploščo Arduino Uno, lahko programsko krmilimo in nadzorujemo, kakšne barve bo svetila RGB LED dioda s pošiljanjem napetosti na posamezne pine oziroma posamezne anode RGB LED diode. Če pošljemo napetost na anodo rdeče LED diode, bo svetila rdeče. Če pošljemo napetost na anodo zelene LED diode, bo svetila zeleno. Če pošiljamo različne napetosti (analogWrite) na vse tri pine (anode) LED diod, dobimo celi spekter različnih barv. Mi bomo v tej vaji krmilili le osnovne: rdečo, zeleno in modro LED diodo.
Anodo rdeče LED diode bomo priključili na pin 11, anodo zelene LED diode bomo priključili na pin 10, anodo modre LED diode pa bomo priključili na pin 6 razvojne plošče Arduino Uno.
Slika 2: Priključitev RGB LED diode na razvojno ploščo Arduino Uno
Senzor barv TCS 230:
Slika 3: Senzor barv TCS 230 (vir: http://www.bdspeedytek.com/product/tcs230-module/)
Priključitev senzorja barv TCS 230:
Senzor barv TCS 230 uporablja za zajemanje svetlobe 64 fotodiod, po 16 fotodiod je vezanih v štiri skupine. Pred vsako skupino je nameščen filter, ki prepušča le svetlobo določene barve. Prva skupina 16-ih fotodiod zajema rdečo svetlobo, druga skupina 16-ih fotodiod zajema zeleno svetlobo, tretja skupina pa zajema modro svetlobo. Četrta skupina 16-ih fotodiod je brez filtra in zajema vso svetlobo, ki jo fotodiode zaznajo.
Senzorski modul vsebuje oscilator, ki generira pravokotne impulze na izhodi pin senzorja (OUT). Frekvenca teh pravokotnih impulzov je odvisna od intenzivnosti svetlobe in izbrane barve. Duty cycle pravokotnih impulzov je 50 % (čas trajanja visokega nivoja je enak času nizkega nivoja).
Izbrani barvni filter določimo z ustrezno nastavitvijo pinov TCS 230 senzorja, S2 in S3.
Istočasno lahko izberemo le en filter. Če na primer izberemo rdeči filter (pina S2 in S3 sta na nivoju logične 0), lahko pride skozi filter le rdeča barva, modri in zeleni bo to preprečeno. Izhodno frekvenco pravokotnih impulzov lahko nastavimo na eno od treh prednastavljenih vrednosti. Lahko je 100 % vrednost osnovne frekvence, 20 % ali 2 % osnovne vrednosti frekvence. Izbrano vrednost osnovne frekvence zmanjšamo (skaliramo) z ustrezno nastavitvijo pinov S0 in S1:
Za vsako barvo (rdečo, zeleno in modro) dobimo pri enaki intenzivnosti svetlobe (v našem primeru bo dnevna svetloba ob že obstoječih štirih belih LED diod nameščenih na senzorju) različno frekvenco pravokotnih impulzov. Večja kot je intenzivnost svetlobe, večja bo količina svetlobe, ki zadane izbrane fotodiode.
Podatek o frekveenci lahko izračunamo na dva načina:
Merimo čas med posameznimi impulzi.
Štejemo pravokotne impulze v enakomernih časovnih presledkih.
1. Merjenje časa med posameznimi impulzi:
Primer izhodnega signala, ko beremo rdečo barvo. V tem primeru vključimo rdeči filter (S2 in S3 postavimo na nivo logične 0). Izmed odbijajoče svetlobe od rdeče podlage, rdeči barvni filter spušča na skupino 16-tih fotodiod le rdečo barvo.
Slika 4: Branje rdeče barve, merjenje izhodnega signala z osciloskopom
Poglejmo natančne podatke izhodnega signala pri obstoječi sobni svetlobi (poleg štirih LED diod na senzorju TCS 230 je bila vklopljena stropna svetilka):
Slika 5: Izhodni signal za rdečo barvo
Frekvenca pravokotnih impulzov f = 212 Hz.
Čas trajanja ene periode T = 1/f = 1/212 Hz = 0,004717 s = 4717 µs.
Čas trajanja visokega stanja (polperiode) je T/2 in znaša 4717/2 = 2359 µs. Čas trajanja visokega stanja je enak času trajanja nizkega stanja, saj je duty cycle 50 %.
Frekvenca pravokotih impulzov na izhodu barvnega senzorja je za vsako barvo (ob vklopu ustreznega barvnega filtra) različna in s tem je različen tudi čas trajanja visokega oziroma nizkega stanja. Na podlagi teh razlik bomo ugotovili, katero barvo je zaznal senzor.
Izhodno frekvenco smo skalirali (zmanjšali) na 2 % osnovne, da dobimo manjšo frekvenco in s tem manjše podatke polperiod v mikro sekundah. Pin S0 smo povezali na maso (logična 0), pin S1 pa na napetost 5 V (logična 1). Z instrukcijo:
SirinaPulza = pulseIn(Izhod, LOW);
beremo dolžino impulza. Če izberemo parametra (Izhod, LOW), pulseIn() čaka na prehod signala na izhodnem pinu (Izhod) iz stanja logične 1 na stanje logične 0. Ob prehodu stanja začne meriti čas do prehoda iz stanja 0 v stanje 1. Takrat preneha z merjenjem časa, izmerjeni čas pa vrne v µs. V spremenljivki SirinaPulza je tako shranjen podatek o dolžini impulza, polperiodi, v mikro sekundah.
Program:
/*
Zaznavanje barv s senzorjem TCS 230, Arduino Uno.
Merjenje časa med posameznimi impulzi.
Avtor: Milan Ivič
Julij 2015
*/
//RGB LED dioda:
int RdecaPin = 11;
int ZelenaPin = 10;
int ModraPin = 6;
//Barvni senzor TCS 230:
int S2 = 7;
int S3 = 8;
int Izhod = 4;
//Spremenljivke za posamezne barve:
int RdecaBarva;
int ZelenaBarva;
int ModraBarva;
int SirinaPulza = 0; //Spremenljivka za branje dolžine impulza v µs.
void setup()
{
Serial.begin(9600); //Komunikacija na serijskem portu.
//Določitev vhodov in izhodov:
pinMode(RdecaPin, OUTPUT);
pinMode(ZelenaPin, OUTPUT);
pinMode(ModraPin, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
pinMode(Izhod, INPUT);
}
void loop()
{
//Začnemo z branjem komponente rdeče barve:
//S2 in S3 postvimo na LOW.
digitalWrite(S2, LOW);
digitalWrite(S3, LOW);
SirinaPulza = pulseIn(Izhod, LOW); //Branje dolžine impulza (polperiode) v µs.
RdecaBarva = SirinaPulza/44; //Kalibriranje za rdeco barvo.
RdecaBarva = (255 - RdecaBarva);
//Začnemo z branjem komponente zelene barve:
//S2 in S3 postvimo na HIGH.
digitalWrite(S2, HIGH);
digitalWrite(S3, HIGH);
SirinaPulza = pulseIn(Izhod, LOW);
ZelenaBarva = SirinaPulza/65;
ZelenaBarva = (255 - ZelenaBarva);
//Začnemo z branjem komponente modre barve:
//S2 postavimo na LOW, S3 postvimo na HIGH.
digitalWrite(S2, LOW);
digitalWrite(S3, HIGH);
SirinaPulza = pulseIn(Izhod, LOW);
ModraBarva = SirinaPulza/58;
ModraBarva = (255 - ModraBarva);
Serial.print(RdecaBarva);
Serial.print(" , ");
Serial.print(ZelenaBarva);
Serial.print(" , ");
Serial.print(ModraBarva);
Serial.print(" , ");
Serial.print("Trajanje impulza v mikro sekundah: ");
Serial.println(SirinaPulza);
Serial.println("");
if(RdecaBarva > ModraBarva && RdecaBarva > ZelenaBarva)
{
digitalWrite(RdecaPin, HIGH); //Vklop rdeče RGB LED diode.
digitalWrite(ZelenaPin, LOW);
digitalWrite(ModraPin, LOW);
}
if(ZelenaBarva > ModraBarva && ZelenaBarva > RdecaBarva)
{
digitalWrite(RdecaPin, LOW);
digitalWrite(ZelenaPin, HIGH); //Vklop zelene RGB LED diode.
digitalWrite(ModraPin, LOW);
}
if(ModraBarva > RdecaBarva && ModraBarva > ZelenaBarva)
{
digitalWrite(RdecaPin, LOW);
digitalWrite(ZelenaPin, LOW);
digitalWrite(ModraPin, HIGH); //Vklop modre RGB LED diode.
}
delay(300);
}
Slika 6 prikazuje branje modre barve ter izpis na serijskem monitorju. Pri modri barvi dobimo na izhodu senzorja pravokotne impulze frekvence 365 Hz. Čas trajanja cele periode znaša T = 1/f = 1/365 = 2740 µs. Čas trajanja polovice periode, ki jo programsko merimo torej znaša T/2 = 2740/2 = 1370 µs. Ta čas se nam izpisuje v zadnji, skrajno desni koloni na serijskem monitorju.
Slika 6: Izpis na serijskem monitorju, senzor zazna modro barvo
Čase trajanja impulzov (polperiod), ki jih dobimo na izhodu senzorja pri različnih barvah želimo spraviti v številčno območje do vrednosti 255 (255 je največja vrednost 8-bitnega števila). Zato te vrednosti za posamezne barve delimo z ustreznim številom in odštejemo od vrednosti 255.
Slika 7: Izhodni signal za modro barvo
Upoštevati moramo, da je največja možna širina impulza po podatkih proizvajalca senzorja TCS 230 za zeleno barvo pri frekvenci 8 KHz. Pri skaliranju (zmanjšanju) te osnovne frekvence na 2 % te vrednosti, dobimo frekvenco 160 Hz. Pri tej frekvenci traja čas impulza (polovica periode) 3125 µs.
Pri kalibriranju, občutljivosti senzorja na rdečo, zeleno in modro barvo, vrednosti trajanja polperiod za vsako barvo delimo z različnim številom. Pri tem upoštevamo tipične izhodne frekvence, ki jih dobimo na izhodu senzorja. Po podatkih proizvajalca senzorja TCS 230 so te vrednosti:
rdeča barva => 19 KHz
zelena barva => 13,6 KHz
modra barva => 16,4 KHz
Vrednosti, s katerimi delimo čase polperiod za posamezne barve naj bodo v enakem razmerju, torej:
rdeča barva => 44
zelena barva => 65
modra barva => 58
2. Štetje pravokotnih impulzov v enakomernih časovnih presledkih:
Za štetje pravokotnih impulzov uporabimo zunanje prekinitve, ki jih prožimo na pinu INT0 (pin 2 Arduino Uno).
Za enakomerne časovne presledke pa uporabimo prekinitev na časovniku Timer2, ki se sproži vsakih 15 ms.
Pravokotne impulze, ki jih generira barvni senzor štejemo v prekinitveni rutini, ki jo sproži vsak prehod impulza iz logičnega 0 na 1 na pinu INT0 (pin 2). Timer 2 smo nastavili tako, da se sproži timerjeva prekinitev (ko prekorači svojo vrednost => overflow) vsakih 15 ms. V timerjevi prekinitveni rutini beremo posamezne barve: rdečo, zeleno in modro. Podatki za posamezne se zapisujejo v spremenljivke RdecaBarva, ZelenaBarva in ModraBarva. Na podlagi vrednosti teh spremenljivk, v glavni zanki vklapljamo rdečo, zeleno oziroma modro RGB LED diodo.
Priključitev senzorja barv TCS 230:
Program:
/*
Zaznavanje barv s senzorjem TCS 230, Arduino Uno.
Štetje impulzov v enakomernih časovnih presledkih.
Avtor: Milan Ivič
Julij 2015
*/
//Barvni senzor TCS 230:
int S2 = 7;
int S3 = 8;
//RGB LED dioda:
int RdecaPin = 11;
int ZelenaPin = 10;
int ModraPin = 6;
int Stevec = 0;
int Zastavica = 0;
int RdecaBarva = 0;
int ZelenaBarva = 0;
int ModraBarva = 0;
void setup()
{
Serial.begin(9600);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
pinMode(RdecaPin, OUTPUT);
pinMode(ZelenaPin, OUTPUT);
pinMode(ModraPin, OUTPUT);
}
void TCSsenzor()
{
Zastavica = 0;
attachInterrupt(0, ISR_INT0, RISING); //Klicanje zunanje prekinitve na INT0 (pin 2).
Timer2_inicializacija();
}
void ISR_INT0() //Prekinitvena rutina
{
Stevec = Stevec + 1;
}
void Timer2_inicializacija(void) //Nastavitev časovnika Timer2
{
TCCR2A = 0x00; //Inicializacija Timer2 registra TCCR2A.
TCCR2B = 0x07; //Biti CS20, CS21 in CS22 so 1. Preddelitev je 1:1024.
TCNT2 = 20; //Preset Timer2, ko prekorači svojo vrednost na vrednost 20.
TIMSK2 = 0x01; //Omogočamo prekinitve na Timer2.
}
//Timer2 proži owerflow prekinitve OVF (Overflow Interrupt Vector).
//Prekinitvena rutina se izvede vsakih 15 ms. (t=(255-20)*1024*0,0625 µs = 15 ms)
ISR(TIMER2_OVF_vect) //Prekinitvena rutina, prekinitev na timerju Timer2
{
TCNT2 = 20;
Zastavica = Zastavica + 1;
if(Zastavica == 1)
{
Stevec = 0;
}
else if(Zastavica == 2)
{
digitalWrite(S2, LOW);
digitalWrite(S3, LOW); //S2 = 0, S3 = 0 => branje rdeče barve.
RdecaBarva = Stevec/1.09; //Korekcija.
Serial.print("Rdeca barva = ");
Serial.print(RdecaBarva);
Serial.print(", Stevec: ");
Serial.println(Stevec);
digitalWrite(S2, HIGH);
digitalWrite(S3, HIGH); //S2 = 1, S3 = 1 => pripravimo za branje zelene barve.
}
else if(Zastavica == 3)
{
ZelenaBarva = Stevec/1.0157; //Korekcija.
Serial.print("Zelena barva = ");
Serial.print(ZelenaBarva);
Serial.print(", Stevec: ");
Serial.println(Stevec);
digitalWrite(S2, LOW);
digitalWrite(S3, HIGH); //S2 = 0, S3 = 1 => pripravimo za branje modre barve.
}
else if(Zastavica == 4)
{
ModraBarva = Stevec/1.114; //Korekcija.
Serial.print("Modra barva = ");
Serial.print(ModraBarva);
Serial.print(", Stevec: ");
Serial.println(Stevec);
digitalWrite(S2, LOW);
digitalWrite(S3, LOW); //S2 = 0, S3 = 1 => pripravimo za branje rdeče barve.
}
else
{
Zastavica = 0; //Inicializacija.
TIMSK2 = 0x00; //Onemogočimo prekinitve na Timer2.
}
Stevec = 0; //Inicializacija.
}
void loop()
{
delay(10);
TCSsenzor(); //Klicanje funkcije.
if((RdecaBarva > ZelenaBarva) && (RdecaBarva > ModraBarva))
{
Serial.println("Zaznana rdeca barva");
Serial.println("");
digitalWrite(RdecaPin, HIGH); //Vklopimo rdečo RGB LED diodo.
digitalWrite(ZelenaPin, LOW);
digitalWrite(ModraPin, LOW);
delay(500);
}
else if((ZelenaBarva > RdecaBarva) && (ZelenaBarva > ModraBarva))
{
Serial.println("Zaznana zelena barva");
Serial.println("");
digitalWrite(RdecaPin, LOW);
digitalWrite(ZelenaPin, HIGH); //Vklopimo zeleno RGB LED diodo.
digitalWrite(ModraPin, LOW);
delay(500);
}
else if((ModraBarva > ZelenaBarva) && (ModraBarva > RdecaBarva))
{
Serial.println("Zaznana modra barva");
Serial.println("");
digitalWrite(RdecaPin, LOW);
digitalWrite(ZelenaPin, LOW);
digitalWrite(ModraPin, HIGH); //Vklopimo modro RGB LED diodo.
delay(500);
}
delay(10);
}
Slika 8: Izpis na serijskem monitorju, senzor zazna modro barvo