Paměti slouží k uchovávání dat. Typů pamětí existuje velké množství a ne všechny se hodí ke všem účelům. Kupříkladu magnetické pevné disky se hodí na dlouhodobé uchovávání velkých objemů dat, protože jejich cena za gigabite je poměrně nízká. Jejich nevýhoda je ale pomalá rychlost čtení a zápisu.
Oproti tomu různé SRAM a DRAM paměti jsou daleko rychlejší, ale zase jsou o poznání dražší. Většinou tedy hledáme nějaký kompromis, co se poměru cena/výkon týče. V počítačích i mikroprocesorech tak můžeme najít celou řadu pamětí různých typů, velikostí a rychlostí.
Na čipech v deskách Arduino najdeme paměti SRAM, Flash a EEPROM. SRAM se používá například pro uložení obsahu proměnných při běhu programu. Ve Flash paměti je uložený program a EEPROM je plně pod kontrolou programátora. Její obsah narozdíl od SRAM zůstává i po restartu desky (či odpojení napájení) a může tak být poměrně užitečná, například pro uchovávání nastavení, nebo různých hodnot z měření. Musíme si jen dát pozor na to, že má omezenou životnost, co se počtu přepisů týče, takže není vhodné do ní zapisovat moc často. Dokumentace uvádí, že paměť vydrží asi 100 000 přepisů. Pokud byste se chtěli o pamětech v Arduino dozvědět více, přečtěte si článek o funkci mikrokontroléru.
Vestavěná EEPROM
Čipy na Arduino deskách obsahují vestavěnou paměť EEPROM. Její velikost se liší podle typu desky a například u čipu ATmega328P (Arduino UNO, …) je to 1024 bytů. Paměť můžeme číst, nebo do ní zapisovat po jednom, ale i více bytech.
Pro čtení a zápis jednoho bytu slouží funkce read, write a update. Read přečte hodnotu na zadané adrese a write ji přepíše. Pozor na to, že hodnota je v rozmezí 0 až 255, protože pracujeme s jedním bytem (8 bitů, tedy 28 = 256 hodnot). Funkce update hodnotu přepíše pouze v případě, že se liší od hodnoty uložené v paměti. To šetří počet zápisů do paměti a tedy prodlužuje životnost paměti.
Program níže nám po spuštění vypíše, po kolikáté byl spuštěn.
#include <EEPROM.h> #define ADDR 100 void setup() { Serial.begin(9600); while(!Serial); // po odkomentování vynuluje paměť na adrese 100 // EEPROM.write(ADDR, 0); byte hodnota = EEPROM.read(ADDR); // přečte byte z adresy 100 byte novaHodnota = hodnota + 1; Serial.print("Program spusten po: "); Serial.println(novaHodnota); // zapíše novaHodnota na adresu 100 EEPROM.write(ADDR, novaHodnota); } void loop() {}
Nejdříve odkomentujte řádek 10: EEPROM.write(ADDR, 0); Ten způsobí vynulování bytu na adrese ADDR (tedy adresa 100). Spusťte sériový monitor a nahrajte program do desky. Nyní řádek zakomentujte a znovu nahrajte program. Nyní se s každým novým restartem desky, popřípadě znovunáhráním tohoto programu vypíše po sériové lince o jedno větší číslo. Program má malou nevýhodu, a to, že začne po dosažení hodnoty 255 počítat znovu od 0. Pokud bychom potřebovali větší periodu, můžeme pro ukládání hodnoty využít více bytů. Pokud použijeme například datový typ long, budeme mít hodnot dostatečně (pro praktické účely až zbytečně moc, ale pro ukázku ho můžeme použít). Tento typ zabere v paměti 4 byty.
Pokud bychom chtěli do EEPROM zapsat hodnotu proměnné, jejíž datový typ má velikost větší, než jeden byte, mohli bychom ji ukládat po bytech, nebo můžeme použít funkce určené pro čtení a zápis více bytů. Jsou to funkce get a put. Ty mají vždy dva parametry. První je adresa a druhý proměnná, jejíž hodnotu ukládáme, nebo do ní zapisujeme. Stejný program, jako výše, ale s většími hodnotami si nyní ukážeme.
#include <EEPROM.h> #define ADDR 100 void setup() { Serial.begin(9600); while(!Serial); // po odkomentování vynuluje paměť na adrese 100 // EEPROM.put(ADDR, 0ul); unsigned long hodnota; EEPROM.get(ADDR, hodnota); unsigned long novaHodnota = hodnota + 1; Serial.print("Program spusten po: "); Serial.println(novaHodnota); // zapíše novaHodnota na adresu 100 EEPROM.put(ADDR, novaHodnota); } void loop() {}
Při ukládání vícebytových hodnot do EEPROM paměti musíme myslet na to, že nezabírají pouze jedno adresovatelné místo, ale více. Například typ long použitý výše má čtyři byty a protože v našem příkladu ukládáme naši hodnotu na adresu 100, zabere ještě buňky s adresou 101, 102 a 103. Pokud bychom omylem zapsali na adresu 102 jeden byte, mohli bychom při čtení získat nesmyslné hodnoty.
K Arduinu je možné připojit i externí EEPROM paměť, například po sběrnici I2C. TinyLab takovou paměť má a my se ji v příštím článku naučíme používat.