Lekce 17 - Arduino a EEPROM

03.05.2013 14:21

Translate to English

Někdy se může stát, že budeme potřebovat uložit nějakou hodnotu nebo proměnou a tuto uchovat i když bude naše zařízení vypnuté, nebo když u Arduina provedeme restart. Samozřejmě, že by jsme mohli tyto data uložit např. na SD kartu, ale v případě malého objemu dat např nastavení intervalu zjištění nějaké hodnoty, kterou by si uživatel mohl nastavit v menu, by připojování SD karty bylo "plácání materiálem". Tyto data si uložíme do EEPROM v našem Arduinu. Jedná se o paměť, která si pamatuje naše data i po vypnutí napájení, a je určena pro ukládání dat. ze angl. zkr. Electrically Erasable Programmable Read-Only Memory. 

tabulka velikostí pamětí v jednotlyvých typech Arduina:

Typ Arduina     Procesor Velikost EEPROM
UNO ATmega328 1kB
MEGA ATmega2650 4kB
NANO ATmega328(168) 1kB (512B)
Micro ATmega32u8 1kB

Z výše uvedené tabulky vidíte, že velikost závisí na procesoru na Arduinu. Nepsal jsem zde různé jiné typy Arduina jako Mega ADK, Esplora a BT. Stačí se podívat na typ použitého procesoru na desce a víte jak jste na tom.

Takže pro první příklad a ukázku nebudeme potřebovat nic jiného, než samotné Arduino a jedno jaký typ a USB kablík k počítači. Samotný zápis do paměti řídí knihovna EEPROM.h, kterou si pomocí "include" zapíšeme na začátek programu. Z té knuhovny potom využijeme funkci:

EEPROM.write(adresa, hodnota); např.: EEPROM.write(49, 177); - na adresu 49 zapíšeme hodnotu 177

adresa je typu integer, a hodnota byte (0-255) a nebo pro čtení

hodnota = EEPROM.read(adresa); např. hodnota =  EEPROM.read(49); - z adresy 49 přečte hodnotu a zapíše do proměné "hodnota". 

Upozornění:

U pamětí EEPROM se uvádí životnost 100 000 cyklů, tudíž tuto pamět využívejte z rozvahou. :-). Opravdu se nehodí, aby jsme s ní programově pracovali nepřetržitě nekolik dní, např při ukládání nějaké hoidnoty 5x za sekundu. Hodí se výborně na ukládání uživatelských dat a různých nastavení, která si uživatel může měnit např. v nějakém menu na dipleji (např. minimílní hodnota z nějakáho čidla pro sepnutí relé, pro nastavení intervalu apod.).

Tak teď si nahrajeme náš prográmek pro práci s touto pamětí:

Timto krátkým a jednoduchým programem jsme si uložili 5 různých hodnot na adresu 0 až 5. Upozorňuji že hodoty můžou být pouze byte tzn. číslo 0 až 255. Po nahrání programu do Arduina, by se nám tento měl automaticky spustit a uložit hodnoty. Zkusíme si odpojit napájení a uvidíme, zda si naše Arduinko bude čísla pamatovat. 

Připravíme si druhý program, který nám naše uložené hodnoty vypíše třeba na seriový port:

Po zapnutí napájení a nahrání programu do arduina si zapneme Serial Monitor a výsledek by měl vypadat takto:

Tak to by jsme měli, ale co když budeme chtít uložit nějaké větší číslo? Máme dvě možnosti. Pokud budeme chtít třeba například uložit číslo z Analogového pinu, které může nabývat hodnot od 0 do 1023, tak ho můžeme vydělit číslem 4 a získat tak sice nepřesnější hodnotu, ale už se nám vejde do paměti, nebo druhý způsob bude využít z paměti bajty dva. A to si teď vyzkoušíme.

V ukázce nepracujeme přímo s EEPROM pouze si demonstrujeme rozdělení 2byte čísla (Integer int) na dvě čísla byte pro možný zápis do EPROM. Jedná se o číslo 28478, výsledek spojení dvou hodnot byte se poté vypíše na serial port.

Nejprve jsme si naši hodnotu z integru převedli do prvního byte. Automaticky se hodnota čisla binárně 0110111100111110 usekne na 00111110, protože se do byte více nedostane (je to proměná o velikosti 1 byte). Tak první byte máme vyřešen. A co druhý? To vyřešíme pomocí bitového posunu. (>> bitový posun doprava, << bitový posun doleva). My použijeme bitový posun doprava a to o 8 bitů. 

Výsledek:

0110111100111110 - původní číslo
0011011110011111 - bitový posun o 1 bit doprava 
0001101111001111 - bitový posun o 2 bity doprava
0000110111100111 - ...
0000011011110011
0000001101111001
0000000110111100
0000000011011110 - bitový posun o 7 bitů doprava
0000000001101111 - bytový posun o 8 bitů doprava 

Tak to je princiop bitového posunu. Má i více využití. Teď si můžeme uložit i druhý byte našeho čísla. Při načítání čísla s EEPROM je postup jen opačný, jak můžete v programu vidět. 

Aby byl postup lépe využitelný vytvořil jsem kód, kde je již zápis celého Integeru (2 byte čísla) a jeho následné vyvolání, je implementováno do dvou funkcí. 

