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