Kurz Arduino úroveň II – #6 – 7-segmentové displeje

V projektech založených na Arduino se nejčastěji používají textové displeje, grafické LCD displeje jsou poměrně vzácné.

Překvapivě mnoho lidí zapomíná na třetí možnost, a to na 7-segmentové displeje. Ty lze použít k zobrazení relativně jednoduchých informací. Každý si je jistě spojuje s digitálními hodinami nebo multimetry.

Objednejte si sadu prvků a začněte se učit v praxi! Kliknutím sem přejdete do obchodu >>

Většina obrazovek, se kterými se setkáváme, se skládá z pixelů, tj. malých svítících bodů. Z nich se vytvoří text/grafika. Zde probírané 7-segmentové displeje jsou zcela odlišné – skládají se ze 7 velkých „bodů“.

Každý z těchto bodů je světelná dioda ve tvaru obdélníku. Úsečky jsou označeny písmeny a, b, c, d, e, f, g – jejich uspořádání je vždy stejné, jak je uvedeno níže:

Popis segmentů displeje.

Pro zobrazení určitého znaku se musí rozsvítit příslušné segmenty. Například pro číslo 1 musí být zapnuty segmenty B a C, pro číslo 2 segmenty A, B, D, E, G atd..

Některé displeje mají také samostatný „osmý segment“ označený P. Jedná se o body, které mohou být užitečné při zobrazování neceločíselných hodnot. Lze je však použít i ve zcela jiné funkci – to záleží pouze na představě vývojáře. Tento prvek lze považovat za samostatnou LED diodu. To však není hlavní funkce takového displeje.

Někdy k tomu dochází i přes přítomnost tečky na přední straně displeje,
že LED dioda není vůbec přítomna a nemůžeme ji ovládat.

Konfigurace 7- segmentového displeje

Displeje jsou nabízeny k prodeji v různých konfiguracích. Zaprvé jsou k dispozici v různých velikostech a barvách. Za druhé, v pouzdře se běžně nachází jediný displej, ale existují samozřejmě i verze, které mohou zobrazovat několik číslic vedle sebe.

Příklady různých 7segmentových displejů.

Uspořádání konektorů na krytu se může v jednotlivých případech lišit, proto je vždy dobré nahlédnout do datového listu displeje. Samozřejmě se můžete pokusit identifikovat všechna spojení sami, ale to zabere více času.

Společná katoda/anoda

Stejně jako u RGB LED kombinují výrobci katody/anody jednotlivých segmentů, aby ušetřili místo uvnitř těchto displejů. V praxi to znamená, že se uvnitř krytu nachází jedna z následujících variant:

Konfigurace: společná anoda.
Konfigurace: Společná anoda.

Zjednodušeně řečeno: V konfiguraci jsou všechny „mínusy“ diod zapojeny tak, že se segment rozsvítí, když je na jeho vstupu „plus“. V druhé konfiguraci jsou „plusové body“ zapojeny tak, že se segmenty rozsvítí, když je na jejich vstup přivedeno „mínus“.

Ale dost teoretizování, teď je čas to uvést do praxe…

Hotové sady pro kurzy Forbot
Sada prvků   Zaručená podpora   Odeslání do 24 hodin

Komponenty pro cvičení z kurzu Arduino (úroveň 2) jsou k dispozici jako hotové sady! Patří sem programovatelné diody, analogové a digitální teploměry, 7-segmentové displeje a senzor pohybu (PIR).

Testovaný displej

Sady součástek pro tento kurz obsahují dvojitý displej se společnou katodou. Symbol výrobce je v závislosti na sadě následující: LDD040AUE-101A nebo LDD040AAG-101. Tyto displeje jsou identické a liší se pouze barvou osvětlení (takže je jedno, který přesně máte).

Nyní se musíte podívat do datového listu, abyste našli popis přiřazení pinů:

Popis připojení použitého displeje.

