Project - Arduino teplomer 4x7

Arduino - teploměr s displejem 4x7 segmentů

Cíl

Zapojit a naprogramovat teploměr s Arduinem, ke kterému jsou připojena čidla termistor a fotoodpor a LED displej 4x7. Případně další součástky

Potřebné součástky

  • Nepájivé pole
  • Arduino NANO
  • Vodiče
  • 4x7 LED display
  • termistor
  • čidlo Dallas DS18B20
  • fotoodpor
  • 8x Rezistor 330R
  • 2x Rezistor 10k

*bitKrnov Osobní krabička

Konstrukce

Připojení LED zobrazovače 4x7 segmentů

Popis LED zobrazovače 4x7

LED zobrazovač má v sobě 7 LED diod uspořádaných do tvaru číslice 8 a LED pro desetinné tečky, takže jich je dohromady 7x4+4=32. 

Pokud by každá LED měla vývody vyvedeny zvlášť, musela by součástka mít 32x2=64 vývodu a i řídící obvod by musel mít tolik výstupu, proto jsou pro sníženi počtu vývodu propojen jeden vývod každé LED na stejné pozici u jednotlivých číslic a druhé vývody LED jedné číslice jsou taky spojeny. Toto nám umožňuje, že připojením napětí na jeden z plusových vývodů (společná katoda) a jeden z minusových vývodů (společná anoda) se rozsvítí jen jedna LED jedné číslice. Počet vývodu bude potom pouhých 12.

Jednotlivé segmenty číslice, se pro lepší orientaci ve vývodech, označují písmeny A až G a tečka DP.

 

Pro jednotlivé číslice desítkové soustavy je vždy třeba rozsvítit patříčne LED.

 Přepínání číslic

Jelikož máme jeden pól LED stejných segmentů propojeny a druhý pól jedné číslice, využijeme pro zobrazení zůzných číslic na jednotlivých pozicích takzvaný multiplexing, to znamená, že budeme postupně zobrazovat číslici na první, druhé, třetí a čtvrté pozici. Pokud to budeme dělat dostatečně rychle, bude se nám zdát, že síti všechny číslice zároveň.

 

 Omezovací rezistor

Jelikož je display složen z LED diod, musíme pro jejich připojení použít rezistor pro omezení proudu, vhodná bude hodnota 330R (ohmů). Označení má oranžová - oranžová - hnědá - zlatá. Poslední proužek zde není důležitý. Celkem jich budeme potřebovat 8, jeden pro každý segment číslice.

Arduino NANO

Jednodeskový počítač Arduino NANO má 14 digitálních výstupu D2 až D13 a TX, RX a 8 vstupů A0 až A7. Vývody TX a RX se používají pro sériovou komunikaci s počítačem a je lepší je nepoužit, pokud to není nutné. Některé D vývody umožňují regulovat výstup jako PWM a tím regulovat výkon, jsou to D3,D5,D6,D9,D10,D11. 

Pro popis jednotlivých vývodu nám poslouží takzvaný pinout neboli rozložení vývodu.

Připojení LED displaye k Arduinu

Vývod 1 LED displaye je vlevo dole a je na něj připojen segment E, tak ho přes rezistor připojíme na Arduino vývod D2. Pokračujeme až do vývodu 6. 2(D) - 330 - D3, 3(DP) - 330 - D4, 4(C) - 330 - D5, 5(G) - 330 - D6. Vývod 6 (Dig1) je společný pro druhou číslici a ten připojíme na Arduino vývod D13. Vývod 7 je na druhé straně displaye vpravo a číslování pokračuje doleva k vývodu 12. 7(B) - 330 - D7, 8(Dig2) - D12, 9(Dig3) - D11, 10(F) - 330 - D8, 11(A) - 330 - D9, 12(Dig4) - D10.

LED 4x7 vývody:

Zapojení

První program - pojmenování vývodu a test zapojení

Teď si připojíme Arduino v PC a v Arduino IDE si napíšeme první jednoduchý program pro nastavení vývodu a test jednotlivých segmentů. První si ale uložíme vývody segmentů do pole, aby se nám s LED displejem lépe pracovalo.

Nastavení zapnuto vypnuto

