• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 1 głosów - średnia: 1
  • 1
  • 2
  • 3
  • 4
  • 5
Potrzebna optymalizacja kodu - program urósł za duży
#11
(01-01-2021, 23:33)Marecki napisał(a): Witam serdecznie i chcę poprosić o pomoc w poprawieniu kodu, jestem bardzo początkującym programistą Arduino i prawdę mówiąc to mój pierwszy projekt Smile który piszę używając przykładów z internetu. Przez co kod jest mało optymalny i niestety doszedłem do ściany bo skończyło się miejsce w pamięci Sad . Niestety na tym etapie nie umiem sobie z tym poradzić samodzielnie. Jeśli więc ktoś mógłby zerknąć na moje dzieło, byłbym bardzo wdzięczny.
Chciałbym aby ten program działał na Arduino UNO.

na początek użyj w Serial.print i lcd.print makro F !!! Zastąp wszędzie (ale tylko te gdzie jest tekst w cudzysłowiu " ", nie gdzie zmienne !!! chodzi o to :
zamiast tak : Serial.println("Writing headers to csv.txt");
z makrem   : Serial.println(F("Writing headers to csv.txt"));

podobnie tutaj: lcd.print("no SD card");
z makrem tak:  lcd.print(F("no SD card"));

oszczędzisz sporo bajtów pamięci RAM, Dołączam mój kod który demonstruje użycie pamięci programu (PROGMEM) oraz funkcja do monitorowanie wolego RAMU. Jeśli zrobisz sobie tak komunikaty, w pamięci programu nie w RAM to na taką ilość tego co masz w kodzie wyjdzie z 500bajtów, dostęp jest utrudniony ale przykład dobrze ilustruje. New() i delete() możesz sobie na początek darować, po prostu twórz statycznie bufor i do niego kopiuj.

PROGMEM, NEW & DELETE


Kod:
// --- funkcja wyświetla ilość wolnej pamięci dynamicznej RAM -----------------------------------------
void freeRAM()
{
  extern int __heap_start, *__brkval;
  int v;
  Serial.print(F("Wolna pamiec [bajty] : "));
  Serial.println( (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval) ); 
}

// --- komunikaty zapisane w pamieci programu --- definiujemy jako const char [] PROGMEM ----------
const char msg_00 [] PROGMEM  = "Nie mozna pozyskac tej wiadomosci! Nie istnieje.";
const char msg_01 [] PROGMEM  = "Hello, twoje Arduino zostalo uruchomione";
const char msg_02 [] PROGMEM  = "Komunikaty ktore widzisz zostaly zdefiniowane z pamieci programu";
const char msg_03 [] PROGMEM  = "Dzieki takiemu rozwiazaniu w RAM masz wiecej wolnej pamieci";
const char msg_04 [] PROGMEM  = "Dostep do tych napisow trzeba wydobyc z pamieci programu";
const char msg_05 [] PROGMEM  = "Nie jest to trudne, a oszczednosci olbrzymie";

// --- tablica ulatwiajaca wybor odpowiedniego komunikatu ----------------------------------------
const char * const wiadomosc [] PROGMEM = { msg_00, msg_01, msg_02, msg_03, msg_04, msg_05 };

// --- funkcja wyciągająca napis z tablic msg_xx -------------------------------------------------
void EkstrakcjaWiadomosci(byte nr_wiadomosci)
{
    // musimy sprawdzic czy nr_wiadomości do wyłuskania z pamięci RAM nie jest
    // już poza tablica wiadomosc [] - zabezpieczamy się przed błędem :-)
    if( nr_wiadomosci >= sizeof (wiadomosc) / 2 )
    {  
        char *bufor = new char [ strlen_P( pgm_read_word (& wiadomosc[0] ) ) ]; // dynamiczny przydział pamięci bufora
        strcpy_P ( bufor, (char*) pgm_read_word (& wiadomosc[0] ));             // kopiujemy z pamięci msg: error do bufor      
        TypeWriter( bufor, 50 );                                                // drukujemy komunikak błędu na ekran
        freeRAM();                                                              // wolna pamięć - bufor jeszcze istnieje
        delete bufor;                                                           // kasujemy bufor z pamięci       
        freeRAM();                                                              // wolna pamięć - bufor już nie istnieje
    }
    // numer wiadomości do wyświetlenia jest w tablicy (zmienna musi mieć wartość 1,2,3,4,5)
    // wiadomosc nr. 0 to nasz komunikat o błędzie, oczywiście dostęp do niej przez podanie 0
    else
    {                  
      char *bufor = new char [ strlen_P( pgm_read_word (& wiadomosc[nr_wiadomosci] ) ) ];           
      strcpy_P ( bufor, (char*) pgm_read_word (& wiadomosc[nr_wiadomosci] ));
      TypeWriter(bufor, 50);
      freeRAM();                                                                // wolna pamięć - bufor isnieje w RAM
      delete bufor;                                                             // kasujemy bufor z pamięci
      freeRAM();                                                                // wolna pamięć - bufor już nie istnieje
    }
}

// --- Serial Type Writer by PowerTGS -------------------------------------------------------------
// jako wejście otrzymuje adres tablicy znaków [] i czas opóźnienia wyświetlenia jednego znaku
void TypeWriter(const String & message, unsigned int wait)
{
  for(const char c : message)
  {
    Serial.write(c);   
    delay(wait); 
  }
  Serial.write("\n");
}

// --- SETUP ------------------------------------------------------------------------------------

void setup()
{
  Serial.begin(9600);
  EkstrakcjaWiadomosci(1);
  EkstrakcjaWiadomosci(2);
  EkstrakcjaWiadomosci(3);
  EkstrakcjaWiadomosci(4);
  EkstrakcjaWiadomosci(5);
  EkstrakcjaWiadomosci(6);              // wiadomosc 6 nie istnieje, sprawdzmy co się stanie
}

void loop()
{
  // put your main code here, to run repeatedly:
}
 
Odpowiedź
#12
(01-01-2021, 23:33)Marecki napisał(a): Witam serdecznie i chcę poprosić o pomoc w poprawieniu kodu, jestem bardzo początkującym programistą Arduino i prawdę mówiąc to mój pierwszy projekt Smile który piszę używając przykładów z internetu. Przez co kod jest mało optymalny i niestety doszedłem do ściany bo skończyło się miejsce w pamięci Sad . Niestety na tym etapie nie umiem sobie z tym poradzić samodzielnie. Jeśli więc ktoś mógłby zerknąć na moje dzieło, byłbym bardzo wdzięczny.
Chciałbym aby ten program działał na Arduino UNO.
Tu trochę zmodyfikowałem twój program, link (wersja ze statycznym buforem):  modyfikacja , a tu (wersja z dynamicznym buforem) mod_dynamiczny byś zrozumiał PROGMEM. W sumie 4 początkowe wiadomości które pokazujesz po restarcie.

Nad funkcją SETUP (twojego programu) masz 2 potrzebne metody - demonstracja tylko dla LCD. W setup wywaliłem twoje LCD.print, zastapiłem wywołenim funkcji gdzie jest wyłuskanie odpowiedniego napisu (adresu) z pamięci programu, skopiowanie do bufora i jego wyświetlenie. Mam nadzieje, że działa bo nie kompilowałem. Pierwsza wersja to char bufor[20] dla LCD - czyli kompilator rezerwuje miejsce od razu, ale druga to już char *bufor = new char [ oblicz_rozmiar i przydziel pamięć ] i jest bardziej efektowna gdy brakuje RAMU (powinno się sprawdzić czy można utworzyć czy jest tyle miejsca - ale to już sam sobie doczytaj kiedys jak), tyle tylko - że trzeba pamiętać by usunąć go później operatorem delete().

A jak potrzeba więcej pamięci do programu to na przyszłość użyj makra (nie wierzę, że będziesz patrzył na serial.monitor) ? przy pisaniu programu tak - by sprawdzić stan zmiennych, działanie pętli czy warunków - ale jego wyłączenie i wszystkich z nim związanych poleceń do już kilobajty w kieszeni - a można to zrobić bez kasowania z kodu. Czyli na początku projektu deklaracja i definicja naszego makra, niech się nazywa MojSerial - ustawiamy na false - wyłącza seriala i wszystkie polecenia z nim związane (dosłownie - nie są dołączone do kodu - nie istnieją w programie wgranym do Arduino) true - włącza, czyli mamy serial monitor na PC. Podstawowe proste rzeczy, a tyle pamięci w kieszeni.

#define MojSerial false

a potem wszędzie gdzie Serial.funkcja() robimy tak (2 linijki, przy każdym wywołaniu, ale warto) :

#if MojSerial
     Serial.begin(9600);
#endif


czy tak:

#if MojSerial
     Serial.println(F("to jest napis"));
#endif

nie jest ro trudne, ale ... mamy fajny program tylko zmieniamy w nim wyświetlacz lcd z 16x2 na 20x4 i co ? przepisywać, poprawiać ? - po co, robić to z głową od razu - false to 16x2 true to 20x4 - zmieniamy tylko 1 wartość

#define lcd_big false

#if lcd_big
   lcd.begin(20,4);
#else
   lcd.begin(16,2);
#endif
 
Odpowiedź
#13
(01-01-2021, 23:33)Marecki napisał(a): Witam serdecznie i chcę poprosić o pomoc w poprawieniu kodu, jestem bardzo początkującym programistą Arduino i prawdę mówiąc to mój pierwszy projekt Smile który piszę używając przykładów z internetu. Przez co kod jest mało optymalny i niestety doszedłem do ściany bo skończyło się miejsce w pamięci Sad . Niestety na tym etapie nie umiem sobie z tym poradzić samodzielnie. Jeśli więc ktoś mógłby zerknąć na moje dzieło, byłbym bardzo wdzięczny.
Chciałbym aby ten program działał na Arduino UNO.
I twój program TUTAJ po modyfikacji przez generator (więc powinno działać chyba, bo klepać koda by mi się nie chciało).
było : 1636 bajtów (79%) pamięci dynamicznej i alert 
teraz: 1278 bajtów (62%) pamięci dynamicznej brak alertu :-)

po co tam pętle while(1); ? wiesz co to znaczy ?
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości