Ale jeszcze 40 lat temu taka pojemność byłaby kosmicznie wielka. Pamięci ferrytowe (na zdjęciu obok) odpowiednik współczesnych EEPROMów miały pojemności rzędu kilkudziesięciu BITÓW na płycie o wymiarach kartki A4. A dodatkowo zawartość pamięci kasowała się samoistnie podczas operacji odczytu danych!!! Nośnikiem informacji był namagnesowany rdzeń toroidalny wielkości obrączki. We współczesnych pamięciach jest nim ładunek elektrostatyczny zgromadzony na nanometrowej powierzchni. To obok tranzystora najbardziej spektakularny przykład miniaturyzacji jaka dokonała się w elektronice przez te lata. Skorzystajmy z tego przy budowie naszego routera.
Ale ESP8266 jak raz nie wyposażono w ani jedną komórkę pamięci EEPROM. A jednak nasz ulubiony procesor jest zdolny do pamiętania danych. Jak? Dziś mikrokontrolery za pomocą bootloaderów same sobie wgrywają program do wewnętrznej lub zewnętrznej pamięci typu flash. I tylko od konstruktora procesora zależy czy udostępni nam choćby odrobinę tej pamięci do zapisu bieżących danych z programu tak byśmy mogli je odtworzyć po zaniku zasilania. Chińczycy przyoszczędzili na EEPROMie ale w zamian stworzyli możliwość zmiany zawartości pamięci flash wprost z programu użytkownika.
Technologicznie obie te pamięci są mocno zbliżone do siebie. Główną różnicą między EEPROMem a FLASHem jest sposób kasowania danych. EEPROM ma możliwość skasowania pojedynczych bajtów, we FLASHu możemy to zrobić jedynie blokiem. Natomiast zapis i odczyt i tu i tu możliwy jest dla pojedynczych bajtów. Różnica wynika z organizacji komórek pamięci. Dla EEPROMa można zaadresować pojedynczy bajt. Dla FLASHa jeden rząd bajtów (blok) który jest następnie odczytywany/zapisywany szeregowo jak w rejestrze przesuwnym. Dużą różnicą jest też gwarantowana ilość możliwych programowań (zapisów lub kasowań).Dla EEPROMa jest to ok 100 000 razy dla FLASHa 10 x mniej.
O tych wszystkich różnicach praktycznie nie musimy wiedzieć. Cały problem z właściwą obsługą pamięci bierze na siebie biblioteka <EEPROM.h> . Radzi sobie dobrze zarówno ze standardową pamięcią EEPROM np. w ATmega jak i z pamięcią flash w ESP8266. Choć sposób obsługi pamięci obu kości w programie nieco się różni. Dla typowej pamięci procedura EEPROM.write(adr,dana) powoduje natychmiastowy zapis do pamięci nieulotnej. Dla ESP w całym procesie pośredniczy dodatkowa pamięć RAM i na niej dokonuje się proces zapisu. Dla ostatecznego zapisu całego bloku danych do pamięci flash należy użyć polecenia EEPROM.commit(); (zapis do pamięci flash) lub EEPROM.end(); (zapis do pamięci flash i wyczyszczenie pamięci RAM).
Kompletna procedura zapisu/odczytu danych dla ESP8266 wygląda tak
EEPROM.begin(512); // deklaracja > ilość bajtów można ustawić od 4 do 4096
EEPROM.write(adres, dana);
EEPROM.read(adres);
EEPROM.commit(); lub EEPROM.end();
Jako ciekawostkę mamy możliwość potraktowania funkcji EEPROM jako tablicy bajtów
Dzięki tamu zapisu danej do komórki o nr 1 możemy dokonać w ten sposób
EEPROM(1) = 123;
a odczytu
byte dana = EEPROM(1);
Tym sposobem wpiszemy lub odczytamy bajt informacji. Dla zmiennych złożonych z większej ilości bajtów mamy dwie drogi.
- użyć funkcji put / get
- wpisać / odczytać sekwencyjnie całą daną bajt po bajcie
Funkcje put i get są wewnętrznymi procedurami biblioteki eeprom.h. Umożliwiają jednym poleceniem wykonanie operacji zapisu/ odczytu zmiennych wielobajtowych ale tylko tych ze zbioru podstawowych typów - int, char, long, float itd.
EEPROM.begin(1024); // ilość bajtów może zawierać się w przedziale 4 - 4096
EEPROM.put(adres, dana); //int dana; char dana; long dana; float dana
EEPROM.commit(); lub EEPROM.end();
Do typów podstawowych nie zalicza się niestety popularny String. Zmienną tego typu musimy zapisać bajt po bajcie lub zamienić na ciąg (tablicę) znaków.
Możemy natomiast tymi funkcjami operować dla innych bardziej złożonych typów np. struktur czy tablic:
struct MojaStruktura {
float zmienna_f;
byte zmienna_b;
char tablica[10];
};
MojaStruktura struc1; // deklaracja zmiennej
EEPROM.put(adres, struc1); //zapisz zmiennej bedącej strukturą od komórki adres
Jeśli wiadomo jak zapisywać dane w pamięci spróbujmy połączyć to z grafem odbioru kodów urządzeń opisywanym w poprzednim wpisie.
Da zapamiętania są dwie liczby reprezentujące "adres" konkretnego urządzenia - KOD i IMPULS.
KOD jest zmienną typu long (4 bajty) IMPULS typu int (2 bajty). potrzeba więc 6 bajtów do zapisu parametrów jednego urządzenia. Dla ułatwienia zarezerwuję 10 bajtów/ układ. Kolejne kody będą umieszczane w kolejnych dziesiątkach pamięci co powinno znaczenie ułatwić adresowanie.
Adresy wyznaczam jak poniżej
adres n-tego KODu = n x 10
adres n-tego IMPULSu = n x 10 + 5
Dla maksymalnego rozmiaru pamięci mogę zapamiętać ponad 400 różnych urządzeń.
Testowe procedury zapisu do pamięci wyglądają tak:
int nrpozkod = 0; //nr pozycji do zapisu kodu
long KOD = 0; // zmienna kodu do zapisu w pamięci
int IMPULS = 0; //zmienna długości impulsu kodu do zapisu w pamięci
long mem_KOD = 0; // zmienna kodu odczytana z pamięci
int mem_IMPULS = 0; //zmienna długości impulsu kodu odczytana pamięci
void savekod (int gdzie, long co1, int co2) { // zapis do eeprom
int liczadres = gdzie * 10;
EEPROM.begin(512);
EEPROM.put(liczadres, co1);
EEPROM.put((liczadres + 5), co2);
// EEPROM.commit();
EEPROM.end();
}
void readkod(int gdzie) { // odczyt z eeprom
int liczadres = gdzie * 10;
EEPROM.begin(512);
EEPROM.get(liczadres, mem_KOD);
EEPROM.get((liczadres + 5), mem_IMPULS);
EEPROM.commit();
EEPROM.end();
}
void zapisz_kod() {
Serial.print(" nr " + String(nrpozkod)); Serial.print(" zapisuje kod " + String(KOD)); Serial.println(" impuls " + String(IMPULS));
savekod(nrpozkod, KOD, IMPULS);
} //procedura wywołania zapisu kodu do pamięci nieulotnej
I efekt działania procedury KOD_do_eeprom()
Klawiszem załączam procedurę (stan automatu z 1 przełącza się na 2) a widgetem MENU ustawiam nr pozycji pamięci do zapamiętania kodu. Dwukrotne powtórzenie nadania tego samego kodu automatycznie zapisuje jego parametry do pamięci flash. Po resecie odczytuję zapamiętane wartości. I o dziwo są identyczne z tymi które zapisywałem.
Automat skończony do dekodowania kodów ᐯ
Zapisywanie kodów do EEPROMu ᐯ
Czekam ze spokojem na ciąg dalszy......
Wcześniejsze odcinki serialu
http://100-x-arduino.blogspot.com/2017/11/router-433-mhz-aczymy-rozne-systemy.html
http://100-x-arduino.blogspot.com/2017/11/router-433-mhz-nauka-czytania-i-pisania.html
http://100-x-arduino.blogspot.com/2017/12/router433-jak-programowac-schematy.html
106
Brak komentarzy:
Prześlij komentarz