You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Next »

Cvičenie je zamerané na prácu s vývojovou doskou Arduino. Cvičenie je orientované na základné programovanie mikroprocesora. V rámci cvičenia budú demonštrované spôsoby obsluhy tlačidiel, I2C zbernice, sériovej linky, analógových a digitálnych vstupov a piezoelektrických akustických meničov. Po osvojení si učiva, študent dokáže realizovať základné zapojenia s využitím vývojovej dosky Arduino, skúšobného nespájkovateľného poľa a pasívnych elektronických prvkov (rezistor, dióda, a pod.). Študent dokáže napísať jednoduchý zdrojový kód pre obsluhu mikroprocesora Atmega328P.   

  • Digitálne vstupno-výstupné piny
  • Analógové vstupné piny
  • Všetko podstatné o tlačidlách 
  • Sériová linka 
  • I2C zbernica a displej 
  • Bzučiaky a zvuky
  • Pulzne-šírková modulácia PWM

Odporúčaná literatúra a dôležité odkazy

[1] KPI-FEI-TUKE: 

[2] KPI-FEI-TUKE:  

[3]  

[4]   


Digitálne vstupno-výstupné piny

 Ako už bolo na predchádzajúcom cvičení a tiež aj na prednáške, Arduino Uno obsahuje 14 digitálnych pinov zvyčajne označených ako D0 - D13. Tiež bolo povedané, že aj analógové piny A0 - A5, ktoré primárne slúžia ako analógový vstup  je možné použiť ako dgitálne. Pri práci s digitálnym pinom je potrebné si osvojiť minimálne tieto príkazy:

  • pinMode(pin, nastavenie)  - Spravidla túto funkciu voláme vo funkcii setup() a pomocou nej určujeme či budeme pin používať ako výstup - OUTPUT, vstup - INPUT alebo vstup so vstavaným pull-up rezistorom INPUT_PULLUP (vysvetlíme pri tlačidlách). 
  • digitalWrite(pin, hodnota) - Slúži na zápis logickej hodnoty na daný pin.
  • digitalRead(pin) - Slúži na prečítanie logickej hodnoty z daného pinu.

Vstup či výstup?

Je potrebné si uvedomiť, že zle nastavený režim pinMode() môže spôsobiť nesprávne chovanie sa zariadenia a vo špecifických prípadoch aj jeho zničenie!

  • Pokiaľ na digitálny pin chceme pripojiť záťaž ako je napríklad dióda, relé ale aj tranzistor (ten ozaj nepredstavuje veľkú záťaž) a podobne, je potrebné, aby z/do procesora tiekol pomerne veľký prúd (max 20mA!). Vtedy sa vnútorná štruktúra procesora musí na tento stav pripraviť. Docieli sa to tak, že daný pin sa prepne do režimu nízkeho odporu. Toto dosiahneme s príkazom pinMode(pin,OUTPUT). Pozor na stav ak je pin nastavený ako výstup a pripojí sa priamo na zem alebo +5V. Môže dôjsť k jeho zničeniu!
  • Pokiaľ pin hodláme použiť ako digitálny vstup, spravidla nechceme, aby ním pretekal vysoký prúd. V elektronike je zvykom, že ak je niečo vstupom má to mať vysoký (teoreticky nekonečne veľký) odbor. Je to preto, že samotným meraním nechceme ovplyvniť chovanie sa meraného obvodu. V konečnom dôsledku na I/O pinoch procesora meriame hodnotu napätia (či už logickú 0 (0V) - 1 (5V) alebo analógovú hodnotu v nejakom rozsahu), teda je nežiadúce aby pinom tiekol prúd. Vtedy použijeme pinMode(pin, INPUT). Vstupu je stále možné v programe priradiť digitálnu hodnotu 0 alebo 1.    

Nasledujúci príklad simuluje situáciu kedy je Arduino použité na monitorovanie či slučka obvodu nie je prerušená. Napríklad si môžeme predstaviť bezpečnostný snímač na okne či dverách. Ak sú dvere otvorené tento sa rozpojí a preruší sa kontrolovaný obvod. 


void setup()
{
  // Pin 13 bude výstup, lebo na neho pripojíme LED diódu, ktorú potrebujeme napájať
  pinMode(13, OUTPUT);
  // Pin 10 bude vstup. Pripojíme naň spínač cez, ktorý sa pin pripojí na zem 
  // alebo zdanlivo bude "vo vzduchu".
  pinMode(10, INPUT);
  // Ono by sa mohlo zdať, že pin nie je pripojený k ničomu ak je spínač v polohe vľavo.
  // Nie je to pravda. Nasledujúcim príkazom tento pin vo vnútri procesora pripojíme
  // cez vysoký odbor na +5V a teda ak je spínač v pozícií vľavo, na pine bude logická 1.
  // Ak je spínač v pozícii vpravo, spínačom potečie veľmi maličký prúd smerom na zem a 
  // na pine bude hodnota logickej 0. 
  digitalWrite(10, HIGH);
}

