Projekt 11.

Cyklické zobrazovanie čísel na LED displeji

Cieľ lekcie:

  1. Zapamätať si spôsoby, ako v Internete vyhľadať katalógové informácie výrobcu 7 segmentového displeja, ktorý žiak nájde v stavebnici.
  2. Na základe získaných informácií porozumieť funkcii  viacznakového (2 , resp. 3 zn.) 7 segmentového displeja  zapojeného buď so spoločnou anódou alebo zo spoločnou katódou - podľa jeho označenia na povrchu. 
  3. Aplikovať získané vedomosti a pripojiť hardvér na konektory mikropočítača Arduino DUEMILANOVE (resp. UNO).
  4. Zapamätať si postup ako kódovať zobrazované číslice v závislosti od vlastného rozhodnutia ako prepojiť jednotlivé bity 7 bitového kódu. 
  5. Porozumieť princípu multiplexného zobrazovania obsahu viacmiestneho displeja. 
  6. Zo vzorov programov vyhľadať podobné riešenia, rozanalyzovať príkazy a vysvetliť ich funkcie a nakoniec aplikovať tieto postupy vo vlastnom riešení.
  7. Vytvoriť funkciu s parametrami podľa počtu znakov displeja (napr. tis, stov, des, jed),  kde sa bude dosadzovať 7 bitový kód zobrazovanej číslice.
  8. Vyriešiť transformáciu 16 bitovej premennej typu celé číslo (unsigned integer) na samostatne zobrazované číslice umiestnené do premenných tis, stov, des, jed typu byte.
  9. Prakticky si odskúšať realizáciu vlastnej funkcie, ktorá v parametri prijme celočíselnú hodnotu a túto po separácii na jednotlivé číslice zobrazí na jednotlivých digitoch viacmiestneho 7 segmentového  displeja.  

 

Zadanie: 

         Vytvorte program ktorý v hlavnom cykle pomocou programu vypisIntCislo(cislo);  zobrazí, na 7 segmentovom displeji s tromi digitmi, číselný údaj predtým vložený do premennej "val" typu integer.

Analýza:

Počiatok analýzy ktorá rieši funkciu LED zobrazovačov je rovnaký ako v Projekte1. Kto to pochopil môže priamo preskočiť ďalej na Analýzu taktiky programovania.

  1. Čo potrebujeme urobiť aby sme rozsvietili LED diódu?  Pripojiť ju priamo na zdroj? V akom smere - priamom či závernom? Nezničí ju prúd? Viete na to odpoveď? Pomôže vám  ZAPOJENIE LED

  2. Ak ste vyriešili prvú otázku nasleduje druhá. Mikropočítač ARDUINOTM  je zariadenie ktoré komunikuje so svojim okolím cez PORTY. Ako môžeme ovládať iné zariadenia mikropočítačom ARDUINO? Odpoveď je - digitálnymi signálmi Log0 (t.j.- NEPRAVDA, FALSE,  LOW, 0V) a Log1 (t.j.- PRAVDA, TRUE, HIGH, +5V). Ako získate logickú 0 a 1 ak máte dostupné len napájanie +5V a GND? Pomôže vám ZDROJ LOG SIGNÁLOV.

  3. Posledná otázka je: Ako programovo nastavovať logické hodnoty tak, aby sa LED dióda zapínala a vypínala. Najjednoduchšie  nájdete odpovede v príklade. Otvorte si vývojové prostredie ARDUINA. Aby ste otvorili  vzor, v hlavnom menu navoľte File / Examples/ 1. Basic/  Blink. Našli ste vzor? Ak áno vypíšte si každú kľúčovú inštrukciu.

Vysvetlíme si ich význam:


              pinMode(13, OUTPUT);  // Nastav režim Vstupno/Výstupného pinu 13 na VÝSTUP
              pinMode(13, INPUT);   // Nastav režim Vstupno/Výstupného pinu 13 na VSTUP
    

