Serwisy partnerskie:
Close icon
Serwisy partnerskie

Używanie pamięci Flash ESP32 do przechowywania danych

Article Image
Elmax
ESP32 posiada około 4MB wewnętrznej pamięci flash, a ponieważ dane przechowywane w pamięci flash są zachowywane nawet po ponownym włączeniu zasilania, staje się to bardzo przydatne w aplikacjach, gdzie trzeba zachować pewną ilość danych nawet po wyłączeniu zasilania. W tym projekcie dowiemy się jak odczytywać i zapisywać dane do pamięci Flash układu ESP32.

Pamięć Flash jest podobna do pamięci EEPROM, która jest powszechna w większości mikrokontrolerów. Jest to pamięć nieulotna (Non-Volatile memory), co oznacza, że zapisane w niej dane pozostają zachowane nawet po zresetowaniu układu ESP lub przełączeniu zasilania.  Może to być bardzo przydatne w aplikacjach, w których trzeba przechowywać określone ustawienia urządzenia, pamiętać ostatni stan określonej zmiennej, lub przechowywać pewne ważne dane runtime do późniejszego wykorzystania, itp. Dla przykładu, powiedzmy, że urządzenie sterowane przez ESP32 było włączone w momencie odcięcia zasilania, w większości przypadków, urządzenie pozostanie wyłączone po powrocie zasilania w zależności od ustawionych parametrów, ale z pomocą pamięci Flash, system może być zaprogramowany, aby powrócić do ostatniego stanu, który został zapisany. Pamięci flash mają jednak zazwyczaj stałą liczbę operacji zapisu, co ogranicza ich zastosowania. Dlatego dane w pamięciach flash powinny być nadpisywane dopiero po ich porównaniu i stwierdzeniu różnicy.

Aby zademonstrować zastosowanie i możliwości pamięci Flash, zbudujemy układ ściemniacza, w którym potencjometr służy do zmiany jasności diody LED, a układ ma za zadanie zapamiętać poziom jasności po zresetowaniu. Oprócz wykorzystania pamięci Flash do przechowywania danych, z tego projektu dowiesz się też jak używać czujnika analogowego z ESP32 i jak działa z nim PWM .

Wykaz elementów
Ilość
Symbol
Nazwa/opis/gdzie kupić

Chociaż projekt jest oparty na płytce DOIT's ESP32 DevKit V1, powinien on również działać z każdą inną płytką rozwojową opartą na ESP32.

Schemat

Podłącz elementy tak, jak pokazano na poniższym schemacie.

Schemat połączeń ESP32 z elementami

W przeciwieństwie do ESP8266, ESP32 posiada 18 pinów analogowych, do których można podłączyć potencjometr, więc można zmieniać piny wedle uznania. Ponadto wszystkie 36 pinów GPIO na płytce ESP32 ma włączoną funkcję PWM, więc dioda LED może być podłączona do dowolnego z pinów GPIO.

Kod

Kod dla tego projektu jest trochę skomplikowany. Algorytm wykonuje kilka prostych zadań, takich jak po prostu odczytuje wartość analogową na potencjometrze, używa jej do zmiany jasności diody LED i zapisuje tę wartość w pamięci Flash, tak aby następnym razem, gdy program uruchomi się bez wejścia z potencjometru, użył ostatniej wartości zapisanej w pamięci Flash.

Jak wspomniałem wcześniej,  pamięć Flash jest odmianą pamięci EEPROM, więc nie może dziwić fakt, że do tego projektu wykorzystamy bibliotekę ESP32 EEPROM. Biblioteka ta jest automatycznie instalowana w Arduino IDE podczas instalacji plików płytki dla ESP32. Korzystanie z niej jest takie samo jak z biblioteki EEPROM Arduino z niewielkimi różnicami w deklaracjach funkcji. Biblioteka EEPROM pozwoli nam na wykorzystanie do 512 bajtów pamięci flash. Oznacza to, że będziemy mieli do dyspozycji 512 różnych adresów i w każdym z nich będziemy mogli zapisać dane z zakresu od 0 do 255. Istnieją trzy główne funkcje z biblioteki EEPROM związane z przechowywaniem i pobieraniem danych;

  1. EEPROM.write(adres, wartość)
  2. EEPROM.commit()
  3. EEPROM.read(adres)

