Arduino v příkladech - I.díl - měření napětí a zobrazení na LCD 16x2
Vážení příznivci webu arduinotech.cz, po dohodě s panem Jaroslavem Boháčem jsem se rozhodl publikovat jeho články na téma práce s Arduinem určené spíše pro začátečníky. Ovšem i z těchto článků bude možné jistě vhodnou kombinací postavit i náročnější projekty a mohou tak sloužit jako dostatečně kvalitní odrazový můstek k projektům s ESP8266 a IoT, kterými se zabývám. V článcích nebudou chybět příkladové skeče a schématka zapojení. Vše je napsáno velmi srozumitelnou formou, posuďte sami.
Měření napětí a zobrazení na LCD 16x2
void setup() { Serial.begin(9600); } void loop() { Serial.println(analogRead(A0)); delay(200); }
Uvidíte řadu ubíhajících čísel. Co na první pohled nelze přehlédnout, je fakt že žádné číslo není stejné ±4 jednotky žádná míra. Když si k Arduinu připojíte např. diodu a začnete blikat, pomocí tlačítka, může přesahovat rozdíl i 40 jednotek. A to už je opravdu hodně. Důvodem je kvalita napájení USB portu, který na zatížení reaguje významným poklesem napětí.
Analogový pin Arduina je 10 bit A/D převodník, který porovnává referenční napětí oproti napětí na analogovém pinu. Výsledek měření je reprezentován číslem v rozsahu 0-1023 (10 bit), tedy 1024 hodnot. Platí – čím větší rozdíl mezi referenčním napětím a měřeným napětím, tím je výstupní hodnota menší.
Protože výsledné číslo reprezentuje pouze rozdíl mezi referenčním napětím a měřeným napětím, může docházet v velkým chybám měření. Např. bude-li Arduino napájeno 4,5 V a měřené napětí bude 4,6 V, uvidíte hodnotu 1023, tedy pokud to přepočtete na 5V, budete si myslet že máte právě 5V, což není pravda. Jediným řešením je napájet Arduino dostatečně stabilním zdrojem s výstupním napětím 5V.
V praxi tedy budeme používat externí zdroj napájení, opojeni od USB, bude zapotřebí jiného zobrazovacího nástroje. Tady se jako ideální řešení nabízí LCD displej. Tímto se budeme zabývat v následující části článku.
Potřebné součástky:
- Libovolné Arduino – v článku je použito UNO
- LCD I2C display 16x2
- Otočný potenciometr 10KΩ
- propojovací kabely
Zapojení:
Potřebných 5V necháme na interním regulároru Arduino, který je poměrně přesný. Pro komunikaci s displejem použijeme I2C komunikaci. Na arduino UNO je SCA pin na A4 a SCL pin na A5. Napětí budeme měřit na pinu A0 a otočný potenciometr použijeme jako dělič napětí.
K samotnému měření. V praxi se můžete setkat se zařízeními, ze kterých je výstup přímo 5V, pak tento připojíme k A0. Jestliže k napájení měřeného zařízení používáte externí zdroj, nezapomeňte propojit GND zdroje a GND Arduino. Pakliže chcete měřit vyváženou smyčku, připojte 10 KΩ mezi A0 a zem a k A0 veďte přes vyvažovací rezistory k napájení 5V. Tímto vytvoříte dělič napětí. Jsou zařízení, ze kterých je výstup 10V (např. servomotory), pak použijte dělič napětí 10 KΩ, tím vydělíte napětí dvěmi bez ohledu na odběr proudu. Pamatujte – vstupní napětí na pinech a to nejen analogových, nesmí přesáhnout 5V. Jinak spálíte arduino.
Pro stanovení referenčního napětí slouží v Arduino funkce analogReference(type);
Podrobný popis najdete na https://www.arduino.cc/en/Reference/AnalogReference
Stručný popis:
- DEFAULT: výchozí nastavení, které není potřeba volat funkcí, u 5V desek je 5V u 3,3V desek je 3,3V. Napětí na pinu nesmí přesáhnout tyto hodnoty
- INTERNAL: referenční napětí bude 1,1V. Za pomoci tohoto nastavení můžete změřit skutečné napětí, desky a hodnotu pro změření hodnoty DEFAULT (pozor podle desky se může lišit)
- EXTERNAL: jako referenční napětí měří napětí připojené k pinu AREF. Pokud používáte jako zdroj napájení 5V arduino a propojíte 5V s AREF, je referenční napětí stejné jako DEFAULT, tedy bez jakéhokoli efektu. Nastavení EXTERNAL má smysl pouze v případě, že očekáváte jiné maximální napětí než je napájení Arduina.
Fukce analogReference(type) musí být volána před použitím funkce analogRead(A..). Může se volat kdykoliv v průběhu programu a lze tak měřit napětí na různých pinech s různým referenčním napětím. Když funkci nezavoláme, platí nastavení jako analogReference(DEFAULT)
A jdeme na program. Samozřejmě je možné Arduino napájet z USB portu, pak je třeba počítat s tím, že hodnoty budou relevantní asi tak, jako předpověď počasí na příští týden.
Ještě před spuštěním programu si stáhneme knihovnu LiquidCrystal_I2C na
http://playground.arduino.cc/Code/LCDi2c
Já osobně používám jeden historický kousek, který je ke stažení na
http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)
//------------------------------------------------------------------ // inicializace zakladnich knihoven #include <Wire.h> // knihovna pro komunikaci I2C #include <LiquidCrystal_I2C.h> // knihovna pro komunikaci s diplejem //------------------------------------------------------------------ // nastaveni nazvu pinu #define inputVoltage A0 // vstup pro měření napětí // ostatní piny si popiseme, ale nechame zakomentovane // #define SDA A4 // komunikace I2C displej // #define SCL A5 // komunikace I2C displej //------------------------------------------------------------------ // promenne int value; // promenna pro ulozeni hodnotu cteni z analogoveho portu int lastValue; // promenna pro ulozeni predchozi hodnoty cteni z analogoveho portu float voltage; // promenna pro ulozeni prepocteneho napeti unsigned long readingTime; // cas posledniho ceteni const int timeout = 500; // prodleva mezi ctenim v milisekundách //------------------------------------------------------------------ //nastaveni nazvu, adresy a typu displeje LiquidCrystal_I2C LCD(0x27, 16, 2); // nazev, adresa, pocez znaku na radku, pocet radku //------------------------------------------------------------------ // inicializace programu void setup() { LCD.init(); // inicialuzujeme displej LCD.backlight(); // rozsvitime pozadi } //------------------------------------------------------------------ // hlavni smycka programu void loop() { // kazdych 500 milisekund (timeout) provedeme funkce if ((unsigned long)(millis() - readingTime) >= timeout) { // pouzivame misto delay();
cekame na uplynuti timeout readingTime = millis(); // nastavime novy cas pro pristi zpracovani lastValue = value; // ulozime predchozi hodnotu cteni value = analogRead(inputVoltage); // precteme hodnotu a nalagoveho portu A0 voltage = value * (5.0 / 1024); // prevedeme prectenou hodnutu na napeti LCD.clear(); // vyčistíme displej LCD.setCursor (0, 0); // nastavime pozici kurzoru na 1 místo 1 radku LCD.print("H:"); // na displeji zobrazime písmeno H - jako hodnota měření LCD.setCursor (2, 0); // nastavime pozici kurzoru na 3 místo 1 radku LCD.print(value); // zobrazime hodnotu cteni LCD.setCursor (8, 0); // nastavime pozici kurzoru na 9 místo 1 radku LCD.print("U:"); // na displeji zobrazime písmeno U - jako vypočtena hodnota napeti LCD.setCursor (10, 0); // nastavime pozici kurzoru na 9 místo 1 radku LCD.print(voltage); // na displeji zobrazime vypoctene napeti LCD.setCursor (0, 1); // nastavime pozici kurzoru na 1 místo 2 radku LCD.print("Rozdil:"); // na displeji zobrazime text - pro vypocetenou hodnutu mezi ctenimy LCD.setCursor (7, 1); // nastavime pozici kurzoru na 8 místo 1 radku LCD.print(value - lastValue); // rozdil mezi aktualnim ctenim a predchozim ctenim } // protoze na nic necekame, tady muzeme v realnem case provadet dalsi cinnosti }
Program je popsaný krok po kroku. Čtení analogového vstupu realizujeme pomocí příkazu analogRead(název pinu). Data na displeji vymažeme LCD.clear(), pak nastavíme kurzor na požadované místo LCD.setCursor (místo, řádek) a pomocí příkazu LCD.print(text) zobrazíme text a stále dokola.
Řešení problémů:
- displej nezobrazuje – na druhé straně displeje najdete potenciometr, zvolna s ním otáčejte až uvidíte text
- písmena se překrývají – ne u tohoto projektu, ale počítejte tím, že pokud postavíte kurzor na místo, kde jste předtím umístili text, prostě ho přepíše. Je nutné stále kontrolovat délku textu.
To je vše. Jednoduché a funkční. Příště si ukážeme jak eliminovat poskakování hodnot a si za pomoci tlakového čidla zobrazíme obsah nádrže rozsvícením progresbaru.
JB