Jak vidíte, struktury uvnitř displeje jsou na sobě zcela nezávislé – v podstatě máme dva samostatné displeje v jednom pouzdře. Za zmínku stojí také to, že zde nejsou uvedeny žádné informace o pinech, které ovládají připojení P (bod). Jak jsem již zmínil, může se stát, že tento bod není aktivní – to bude tento případ.

Poznámka: Doufám, že je v této fázi kurzu jasné, že LED diody musí být napájeny přes rezistory. Zde je ještě důležitější, že diody uvnitř displeje ještě snadněji vyhoří než běžné LED diody!

Zbývá vyřešit hádanku, jak jsou tato spojení očíslována. Tady je to snadné, protože výrobce označil příslušná čísla (1 a 16) na zadní straně displeje:

Popis číslování vývodů pro připojení displeje.

Nyní připojíme první ze dvou displejů k Arduino. V tuto chvíli mám špatné zprávy. Z této části hřiště bude obtížné správně zapojit celý okruh. Můžete to samozřejmě udělat rychleji, chaoticky. Ve svých řešeních jsem se však snažil postupovat zcela správně….

Připojení displeje k Arduino

Nás zajímá první displej, tj. segmenty připojené na piny 1, 2, 3, 13, 14, 15, 16. Samozřejmě musíme ke každému z těchto pinů připojit rezistory, a to je dobrý začátek. Diody v displeji jsou jasné, takže zde bude dobře fungovat odpor 1k.

Začneme tedy připojením rezistorů k jednotlivým segmentům displeje č. 1. Později chceme mít možnost připojit každý rezistor na linku z Arduino. V mém případě to vypadalo takto:

Rezistory připojené k displeji.
Zobrazení bez displeje.

Protože je deska plošných spojů úzká (každý signál má pouze 5 společných pinů), musel jsem využít prostor pod displejem pro dobré rozmístění odporů. Tímto způsobem jsem přivedl rezistor k noze 13 (segment B):

Rezistor je instalován zespodu.
Zobrazení se zvednutým displejem.

Další krok je jednoduchý, jednotlivé rezistory připojíme drátem k Arduinu UNO. Pořadí může být libovolné, já jsem předpokládal následující:

  • Připojení č. 1 (segment C), na pin č. 2 Arduino,
  • Připojení č. 2 (segment E), na pin č. 3 Arduino,
  • Připojení č. 3 (segment D), na pin č. 4 Arduino,
  • Připojení č. 13 (segment B), na pin č. 5 Arduino,
  • Připojení č. 14 (segment G), na pin č. 6 Arduino,
  • Připojení č. 15 (segment A), na pin č. 7 Arduino,
  • Připojení č. 16 (segment F), na pin č. 8 Arduino.
První 3 připojení.
Další spojení.

Nakonec musíme připojit zem ke čtvrtému konektoru na Arduino. Na obrázku níže vidíte, že jsem to udělal pomocí modrého drátu a kousku odříznuté nožičky rezistoru.

Připojení uzemnění k displeji.

Nyní můžete přejít k programu, který je velmi jednoduchý, ovládáme pouze 7 LED diod…. Níže uvedený příklad by měl postupně ovládat jednotlivé segmenty (A až F).

				
					#define SEG_C 2
#define SEG_E 3
#define SEG_D 4
#define SEG_B 5
#define SEG_G 6
#define SEG_A 7
#define SEG_F 8

void setup() {
  //Konfigurace pinů jako výstupu
  pinMode(SEG_A, OUTPUT);
  pinMode(SEG_B, OUTPUT);
  pinMode(SEG_C, OUTPUT);
  pinMode(SEG_D, OUTPUT);
  pinMode(SEG_E, OUTPUT);
  pinMode(SEG_F, OUTPUT);
  pinMode(SEG_G, OUTPUT);

  //Test segmentů
  digitalWrite(SEG_A, HIGH);
  delay(800);
  digitalWrite(SEG_B, HIGH);
  delay(800);
  digitalWrite(SEG_C, HIGH);
  delay(800);
  digitalWrite(SEG_D, HIGH);
  delay(800);
  digitalWrite(SEG_E, HIGH);
  delay(800);
  digitalWrite(SEG_F, HIGH);
  delay(800);
  digitalWrite(SEG_G, HIGH);
}

