Lekce 17 - Arduino a EEPROM
03.05.2013 14:21Translate 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ětDiskusní téma: Lekce 17 - Arduino a EEPROM
Datum | 22.04.2023 |
---|---|
Vložil | mac |
Titulek | EEPROM |
9 let asi nikdo...
———
Datum | 17.01.2022 |
---|---|
Vložil | loveawake.ru |
Titulek | Are you 18? Come in and don't be shy! |
Welcome to the world of adult Dating loveawake.ru
———
Datum | 30.10.2020 |
---|---|
Vložil | George |
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 | 30.01.2018 |
---|---|
Vložil | Ludvík |
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 | 13.11.2016 |
---|---|
Vložil | Wamby |
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 | 08.10.2016 |
---|---|
Vložil | Pavel Terber |
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 | 08.05.2016 |
---|---|
Vložil | zao |
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 | 30.06.2016 |
---|---|
Vložil | Tom |
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 | 05.12.2019 |
---|---|
Vložil | DnD |
Titulek | Re: dělení |
zkusil bych místo dělení tisícem násobit 0.001
———
Datum | 04.06.2020 |
---|---|
Vložil | Franta |
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