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

9 let asi nikdo...

Datum
Vložil
Titulek

Are you 18? Come in and don't be shy!

Welcome to the world of adult Dating loveawake.ru

Datum
Vložil
Titulek

binární číslo

Myslím si, že je trochu špatně vypočítaný příklad při ukládání hodnoty.
Číslo se čte od konce, takže první uložené číslo je:
00111110 = 62
a druhé, kterému doplní nulou:
(0)1101111 = 111


Datum
Vložil
Titulek

jak naplnit EEPROM při programování

prosím, nevíte někdo, jak naplnit při programování 4 zvolené adresy z EEPROM potřebnou hodnotou? Při programování mi to zatím zatvrzele přepisuje EEPROM na 0xff. Poradte prosím někdo, co s tím. Potřebuji naplnit při programování EEPRO bunky 1-4 hodnotou 0x00. Ale nesmí se při resetu přepsat. Slouží mi jako počítadlo a musí se po restaru obnovit původní stav eeprom. Kdežto po naprogramování tam potřebuji nuly. Dík.

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

Re: dělení

zkusil bych místo dělení tisícem násobit 0.001

Datum
Vložil
Titulek

Re: dělení

Je třeba dělit 1000.0 (nebo přetypovat číslo z EEPROM na float). INT / INT = INT, INT / FLOAT = FLOAT

1 | 2 >>

Vyhledávání

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