void loop() {

}
				
			

Vše lze samozřejmě napsat kratší, rychleji a lépe. Soustředil jsem se však na to, aby byl celý program čitelný a jednoduchý. Všechny segmenty fungují správně, pokud je efekt následující:

Test jednotlivých segmentů (animace je zacyklená, v praxi se na konci rozsvítí všechny prvky po celou dobu).

Zobrazení jednotlivých číslic

Zatím (!) je situace stále jednoduchá, takže si můžeme snadno napsat vlastní funkci, která jako argument přijme číslo, které pak přenese na displej. Ideální zde bude návod na switch popsaný v 6. části prvního kurzu Arduino.

Naše funkce může být následující:

				
					void Display(int Zahl) {
  //Instrukce switch nastaví na výstupech příslušné stavy
  //v závislosti na zadané cifře.
  switch (cifra) {
    case 0:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, LOW);
    break; 
    
    case 1:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
    break; 
    
    case 2:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 3:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 4:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 5:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 6:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
   
    case 7:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
    break;
    
    case 8:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
    
    case 9:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
  }
}
				
			

Zapínání a vypínání jednotlivých prvků jsem rozdělil podle rozložení segmentů. Každý si samozřejmě může provést vlastní změny a přizpůsobit si „písmo“. Stačí mít před sebou následující obrázek:

Popis segmentů displeje.

Například číslo „1“ se může zobrazit i na segmentech F a E.

Počítadlo na 7- segmentovém displeji

Je čas zkontrolovat, zda vámi napsaná funkce zobrazuje po sobě jdoucí číslice. Následující testovací program se skládá ze smyčky for (která běží od 0 do 9), která vyvolává po sobě jdoucí číslice:

				
					#define SEG_C 2
#define SEG_E 3
#define SEG_D 4
#define SEG_B 5
#define SEG_G 6
#define SEG_A 7
#define SEG_F 8

void setup() {
  //Konfigurace pinů jako výstupu
  pinMode(SEG_A, OUTPUT);
  pinMode(SEG_B, OUTPUT);
  pinMode(SEG_C, OUTPUT);
  pinMode(SEG_D, OUTPUT);
  pinMode(SEG_E, OUTPUT);
  pinMode(SEG_F, OUTPUT);
  pinMode(SEG_G, OUTPUT);
}

void loop() {
  int i = 0;
  //Smyčka od 0 do 9
  for (i = 0; i < 10; i++) {
    Display(i); //Zobrazení hodnoty na obrazovce
    delay(500); //Počkej 500 ms 
  }
}

void Display(int cifra ) {
  //Instrukce switch nastaví na výstupech příslušné stavy
  //v závislosti na zadané cifře.
  switch (cifra ) {
    case 0:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, LOW);
    break; 
    
    case 1:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
    break; 
    
    case 2:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 3:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 4:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 5:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 6:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
   
    case 7:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
    break;
    
    case 8:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
    
    case 9:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
  }
}
				
			

Správné fungování programu je vidět na následující animaci:

Efekt počítadla.

Doplňkový úkol 6.1

Rozšíření funkce display() tak, aby byla schopna zobrazit informaci o překročení rozsahu. Pokud zadáme hodnotu větší než 9, měl by se zobrazit symbol chyby sestávající z rozsvícených segmentů A, G, D.

Doplňkový úkol 6.2

Přidejte do obvodu tlačítka a sestavte čítač:

  • S1 – zvýší číslo zobrazené na displeji o 1,
  • S2 – sníží číslo zobrazené na displeji o 1,
  • S3 – resetuje obvod.