Na začátku programu si nadefinujeme proměnné pro zapnutí/vypnutí segmentů čísla a podobně i pro číslici.

#define SEGMENT_ON HIGH 
#define SEGMENT_OFF LOW
#define DIGIT_ON 0
#define DIGIT_OFF 255

Přiřazení výstupu k vstupům

Aby se nám lépe s LED display pracovalo, vytvoříme si dvě proměnné pole int. První digit[4] bude odkazovat na výstupy ke kterým jsou připojeny číslice 1 až 4.

int digit[4] = {10,11,12,13};

A pro jedtlivé segmenty pole seg[8].

int seg[8] = {9,7,5,3,2,8,6,4};

Reset vývodů

Teď bude jednoduché napsat funkci, která nám nastaví všechny vývody pro LED display na výstup (OUTPUT) a vypne je.
 
void reset7() {
  for (int d=0; d < 4; d++) {
    pinMode(digit[d], OUTPUT);
    digitalWrite(digit[d], DIGIT_OFF);
  }

  for (int s=0; s < 8; s++) {
    pinMode(seg[s], OUTPUT);
    digitalWrite(seg[s], SEGMENT_OFF);
  }
}

Tuto funkci si zavoláme při spuštění z funkce setup().

void setup() {
  reset7();
}

Test segmentů

A nekonečné do funkce loop() si zapíšeme jednoduchý dvojtý cyklus, který bude procházet pole vývodů segmentů a číslic a tyto postupně zapínat a vypínat. Pro otestování správného zapojení.

