wtorek, 9 lutego 2021

Arduino : Serial Type Writer i dynamiczna alokacja

 Po raz kolejny - temat oszczędności pamięci RAM. Tym razem będzie trochę trudniej, wykorzystamy kilka sposobów na raz :-) Przesunięcie łańcuchów znaków (nasze komunikaty będą w pamięci programu) - w Arduino jest jej więcej niż pamięci RAM. Druga sprawa, dynamiczny przydział pamięci dla tych komunikatów - w zależności od jego długości. Teoretycznie zmienna bufor znika po wyjściu z funkcji, ale warto znać te sposoby :-)

Przyjrzyjmy się źródle. Funkcja void freeRAM() została napisany tylko na potrzeby demonstracji jak zmienia się dynamicznie pamięć RAM - nie ma potrzeby byś rozumiał jej działania, robi swoje - może kiedyś Ci się przyda. Następnie mamy definicje naszych komunikatów, prezentacja działania będzie na monitorze szeregowym, nie ma przeszkód by to robić na wyświetlaczach LCD lub OLED - zasada jest ta sama.

kod do ściągnięcia z PASTEBIN : Serial Type Writer

  1. void freeRAM()
  2. {
  3.   extern int __heap_start, *__brkval;
  4.   int v;
  5.   Serial.print(F("Wolna pamiec [bajty] : "));
  6.   Serial.println( (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval) );  
  7. }
  8.  
  9. // --- komunikaty zapisane w pamieci programu --- definiujemy jako const char [] PROGMEM ----------
  10. const char msg_00 [] PROGMEM  = "Nie mozna pozyskac tej wiadomosci! Nie istnieje.";
  11. const char msg_01 [] PROGMEM  = "Hello, twoje Arduino zostalo uruchomione";
  12. const char msg_02 [] PROGMEM  = "Komunikaty ktore widzisz zostaly zdefiniowane z pamieci programu";
  13. const char msg_03 [] PROGMEM  = "Dzieki takiemu rozwiazaniu w RAM masz wiecej wolnej pamieci";
  14. const char msg_04 [] PROGMEM  = "Dostep do tych napisow trzeba wydobyc z pamieci RAM";
  15. const char msg_05 [] PROGMEM  = "Nie jest to trudne, a oszczednosci olbrzymie";
  16.  
  17. // --- tablica ulatwiajaca wybor odpowiedniego komunikatu ----------------------------------------
  18. const char * const wiadomosc [] PROGMEM = { msg_00, msg_01, msg_02, msg_03, msg_04, msg_05 };
  19.  
  20. // --- funkcja wyciągająca napis z tablic msg_xx -------------------------------------------------
  21. void EkstrakcjaWiadomosci(byte nr_wiadomosci)
  22. {
  23.     // musimy sprawdzic czy nr_wiadomości do wyłuskania z pamięci RAM nie jest
  24.     // już poza tablica wiadomosc [] - zabezpieczamy się przed błędem :-)
  25.     if( nr_wiadomosci >= sizeof (wiadomosc) / 2 )
  26.     {  
  27.         char *bufor = new char [ strlen_P( pgm_read_word (& wiadomosc[0] ) ) ]; // dynamiczny przydział pamięci bufora
  28.         strcpy_P ( bufor, (char*) pgm_read_word (& wiadomosc[0] ));             // kopiujemy z pamięci msg: error do bufor      
  29.         TypeWriter( bufor, 50 );                                                // drukujemy komunikak błędu na ekran
  30.         freeRAM();                                                              // wolna pamięć - bufor jeszcze istnieje
  31.         delete bufor;                                                           // kasujemy bufor z pamięci        
  32.         freeRAM();                                                              // wolna pamięć - bufor już nie istnieje
  33.     }
  34.     // numer wiadomości do wyświetlenia jest w tablicy (zmienna musi mieć wartość 1,2,3,4,5)
  35.     // wiadomosc nr. 0 to nasz komunikat o błędzie, oczywiście dostęp do niej przez podanie 0
  36.     else
  37.     {                  
  38.       char *bufor = new char [ strlen_P( pgm_read_word (& wiadomosc[nr_wiadomosci] ) ) ];            
  39.       strcpy_P ( bufor, (char*) pgm_read_word (& wiadomosc[nr_wiadomosci] ));
  40.       TypeWriter(bufor, 50);
  41.       freeRAM();                                                                // wolna pamięć - bufor isnieje w RAM
  42.       delete bufor;                                                             // kasujemy bufor z pamięci
  43.       freeRAM();                                                                // wolna pamięć - bufor już nie istnieje
  44.     }
  45. }
  46.  
  47. // --- Serial Type Writer by PowerTGS -------------------------------------------------------------
  48. // jako wejście otrzymuje adres tablicy znaków [] i czas opóźnienia wyświetlenia jednego znaku
  49. void TypeWriter(const String & message, unsigned int wait)
  50. {
  51.   for(const char c : message)
  52.   {
  53.     Serial.write(c);    
  54.     delay(wait);  
  55.   }
  56.   Serial.write("\n");
  57. }
  58.  
  59. // --- SETUP ------------------------------------------------------------------------------------
  60.  
  61. void setup()
  62. {
  63.   Serial.begin(9600);
  64.   EkstrakcjaWiadomosci(1);
  65.   EkstrakcjaWiadomosci(2);
  66.   EkstrakcjaWiadomosci(3);
  67.   EkstrakcjaWiadomosci(4);
  68.   EkstrakcjaWiadomosci(5);
  69.   EkstrakcjaWiadomosci(6);              // wiadomosc 6 nie istnieje, sprawdzmy co się stanie
  70. }
  71.  
  72. void loop()
  73. {
  74.   // put your main code here, to run repeatedly:
  75. }

Brak komentarzy:

Prześlij komentarz

BME280 - Sensor temperatury, wilgotności i ciśnienia

  BME280 (ESP32/ESP2866) BME280 to prosty w użyciu czujnik temperatury, wilgotności oraz ciśnienia atmosferycznego. Zasilany jest napię...