Aby zapisać dane pod adres pamięci, wywoływana jest funkcja EEPROM.write() z podanymi jako argumenty danymi i adresem, pod który mają być zapisane. Aby zakończyć zapis danych, należy wywołać funkcję EEPROM.commit(). Funkcja commit sprawdza, czy dane wskazane w funkcji write() różnią się od tych, które są tam obecnie, przed zapisaniem ich do pamięci flash. Ze względu na skończoną liczbę powtórzeń zapisu danych do pamięci Flash, funkcja commit() pomaga ograniczyć niepotrzebne operacje zapisu, aby utrzymać ich liczbę na niskim poziomie.

Funkcja read(), z drugiej strony, jest używana do pobierania informacji z adresu, który jest określony jako argument funkcji. Te trzy funkcje będą stanowiły centrum dzisiejszego projektu.

Zaczynamy jak zwykle, od dołączenia bibliotek potrzebnych do wykonania kodu, czyli w tym przypadku po prostu biblioteki EEPROM.

// include library to read and write from flash memory
#include <EEPROM.h>

Następnie określamy piny ESP32, do których będą podłączone pozostałe elementy oraz deklarujemy zmienne, które będą używane do przechowywania danych w kodzie. Jednym z minusów ESP32 jest to, że poziom wsparcia nie jest jeszcze tak wysoki jak w przypadku innych płytek. Aby zapisać wartości do pinu PWM na płytce arduino, wystarczy wywołać funkcję analogWrite(), ale ta funkcja nie jest dostępna dla ESP32, dlatego zmienne; freq, ledchannel i resolution zostaną użyte do realizacji tych samych zadań co funkcja analogWrite().

//GPIO pin declarations
#define ANALOG_PIN_0 36
#define LED_PIN 26

// PMW Parameters 
int freq = 5000;
int ledChannel = 0;
int resolution = 8;
int dutyCycle;


// Variables to store the potentiometer;s value and the current state of the LED
int analog_value;
int ledState = 0;         // the current state of the output pin we start with 0

Następnie piszemy funkcję void setup(). Rozpoczynamy ją od zainicjalizowania komunikacji szeregowej oraz komunikacji z EEPROMem.

void setup() { 
  Serial.begin(115200);
  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);

Następnie za pomocą funkcji ledcSetup() ustawiamy właściwości kanału PWM podając jako argumenty rozdzielczość, częstotliwość i kanał(ledChannel), po czym dołączamy pin do którego podłączona jest dioda LED do skonfigurowanego kanału PWM. Przetwornik ADC w ESP32 ma rozdzielczość 10bitów i ustawiając rozdzielczość kanału PWM na 8bitów, upodabniamy jego wartości do tego z Arduino.

ledcSetup(ledChannel, freq, resolution);
ledcAttachPin(LED_PIN, ledChannel);

Aby zakończyć działanie funkcji voidsetup(), odczytujemy pamięć EEPROM, sprawdzając czy istniała poprzednia wartość jasności diody LED  za pomocą funkcji EEPROM.read() i używamy funkcji ledcWrite() (która jest naszym odpowiednikiem funkcji analogWrite()), aby ustawić jasność diody LED.

// read the last LED state from flash memory
ledState = EEPROM.read(0);
ledcWrite(ledChannel, ledState);

Następnie piszemy funkcję void loop(). Funkcja ta po prostu sprawdza wartość wejściową z potencjometru, porównuje ją z ostatnią zapamiętaną wartością i jeśli jest różnica, jasność diody LED jest ustawiana na nową wartość, a pamięć flash jest aktualizowana za pomocą komend EEPROM.