void loop() {
  for ( int s=0;s < 8; s++) {
    digitalWrite(seg[s], SEGMENT_ON);
    for (int d=0; d<4; d++){
      digitalWrite(digit[d],DIGIT_ON);
      delay(200);
      digitalWrite(digit[d],DIGIT_OFF);
    }
    digitalWrite(seg[s], SEGMENT_OFF);
 
 
Celý program ArduTemp1-1 nahrajeme do Arduina a otestujeme, že všechny segmenty svítí jak mají.
 
Simulace ArdTemp1.4

Regulace svitu přes PWM

Prohození vývodu s PWM

Jak už bylo poznamenáno výše, vývody D3,D5,D6,D9,D10,D11 umožňují regulovat výstup přes PWM. Vývody D10 a D11 už máme správně a teď přepojíme D3 s D13 a D9 s D12. Toto musíme opravit i v programu.
 
//výstupy připojených číslic
int digit[4] = {10,11,9,3};

//výstupy segmentů čísle A-G a DP
int seg[8] = {12,7,5,13,2,8,6,4}
 
Upravený program ArduTemp1-2 znovu nahrajeme do Arduina a vyzkoušíme.

Úprava na PWM

Pro ovládání jasu LED, musíme v programu změnit funkce digitalWrite na analogWrite pro číslice a také hodnoty pro zapnutí a vypnutí číslic z LOW, HIGH na 0 a 255.

#define DIGIT_ON 0
#define DIGIT_OFF 255 
 
Program ArduTemp1-3 zkompilujeme, znovu nahrajeme do Arduina a vyzkoušíme.
 

Ovládání svitu LED

Segment je zapnutý, když je na jeho vývodu napětí 0V a PWM 0, tak si #define DIGIT_ON budeme zvyšovat od 80 k 250 a vyzkoušíme, jestli budou LED svítit méně. Dle mě LED svítí tlumeně, někde u 240.
 
#define DIGIT_ON 240

Tady nám úplně nevyhovuje mít hodnotu svitu v definici a proto si definici DIGIT_ON nastavíme zpět na 0 a budeme je používat jen jako výchozí hodnoty pro proměnné int bright_on a bright_off, které budou určovat sílu svitu. bright_off, bychom měnit neměli.

#define DIGIT_ON 0
#define DIGIT_OFF 255

//výstupy připojených číslic
int digit[4] = {10,11,9,3};
int bright_on = DIGIT_ON;
int bright_off = DIGIT_OFF; 
 
Celý program ArduTemp1-4 je zde.
 

Zobrazování číslic

Definice číslic

Dalším krokem, je nadefinování zobrazování číslic, pro toto, si vytvoříme dvourozměrné pole number[10][7], kde ve sloupcích řádků bude informace, který ze sedmi segmentů má být zapnutý a číslo řádku bude určovat zobrazenou číslici.
 
//mapa číslic
byte number[10][7] = {{1,1,1,1,1,1,0},   //0
                     {0,1,1,0,0,0,0},   //1
                      {1,1,0,1,1,0,1},   //2
                     {1,1,1,1,0,0,1},   //3
                      {0,1,1,0,0,1,1},   //4
                      {1,0,1,1,0,1,1},   //5
                      {1,0,1,1,1,1,1},   //6
                      {1,1,1,0,0,0,0},   //7
                      {1,1,1,1,1,1,1},   //8
                      {1,1,1,1,0,1,1}};  //9
 

Potom si v setup() zapneme všechny číslice

for (int d=0; d<4; d++){              //vnořený cyklus, jedna číslice za druhou
    analogWrite(digit[d],bright_on);     //zapne číslici
  }
 
a v loop() uděláme vnořený cyklus pro postupné zobrazení číslic 0 až 9.
 
void loop() {
  byte l;
  for (int i=0;i < 10;i++) {
    for ( int s=0;s < 7; s++) {             //jeden segment za druhým
      if (number[i][s] == 1) l = SEGMENT_ON;
      else l = SEGMENT_OFF;
      digitalWrite(seg[s], l);     //zapne segment
    }
    delay(1000);
  }  
}
</
 
Takto upravená verze programu je zde ArduTemp1-5

Každé číslo jiné

Teď si přidáme další pole value[4] ve kterém budeme mít pro každý řád čísla položku a k ní si napíšeme funkci, která celkové číslo z value[] bude zobrazovat a proměnnou dot pro pozici desetinné tečky.
A do definic čísel si přidáme prázdný znak.
 
//mapa číslic  segment A B C D E F G
byte number[11][7] = {{1,1,1,1,1,1,0},   //0
                      {0,1,1,0,0,0,0},   //1
                      {1,1,0,1,1,0,1},   //2
                      {1,1,1,1,0,0,1},   //3
                      {0,1,1,0,0,1,1},   //4
                      {1,0,1,1,0,1,1},   //5
                      {1,0,1,1,1,1,1},   //6
                      {1,1,1,0,0,0,0},   //7
                      {1,1,1,1,1,1,1},   //8
                      {1,1,1,1,0,1,1},   //9
                      {0,0,0,0,0,0,0}};  //nic

//jednotlivé číslice
byte value[4] = {7,1,5,3};
byte dot = 1;                        // pozice desetiné tečky, >4 vypnuto
 
//funkce pro výpis číslic z pole value[]
void show() {
  byte l;
  for (int v=0;v < 4;v++) {                 // číslice 1 až 4
    analogWrite(digit[v],bright_on);        //zapne číslici
    for ( int s=0;s < 7; s++) {             //jeden segment za druhým
      if (number[value[v]][s] == 1) l = SEGMENT_ON;    //řádek number dle hodnoty v value[v]
      else l = SEGMENT_OFF;
      digitalWrite(seg[s], l);             //zapne segment
    }
    if (dot == v) digitalWrite(seg[7], SEGMENT_ON);     //zapne desetinou tečku
    delay(1);                               // svíti milisekundu v cyklu
    analogWrite(digit[v],bright_off);       //vypne číslici
    for ( int s=0;s < 7; s++) {             //vynulovat segment
      digitalWrite(seg[s], SEGMENT_OFF);              
    }
    digitalWrite(seg[7], SEGMENT_OFF);      //vypne tečku
  }  
}
 
Program s funkci show() ArduTemp1-6.

Převedení čísla na text a číslice 

Dále si do programu přidáme funkci set_value(float v), která převede desetinné číslo na řetězec (znaky) s tyto potom na po jednom na číslice a uloží je do pole.
  
void set_value(float v) {
String s = String(v); //převede číslo na text
for (int d=0; d<4; d++){ //vnořený cyklus, jedna číslice za druhou
value[d] = s.substring(d,d+1).toInt(); // uloží číslice do pole value
}
}
 
Přidáme ji do setup()
 
void setup() {
reset7(); //nastavení vývodu
set_value(2345); //převod čísla na číslice.
}
 
 

Připojení termistoru

Termistor je  rezistor jehož odpor se mění s teplotou. Když ho zapojíme spolu s rezistorem 1k jako dělič napětí, bude se na něm s teplotou měnit napětí. A toto napětí budeme sledovat na analogovém vstupu A0, který vrací hodnotu od 0 do 1023.
Odpor 1k zapojíme mezi vývody REF (základní napětí pro převodník napětí) a A0 a termistor mezi A0 a GND (zem).
 


 
Zde budeme potřebovat matematiku a vzorec pro přepočet napětí na teplotu.
 
//přečte hdnotu z termistoru a převede ji na teplotu
float read_temperature() {
const float BETA = 3600; // should match the Beta Coefficient of the thermistor
int analogValue = analogRead(A0);
//https://docs.wokwi.com/parts/wokwi-ntc-temperature-sensor
float celsius = 1 / (log(1 / (1023. / analogValue - 1)) / BETA + 1.0 / 298.15) - 273.15;
return celsius;
}
 
Tady je k tomu článek Měření teploty s termistorem.
 
Teplotu na termistoru si budeme čís v loop() a hned si nastavíme novou hodnotu k zobrazení.

void loop() {
t = read_temperature();
set_value(t);
show();
}
 
A ve funkci set_value si přidáme omezení teploty do 1000 a nastavení pozice desetinné tečky..
 
void set_value(float f) {
if ( f < 10000) {
String s = String(f).substring(0,5);
dot = s.indexOf('.') - 1;
s.remove(dot+1,1);
for (int d=0; d<4; d++){ //vnořený cyklus, jedna číslice za druhou
value[d] = s.substring(d,d+1).toInt();
}
} else {
value[0] = 10;
value[1] = 11;
value[2] = 12;
value[3] = 12;
}
}
 
A pokud bude číslo vyšší, tak vypíšeme chybu (error) jako Err. K tomu si musíme přidat další znaky 11 E a 12 r, do pole number.

//mapa číslic segment A B C D E F G
byte number[13][7] = {{1,1,1,1,1,1,0}, //0
{0,1,1,0,0,0,0}, //1
{1,1,0,1,1,0,1}, //2
{1,1,1,1,0,0,1}, //3
{0,1,1,0,0,1,1}, //4
{1,0,1,1,0,1,1}, //5
{1,0,1,1,1,1,1}, //6
{1,1,1,0,0,0,0}, //7
{1,1,1,1,1,1,1}, //8
{1,1,1,1,0,1,1}, //9
{0,0,0,0,0,0,0}, //nic
{1,0,0,1,1,1,1}, //E
{0,0,0,0,1,0,1}}; //r
 
 Zde je celý kód pro zobrazení teploty ArduTemp1-9

Simulace ArdTEmp1.9

Pod nulou

Pokud bude teplota pod nulou, bude teploměr ukazovat jako první znak 0. Pokud zde budeme chtit zobrazit - , musíme tu nulu na první pozici nahradit - .
Prvni si znak mínus přidáme do pole definic znaků. - bude mít index 13.

//mapa číslic segment A B C D E F G
byte number[14][7] = {{1,1,1,1,1,1,0}, //0
{0,1,1,0,0,0,0}, //1
{1,1,0,1,1,0,1}, //2
{1,1,1,1,0,0,1}, //3
{0,1,1,0,0,1,1}, //4
{1,0,1,1,0,1,1}, //5
{1,0,1,1,1,1,1}, //6
{1,1,1,0,0,0,0}, //7
{1,1,1,1,1,1,1}, //8
{1,1,1,1,0,1,1}, //9
{0,0,0,0,0,0,0}, //nic
{1,0,0,1,1,1,1}, //E
{0,0,0,0,1,0,1}, //r
{0,0,0,0,0,0,1}}; //-

A upravíme funkci set_value(), kde přidáme podmínku, že když je teplota záporna a nastavujeme první znak, tak tam dáme -.

void set_value(float f) {
if ( f < 10000) {
String s = String(f).substring(0,5);
dot = s.indexOf('.') - 1;
s.remove(dot+1,1);
for (int d=0; d<4; d++){ //vnořený cyklus, jedna číslice za druhou
if ( d == 0 and f < 0) { // pokud je teplota - a první číslice
value[d] = 13; // první znak mínus
} else {
value[d] = s.substring(d,d+1).toInt();
}
}
} else { // teplota je větší než 9999
value[0] = 10; //
value[1] = 11; // E
value[2] = 12; // r
value[3] = 12; // r
}
}

Zde je celý kód pro zobrazení teploty ArduTemp1-10.

A odkaz na simulaci ArdTemp1.10

Stmívací čidlo 

Teploměr ještě rozšíříme o funkci stmívání, aby nás v noci neoslňoval. K tomu použijeme fotoodpor GM5528 . To je součástka, ne které se se zvyšujícím svitem snižuje odpor.

Fotorezistor 10...20k ohm 0.1W 540nm WDYJ GM5528 

Zapojíme ho podobně  jako termistor. Jeden vývod zapojíme na GND Arduina a druhý na vstup A1 a dále mezi mvstup A1 a vývod REF zapojíme odport 10k (hnědá, černá, černá, červená, fialová).

 V emulátoru už je odpor na destičce čidla.

Teď budeme muset udělat několik úprav  v našem programu. Na začátku si nahradíme DIGIT_ON za dvě hodnoty pro nízký a vysoký svit.

#define SEGMENT_ON HIGH
#define SEGMENT_OFF LOW
#define DIGIT_ON_HIGH 100
#define DIGIT_ON_LOW 240
#define DIGIT_OFF 255

A promněnnou bright_on dle toho upravíme.

byte bright_on = DIGIT_ON_HIGH;

Pod funkci read_temperature() si přidáme funkci read_light(), která bude číst hodnoty v fotorezistoru a převede je na hodnoty pro řízení svitu přes PWM.

//přečte hdnotu z fotodporu a převede ji na požadovanou PWM (100-240) hodnotu
float read_light() {
int analogValue = analogRead(A1);
int pwm_light = map(analogValue, 0, 390, DIGIT_ON_HIGH, DIGIT_ON_LOW);
//int pwm_light = analogValue; // pro testování fotoodporu
return pwm_light;
 
První přečteme hodnotu ze vstupu A1. Hodnota může být teoreticky od 0 do 1023, ale zkusmo si zjistíme, že je jen od cca 20 do 390. Následně tuto hodnotu uloženou do avalogValue převedeme pomocí Arduino funkce map() na hodnoty pro svit. map() nám převede rozsah na vstupu 0-390 na hodnoty 100-240 pro ovládání svitu.

Teď ještě si přidáme nastavení svitu do funkce loop, kde si budeme přímo nastavovat promněnou bright_on z funkce read_light(). Tato promněná je pak použita ve funkci show(), kde se rozvěcí jednotlivé číslice.

void loop() {
bright_on = read_light();
t = read_temperature();
//set_value(read_light()); // pro testování fotoodporu
set_value(t);
show();
}

Zde je celý program ArduTemp1-11.
A odkaz na simulaci ArdTemp1.11, zde ale není vidět regulace svitu.

Program si nahrej pomocí Arduino IDE do Arduina a tím máme hotovo.
 
Ještě by bylo možno v programu pár věcí uklidit a předělat, ale to už necháme na každém z vás.

Zdroje

  1. Čidla

    1. Měření teploty s termistorem

    2. Teplotní senzor DS18B20

    3. Arduino s teploměrem DALLAS DS18B20

    4. Jak na vodotěsné teplotní čidlo DS18B20?

    5. DS18B20-PAR 1-Wire Parasite datasheet

  2. Serial

    1. Arduino Academy – Sériový monitor

    2. Sériová komunikace a cykly

  3. LED display

    1. Dokumentace - datasheet 4x7LED

    2. 19. díl o Arduinu – 4. bitový sedmisegmentový displej

    3. Lekce 10 - Sedmisegmentový display a pole pro Arduino

    4. 7 segmentový displej a jeho zapojení

    5. Zapojení více LED se společnou katodou nebo anodou

    6. TinyLab: Sedmisegmentový displej

  4. Základní struktury jazyka Wiring

  5. Pokročilejší struktury jazyka Wiring

Žádné komentáře:

Okomentovat

Děkuji za komentář, co nejdříve ho zkontroluji a schválím. Pokud se nechcete přihlásit, vyberte - Komentovat jako: Anonymní