Použití druhého displeje

Nyní je to stále obtížnější… Přinejmenším pokud jde o spojení. Nyní použijeme druhé zobrazení. Nejvhodnější by bylo připojit jej na dalších 7 pinů Arduino, ale pak bychom neměli téměř žádné volné spoje.

A co hůř, nikdy by nebylo možné připojit více displejů (např. 3). Naštěstí to můžete udělat o něco šikovněji!

Nejprve spojíme segmenty obou displejů dohromady. Tímto způsobem použijeme 7 pinů k zobrazení hodnot na obou displejích současně – prozatím se bude jednat o stejné číslo. Zobrazení různých hodnot se budeme věnovat o něco později.

Jinými slovy, nyní usilujeme o takovouto situaci:

Zapnutí druhého displeje.

Spojení mezi segmenty obou displejů lze zatraktivnit pomocí nožiček odříznutých od rezistorů. To však vyžaduje určité riskantní řešení. Vzhledem k omezenému prostoru, který je k dispozici, vložíme do každého otvoru v kontaktní desce 2 dráty.

Toto řešení je riskantní a pravděpodobně se nebude používat často, protože může vést k chybám, které se obtížně diagnostikují. Ale s tak jednoduchým obvodem můžeme riskovat.

Pro připomenutí uvádíme schéma zapojení:

Popis připojení použitého displeje.

Začneme segmenty C, D a E. Spojení tedy musíme provést v tomto pořadí:

  • 1 > 8
  • 2 > 7
  • 3 > 6

To lze provést následujícím způsobem:

Propojení segmentů dvou displejů.

K tomuto připojení je samozřejmě nutné odpojit vodič, který vedl uzemnění k prvnímu displeji. Nyní vyvedeme země do stran (vlevo od první a vpravo od druhé):

Společná katodová vedení (uzemnění) displejů.

Dalším krokem je připojení zbývajících segmentů, tj. připojíme konektory:

  • 13 > 12
  • 14 > 11
  • 15 > 10
  • 16 > 9

V mém případě se mi podařilo dát celou věc dohromady takto:

Komplet spojení.
Téměř hotové schéma...

Na konci je samozřejmě ještě třeba doplnit chybějící zemnící spoje. V tuto chvíli postačí jednoduché kabelové připojení. Na fotografii níže jsem je pro lepší přehlednost omotal mašličkami:

Zobrazení stejných hodnot na displejích.

Způsob, jakým displeje fungují, se osvědčil, a tak je na čase postoupit o krok dál. Dvojí zobrazení stejné hodnoty nám pravděpodobně nikdy nebude k ničemu…..

Multiplexování displejů

Řešením tohoto problému je multiplexování. Pokud postupně zapínáme a vypínáme jednotlivé displeje, můžeme při rychlé změně zobrazované hodnoty vidět na každém z nich jinou číslici (díky setrvačnosti našeho zraku se jedná o iluzi)! Katody samozřejmě nebudeme od hmoty oddělovat ručně. Použijeme Arduino!

Pokud jsou zapnuty všechny segmenty, může být celý displej
„z katody“ odebírají více než 20 mA, takže byste je neměli připojovat přímo k Arduino!

Řízení displejů pomocí tranzistorů

Z bezpečnostních důvodů Arduino ovládá společné katody pomocí tranzistorů NPN. Sada součástek obsahuje tranzistory BC547, které zde budou dokonale fungovat.

Připojení bude vypadat následovně:

  • Kolektory tranzistorů připojujeme přímo ke katodám displejů. To znamená, že kolektor prvního tranzistoru připojíme k noze 4 displeje a kolektor druhého tranzistoru BC546 k noze 5.
  • Bázi tranzistorů připojíme k pinům Arduino přes rezistor 10k. Bázi prvního tranzistoru připojíme na pin Arduino č. 10 a druhý tranzistor na pin č. 9.
  • Emitory obou tranzistorů připojíme k zemi.