Zde už musíme dát pozor. V kódu je nastavena hodnota adresy čísla 10, ale využitý prostor pro číslo je na adresách 10 a 11. Takže nemůžeme ukládat zase něco na adresu 11, ale využijeme až další prostor v paměti. Dají se ukládat samozřejmě i daleko větší čísla, postup bude podobný avšak zabere více bytů v paměti.

TIP - Jak uložíme číslo s desetinou čárkou?

Pro příklad máme číslo 14,742. Do paměti umíme ukládat pouze hodnoty velikosti 1 bytu, ale umíme uložit integer. Takže si číslo vynásobíme např. číslem 1000 (dostaneme pak přesnost na 3 desetiná místa, když vynásobíme číslem 100 tak 2 desetiná místa - počet nul = počet desetiných míst) Číslo 14742 uložit umíme, když ho poté přečteme z paměti číslo vydělíme opět číslem 1000. Nesmíme zapomenout, že číslo Integer může být od -32768 do 32767. 

Na závěr si ukážeme jak si můžeme uložit také text pro nějaký účel. Pokud víme, že každý znak v textu reprezentuje nějaká číselná hodnota, uložení nebude složité. Zde je program:

Vidíte, že jsme si pro práci s textem a EEPROM vytvořil dvě funkce. Jedna z nich text ukládá a druhá ho zase čte. Tady si musíme uvědomit, že ve funkci si také nastavujeme počet rezervovaných znaků v paměti. 

TextToEEPROM(50,10,"Ahoj...");    --> Znamená, že uloží na adresu 50 text o maximální délce 10 znaků. Uložený text je "Ahoj...". V případě, jako v tomto, že je text kratší zbytek v paměti do zbývajích znaků (celkem 10 - 7) vyplní mezerami a to proto, aby smazal zbytem naší paměti pro tento text. Delší text by měla funkce automaticky zkrátit.  

TextFromEEPROM(50,10)    --> Načte String (text) z adresy 50 o délce max 10 znaků. Když je text kratší, automaticky smaže mezery na konci. 

Příklad jsem moc nekomentoval v kódu, ale snad je vše jasné. Stačí si celé funkce z kódu zkopírovat a použít ve Vašem programu. Ukázka pouze uloží nějaké dva texty do EEPROM a potom znovu z paměti načte a vypíše na seriový port. 

 

 

 

 

Zpět

Diskusní téma: Lekce 17 - Arduino a EEPROM

Datum
Vložil
Titulek

EEPROM

Myslím, že knihovna EEPROM obsahuje funkce put a get, které umí uložit a vrátit vícebajtové proměnné, dokonce snad i struktury. Pak se ptám, proč to dělat tak složitě?

Datum
Vložil
Titulek

Union

Mnohem lepší než násobit a dělit, nebo rotovat bity, je použití unionu. Příklad udělaný v C na PC, ale na Arduinu taky tak nějak podobně:

union{
unsigned char c[4];
float f;
int i;
} mix;

mix.i = 1023;
printf("%d\n", mix.i);
printf("%d.%d.%d.%d\n", mix.c[0], mix.c[1], mix.c[2], mix.c[3]);

mix.f = 5.321;
printf("%f\n", mix.f);
printf("%d.%d.%d.%d\n", mix.c[0], mix.c[1], mix.c[2], mix.c[3]);

Datum
Vložil
Titulek

dělení

Dobrý den, mám takový problém. Dejme tomu potřebuji uložit číslo 5,50 tak ho násobím tisícem a ukládám do dvou bajtů, pak ho přečtu a dostanu 5499, což je první menší problém, který mě až tak nevadí, ale co mě vadí tak je, že když to vydělím 1000 tak dostanu 5,0 a za boha nemůžu přijít na to proč se to děje

Datum
Vložil
Titulek

Re: dělení

Možná se mýlím, ale vidím to takto. Je to matematika. Ve skutečnosti je to ukládané číslo 5,499xxxx..., ale vy to máte viditelné na 2 desetiny, čili zaoukrouhlené to je 5,50. Ale při následném násobení se ke slovu dostanou všechny desetinné čísla a z toho vznikne celý váš problém. Zaměřte se na desetinné místa které máte viditelné a které máte skutečně v proměnné (při operacích je pak podstatný rozdíl).

Datum
Vložil
Titulek

ee

A k té chybě dochází při manipulaci s EEPROM nebo i bez manipulace?

Datum
Vložil
Titulek

EEPROM a praxe

Rád bych se zeptal, jakou máte zkušenost s použitím interní EEPROM v praxi? Můj problém konkrétně u procesoru ATmega8 je, že pokud vlivem rušení, poklesu napájecího napětí, nebo aktivaci watchdogu dojde k resetu mikroprocesoru, tak velice často dojde i k přepsání interní EEPROM náhodnými daty. Detekci poklesu napětí mám nastavenou na 4V a vyzkoušeli jsme i napájení z autobaterie, ale i tak dochází k náhodnému přepsání dat v EEPROM :-(
Řešil někdo z vás podobné problémy v praxi?

Vyhledávání

arduino8.cz © 2015 Všechna práva vyhrazena.