lauantai 17. joulukuuta 2016

Pyörivä kooderi KY-040 ja 3-värin LED KY-009

Tämä ohjelma valottaa lähinnä kooderin (KY-040) käyttöä. Se on nykyään korvannut säädettävän potentiometrin monissa tehtävissä, kuten esim. audiolaitteiden voimakkuuden säätiminä. Potentiometreissä vastuksen muodostanut hiilikarvo kuluu ajan oloon asentoa muutettaessa, ja ikääntyneeseen laitteeseen alkaa tulla rahinaa.

Kuva 1. Kooderimoduuli.
Tällaisessa kooderissa tieto kiertosuunnasta ja kulman suuruudesta muodostetaan reiällisen koodilevyn ja optoerottimien avulla. Periaatteessa siten, että LEDi lähettää valoa (tai infrapunaa) ja fotodiodi (tai fototransistori) ottaa signaalin vastaan rakojen toisella puolella. Siinä on joko kaksi rei'itystä, joiden kohdistuskulmat poikkeavat hiukan toisistaan, tai kaksi optoryhmää hiukan eri kulmissa. Kumpiko menetelmä on tässä käytössä; en tiedä. Aiheeseen voi tutustua tarkemmin, kun eteen tulee aikansa palvellut tietokonehiiri. Sen rullassa koodataan myös suunta ja määrä.

 
Kuva 2. LED-moduuli
3-väriLEDissä (KY-009) on sininen (B), punainen(R) ja vihreä (G) valo. Moduuli toimi, mutta merkinnät (-, R, G, B) olivat väärässä järjestyksessä. Virhe on sekä netin kuvassa että todellisuudessa (siis ainakin tämän ysikön kohdalla). Toimiva järjestys näkyy oheisesta kytkentäkaaviosta.


Kuva 3. Tämän ohjelman laitekytkentä.
Kuva 4.
Kooderissa KY-040 on seuraavat merkinnät: GND (maa eli miinus (-)), + (+5V DC), SW (kytkin, mikä oikosulkee pinnin maahan. Toimii painamalla nuppia), DT (data, mikä seuraa akselin kiertymistä) ja CLK (kello, mikä seuraa akselin kiertymistä). Varsinainen informaatio saadaan siis pinneistä DT ja CLK.






Kuva 5. DT ja CLK aktiivisia.
Kierrettäessä akselia myötäpäivään, menee DT-pinni ensin nollaan (siksi ohjelmassa on käänteinen tilan luku: Bol_DT = !digitalRead(Con_DT);), sitten molemmat (DT ja CLK), ja edelleen käännettäessä DT-pinni nousee ensin ykköseksi ja sen jälkeen CLK-pinni. Käännettäessä vastapäivään, järjestys on tietysti päinvastainen.






OHJELMASTA
Tässä ohjelmassa nämä (suunnat) erotellaan 6-askelisella sekvenssillä (Seq_Suunta). Myötäpäivään käännettäessä sekvenssi käynnistetään askeleesta yksi (1) ja vastapäivään kierrettäessä askeesta neljä (4). Näiden kummankin tapauksen pääteaskeleessa (3 ja 6) sekvenssi sammutetaan (Seq_Suunta saa arvon nolla (0)). Varsinaiset toiminta- ja ohjausaskeleet ovat ne (1 ja 4), missä molemmat (DT ja CLK) ovat aktiivisia. Riippuen halutusta kiertosuunnasta, käynnistetään vastaava LEDien kirkkautta ja järjestystä ohjaava sekvenssi (Seq_LEDitMyota tai Seq_LEDitVasta ). Samalla sammutettaan vastakkaisen suunnan sekvenssi.

LEDien kirkkauden ohjaus (PWM) suoritetaan näissä suuntasekvensseissä. Ensin LEDi kirkastuu täyteen kirkkauteen, minkä jälkeen himmenee nollaan. Sitten vaihtuu LEDi ja sama toistuu. Myötäsuuntaan järjestys on: sin → pun → vih ja vastasuuntaan sin → vih → ja pun.
     Tähän asti kaikki hyvin. Parissa kohtaa jouduin taipumaan Arduinon omaani voimakkaampaan tahtoon. Tavoitteenani oli, että suunnan vaihto tapahtuu samalla värillä ja jatkaa siitä väristä ja kirkkaudesta, mihin toiminta edellisellä kiertosuunnalla jäi. Nyt vaihto tapahtuu aina sinisen LEDin nousevasta kirkkaudesta (siis sekvenssin alusta). En jaksanut pitkään puurtaa tämän ongelman parissa, sillä ajan ja energian vei toinen ongelma, virhetoiminto, mikä myös jäi ohjelmaan. Jos vaihto tapahtuu muun kuin sinisen LEDin kohdalla, jää muun värinen LED palamaan pohjalle, kunnes sen värin askeleet on käyty kerran läpi uuden suunnan ohjauksella. Ei auttanut, vaikka muihin väreihin kirjoitti nollaa (0), ei mikään muukaan kokeilemistani variaatioista. Varmaan tässä olisi hyvä projekti tulevaisuuteen, projekti, mikä lähestyy ratkaisua ainoastaan tuon ongelman näkökulmasta.