Výše uvedené spojení lze realizovat následovně:

Pohled na celý obvod.
Přidány tranzistory NPN.

Od této chvíle bude na piny 9 nebo 10 Arduino přiváděn vysoký stav.
Zapněte jeden z displejů.

Multiplexování v praxi

Nyní je čas použít přidané tranzistory v praxi. Nejprve je třeba doplnit nové definice:

				
					#define WYSW_1 10
#define WYSW_2 9
				
			

Druhým krokem je přidání konfigurace výstupů:

				
					  pinMode(WYSW_1, OUTPUT);
  pinMode(WYSW_2, OUTPUT);
				
			

Nyní je možné používat displeje samostatně. Začněme programem, který střídavě (každou sekundu) spustí jeden z displejů, zobrazí hodnotu a po chvíli spustí druhý displej s jinou hodnotou. Jinými slovy, tento efekt očekáváme:

Zobrazení různých hodnot na displeji (animace).

V hlavní smyčce programu musíme cyklicky zapínat první displej, na kterém se zobrazuje například hodnota 5. Pak jej po sekundě vypneme, zapneme druhý displej a zobrazíme na něm hodnotu 3. Tento úkol provádí následující program:

				
					#define SEG_C 2
#define SEG_E 3
#define SEG_D 4
#define SEG_B 5
#define SEG_G 6
#define SEG_A 7
#define SEG_F 8

#define WYSW_1 10
#define WYSW_2 9

void setup() {
  //Konfigurace pinů jako výstupu
  pinMode(SEG_A, OUTPUT);
  pinMode(SEG_B, OUTPUT);
  pinMode(SEG_C, OUTPUT);
  pinMode(SEG_D, OUTPUT);
  pinMode(SEG_E, OUTPUT);
  pinMode(SEG_F, OUTPUT);
  pinMode(SEG_G, OUTPUT);

  pinMode(WYSW_1, OUTPUT);
  pinMode(WYSW_2, OUTPUT);  
}

void loop() {
    digitalWrite(WYSW_1, HIGH); //Zapni první displej
    digitalWrite(WYSW_2, LOW); //Vypni druhý displej
    displej(5); //Zobraz hodnotu na displeji
    delay(1000);
    digitalWrite(WYSW_1, LOW); //Vypni první displej
    digitalWrite(WYSW_2, HIGH); //Zapni druhý displej
    displej(3); //Zobraz hodnotu na displeji
    delay(1000);
}

void displej(int cifra) {
  //Instrukce switch nastaví na výstupech příslušné stavy
  //v závislosti na zadané cifře.
  switch (cifra) {
    case 0:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, LOW);
    break; 
    
    case 1:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
    break; 
    
    case 2:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, LOW);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 3:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 4:
        digitalWrite(SEG_A, LOW);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 5:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break; 
    
    case 6:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, LOW);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
   
    case 7:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, LOW);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, LOW);
        digitalWrite(SEG_G, LOW);
    break;
    
    case 8:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, HIGH);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
    
    case 9:
        digitalWrite(SEG_A, HIGH);
        digitalWrite(SEG_B, HIGH);
        digitalWrite(SEG_C, HIGH);
        digitalWrite(SEG_D, HIGH);
        digitalWrite(SEG_E, LOW);
        digitalWrite(SEG_F, HIGH);
        digitalWrite(SEG_G, HIGH);
    break;
  }
}
				
			

Nezapomeňte se podívat, co se stane, když budeme postupně zkracovat dobu mezi změnami. Vyplatí se vyzkoušet například 100 ms, 50 ms, 20 ms a 10 ms.

Blikání - 100 ms.
Blikání - 50 ms.

U velmi rychlých změn využíváme toho, že lidské oko není schopno rozpoznat tak časté změny. V ~10 ms vidíme místo blikání konstantní hodnotu 53!