Funkcję loop() rozpoczynamy od odczytania wartości analogowej z potencjometru.

analog_value = analogRead(ANALOG_PIN_0);

Ponieważ przetwornik ADC ma domyślnie 10 bitów, mapujemy wartość na 8 bitów, aby zapewnić zgodność z rozdzielczością PWM, którą zadeklarowaliśmy wcześniej.

dutyCycle = map(analog_value, 0, 4095, 0, 255);

Następnie sprawdzamy, czy jest różnica między ostatnią wartością a aktualną i jeśli tak, to ustawiamy jasność diody LED na tę nową wartość i aktualizujemy pamięć flash poleceniem EEPROM.write(), po którym następuje funkcja commit.

Serial.println("value changed");
   ledcWrite(ledChannel, dutyCycle);
   ledState = dutyCycle;
   // save the brightness value in flash memory
   EEPROM.write(0, ledState);
   EEPROM.commit();
   Serial.println("New value saved in flash memory");

Kompletny kod jest dostępny poniżej, a także załączony w sekcji download projektu.

// include library to read and write from flash memory
#include <EEPROM.h>

// define the number of bytes you want to access
#define EEPROM_SIZE 1

//GPIO pin declarations
#define ANALOG_PIN_0 36
#define LED_PIN 26

// PMW Parameters 
int freq = 5000;
int ledChannel = 0;
int resolution = 8;
int dutyCycle;

int analog_value;
int ledState = 0;         

void setup() { 
  Serial.begin(115200);
  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);

  ledcSetup(ledChannel, freq, resolution);
  ledcAttachPin(LED_PIN, ledChannel);

  // read the last brightness level from flash memory
  ledState = EEPROM.read(0);
  ledcWrite(ledChannel, ledState);
}

void loop() {
  // read the potvalue into a local variable:
 analog_value = analogRead(ANALOG_PIN_0);
 dutyCycle = map(analog_value, 0, 4095, 0, 255);
 if (dutyCycle != ledState) 
 {  
    Serial.println("value changed");
    ledcWrite(ledChannel, dutyCycle);
    ledState = dutyCycle;
    // save the brightness level in flash memory
    EEPROM.write(0, ledState);
    EEPROM.commit();
    Serial.println("level saved in flash memory");
  }
}

Demo

Upewnij się, że komponenty są podłączone zgodnie z opisem w części schematycznej, a jeśli dokonałeś jakichkolwiek zmian w konfiguracji pinów, upewnij się, że kod został zaktualizowany, aby je odzwierciedlić. Po wykonaniu tych czynności, podłącz DOIT ESP32 DevKit do komputera i załaduj kod. Powinieneś zobaczyć, że jasność diody LED zmienia się w miarę obracania gałki potencjometru. Ustaw potencjometr na konkretny, rozpoznawalny poziom jasności, a następnie odłącz układ. Urządzenie zachowa ostatnio zapisaną wartość i ustawi jasność diody LED na tę wartość po ponownym podłączeniu zasilania.

Choć jest to prosty przykład, można go wykorzystać do bardziej użytecznych zadań w bardziej złożonym projekcie, używając tych samych, dokładnych komend.

Do pobrania
Download icon Flash ESP32 do przechowywania danych

Artykuł USING ESP32’S FLASH MEMORY FOR DATA STORAGE opracowano w wersji polskiej na podstawie współpracy z portalem www.electronics-lab.com.

Firma:
AUTOR
Źródło
www.electronics-lab.com
Udostępnij
Zobacz wszystkie quizy
Quiz weekendowy
Edukacja
1/10 Jak działa rezystor LDR?
UK Logo
Elektronika dla Wszystkich
Zapisując się na nasz newsletter możesz otrzymać GRATIS
najnowsze e-wydanie magazynu "Elektronika dla Wszystkich"