Testujeme Arduino Multi-function Shield (Funduino)
1. VÝSTUPY
1.1. Signalizační LED
Ukážeme si, jak rozsvítit a zhasnout čtveřici signalizačních LED a též, jak lze jejich svit regulovat pomocí tzv. pulzní šířkové modulace (PWM).
1.1.1. Blikáme
Funkčnost signalizačních LED si vyzkoušíme pravidelným cyklickým blikáním (1 s LED svítí, 1 s budou LED zhasnuté).
Kód:
char ledPin1 = 10; // LED na pinu 10
char ledPin2 = 11; // LED na pinu 11
char ledPin3 = 12; // LED na pinu 12
char ledPin4 = 13; // LED na pinu 13
void setup()
{
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT); // nastaveni vystupu
}
void loop()
{
digitalWrite(ledPin1, LOW); // rozsvit LED 1
digitalWrite(ledPin2, LOW); // rozsvit LED 2
digitalWrite(ledPin3, LOW); // rozsvit LED 3
digitalWrite(ledPin4, LOW); // rozsvit LED 4
delay(1000); // cekej 1s
digitalWrite(ledPin1, HIGH); // zhasni LED 1
digitalWrite(ledPin2, HIGH); // zhasni LED 2
digitalWrite(ledPin3, HIGH); // zhasni LED 3
digitalWrite(ledPin4, HIGH); // zhasni LED 4
delay(1000); // cekej 1s
}
Popis:
Signalizační LED jsou na shieldu připojeny na výstupy 10 – 13. V první části programu si tyto čísla nastavíme do proměnných ledPin1
–ledPin4
. Typ proměnné byte
znamená, že se jedná o jedno bytovou proměnou s rozsahem hodnot (0–255). To nám stačí. Možná je i volba int
(integer), ale ta by zbytečně alokovala v paměti dvojnásobek místa.
V části setup
nastavíme piny, ke kterým jsou připojeny signalizační LED, do režimu výstup.
Následná smyčka loop
vždy rozsvítí všechny LED (hodnota LOW), vteřinu počká (1000 milisekund) a pak je zhasne (hodnota HIGH). To vše se cyklicky opakuje v sekci loop
.
1.1.2. Postupné rozsvěcení (PWM - „analogový“ výstup)
Výstupní piny 10 a 11 podporují pulzní šířkovou modulaci (tzv. PWM), což je jakási digitální „náhražka“ analogového signálu. Ta v praxi funguje tak, že se rychle střídá napětí 0 V a 5 V na daném výstupu. Podle poměru časů, ve kterých je nastaveno na výstupu +5 V a 0 V, se pak odvíjí intenzita svícení zvolené LED diody.
Kód:
byte ledPin1 = 13; // LED D1 - pin13 PWM regulace jen pro LEONARDO pro UNO bude binarni
byte ledPin2 = 12; // LED D2 - pin12 PWM nepodporuje - bude binarni
byte ledPin3 = 11; // LED D3 - pin11 PWM regulace
byte ledPin4 = 10; // LED D4 - pin10 PWM regulace
void setup()
{
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT); // nastaveni vystupu
}
void loop()
{
for (int i = 255; i > 0; i--)
{
analogWrite(ledPin1, i); // rozsvit LED D1 - intenzita dle hodnoty promenne i
analogWrite(ledPin2, i); // totez pro LED D2
analogWrite(ledPin3, i); // totez pro LED D3
analogWrite(ledPin4, i); // totez pro LED D4
delay(100); // cekej 100 ms
}
delay(1000); // cekej 1 s, pak znova
}
Popis:
Opět nastavíme piny 10-13, na kterých jsou připojeny signalizační LED, na stav výstupu (proměnné pinLED1-4 a blok setup).
V části loop postupně cyklem odesíláme na jednotlivé výstupy hodnoty od 255 (zcela zhasnuto) až 0 (plné rozsvícení). Každá nastavená hodnota zůstane platná 100 ms, pak je nastavena vyšší svítivost. Regulace je patrná zejména u nižší svítivosti, u vyšších hodnot již lidské oko jen velmi těžko pozná rozdíl ve světelné intenzitě.
Po „proběhnutí“ všech možných 256 intenzit, se po vteřinovém čekání vše opakuje od zhasnutí po plný svit.
POZOR, protože jsou LED na shieldu zapojeny tak, že jsou rozsvíceny při LOW a naopak zhasnuty při HIGH, je i nyní nejvyšší svit při nejnižší výstupní hodnotě.
Pokud máte shield připojený k modulu Arduino LEONARDO, bude se postupně rozsvěcet trojice LED (pin 10, 11 a 13), naopak pin 12 se bude střídat jen ve dvou stavech (svítí × nesvítí – mezní výstupní hodnota změny stavu je 128). Pokud používáte Arduino UNO, budou se postupně rozsvěcet (vliv PWM) pouze diody na pinech 10 a 11. LED na pinech 12 a 13 budou střídat jen žádný a plný svit (PWM není na těchto pinech podporováno).
1.2. Bzučák
Bzučák použitý na shieldu Funduino je pasivní – to znamená, že po připojení napětí nevydává předem zvolený tón, ale musíme si tón vygenerovat. Kupříkladu střídáním stavu HIGH a LOW výstupu 3, ke kterému je bzučák připojen. Druhou možností by mohlo být využití PWM stejně jako v předchozím příkladu u LED. Je ale otázkou, zda tím dosáhneme slyšitelné frekvence (vyzkoušejte to!). My si nejdříve vygenerujeme tón klasickým „přepínacím“ způsobem a pak to zkusíme připravenou funkcí.
1.2.1. Tón klasicky
Kód:
int buzzer = 3; // pin bzucaku
void setup()
{
pinMode(buzzer,OUTPUT); // nastaveni bzucaku na vystup
}
void loop()
{
for(int i = 0; i < 80; i++) // chvilku jedna frekvence
{
digitalWrite(buzzer, HIGH); // nastav HIGH
delay(2); // pockej 2 ms
digitalWrite(buzzer, LOW); // nastav LOW
delay(2); // pockej 2 ms
}
for(int i = 0; i < 100; i++) // a ted zase jina frekvence
{
digitalWrite(buzzer, HIGH);
delay(4);
digitalWrite(buzzer, LOW);
delay(4);
}
}
Popis:
Opět nastavíme pin, ke kterému je shieldu připojen bzučák (tj. pin č. 3), na výstup. První cyklus generuje vyšší tón (čekání mezi stavy HIGH a LOW 2 ms), pak se tón změní na hlubší (druhý cyklus – čekání 4 ms).
Upřímně řečeno, ten kdo má hudební sluch možná ví, jaké to jsou tóny.
POZN: U mého shieldu je hlasitost pískání velmi malá – bzučák je slyšet až po přiložení k uchu. (předpokládám, že je to vada mého konkrétního kusu a ne obecný jev – jinak by bzučák byl dosti nepoužitelný)
1.2.2. Funkce Tone(pin, freq, [time])
Funkce Tone()
slouží ke generování tónu. Má tři parametry – dva povinné (pin
a freq
) a jeden nepovinný (time
). První z nich udává pin, na kterém je připojen pasivní bzučák (u našeho shieldu to je pin 3), druhý parametr je frekvence generovaného tónu. Nepovinným parametrem je délka tónu v milisekundách.
Hned si řekneme i o existenci funkce noTone(pin)
, která vypne generovaný tón na daném pinu – např. není-li stanovena délka tónu ve funkci Tone()
.
Kód:
int buzzer = 3; // adresa bzucaku
void setup()
{
pinMode(buzzer, OUTPUT); // nastaveni bzucaku na vystup
}
void loop()
{
tone(buzzer, 440); // nastav komorni A
delay(1000); // pockej 1 s
tone(buzzer, 1000); // nastav technicke A
delay(1000); // pockej 1 s
}
Popis:
Nastavení pinu 3 na výstup je obdobné předchozímu příkladu. Ve smyčce loop
pak vidíme velice jednoduchý kód. Nejdříve se nastaví výstupní frekvence 440 Hz, po vteřině se tato frekvence změní na 1 kHz. To vše se neustále opakuje.
1.3. LCD zobrazovače
Multi-function Shield je osazen čtveřicí LED segmentovými zobrazovači, které jsou řízeny dvojicí obvodů 74HC595. Jedná se o registry, do kterých se ukládá rozsvícení/zhasnutí jednotlivých segmentů daného LED zobrazovače a číslo zvoleného zobrazovače. Registry jsou na shieldu zapojeny tak, že zápis do registrů probíhá následujícím způsobem. Zahájí se nastavením výstupního pinu 4 do stavu LOW. Do registrů pak se zapisuje sériově pomocí pinu 8 s hodinovým signálem (taktem) na pinu 7. První osmice bitů volí rozsvícení LED v zobrazovači (POZOR: LOW znamená rozsvítit, HIGH zhasnout), druhá osmice volí „adresu“ zvoleného zobrazovače (zajímají nás jen poslední 4 bity daného byte).
Následující obrázek zachycuje, jak odpovídají jednotlivé LED v zobrazovači bitům v bytu registru:
![segmety a bity pro zobrazení](funduino-test/segment-bity.png)
1.3.1. Světe AHOJ
Pro zjednodušení zápisu dat do registrů využijeme funkci shiftOut(dataPin, clockPin, bitOrder, data)
. Tato funkce má čtyři parametry: První dataPin
je číslo pinu, na který budou odesílaná sériová data (v našem případě pin 8). Druhý clockPin
je pin, na kterém bude generován hodinový signál (takt) pro zápis (u nás pin 7). Třetí bitOrder
udává směr odesílaných bitů ze zadaného byte (konstanta MSBFIRST
– nejvyšší bit jako první; opakem je konstanta LSBFIRST
). Čtvrtým parametrem je samotná hodnota, která bude odeslána – my budeme hodnoty v kódu zapisovat v binární podobě, aby bylo patrné, které LED v zobrazovači chceme rozsvítit.
Budeme chtít na čtveřici zobrazovačů zobrazit nápis AHOJ. Znamená to tedy zapsat na první zobrazovač (počítáno zleva) písmeno A, na druhý H atd. Jakmile však zapíšeme do společného registru hodnoty pro druhý zobrazovač (tj. písmeno H), první zobrazovač pochopitelně zhasne (registr nyní rozsvěcí druhý zobrazovač) Stejně tomu bude při zápisu třetího a čtvrtého znaku. Musíme tedy jednotlivá písmena zobrazovat neustále dokola a to tak rychle, aby lidské oko nepostřehlo přeblikávání.
Kód:
int latchPin = 4;
int clockPin = 7;
int dataPin = 8; // data pro segmentovky
void setup()
{
pinMode(latchPin,OUTPUT);
pinMode(clockPin,OUTPUT);
pinMode(dataPin,OUTPUT); // nastaveni vystupu pro segmentovky
}
void loop()
{
digitalWrite(latchPin,LOW); // start zapisu
shiftOut(dataPin,clockPin,MSBFIRST,B10001000); // zobrazeni znaku A
shiftOut(dataPin,clockPin,MSBFIRST,B00000001); // adresa 1. segmentovky
digitalWrite(latchPin,HIGH); // konec zapis - data jdou na vystup
delay(5);
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,MSBFIRST,B10001001); // H
shiftOut(dataPin,clockPin,MSBFIRST,B00000010); // adresa 2. segmentovky
digitalWrite(latchPin,HIGH);
delay(5);
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,MSBFIRST,B11000000); // O
shiftOut(dataPin,clockPin,MSBFIRST,B00000100); // adresa 3. segmentovky
digitalWrite(latchPin,HIGH);
delay(5);
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,MSBFIRST,B11100001); // J
shiftOut(dataPin,clockPin,MSBFIRST,B00001000); // adresa 4. segmentovky
digitalWrite(latchPin,HIGH);
delay(5);
}
Popis:
Nastavení pinů 4, 7 a 8 pro výstup je pro nás již standardním postupem. Podíváme se na čtveřici odstavců v bloku loop
. Každý nastavuje právě jeden zobrazovač. Přesně, jak bylo popsáno výše, dojde k nastavení pinu 4 do stavu LOW – registr je připraven pro zápis. Poté funkce shiftOut
„nasype“ bity pro jednotlivé LED zobrazovače. Pro názornost ukázky je použit binární odeslané hodnoty. Např. pro písmeno A: První bit je desetinná tečka (viz obr. 1), tu chceme zhasnout – nastavena na 1, další je střední vodorovná LED, tu ve znaku A chceme rozsvítit – nastavíme na 0. Třetí je levá horní LED – chceme rozsvítit… atd… až dojdeme k binární hodnotě 10001000
. V kódu ji zapíšeme jako B10001000
(aby překladač věděl, že jde o binární hodnotu).
Druhé použití funkce shiftOut
určí číslo zobrazovače, pro který jsou data platné – nejnižší bit 1. zobrazovač, druhý bit = 2. zobrazovač atd.)
K zobrazení hodnoty dojde až po nastavení pinu 4 na LOW. Až nyní dojde v registru k prokopírování dat ze vstupu na výstupy.
Obdobně je tomu pro zbylé zobrazení znaky.
- Tip:
- Zkuste zvýšit čekání mezi jednotlivými bloky pro zobrazení znaků kupříkladu na hodnotu 500 ms. Rázem se ze statického nápisu AHOJ, stanou postupně blikající a posouvající se znaky A, H, O, J. Taky hezké, ne?
2. VSTUPY
Multi-funkční Shield je pochopitelně osazen i vstupy. Nejdříve se podíváme na vstupy analogové, které ale občas použijeme i trochu „digitálně“. Nakonec si některé digitální piny nastavíme jako čistě digitální vstupy a třeba připojíme i nějakou jednoduchou „periférii“ (IR dioda, sonarové čidlo…), která však již není součástí zde popisovaného multifunkčního shieldu.
2.1. Trimr na A0
Na multifunkčním shieldu nalezneme i víceotáčkový trimr, pomocí kterého můžeme měnit vstupní napětí na jednom z analogových vstupů – zde konkrétně na vstupu A0.
Otázkou je, jak můžeme ověřit, že modul Arduino patřičnou analogovou hodnotu načetl. Ukážeme si dva příklady. V tom prvním se kromě načítání vstupní hodnoty seznámíme i s možností modulu Arduino odesílat data do PC prostřednictvím sériového portu (USB portu). V druhém příkladu si z modulu Arduino a připojeného Multi-function Shieldu vytvoříme jednoduchý digitální voltmetr.
2.1.1. Načítání A0, komunikace přes sériový port
Hodnoty odeslané do PC (připojené přes sériový port, či USB) budeme sledovat přes „Seriový Monitor“ (menu Nástroje) v prostředí určeném pro programování modulu Arduino (viz obr. 2).
![Arduino - serial monitor](funduino-test/serial-monitor.gif)
Při otáčení trimrem uvidíme, jak se nám postupně zobrazují postupně se měnící načtené hodnoty na pinu A0.
Kód:
#define Pot A0 // nastaveni vstupu pro trimr
int PotBuffer = 0; // hodnota na vstupu
void setup()
{
Serial.begin(9600); // nastaveni seriove komunkace
}
void loop()
{
PotBuffer = analogRead(Pot); // nacitej A/D prevodnik na A0 (trimrt)
Serial.print("Pot = "); // odesli do PC text: 'Pot ='
Serial.println(PotBuffer); // odesli hodnotu PotBuffer a pak odradkuj
delay(500); // pockej 500 ms
}
Popis:
Abychom poznali i něco nového z jazyka Wiring, ve kterém se píše kód pro moduly Arduino, máme zde v uvedeném kódu hned několik „novinek“:
Hned tu první najdeme na prvním řádku. Výraz #define
dělá to, že při překladu zamění dva následující výrazy – tedy narazí-li na výraz Pot
, dosadí za něj konstantu A0
(tj. označení pro vstup A0, na kterém je připojen trimr). POZOR: #define
ve skutečnosti není příkazem jazyka Wiring (např. jako deklarace konstanty), ale je vlastností překladače. Ten při překladu programu „podstrkává“ za výraz Pot
konstantu A0
. Z hlediska programu (uloženém v modulu Arduino) žádná konstanta Pot
neexistuje.
Druhou novinkou je řízení komunikace modulu Arduino přes sériový port (popř. USB port, který sériový port emuluje). Funkce Serial.begin()
se používá k zahájení sériové komunikace. Do závorek se píše parametr rychlosti této komunikace. Nejčastěji se používá hodnota 9600 (odpovídá počtu přenosů za sekundu). Funkce Serial.begin()
se většinou volá v části setup
.
Pro odeslání hodnoty do PC (či jiného zařízení) použijeme funkci Serial.print()
nebo Serial.println()
, která navíc na konci odeslaných dat přidá znak pro zalomení řádku.
Třetí novinkou je fakt, že blok setup
vůbec neobsahuje deklaraci toho, že pin A0 má být nastaven jako analogový vstup. Přesto, když kód přeložíte, vše bude fungovat, jak má. Jak je to tedy možné? Některé piny mají svou roli tak trochu předurčenou a tak ji nemusíme (ale můžeme!) uvádět. Případem takového pinu je analogový pin A0 – pokud jej tedy budeme využívat, tak jak je předurčeno, nemusíme to v bloku setup uvádět. Ale když tak učiníte, nic tím nezkazíte!
Samotný princip načítání hodnoty na trimru (pinu A0) je jednoduchý. Program se točí ve smyčce loop
, kdy pomocí funkce analogRead()
načte napětí (0–5 V)* na pinu A0 do proměnné PotBuffer
(hodnoty: 0–1024). Hodnota je pak sériovou linkou odeslána v podobě řetězce Pot =
×××× (kde ×××× je hodnota proměnné PotBuffer
).
* Hodnota (0–5 V) referenčního napětí lze programově změnit, ale zatím se tím nebudeme zabývat!
2.1.2. Jednoduchý voltmetr
Tento příklad již není jen pouhým otestováním vstupního trimru multifunkčního shieldu, ale trochu nám ukazuje, že už jsme se naučili docela prima věci!
Pomocí trimru budeme nastavovat napětí na vstupu A0, které budeme zobrazovat na čtyřech LED zobrazovačích. Chcete-li z multifunkčního shieldu udělat skutečný voltmetr (s rozsahem 0–5 V), změňte jen v #define
na první řádce A0
na A4
a na pin A4 (dostupný na konektoru pro teplotní čidlo LM35) připojte požadované měřené napětí.
Kód:
#define Pot A0 // nastaveni vstupu pro trimr
int latchPin = 4;
int clockPin =7;
int dataPin = 8; // nastaveni pro LED zobrazovac
unsigned char Dis_table[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; // definice cisel 0-10
unsigned char Dis_buf[] = {0xF1,0xF2,0xF4,0xF8}; // adresy LED zobrazovacu
unsigned char disbuff[] = {0, 0, 0, 0}; // pole odesilanych hodnot na LED
int rT=0; // pomocna promena
void setup()
{
pinMode(latchPin,OUTPUT);
pinMode(clockPin,OUTPUT);
pinMode(dataPin,OUTPUT); // nastaveni vystupu pro segmentovku
}
void display()
{
for(char i = 0; i <= 3; i++) // probene zobrazovace a zobrazi, co je treba
{
digitalWrite(latchPin,LOW); // nastavi latch pro zapis
if(i == 0)
{
shiftOut(dataPin,clockPin,MSBFIRST,Dis_table[disbuff[i]]&0x7F); // za prvnim cislem rozsvit i des. tecku
}
else
{
shiftOut(dataPin,clockPin,MSBFIRST,Dis_table[disbuff[i]]);
}
shiftOut(dataPin,clockPin,MSBFIRST,Dis_buf[i] ); // zapise adresu zobrazovace
digitalWrite(latchPin,HIGH); // vypni latch
delay(2); // pockej 2 ms
}
}
void loop()
{
float vol = analogRead(Pot)*(4.97 / 1023); // nacte dohnotu z A0 a prevede na Volty
rT= (int) (vol*1000); // vyrobi 4-ciferne cislo
disbuff[0]= rT/1000; // pocet tisicu na 1 zobrazovac
disbuff[1]= rT%1000/100; // pocet stovek na 2 zobrazovac
disbuff[2]= rT%100/10; // pocet desitek na 3 zobrazovac
disbuff[3]= rT%10; // pocet jednotek na 4 zobrazovac
for(char time = 0; time < 20; time++) // zapisovanim stejne hodnoty se to zdrzi a pritom neblikaji zobrazovace
{
display();
}
}
Popis:
S většinou věcí, které jsou použity v tomto kódu, jsme se setkali. Je tu nastavení pinů pro LED zobrazovače, načítání analogového vstupu A0 atd. Za zmínku však stojí ukázka definice vlastní uživatelské procedury/funkce. Konktrétně vytvoření procedury display()
. Stejně jako u jiných programovacích jazyků můžeme i v jazyce Wiring části kódu, které se opakovaně používají, „zabalit“ do svého vlastního příkazu. Zde je to obsluha LED zobrazovačů. Začíná deklarací void, pak následuje jméno procedury. Mohly by v závorce následovat parametry. Tělo funkce/procedury je uzavřeno ve složených závorkách.
Druhou novinkou oproti dosud používanému kódu, je použití datové struktury pole – zde jde o předem připravené hodnoty Dis_table
pro LED zobrazovače (definice pro číslice 0, 1, 2…9), stejně tak adresy Dis_buf
LED zobrazovačů. Poslední použité pole disbuff
je složeno ze čtveřice hodnot, které se budou zobrazovat na prvním, druhém… LED zobrazovači.
2.2. Vstupní tlačítka
Začíná to být příliš velká divočina? Zvolníme tedy. Začneme analogové vstupy (konkrétně A1–3) používat pro zjišťování stisknutí tlačítek. Takže vlastně tak trochu „digitálně“.
2.2.1. Načítání A1: Stiskni tlačítko S1
Jak již bylo naznačeno, použijeme analogový vstup A1 pro zjištění jednoho ze dvou stavů tlačítka S1 (zapnuto/vypnuto). Stav zapnutu (stisknuto) je na desce multifunkčního shieldu řešen připojením vstupního pinu k uzemnění. Otevření (nestisknutí) tlačítka má dvě možnosti. Buď je na shieldu zkratována propojka J2 (poblíž tlačítek) – pak je na vstupní pin přes PullUp rezistor přivedeno napětí +5 V, nebo je propojka rozpojena a vstupní pin je „volný“ – není na něj připojena žádná napěťová hodnota (značně neurčitý stav)**. Následující příklad by měl dělat jen to, že po dobu stisknutí tlačítka S1 (pin A1) se rozsvítí LED 1 (pin 13).
Kód:
int ledPin = 13; // cislo pinu LED 1
int inPin = A1; // cislo tlacitka S1
int val; // pomocna promena val
void setup()
{
pinMode(ledPin, OUTPUT); // LED jako vystup
pinMode(inPin, INPUT); // S1 jako vstup (zkratujte jumper J2 - jinak chybi PullUp rezistor)
}
void loop()
{
val = digitalRead(inPin); // nactu vstup
if (val == LOW) // pokud je stisknuto PAK
{
digitalWrite(ledPin, LOW); // rozsvit
}
else // JINAK
{
digitalWrite(ledPin, HIGH); // zhasni
}
}
Popis:
Nastavení pomocných proměnných i konfigurace pinů pro INPUT a OUTPUT je stejné jako u předešlých příkladů, kde jsme četli hodnotu vstupu A0. Načítání analogového vstupu A1 je však prováděno pomocí funkce digitalRead()
. Jde o funkci, která dle napětí na vstupu vrací jen dva stavy: buď LOW, nebo HIGH.
A nyní si zkusíme následující věc: Zkuste si funkčnost našeho příkladu a pak rozpojte propojku J2 a zkuste několikrát stisknout S1 znova. A… asi je to rozbité!!! Ne, nebojte, zasuňte propojku zpět a je vše zase O.K. Proč?
Problém je právě ve stavu rozpojeného tlačítka, kdy na vstup A1 není přivedeno žádné definované napětí. Musí se to řešit buď externím PullUp rezistorem, nebo pomocí nastavení modulu Arduino, které si na vstupní pin „umí“ připojit PullUp rezistor svůj vlastní – ale musíme mu to nařídit.
To provedeme při nastavení vstupního pinu v sekci setup
. Stačí jen vstupní pin místo typu INPUT změnit na INPUT_PULLUP. Patřičný řádek v bloku setup tedy bude vypadat takto:
pinMode(inPin, INPUT_PULLUP);
A je to! Zkuste nyní rozpojit propojku JP2 a stisknout tlačítko S1. Vše je O.K.
Obdobně je to i s tlačítky S2 (pin A2) a S3 (pin A3). A hned jsme si i vysvětlili, k čemu je propojka (jumper) J2 na desce Multi-function Shield.
** Jak tomu předejít si ukážeme po vyzkoušení následujícího příkladu.
2.2.2. Čítač s nulováním
Nyní si zase s modulu Arduino a Multi-function Shield postavíme jednoduchý čítač. Pomocí jednoho tlačítka (S1) budeme čítat pulzy a pomocí druhého tlačítka (S2) získanou hodnotu vynulujeme. Pochopitelně hodnota „namačkaná“ se bude zobrazovat na LED segmentech. Budiž tento příklad i ukázkou, že jsme nákupem Multi-function Shield neutratili své peníze zas tak úplně zbytečně.
Kód:
int latchPin = 4;
int clockPin =7;
int dataPin = 8; // pro zobrazovace
int KEY_Count = A1;
int KEY_Reset = A2; // tlacitka
unsigned char Dis_table[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; // data pro zobrazovace
unsigned char Dis_buf[] = {0xF1,0xF2,0xF4,0xF8};
unsigned char disbuff[] = {0, 0, 0, 0};
int rT = 0; // pomocna promenna
void setup(void)
{
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT); // nastaveni pro zobrazovace
pinMode(KEY_Count, INPUT); // citaci tlacitko
pinMode(KEY_Reset, INPUT); // tlacitko RESET
}
void display(void)
{
for(char i = 0; i <= 3; i++) // probehne segmenty a zobrazi hodnoty
{
digitalWrite(latchPin, LOW); // zapis na latch
shiftOut(dataPin, clockPin, MSBFIRST, Dis_table[disbuff[i]]); // data pro zobrazovac
shiftOut(dataPin, clockPin, MSBFIRST, Dis_buf[i] ); // adresa zobrazovace
digitalWrite(latchPin, HIGH); // zobraz zapsana data
delay(2); // cekej 2 ms
}
}
void GetKey(void) // nacitani tlacitek
{
if(digitalRead(KEY_Count) == LOW) // je prvni stisknute?
{
while( !digitalRead(KEY_Count) ) {display();} // je stale dole – jen zobrazuj, nic necitej
rT++; // uz je povoleno, tak zapocti
if (rT>9999) { rT=0; } // preteklo to hodnotu 9999
disbuff[0]= rT/1000; // predelej hodnoty pro zobrazovace
disbuff[1]= rT%1000/100;
disbuff[2]= rT%1000%100/10;
disbuff[3]= rT%1000%100%10;
}
if(digitalRead(KEY_Reset) == LOW) // stisknute nulovani
{
while( !digitalRead(KEY_Reset) ) {display();} // tlacitko dole, cekej az pusti
rT = 0; // vynulovani
disbuff[0] = rT/1000; // nova data pro zobrazovac
disbuff[1] = rT%1000/100;
disbuff[2] = rT%1000%100/10;
disbuff[3] = rT%1000%100%10;
}
}
void loop(void)
{
display(); // zobrazovani
GetKey(); // test tlacitek
}
Popis:
Věci kolem zobrazení číslic na LED zobrazovačích jsou zahrnuty v proceduře display
, jejíž princip byl již vysvětlen dříve. Zaměříme se tedy na proceduru GetKey
, která obsluhuje stisknutí jednotlivých tlačítek. Počáteční podmínka načte a otestuje tlačítko S1 (navyšování počtu kliknutí). Pokud je tlačítko stále stisknuté, zastaví se běh programu v následujícím cyklu while
. Hodnota čítané proměnné se tak zvětší až při puštění tlačítka (funkce digitalRead
vrátí HIGH). To je proto, aby se počítaly skutečně jednotlivá stisknutí – klidně zkuste tento cyklus vynechat a pak dlouze stisknout tlačítko. A jestliže při stisknutém tlačítku program „uvízne“ v cyklu, stalo by se, že přestanou být obsluhované zobrazovače a po dobu zmáčknutého tlačítka by náhodně svítila jen jedna číslice na čtveřici zobrazovačů. Proto je v tomto cyklu neustále na zobrazovačích zobrazována aktuální hodnota počtu pulzů – procedura display
(opět pro pochopení, doporučuji z cyklu tuto proceduru dočasně vynechat a zkusit, co se stane). Projde-li program přes tento cyklus (tj. opět bylo tlačítko puštěno), dojde k navýšení proměnné rT
a přepočtení číslic pro zobrazení (pole disbuff[0-3]
). Přesáhne-li hodnota rT
zobrazitelnou hodnotu 9999, dojde k vynulování této proměnné. Ke stejnému vynulování dojde i při stisknutí druhého tlačítka. Zobrazování číslic na zobrazovačích a test tlačítek se pak opakuje ve smyčce loop
.
Závěr (?)
Výše uvedenými příklady jsme si ukázali základní použití, či otestování funkčnosti Arduino Multi-function Shield (též někdy označovaného Funduino).
Pochopitelně to není vše!
Tento shield je připraven pro připojení teplotních čidel (LM35, Dallas 18B20), modulu sonaru (HCSR04), serva či krokového motoru, radiového modulu (APC220). Ovšem tyto moduly a součástky již nejsou součástí běžného dodání modulu Multi-function Shield. Je tedy třeba si je dokoupit. A pak si zase začít „hrát“.
Ale o tom třeba zase někdy příště…