EEPROM paměť AT24C256 je Arduino modul, který umožňuje ukládat různé údaje z Arduina na externí paměť. Tento druh paměti je elektricky mazatelná a programovatelná paměť a pro komunikaci využívá protokol I2C. Díky tomu můžeme do EEPROM zapsat libovolné údaje, které ale zůstanou uložené i po odpojení napájení. EEPROM AT24C256 má kapacitu 256 kbit neboli 32 kbyte, díky které můžeme uložit až 32 768 bajtů (bajt = byte = znak z ASCII, 8 bitů). Pro napájení tohoto modulu lze použít stejnosměrné napětí v rozmezí 2,7 až 5,5 Voltů. Proudový odběr v klidu se pohybuje okolo 18 mikroAmpér, při čtení se můžeme dostat na hodnotu 1 miliAmpér a při zápise na 3 miliAmpéry. U této paměti AT24C256 si také můžeme pomocí propojek na modulu nastavit adresu pomocí pinů A0-A2 a také zablokovat zápis do paměti pomocí propojky WP.
Pro úspěšné propojení EEPROM paměti AT24C256 s Arduinem stačí zapojit celkem čtyři vodiče. Propojíme VCC s 5 V Arduina, SCL s pinem A5, SDA s pinem A4 a GND se zemí Arduina. Vzhledem k tomu, že komunikace mezi Arduinem a EEPROM probíhá po sběrnici I2C, tak je nutné využít pro datové piny SCL a SDA odpovídající I2C piny na Arduinu.
Ukázkový kód obsahuje na svém začátku připojení knihovny Wire pro práci se sběrnicí I2C, po kterém následuje definování adresy EEPROM paměti. Jak již bylo zmíněno, můžeme tuto adresu měnit pomocí tří adresných propojek, kdy tyto propojky odpovídají posledním třem bitům (viz komentář v programu). Po adrese následuje vytvoření proměnné, která slouží pro práci s ukládanými zprávami, kdy je doporučeno vytvářet najednou maximálně zprávy o 30 znacích kvůli omezení knihovny Wire. V podprogramu setup jako první zahájíme komunikaci po sériové lince spolu s komunikací po sběrnici I2C. Následně zapíšeme do EEPROM znak vykřičníku na maximální adresu 32 767 (adresy začínají od nuly). Po krátké pauze ze zmíněné adresy zkusíme zpětně vyčíst zapsaný bajt a následně ho vypsat po sériové lince ve tvaru znaku, abychom si ověřili úspěšný zápis. V dalším kroku si vytvoříme ukázkovou zprávu a pomocí dané funkce ji zapíšeme od adresy 100. A jako v předchozím případě využijeme opět načtení uložené informace z paměti od adresy 100 a po úspěšném načtení si zprávu vytiskneme po sériové lince. V nekonečné smyčce loop si nejprve načteme do vytvořené proměnné aktuální čas od zapnutí od Arduina s převedením na vteřiny. Následně si vytvoříme proměnnou typu String pro uložení celé zprávy a postupně do ní zapíšeme text a přidáme obsah proměnné cas. Po dokončení zprávy si ji převedeme pomocí funkce toCharArray na pole znaků a toto pole zapíšeme do EEPROM od adresy 0. Po úspěšném zápisu si vyzkoušíme načtení zprávy pomocí načítání jednotlivých bajtů. Pro tento postup si tedy vytvoříme proměnnou pro počítadlo čtených adres a načteme první znak z paměti. Poté provedeme kontrolu, jestli znak není rovný nule, která označuje prázdné místo v paměti. V případě existujících dat vytiskneme načtený znak po sériové lince a pokračujeme zvýšením ukazatele na adresu společně s načtením dalšího znaku. V této while smyčce zůstáváme do té doby, dokud nenačteme zmíněný prázdný znak, přičemž v tomto okamžiku přesuneme tisknutí po sériové lince na nový řádek a po pauze dvou vteřin opakujeme smyčku loop. V programu se dále nachází ještě pomocné podprogramy, které slouží pro práci s EEPROM. Je zde podprogram pro zápis jednoho znaku či celé zprávy a také pro čtení jednoho znaku či celé zprávy.
// Arduino I2C EEPROM AT24C256 // připojení potřebné knihovny #include <Wire.h> // definování adresy EEPROM paměti, // adresa má tvar 1010-A2-A1-A0 #define eeprom B1010000 // vytvoření proměnné pro uložení zprávy do pole znaků char zpravaChar[30]; void setup() { // zahájení komunikace po sériové lince rychlostí 9600 baud Serial.begin(9600); // zahájení komunikace po sběrnici I2C Wire.begin(); // zápsání jednoho znaku na zařízení eeprom, na adresu 32767 (maximum) eeprom_zapis_znak(eeprom, 32767, '!'); // krátká pauza po zápise delay(10); // vytvoření proměnné typu znak a načtení jednoho znaku // na zařízení eeprom, od adresy 0 byte znak = eeprom_precti_znak(eeprom, 32767); // vytištění obsahu proměnné s posledním načteným znakem Serial.print("Nacteni jednoho znaku z EEPROM: "); Serial.println((char)znak); // vytvoření ukázkové zprávy char zprava[30] = "Arduino navody"; // zapsání vytvořené zprávy na zařízení eeprom, od adresy 100, // data z proměnné "zprava" o velikosti proměnné "zprava" eeprom_zapis_zpravu(eeprom, 100, (byte *)zprava, sizeof(zprava)); // krátká pauza po zápise delay(10); // čtení z vyšší adresy Serial.print("Cteni od adresy 100: "); // načtení zprávy ze zařízení eeprom, od adresy 100, // data uložíme do proměnné "zpravaChar" o velikosti proměnné "zpravaChar" eeprom_precti_zpravu(eeprom, 100, zpravaChar, sizeof(zpravaChar)); // vytištění celé zprávy po sériové lince Serial.print(zpravaChar); Serial.println(" "); } void loop() { // vytvoření proměnné s načtením času od zapnutí Arduina long cas = millis()/1000; // vytvoření zprávy v proměnné String String zpravaString = "Cas: "; zpravaString += cas; // převod zprávy z proměnné String na pole znaků zpravaString.toCharArray(zpravaChar, sizeof(zpravaChar)); // zapsání vytvořené zprávy na zařízení eeprom, od adresy 100, // data z proměnné "zprava" o velikosti proměnné "zprava" eeprom_zapis_zpravu(eeprom, 0, (byte *)zpravaChar, sizeof(zpravaChar)); // krátká pauza po zápise delay(10); // vytvoření proměnné pro práci s čtecí adresou int addr = 0; // vytvoření proměnné typu znak a načtení jednoho znaku // na zařízení eeprom, od adresy 0 byte znak = eeprom_precti_znak(eeprom, 0); // dokud nenarazíme na načtení nulového znaku, // budeme v této while smyčce while (znak != 0) { // vytištění obsahu proměnné s posledním načteným znakem Serial.print((char)znak); // inkrementace adresy pro načtení dalšího znaku addr++; // načtení jednoho znaku na zařízení eeprom, od adresy, která je v proměnné addr znak = eeprom_precti_znak(eeprom, addr); } // pokračování výpisu na novém řádku Serial.println(); // pauza po dobu 2 vteřin delay(2000); } // podprogram pro zapsání jednoho znaku void eeprom_zapis_znak( int adresaZarizeni, unsigned int adresaCteni, byte data ) { int rdata = data; Wire.beginTransmission(adresaZarizeni); Wire.write((int)(adresaCteni >> 8)); // MSB Wire.write((int)(adresaCteni & 0xFF)); // LSB Wire.write(rdata); Wire.endTransmission(); } // podprogram pro zapsání zprávy o velikosti max. 30 znaků void eeprom_zapis_zpravu( int adresaZarizeni, unsigned int adresaCteniZpravy, byte* data, byte delkaDat ) { Wire.beginTransmission(adresaZarizeni); Wire.write((int)(adresaCteniZpravy >> 8)); // MSB Wire.write((int)(adresaCteniZpravy & 0xFF)); // LSB byte c; for ( c = 0; c < delkaDat; c++) Wire.write(data[c]); Wire.endTransmission(); } // podprogram pro přečtení jednoho znaku byte eeprom_precti_znak( int adresaZarizeni, unsigned int adresaCteni ) { byte rdata = 0xFF; Wire.beginTransmission(adresaZarizeni); Wire.write((int)(adresaCteni >> 8)); // MSB Wire.write((int)(adresaCteni & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(adresaZarizeni,1); if (Wire.available()) rdata = Wire.read(); return rdata; } // podprogram pro přečtení zprávy o velikosti max. 30 znaků void eeprom_precti_zpravu( int adresaZarizeni, unsigned int adresaCteni, byte *buffer, int delkaDat ) { Wire.beginTransmission(adresaZarizeni); Wire.write((int)(adresaCteni >> 8)); // MSB Wire.write((int)(adresaCteni & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(adresaZarizeni,delkaDat); int c = 0; for ( c = 0; c < delkaDat; c++ ) if (Wire.available()) buffer[c] = Wire.read(); }
Po nahrání ukázkového kódu do Arduino desky s EEPROM pamětí AT24C256 dostaneme například tento výsledek:
Nacteni jednoho znaku z EEPROM: ! Cteni od adresy 100: Arduino navody Cas: 0 Cas: 2 Cas: 4 Cas: 6 Cas: 8 Cas: 10
EEPROM paměť AT24C256 nám umožňuje přidat externí uložiště pro Arduino s kapacitou zápisu 32 768 bajtů neboli znaků. Můžeme ji tedy použít například pro uložení různých konfigurací či jako zálohu ukládaných dat v případě výpadku bezdrátového spojení s hlavním systémem. Velkou výhodou je také možnost nastavit adresu pomocí tří adresních propojek a tím připojit až 8 pamětí na jedno Arduino anebo také možnost po zápisu potřebných dat zablokovat další zápis dat.
Seznam použitých komponent:
http://dratek.cz/arduino/1511-original-arduino-uno-rev3-1485165418.html
http://dratek.cz/arduino/1359-i2c-eeprom-at24c256-pro-ukladani-dat-pro-arduino-pic-1467272598.html