Kuva 6. Ohjelman mukainen versio.
     Kirkkauden lisäksi muutosnopeutta voidaan säätää kooderin painikkeella, mikä toimii painamalla kiertoakselia. Pohjalukema on 15 (analogialähtö, 8 bittiä, alue 0 .. 255, PWM - ohjaus). Jokainen painikkeen päästäminen kasvattaa muutosnopeutta 15:llä. Kun ylitetään luku 60, palataan takaisin pohja-arvoon 15. Vihreä LEDi oli lisäksi huomattavasti kirkkaampi kuin kaksi muuta. Siksi sitä ohjataan jakamalla ohjausarvo kolmella (3).



Alla olevasta ohjelmasta on karsittu pois kaikki ohjelmakehityksen aikaiset kokeilut ja lisät (esim. Selial.print muutujien arvojen tulostamiseksi ruudulle). Aluksi tutkin pelkän kooderin toimintaa (Kuvat 4 ja 5). Siinä oli ainoastaan LEDit ilmaisemassa kooderin pinnien tilaa sekä suuntien tilaa. Sen vaiheen toimintaa havainnoi myös suttuinen video (antinarduvideo29a. youtube.com)
     Ohjelmasta on karsittu myös edellä mainitsemani virheen ja toiminnan kokeilut. Toinen video (antinarduvideo29b. youtube.com) antaa jonkinlaisen kuvan ratkaisun toiminnasta. Siitä pystyy myös hiukan näkemään suunnanvaihdossa tapahtuvan virheen; edellisen LEDin jäämisen palamaan (värit eivät ole puhtaita, vaan sekoittuvat).

OHJELMA 29
/***************************************
* Ohjelma 29
* 15.12.2016
* Ohjataan kolmen LEDin kirkkautta
* kahteen suuntaan neljällä eri
* nopeudella
**************************************/

// MÄÄRITTELYT:
boolean Bol_MyotaSuunta = false;
boolean Bol_VastaSuunta = false;
const int Con_CLK = 2; // Kooderin kello
boolean Bol_CLK = false;
const int Con_DT = 3; // Kooderin data
boolean Bol_DT = false;
const int Con_LEDsin = 9;
boolean Kep_LEDsin = false;
const int Con_LEDpun = 10;
boolean Kep_LEDpun = false;
const int Con_LEDvih = 11;
boolean Kep_LEDvih = false;
int Int_OhjausArvo = 0;
int Int_LedOhjaus = 0; // LEDeille menevä analogia-arvo
int Int_Muutos = 15; // Muutosnopeutta voihetaan painikkeella
const int Con_Kytkin = 4; // Kooderin painikkeen tulo
boolean Bol_Kytkin = false;
int Int_KykinViive = 0;
int Seq_kytkin = 1;
int Seq_Suunta = 0;
int Seq_LEDitMyota = 0;
int Seq_LEDitVasta = 0;

// ASETUKSET:
void setup(){
Serial.begin(9600);
pinMode(Con_Kytkin, INPUT_PULLUP); // Sisäinen ylösveto
pinMode(Con_CLK, INPUT);
pinMode(Con_DT, INPUT);
}// Asetuksen loppu