Přesně o to šlo – nezapomeňte, že displeje jsou zapojeny prakticky stejně a my vidíme různé hodnoty.

Doplňkový úkol 6.3

Napište program pro čítač, jehož hodnota se mění od 0 do 99. Hodnotu lze měnit automaticky („v libovolném pevném čase“) nebo například stisknutím tlačítka.

Jak lze takové řešení uplatnit v praxi?

Všechna elektronická spojení, která jsme zde uvedli, jsou dobrá a jistě je lze použít v mnoha projektech. Pokud však jde o programování, je tento přístup ….. je slabý!

Při psaní složitějších programů si nemůžeme dovolit
zastavit celou věc s takovým zpožděním!

Cílem výše uvedených cvičení bylo prakticky ukázat, jak fungují 7-segmentové displeje a co znamená multiplexování. V praxi smysluplné multiplexování vyžaduje použití složitějších mechanismů, které jsou zabudovány v mikrokontrolérech.

Arduino je však známé tím, že pro všechny složité věci
najdete hotové knihovny!

Připravená knihovna pro displeje 7-seg.

Samozřejmě, že pro „rozumné“ použití 7-segmentových displejů najdeme mnoho knihoven, které budou provádět složitější věci v pozadí. Nechtěl jsem hned začít s hotovým řešením, protože někteří čtenáři by nemuseli pochopit princip takového zobrazení – proto tento ručně vyrobený kód…

Je čas spustit naše 7-segmentové displeje s předpřipravenou knihovnou, což usnadní jejich použití v dalších projektech. Na internetu lze nalézt alespoň několik takových hotových funkcí; my použijeme funkci SevSeg Library v dalším popisu.

Na výše uvedené stránce je uvedeno, že aktuální kód lze nalézt na GitHubu, pro stažení knihovny použijeme tlačítko Clone or download → Download ZIP:

Stažení nejnovější verze kódu z GitHubu.

Poté archiv rozbalíme a zkopírujeme celou složku SevSeg-master, kterou pak vložíme do adresáře Arduino libraries, v mém případě to byl adresář:

C:\Users\Damian\Documents\Arduino\libraries

Po restartu Arduino IDE najdeme v nabídce Soubor → Příklady novou kategorii s názvem SevSeg. To znamená, že knihovna byla nainstalována správně. Nyní však nebudeme používat hotové příklady.

Zkusme si displeje spustit sami – informace obsažené v dokumentaci by měly stačit. Na začátku nalezneme fragment vzorové konfigurace:

				
					byte numDigits = 4;   
   byte digitPins[] = {2, 3, 4, 5};
   byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
   bool resistorsOnSegments = false; // Use 'true' if on digit pins
   byte hardwareConfig = COMMON_ANODE; // See README.md for options
   sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
[...]
				
			

Samozřejmě ji nyní musíme přizpůsobit našemu hardwaru. Nejprve změníme šířku displeje (ze 4 na 2 číslice). První řádek konfigurace by tedy měl vypadat takto:

				
					   byte numDigits = 2;
				
			

Dále určíme čísla pinů, ke kterým jsou připojeny tranzistory „ řízené číslicemi“:

				
					   byte digitPins[] = {10, 9};
				
			

Následně musíme knihovně předat informace o připojení segmentů (A-G):

				
					  byte segmentPins[] = {7, 5, 2, 4, 3, 8, 6};
				
			

V dalším kroku přidáme informace o způsobu navázání spojení:

				
					bool resistorsOnSegments = true; // Use 'true' if on digit pins
byte hardwareConfig = N_TRANSISTORS; // See README.md for options
				
			

N_TRANSISTORS – If you use N-type transistors to sink current
(or any other active-high, low-side switches).

Po doplnění výše uvedených informací vypadá náš základní nákres takto:

				
					#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment controller object