void loop()
{
  // Ak sa na pine nachádza logická 1 LED svieti.(Okno je otvorené - obvod bol prerušený )
  if( digitalRead(10) == 1)
    digitalWrite(13, HIGH);
  else // Ak sa na pine nachádza logická 0 LED nesvieti.(Okno je zatvorené)
    digitalWrite(13, LOW);
}

Analógové vstupné piny

Pre pochopenie a správnu prácu s analógovým vstupom je nutné porozumieť tomu ako vlastne tento vstup dokáže merať hodnotu napätia. Nechceme a ani nemôžeme ísť do detailov problematiky, ale určite musíme skonštatovať, že vo vnútri procesora Atmel ATMega328p je integrovaný Analógovo Číslicový  Prevodník ( Analog Digital Coverter - ADC). Existuje viacero typov prevodníkov ale v ATMege je takzvaný  Successive Approximation Register Analog to Digital Converter (SAR ADC) s rozlíšením 10 bitov. Rozlíšenie 10 bitov znamená, že hodnotu meraného napätia dokáže rozlíšiť na 1023 úrovní. Tomuto procesu sa tiež hovorí kvantizácia o ktorej sa budete učiť neskôr. Ďalším dôležitým parametrom pri analógovom vstupe je referenčné napätie. Toto napätie môžeme priviesť na pin Aref ale tiež ho na tomto pine môžeme aj namerať. Arduino má toto napätie vnútorne nastavené na +5V ale programovo ho môžeme meniť   príkazom analogReference(). Rôzne vývojové dosky majú rôzne možnosti voľby úrovne tohto napätia. Pre Arduino UNO a Nano sú nasledovné: 5V a 1.1V a prípadne ľubovoľná externá hodnota (z rozsahu 0 - 5V) privedená na pin Aref.  Pre Arduino Uno hodnotu referenčného napätia nastavíme takto:

  •  analogReference(DEFAULT) - Referenčná hodnota bude nastavená na hodnotu 5V
  •  analogReference(INTERNAL) - Referenčná hodnota bude nastavená na hodnotu 1.1V
  •  analogReference(EXTERNAL) - Referenčná hodnota bude nastavená na hodnotu aká je pripojená na pin Aref.

Nastavením referenčnej hodnoty určíme v akom rozsahu chceme napätie merať. Toto je napríklad výhodné vtedy ak vieme, že budeme merať hodnoty napätia, ktoré nebudú prevyšovať hodnotu 1.1V. Vtedy je rozumné nastaviť Aref na 1.1V. Získame tak oveľa presnejšie meranie. Ako už bolo uvedené vyššie. Vieme merať s presnosťou na 10 bitov. To znamená, že najmenšie možné napätie, ktoré vieme zmerať je rovné Aref/1023. Teda pre 1.1V/1023 =  0,0011V ale pre 5V refenciu to bude 0,0049V. 

Ďalej musíme poznamenať, že vnútorné referenčné napätie nemusí byť vždy identické s katalógovou hodnotou. Môže sa trochu líšiť a to môže zásadne ovplyvniť presnosť merania. Preto si pri návrhu zariadenia musíme odmerať skutočnú hodnotu referenčného napätia na pine Aref a vo výpočtoch potom používať túto hodnotu.  Na Analógový a referenčný vstup  nesmie byť pripojené napätie vyššie ako 5.5V dôjde k jeho zničeniu! 

Príklad: Pomocou analógového vstupu A1 odmerajte hodnotu naň pripojeného napätia. Ak toto napätie prevyšuje 3V rozsvieti sa LED dióda pripojená k pinu D13. 

void setup()
{
 // Pin 13 bude výstup, lebo na neho pripojíme LED diódu, ktorú potrebujeme napájať
  pinMode(13, OUTPUT);
 // Zvolili sme referenčnú hodnotu napätia na +5V
  analogReference(DEFAULT);
 // Aby sa inicializovala referenčná hodnota je potrebné urobiť jeden analogRead. 
 // Hodnota nás nezajíma ide len o to, aby sa nastavila referenčná hodnota 
  analogRead(15);
}

void loop()
{
 float Aref = 5.0;
 // Hodnotu napätia vo voltoch získame tak že meranú hodnotu z ADC predelíme hodnotou
 // 1023 a tento výsledok vynásobíme hodnotou Aref. Musí sa to pretypovať na float!  
 // A1 je na pine č. 15, mohla by sa to zapísať aj ako A1. 
 float voltage = (float) Aref*analogRead(15)/1023;

  if(voltage > 3.0)
    digitalWrite(13,HIGH);
  else
    digitalWrite(13,LOW);
}

Ešte si ukážme príklad kedy sa zvolí vonkajšie referenčné napätie. Referenčné napätie bolo získané pomocou napäťového deliča, ktorý je vyhotovený pomocou potenciometra (pokojne aj 5kohm). V kóde vpravo došlo len k malej zmene. Takto nastavená referenčná hodnota umožňuje merať napätie z rozsahu 0-4V. Vyššie pripojené napätie na analógovom vstupe bude stále vyhodnotené ako 4V. Presnosť merania je teraz približne 0.004V. 



Na záver je potrebné poznamenať, že ADC môže zavádzať rôzne nelinearity, offset a tiež šum. Tieto nedostatky sa odstraňujú kalibráciou, ktorá však nie je náplňou predmetu Programovanie.  

void setup()
{
 // Pin 13 bude výstup, lebo na neho pripojíme LED diódu, ktorú potrebujeme napájať
  pinMode(13, OUTPUT);
 // Zvolili sme referenčnú hodnotu napätia z vonkajšieho zdroja
  analogReference(EXTERNAL);
 // Aby sa inicializovala referenčná hodnota je potrebné urobiť jeden analogRead. 
 // Hodnota nás nezajíma ide len o to, aby sa nastavila referenčná hodnota 
  analogRead(15);
}
void loop()
{
 float Aref = 4.0;
 // Hodnotu napätia vo voltoch získame tak že meranú hodnotu z ADC predelíme hodnotou
 // 1023 a tento výsledok vynásobíme hodnotou Aref. Musí sa to pretypovať na float!  
 // A1 je na pine č. 15, mohla by sa to zapísať aj ako A1. 
 float voltage = (float) Aref*analogRead(15)/1023;

  if(voltage > 3.0)
    digitalWrite(13,HIGH);
  else
    digitalWrite(13,LOW); 
}

Všetko podstatné o tlačidlách 

Ako nie!

Na internete sa môžeme stretnúť s mnohými spôsobmi pripojenia tlačidiel na digitálne piny. Asi úplne jahorší spôsob je zobrazený na obr. vpravo. Takéto zapojenie sa môže chovať nepredvídateľne a navyše je to zaručený spôsob ako zničiť port ak sa nechá v režime výstupu! Digitálny pin doslova "visí vo vzduchu" pokiaľ nie je tlačidlo stlačené. Nikdy to takto nerobte!

Ako áno.

Existuje viacero správnych riešení ale najčastejšie sa stretnete s takzvaným PULL UP a PULL DOWN zapojením. Tieto zapojenia sa líši tým ktorý stav je pine stabilný - teda prítomný v čase keď tlačidlo nie je zopnuté.

PULL UP - Pin je neustále pripojený cez rezistor na napájacie napätie +5V a môže ním pretekať veľmi malý prúd. V prípade stlačenia tlačidla sa pin pripojí k zemi. Obvodom zdroj>rezistor>tlačidlo>zem  tečie malý prúd ale na pine je meraná hodnota 0V. 

PULL DOWN - Pin je neustále pripojený na cez rezistor na zem (GND) a v prípade stlačenia tlačidla sa pin pripojí k napätiu +5V. Obvodom zdroj>tlačidlo>rezistor>zem  tečie malý prúd a na pine je meraná hodnota +5V. Pokiaľ tlačidlo nie je zopnuté obvodom netečie žiadny prúd.  

INTERNAL PULL UP - V tomto prípade je možné využiť vstavaný rezistor, ktorý je možné programovo pripojiť ku každému I/O vstupu. Obvod sa chová rovnako ako v prípade klasického PULL UP riešenia

Tieto tri spôsoby sú spolu s obslužným kódom zobrazené nižšie. Po stlačení tlačidla má dôjsť k rozsvieteniu diódy pripojenej na pin 13. 

ZLE RIEŠENIE


PULL UP:

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(6, INPUT);
}
void loop()
{
  if(digitalRead(6) == 0)
  	digitalWrite(13, HIGH);
  else
    digitalWrite(13, LOW);
}

PULL DOWN:

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(6, INPUT);
}
void loop()
{
  if(digitalRead(6) == 1)
  	digitalWrite(13, HIGH);
  else
    digitalWrite(13, LOW);
}

INTERNAL PULL UP

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(6, INPUT_PULLUP);
}
void loop()
{
  if(digitalRead(6) == 0)
  	digitalWrite(13, HIGH);
  else
    digitalWrite(13, LOW);
}

Skutočný hardvér sa môže chovať inak ako simulačný sofvér....

Doposiaľ sme uvažovali o ideálnych podmienkach a ideálnych súčiastkach. Problém však je ten, že nič nie je ideálne. Tlačidlá sú známe tým, že po stlačení dochádza k zákmitu (rýchle zopnutie a rozopnutie) to pri rýchlom Arduine znamená to, že v podstate to zaregistruje, že tlačidlo bolo stlačené mnohokrát. Riešiť sa to môže hardvérovo, pripojením kondenzátorov a podobne ale skôr sa stretneme so softvérovým riešením. To spočíva v tom, že po tom ako je prvý krát zachytené stlačenie tlačidla na nejakú dobu sa prestane sledovať jeho stav. Zvyčajne sa to robí veľmi zle cez funkciu delay(). Túto pre ukážku použijeme v nasledujúcom príklade. Pritom uvažujeme zapojenie s INTERNAL PULL UP  To ako to urobiť elegantne si ukážeme na ďalšom cvičení.   


void loop()
{
  if(digitalRead(6) == 0)
	{
  	delay(50);
	digitalWrite(13, HIGH);
	} else
    digitalWrite(13, LOW);
}



Diagram Arduino debounce push button


  • No labels