// PÄÄLOOPPI
void loop(){
Bol_Kytkin = !digitalRead(Con_Kytkin);
switch (Seq_kytkin) {
case 1: // tämä on vakio
if(Bol_Kytkin == true){
Int_KykinViive++;
if(Int_KykinViive > 7){
Int_KykinViive = 0;
Seq_kytkin = 2;
}
}
break;
case 2:
if(Bol_Kytkin == false){
Int_Muutos = Int_Muutos + 15;
if(Int_Muutos > 60){
Int_Muutos = 15;
}
Seq_kytkin = 1; }
break;
} // Kytkinsekvenssi loppu

Bol_CLK = !digitalRead(Con_CLK);
Bol_DT = !digitalRead(Con_DT);

// Kiertosuunnan määrittely
if(Bol_DT == true && Bol_CLK == false && Seq_Suunta == 0){
Seq_Suunta = 1;}
if(Bol_CLK == true && Bol_DT == false && Seq_Suunta == 0){
Seq_Suunta = 4;}

switch (Seq_Suunta) {
case 1:
if(Bol_DT == true && Bol_CLK == true){
Int_OhjausArvo = Int_OhjausArvo + Int_Muutos;
Int_OhjausArvo = constrain(Int_OhjausArvo, 0, 255);
if(Seq_LEDitMyota == 0){
Seq_LEDitMyota = 1;
Seq_LEDitVasta = 0;
}
Seq_Suunta = 2;
}
break;
case 2:
if(Bol_DT == false && Bol_CLK == true){
Seq_Suunta = 3;
}
break;
case 3:
if(Bol_DT == false && Bol_CLK == false){
Seq_Suunta = 0;
}
break;
case 4:
if(Bol_CLK == true&& Bol_DT == true){
Int_OhjausArvo = Int_OhjausArvo + Int_Muutos;
Int_OhjausArvo = constrain(Int_OhjausArvo, 0, 255);
if(Seq_LEDitVasta == 0){
Seq_LEDitVasta = 1; // Vastasuuntanen käynnistetään
Seq_LEDitMyota = 0; // Myötäsuuntanen lukitaan
}
Seq_Suunta = 5;
}
break;
case 5:
if(Bol_CLK == false && Bol_DT == true){
Seq_Suunta = 6;
}
break;
case 6:
if(Bol_CLK == false && Bol_DT == false){
Seq_Suunta = 0;
}
break;
} // Suunta-sekvenssin loppu

// LEDien ohjaus myötäpäivään sin -> pun -> vih -> sin jne.
switch (Seq_LEDitMyota) {
case 1: // sininen kirkastuu
analogWrite(Con_LEDvih, 0);
Kep_LEDsin = true;
Int_LedOhjaus = Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Seq_LEDitMyota = 2;
}
break;
case 2: // sininen himmenee
Int_LedOhjaus = 255 - Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Kep_LEDsin = false;
Seq_LEDitMyota = 3;
}
break;
case 3: // punainen kirkastuu
analogWrite(Con_LEDsin, 0);
Kep_LEDpun = true;
Int_LedOhjaus = Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Seq_LEDitMyota = 4;
}
break;
case 4: // Punainen himmenee
Int_LedOhjaus = 255 - Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Kep_LEDpun = false;
Seq_LEDitMyota = 5;
}
break;
case 5: // vihreä kirkastuu
analogWrite(Con_LEDpun, 0);
Kep_LEDvih = true;
Int_LedOhjaus = Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Seq_LEDitMyota = 6;
}
break;
case 6: // vihreä himmenee
Int_LedOhjaus = 255 - Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Kep_LEDvih = false;
Seq_LEDitMyota = 1;
}
break;
}// Myötäsekvenssi loopu

// LEDien ohjaus vastapäivään sin -> vih -> pun -> sin jne.
switch (Seq_LEDitVasta) {
case 1: // sininen kirkastuu
analogWrite(Con_LEDpun, 0);
Kep_LEDsin = true;
Int_LedOhjaus = Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Seq_LEDitVasta = 2;
}
break;
case 2: // sininen himmenee
Int_LedOhjaus = 255 - Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Kep_LEDsin = false;
Seq_LEDitVasta = 5;
}
break;
case 3: // punainen kirkastuu
analogWrite(Con_LEDvih, 0);
Kep_LEDpun = true;
Int_LedOhjaus = Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Seq_LEDitVasta = 4;
}
break;
case 4: // punainen himmenee
Int_LedOhjaus = 255 - Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Kep_LEDpun = false;
Seq_LEDitVasta = 1;
}
break;
case 5: // vihreä kirkastuu
analogWrite(Con_LEDsin, 0);
Kep_LEDvih = true;
Int_LedOhjaus = Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Seq_LEDitVasta = 6;
}
break;
case 6: // vihreä himmenee
Int_LedOhjaus = 255 - Int_OhjausArvo;
if(Int_OhjausArvo == 255){
Int_OhjausArvo = 0;
Kep_LEDvih = false;
Seq_LEDitVasta = 3;
}
break;
}// Vastasekvenssi loppu

// LEDien ohjaukset
if(Kep_LEDsin == true){
analogWrite(Con_LEDsin, Int_LedOhjaus);}
if(Kep_LEDpun == true){
analogWrite(Con_LEDpun, Int_LedOhjaus);}
if(Kep_LEDvih == true){
analogWrite(Con_LEDvih, Int_LedOhjaus / 3);}
delay(1);
} // Pääohjelma LOPPU

Ei kommentteja:

Lähetä kommentti