void setup() {
  byte numDigits = 2;   
  byte digitPins[] = {10, 9};
  byte segmentPins[] = {7, 5, 2, 4, 3, 8, 6};
  bool resistorsOnSegments = true; // Use 'true' if on digit pins
  byte hardwareConfig = N_TRANSISTORS; // See README.md for options
  
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
}

void loop() {

}
				
			

Od této chvíle můžeme v našem programu používat objekt sevseg. Začněme zobrazením čísla:

				
					#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment controller object

void setup() {
  byte numDigits = 2;   
  byte digitPins[] = {10, 9};
  byte segmentPins[] = {7, 5, 2, 4, 3, 8, 6};
  bool resistorsOnSegments = true; // Use 'true' if on digit pins
  byte hardwareConfig = N_TRANSISTORS; // See README.md for options
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
}

void loop() {
  sevseg.setNumber(34, 2); //Zobraz číslo 34 pomocí dvou displejů
  sevseg.refreshDisplay();
}
				
			

První řádek v cyklu() je zodpovědný za zobrazení čísla 34 pomocí 2 displejů. V našem případě bude druhý argument funkce vždy 2, protože nemáme možnost aktivovat „bodů“ na displeji. Pokud by taková možnost existovala, mohli bychom pomocí tohoto parametru určit formátování čísel, např. hodnota 3 by se mohla zobrazit jako „03“ nebo „3.0„.

Druhý řádek sevseg.refreshDisplay(); je zodpovědný za obnovení zobrazení, tj. za multiplexování, které jsme předtím provedli ručně. Na základě naší konfigurace knihovna sama vypočítá, jak často je třeba přepínat displeje, aby byl obraz stabilní.

Účinek programu je vidět níže:

Hodnota se zobrazuje díky knihovně SevSeg.

Tato knihovna umožňuje používat 7-segmentové displeje složitějším způsobem. Definuje například také písmena/symboly. Většina z nich se samozřejmě zobrazuje špatně (nebo vůbec) kvůli omezenému počtu segmentů…..

Určitě je však možné číst písmena jako A, b, H, C atd. K tomu slouží nová funkce sevseg.setChars(); V následujícím příkladu jsou zobrazena písmena AC:

				
					#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment controller object

void setup() {
  byte numDigits = 2;   
  byte digitPins[] = {10, 9};
  byte segmentPins[] = {7, 5, 2, 4, 3, 8, 6};
  bool resistorsOnSegments = true; // Use 'true' if on digit pins
  byte hardwareConfig = N_TRANSISTORS; // See README.md for options
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
}

void loop() {
  sevseg.setChars("AC");
  sevseg.refreshDisplay();
}
				
			

Účinek kódu je vidět na následujícím obrázku:

Všechny definované znaky lze zobrazit v souboru SevSeg.cpp (který je hlavním souborem této knihovny). Samotný fragment s definicí všech znaků vypadá následovně:

				
					  //     GFEDCBA  Segments      7-segment map:
  B00111111, // 0   "0"          AAA
  B00000110, // 1   "1"         F   B
  B01011011, // 2   "2"         F   B
  B01001111, // 3   "3"          GGG
  B01100110, // 4   "4"         E   C
  B01101101, // 5   "5"         E   C
  B01111101, // 6   "6"          DDD
  B00000111, // 7   "7"
  B01111111, // 8   "8"
  B01101111, // 9   "9"
  B01110111, // 65  'A'
  B01111100, // 66  'b'
  B00111001, // 67  'C'
  B01011110, // 68  'd'
  B01111001, // 69  'E'
  B01110001, // 70  'F'
  B00111101, // 71  'G'
  B01110110, // 72  'H'
  B00000110, // 73  'I'
  B00001110, // 74  'J'
  B01110110, // 75  'K'  Same as 'H'
  B00111000, // 76  'L'
  B00000000, // 77  'M'  NO DISPLAY
  B01010100, // 78  'n'
  B00111111, // 79  'O'
  B01110011, // 80  'P'
  B01100111, // 81  'q'
  B01010000, // 82  'r'
  B01101101, // 83  'S'
  B01111000, // 84  't'
  B00111110, // 85  'U'
  B00111110, // 86  'V'  Same as 'U'
  B00000000, // 87  'W'  NO DISPLAY
  B01110110, // 88  'X'  Same as 'H'
  B01101110, // 89  'y'
  B01011011, // 90  'Z'  Same as '2'
  B00000000, // 32  ' '  BLANK
  B01000000, // 45  '-'  DASH
				
			