Sú len dve možnosti použitia pinov ARDUINA:  OUTPUT (VÝSTUP) a INPUT (VSTUP). Piny 0 až 13 označené DIGITAL na doske ARDUINA predstavujú digitálne Výstupy a Vstupy. Niektoré z nich umožňujú aj tzv. "Analógový" PWM výstup,  ktorý je v podstate digitálny, ale periodický signál  (pravidelne strieda log0 a log1 s periódou zvyčajne okolo 10kHz. Pomer plôch medzi log1 a log0  v takomto signáli môžeme programovo meniť, čím ovplyvňujeme množstvo tečúcej energie. Takýto signál nahradí analógový regulátor napätia). Ďalší konektor ARDUINA označený ANALOG IN používa piny 0 až 6 ako samostatné detektory analógových napätí v rozsahu 0 - 5 V. Pomocou týchto vstupov vie mikropočítač vzorkované hodnoty digitalizovať a spracovať do formy celého čísla v intervale hodnôt 0 až 1023. V prípade vyšších napätí sa tieto dajú prispôsobiť odporovým deličom ( presne kalibrovanom a presne určeným pomerom ) a ošetriť prepočtom v programe v priamej úmere medzi nameranou a skutočnou hodnotou.

Nasledovné inštrukcie vám pomôže pochopiť animácia s doskou ARDUINA.


              digitalWrite(13, HIGH);  // Nastav na pine 13 logickú úroveň HIGH t.j. log1
              digitalWrite(13, LOW);   // Nastav na pine 13 logickú úroveň LOW  t.j. log0 
    

Poslednou inštrukciou vo vzorovom príklade je inštrukcia vyvolávajúca spomalenie programu:


              delay(1000);             // Počkaj sekundu t.j. 1000 milisekúnd
        

Ovládanie 7 segmentového displeja  využíva 7 bitov pre každý segment samostatne. Nastavovať ich postupne samostatnými bitovými príkazmi sa dá, ale efektívnejší spôsob je zápis celého kódu do výstupného portu naraz viď. dokumentácia Arduina http://www.arduino.cc/en/Reference/PortManipulation.


               PORTD = B10101000;     // nastaví digitálne bity portu D piny 7,5,3  na HIGH (log1)  
         

Analýza taktiky programovania

Hľadajte odpovede na tieto čiastkové úlohy:

  1.  Ako môžeme ovládať iné zariadenia mikropočítačom? Tu si môžete pozrieť JEDNOPÓLOVÉ ovládanie (t.j. druhý pól predstavuje Vcc=+5V alebo GND=0V) a tu DVOJPÓLOVÉ. Animované obrázky obsahujú informácie ktoré rozanalyzujte a urobte si s nich závery dôležité pre ovládanie externých zariadení.  

  2.  Trojznakový 7 segmentový Kingbright BC56-12GWA, ktorý máte k dispozícii, obsahuje LED diódy segmentov zapojené - so spoločnou katódou pre každý digit (číslicu), pričom anódy segmentov displeja na rovnakej pozícii v digite (číslici) - sú prepojené paralelne. Dióda sa ROZSVIETI kombináciou kladného potenciálu (log1) na anóde a nulového potenciálu GND t.j. log0 na spoločnej katóde digitu. Spoločné katódy určujú ktorý digit bude svietiť. Ako pripojiť ochranný odpor? Pred anódu alebo pred katódu? Vychádzajte z Kirchhoffových zákonov a rovníc.  Musíte sa rozhodnúť ako zapojiť ochranný odpor, ale myslite na to, že pri ľubovoľnej kombinácii potenciálov na jednotlivých anódach musia prúdy tečúce cez diódy mať rovnakú hodnotu a mal by byť okolo 20mA.    

  3. Na začiatok, aby ste sa zacvičili, vyskúšate si jednoduchú aplikáciu. Pozrite si program Examples/1.Basic/Blink. A z neho aplikujte ovládanie tohto zapojenia  displeja 3x7LED, ktoré predstavuje ručné ovládanie LED displeja. Spínače v schéme nahradíte odpovedajúcimi logickými hodnotami na výstupe Arduina. Tam kde zopnutím spínača uzemníte kontakt tam privediete odpovedajúcu logickú hodnotu buď - Log0 resp. Log1. Vašou prvou úlohou bude pripojiť segment "a" na potenciál log1 a potom výstupy Dig1, Dog2 a Dig3 postupne uzemňovať potenciálom Log0. Dosiahnete efekt postupného prepínania Digitov. Skúšaním a kombinovaním stavov Delay dosiahnite také stavy aby prepínané digity prestali blikat a navodili trvaly stav zapnutia.

  4. Ako vytvoríte vzťah medzi zobrazovaným číslom a jeho kódom? Číslice majú tú vlastnosť že nasledujú jedna po druhej podľa veľkosti. Hodnota 0 má aj ASCII kód menší ako hodnota 1. Dajú sa zoradiť podobne ako  prvky poľa. Aké vlastnosti má každé pole?  Jednak obsahuje prvky všetky rovnakej veľkosti a jednak prvky pola v C jazyku sa adresujú indexom uzavretom v hranatých zátvorkách počnúc hodnotou 0. Podobne ako číslice. Sedem segmentový displej má 7 bitov a premenná typu byte - 8 bitov. Preto pre 7 segmentový displej je výhodné použiť pole typu byte.

  5. 
     byte kod7segZn[]={ // pole pre uloženie kódov číslic pre sedem segmentový displej 
                        B01111111, //0  
                        B00001101, //1
                        ...
                        B11011111  //9
                        };  
             
    
  6.  Keďže v jednom čase bude svietiť vždy len jeden digit displeja, musíme pravidelne prepínať jednotlivé digity - ovládaním spoločných katód digitu (resp. anód pri zapojení so spoločnou anódou), t.j. pri viacznakovom displeji postupne cyklicky zapínať a zobrazovať iný kód pre každú pozíciu. Ľudské oko nedokáže rozlíšiť zmeny ktoré sa vykonávajú rýchlejšie ako 1/100 sekundy t.j. 10 msek. To znamená, že ak každý digit bude zobrazovaný len takúto dobu, naše oko to bude vnímať ako neprerušovaný svit. Efekt sa nakoniec prejavý ako viacciferný údaj na displeji.
    V nasledovnom programovom kóde sa bude opakovať sekvencia troch akcií, z ktorých každá sa bude opakovať minimálne po dobu 10 milisekúnd. Rozanalyzujte tento jednoduchý program a vysvetlite, a experimentom odskúšajte. Budete ho potrebovať na ovládanie prepínania digitov.

  7. 
             unsigned long timediff;
             int cas=10;
             
             void loop()
             { 
                timediff=millis();                        // nastav nové počítanie času
                while(millis()-timediff<=cas) { AKCIA1 } //  Akcia bude Tri krát zopakuj AKCIU
                
                timediff=millis();                        // nastav nové počítanie času
                while(millis()-timediff<=cas) { AKCIA2 } //  Akcia bude Tri krát zopakuj AKCIU
                
                timediff=millis();                        // nastav nové počítanie času
                while(millis()-timediff<=cas) { AKCIA3 } //  Akcia bude Tri krát zopakuj AKCIU
                }
            
    
  8. Jednou z úloh riešenia je separácia číslic z číselného údaja. Ako zistíte koľko je jednotiek v čísle? Ak máme kalkulačku môžeme to urobiť delením desiatimi. Dostaneme reálne číslo, ktoré má celú časť a desatinnú časť.  Separujeme celú časť a desatinnú znova vynásobíme desiatimi. Dostávame jednotky. V C jazyku na separovanie jednotiek a zvyšku využijeme dve operácie. Obyčajné delenie celého čísla vytvorí celočíselný podiel bez zvyšku. Naopak na zvyšok musíme aplikovať operáciu modulo. Viď. príklad ktorý môžete uložiť do cyklu  loop a monitorovať pomocou sériového monitoru:


   int cislo=1235;         // v premennej cislo nastavíme hodnotu obsahujúci tis, stov, des a jed
   byte tis,stov,des,jed;  // premenné na uloženie separovaných číslic

   int pom;                // pomocná premenná
   int cis=cislo;          // pracovná premenná 
   
   pom=cis/10;             // do premennej pom odseparovalo tisíce, stovky a desiatky
   jed=(byte)(cis % 10);   // odseparovanie jednotiek
   
   pom=cis/10;             // do premennej pom odseparovalo tisíce, stovky a desiatky
   des=(byte)(cis % 10);   // odseparovanie desiatok
   
   // ... atď.
   

Nasledovný príklad využíva premenné typu pointer (je určený pre chápavejších žiakov, takže sa rozhodnite sami) :


val=1253;                            // premenná obsahujúca originál hodnoty

// originál číslo val zmenší 10 násobne a vráti ASCII kód jednotky

byte separujJednotky(int* hodnota)   // pôvodná premenná "val", na ktorú ukazuje pointer "hodnota" 
{                                    // sa zmenší o jednotky
  int pom=*hodnota;
 
  *hodnota= *hodnota/10;             // odseparovanie jednotiek - celočíselným podielom
  pom=(*hodnota) % 10;               // odseparovanie jednotiek - oper.modulo (zvyšok po delení)
  return ((byte)pom);                
  }

 void loop() 
 {...
 
  jed=separujJednotky(&val);         // &val predstavuje adresu premennej val 
  des=separujJednotky(&val);         //  po každom použití sa z premennej val odseparujú jednotky
  stov=separujJednotky(&val);        //  a zvyšok sa zmenší na 1/10-tinu
  tis=separujJednotky(&val);
  ...
  }
  

Dostávame sa ku konečnému riešeniu. Cieľom je vytvoriť taký algoritmus funkcie (podprogramu), ktorý dokáže meniť svoju pracovnú činnosť podľa hodnôt parametrov uvádzaných v zátvorke za názvom funkcie (pri väčšom počte sú oddelené čiarkami). Parametre sú premenné, ktoré sa odovzdajú bloku podprogramu ako lokálne premenné nastavené pri volaní funkcie (t.j. podprogramu)(Poznámka: zavolať podprogram - znamená v jazyku programátorov spustiť podprogram z iného programu s tým, že po ukončení podprogramu sa postupnosť vykonávania inštrukcií vráti za inštrukciu, ktorá spustila podprogram). Pri štarte funkcie (podprogramu) sa skutočné parametre - hodnoty použité pri volaní funkcie-  priradia tzv. formálnym parametrom funkcie t.j. externé údaje sa skopírujú do lokálnych premenných bloku funkcie. Ak vytvárame podprogramy schopné vykonávať rôzne činnosti na základe zmenených parametrov nazývame ich - programy riadené údajmi.

Prevedenie: 

Vytvorte program s názvom zobrazNa3x7segmLed(int udaj). Upravte ho tak, aby pri hodnote prevyšujúcej 999 vypísal na displeji správu Err. Ak máte bredboard (prepojovaciu skúšobnú dosku) prepojte na nej LED displej aj s ochrannými odpormi a napojte ho na PORTD mikropočítača ARDUINA. Vyskúšajte vytvorený podprogram a naučte sa čiastkové algoritmy (t.j. vykonávajúce konkrétnu prácu ktorú viete pomenovať) zjednodušovať tak, aby ste pri programovaní vytvárali čo najviac podprogramov. Do programu skúste vpašovať snímanie analógovej hodnoty z potenciometra podľa vzoru (http://arduino.cc/en/Tutorial/AnalogReadSerial)  v ktorom sa sníma analógová veličina na potenciometri a zobrazujú namerané hodnoty . 

Otázky:

  1. Akou inštrukciou určíte režim pinu v porte mikropočítača?
  2. Máte predstavu aký čas trvá vykonanie zmeny stavu bitu výstupného portu?
  3. Na čo slúži funkcia delay(); ?
  4. Ako uchováte v programe usporiadanú postupnosť kódov?
  5. Aké napätie (potenciál) má vývod označený GND?
  6. Čo je to funkcia?
  7. Ako volajúci program odovzdá podprogramu údaj?
  8. Aký štatút majú parametre? Sú rovnaké ako GLOBÁLNE alebo ako LOKÁLNE premenné?
  9. Ktorá kombinácia potenciálov anoda - katoda rozsvieti LED diódu.
  10. Akou operáciou zapíšete kód na vstup 7 segmentového displeja. 

 

Ak ste nezaváhali ani v jednej otázke a úlohu ste zvládli postupujete do projektu 12.