Díky knihovně SevSeg se zobrazí text "AC".

Poslední příklad se 7-segmentovým displejem

Jako praktický příklad by bylo vhodné připojit k Arduino senzor, jehož informace se mají později zobrazit na displeji. V ideálním případě je zde vhodné „něco“, co lze číst v analogové podobě. Může to být například fotorezistor, který je zapojen v obvodu děliče napětí.

Toto řešení bylo v kurzu použito již mnohokrát, takže tuto hardwarovou část přeskočím. Každý si tam pravděpodobně najde něco, co by chtěl propojit. Pro svůj test jsem použil poslední volné místo na kontaktní desce a umístil tam potenciometr.

Spojení bylo následující:

  • nejlevější připojení na 5V,
  • středové připojení k A0,
  • nejpravější připojení k zemi (GND).
Připojení potenciometru (žlutá - 5V, zelená A0, bílá - GND).

Měřítko je nutné pro zobrazení aktuální hodnoty na displeji. Zde je samozřejmě užitečná funkce map(). Celý program si můžete prohlédnout níže:

				
					#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment controller object

void setup() {
  byte numDigits = 2;   
  byte digitPins[] = {10, 9};
  byte segmentPins[] = {7, 5, 2, 4, 3, 8, 6};
  bool resistorsOnSegments = true; // Use 'true' if on digit pins
  byte hardwareConfig = N_TRANSISTORS; // See README.md for options
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
}

void loop() {
  int potenciometr  = analogRead(A0); //Odečtij informace z fotorezistu
  potenciometr  = map(potenciometr , 0, 1023, 0, 99); //Škáluj na displej
  
  sevseg.setNumber(potenciometr , 2);
  sevseg.refreshDisplay();
}
				
			

Po zapnutí se na 7-segmentovém displeji zobrazí hodnota v rozsahu 0-99, kterou lze plynule měnit pomocí potenciometru:

Plynulé nastavení hodnoty.

Knihovna neřeší všechny problémy

Zde popsaná knihovna usnadňuje nastavení a obsluhu displejů tohoto typu. Neřeší však všechny problémy. „Problémem“ je vždy nutnost častého multiplexování displejů. V tomto případě to nutí k častému volání funkce sevseg.refreshDisplay();

Programy, které mají pracovat se 7-segmentovými displeji, proto nesmí používat funkci delay()!

Všechna zpoždění by měla být nahrazena sofistikovanějším mechanismem založeným na funkci millis(). Pokud máte zájem, odkazuji na odpovídající dokumentaci k Arduino a na příklad obsažený v knihovně SevSeg, konkrétně: File → Examples → SevSeg → SevSeg_Counter.

Funkci milis() v tomto kurzu neprobírám, protože se tomuto tématu budu věnovat
pravděpodobně v samostatné sérii o „multithreadingu v Arduino“.

Shrnutí

Tato část kurzu vyšla poněkud kuriózně. Několikrát byl prakticky od základu přestavěn, protože pokaždé byl jeho plán trochu jiný. Doufám, že se mi nakonec podařilo vysvětlit, jak displej funguje, aby se dal později lépe využít v praxi.

V příštím díle se podíváme na nové senzory. Tentokrát se seznámíme s analogovými a digitálními snímači teploty v praxi.

Objednejte si sadu prvků a začněte se učit v praxi! Kliknutím sem přejdete do obchodu >>

Přejít nahoru