Zawieszające sie Arduino

Masz problem, z którym nie możesz sobie poradzić? Pisz śmiało!
ODPOWIEDZ
pawel_123
Młodszy majsterkowicz
Posty: 8
Rejestracja: 6 sie 2018, 12:32

Zawieszające sie Arduino

Post autor: pawel_123 » 6 sie 2018, 13:17

Witam,
Mam problem z zawieszającym się arduino, układ chodzi 24h/dobę a problem pojawia się w nocy.
Mam podejrzenie, że może być to zapychająca się pamięć SRAM, ale tu mam pytanie do bardziej doświadczonych:
zgodnie z informacjami znalezionymi w sieci (niestety linka dac nie mogę)
jeśli dobrze zrozumiałem mozliwe, że zmienne lokalne pozostawiają po sobie dziury, a za następnym razem zapisywane są gdzie indziej i znowu po usunięciu zostają dziury i tak łatwo zapełnić całe dostępne 8KB (arduino mega). Czyli kontroler nie jest na tyle sprytny, żeby wykorzystywać zwolnione miejsce? W takim razie nie opłaca się dynamicznie alokowac pamięci a wszystko co się da dawac do zmiennych globalnych?
Czyli taka konstrukcja się nie opłaca?
String content="";
(zapisywanie treści sms z modułu sim do zmiennej content)
(zrobienie czegoś na zmiennej content)
content=""; //czyszczenie pamięci po zmiennej

czy taka jest lepsza?
char *content;
content=(char *)malloc(100);

i na końcu:
free(content);

a co ze zmiennymi zadeklarowanymi wewnętrz fukcji/ pętli?

Trochę dziwi mnie fakt, że w ciągu dnia wszystko działa poprawnie a w nocy nie dzieje się raczej nic nadzwyczajnego.

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Awatar użytkownika
ethanak
Złota rączka
Posty: 784
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Zawieszające sie Arduino

Post autor: ethanak » 7 sie 2018, 01:33

Zmienne lokalne żadnych dziur po sobie nie pozostawiają (chyba nie to czytałeś co trzeba) - są alokowane na stosie i zawsze zwalniane w odwrotnej kolejności. To wszystko dotyczy zmiennych lokalnych funkcji, zmiennych deklarowanych w blokach, zmiennych przydzielanych funkcją alloca() i tak dalej. Co innego wszelkie konstrukcje dynamiczne oparte na malloc() (czyli również String) - te potrafią naśmiecić. Tu nie można polegać na "sprycie" - po prostu tej pamięci jest zbyt mało, aby uruchomić jakiś sensowny algorytm.
Dlatego najlepszą konstrukcją będzie coś w stylu:

Kod: Zaznacz cały


void sms(void)
{
    char content[100];
    // robimy coś z content
}

void loop(void)
{
    // coś robimy
    sms();
   // robimy coś dalej, a pamięć przydzielona na wewnętrzne zmienne funkcji sms została automatycznie zwolniona
}
Można również zadeklarować statyczny bufor content - wtedy zostanie przydzielony raz na zawsze, pamięć co prawda nie będzie zwalniana ale ponieważ co chwila nam jest potrzebna zawsze bufor czeka gotowy do użycia. Taki bufor można w różnych miejscach programu wykorzystać do różnych celów ale z tym trzeba uważać i szczególnie osobom z małym doświadczeniem tego nie polecam,
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
pawel_123
Młodszy majsterkowicz
Posty: 8
Rejestracja: 6 sie 2018, 12:32

Re: Zawieszające sie Arduino

Post autor: pawel_123 » 7 sie 2018, 12:21

Dziękuje serdecznie za odpowiedź, faktycznie teraz znalazłem inne opracowanie i jest wprost napisane, ze zmienne lokalne są w stack, a dynamiczne w heap, chociaż wciąż nie wiem, dlaczego stack nie ma tendencji do fragmentacji...

W Twoim przykładzie zmienna content jest zmienną lokalną? W związku z czym będzie w STACK? Tylko właśnie czemu to ma uchronić od fragmentacji?

mógłbyś rozwinąć myśl o statycznym buforze? Jak do zadeklarować (w którym miejscu w kodzie) i jak do niego się odwoływać.

Znalazłem jeszcze przykład z funkcją reserve()

Kod: Zaznacz cały

String myString;

void setup() {
  // initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB
  }

  myString.reserve(26);
  myString = "i=";
  myString += "1234";
  myString += ", is that ok?";

  // print the String:
  Serial.println(myString);
}

void loop() {
 // nothing to do here
}
tu jest zadeklarowana raz, w setup, jeśli chciałbym skorzystać z myString w loop, to kiedy mam użyć .reserve(); ? Czy wówczas czyszczenie też może wyglądać tak: myString=""; a raz zarezerwowane miejsce będzie czekać aż znów coś tam zapiszę?

Przepraszam jeśli sa to trywialne pytania, ale elektroniką zajmuję się amatorsko, jak coś robię to lubię wiedzieć czemu akurat tak a nie inaczej a w sieci bardzo ciężko znaleźć rzetelne jednoznaczne informacje.
Ostatnio zmieniony 7 sie 2018, 14:26 przez pawel_123, łącznie zmieniany 1 raz.
Awatar użytkownika
ethanak
Złota rączka
Posty: 784
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Zawieszające sie Arduino

Post autor: ethanak » 7 sie 2018, 14:24

Dla jasności: zmienne lokalne (w funkcji, bloku czy gdziekolwiek) są alokowane w momencie wejścia do bloku i zwalniane z chwilą wyjścia z bloku - i w praktyce nie ma od tego żadnych wyjątków (chyba że uprzesz się aby użyć goto - ale to już robisz na własną odpowiedzialność). Nie czytałeś żadnego podręcznika czy co?

Na czym polega to złe doświadczenie? Co się stało jeśli millis() umieściłeś w funkcji i w czym poprawiło to działanie umieszczenia millis() w bloku np. if? Jakoś nie mogę sobie tego wyobrazić...

Co do reserve... a koniecznie chcesz używać klasy String? Do czego? Podaj powód, dla którego nie wystarczą konstrukcje które nie wymagają dynamicznych przydziałów pamięci.

Co do statycznego bufora...
Przykład numer jeden:

Kod: Zaznacz cały

char content[100];

void loop(void)
{
    // wymyślona funkcja czytająca jakiś string z jakiegoś tam wejścia
    read_cośtam(content); // w content masz to co funkcja wyczytała
    // teraz chcemy zrozumieć o co chodzi - załóżmy że w content siedzi liczba
    int x = strtol(content, NULL, 10);
    // no i w x mamy liczbę i content możemy wykorzystać np. w takim miejscu:
    sprintf(content,"Liczba to %d", x);
    Serial.println(content);
    // i mamy na serialu wypisaną wartość x
{

Wszystko to fajnie... ale np. przykład numer dwa:

Kod: Zaznacz cały

char content[100];

void loop(void)
{
    read_cośtam(content);
    // wiadomo, że po spacji będzie jakiś tam argument
    char *c = strchr(content,' ') +1; // radośnie zakładamy że spacja wystąpiła...
    sprintf(content,"Wartość to %s",c); 
    Serial.println(conent);
    // i Arduino w najlepszym przypadku robi reset niezależnie od tego czy spacja wystąpiła czy nie.
}
Poniał?

Co do amatorskiego zajmowania się elektroniką:

Ja się amatorsko zajmuję hodowlą jeżyn w ogródku, i nie bardzo widzę korelację między hodowlą jeżyn a pisaniem programów na Arduino. Możesz wyjaśnić, co ma do rzeczy amatorskie zajmowanie się elektroniką z pisaniem programów na cokolwiek?
po chwili przypomnienia
Pytałeś dlaczego stos (stack) się nie fragmentuje a sterta (heap) może... a próbowałeś przeczytać na ten temat coś więcej niż artykuł na pudelku czy dyskusję Antka Emigranta na onecie? Trochę samodzielności, please... nikt tu nie będzie robić copy/paste z Wikipedii tylko dlatego że Ci się nie chce!
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
pawel_123
Młodszy majsterkowicz
Posty: 8
Rejestracja: 6 sie 2018, 12:32

Re: Zawieszające sie Arduino

Post autor: pawel_123 » 7 sie 2018, 14:45

Dzięki za konkretną odpowiedź,
ethanak pisze:
7 sie 2018, 14:24
Dla jasności: zmienne lokalne (w funkcji, bloku czy gdziekolwiek) są alokowane w momencie wejścia do bloku i zwalniane z chwilą wyjścia z bloku - i w praktyce nie ma od tego żadnych wyjątków (chyba że uprzesz się aby użyć goto - ale to już robisz na własną odpowiedzialność). Nie czytałeś żadnego podręcznika czy co?
Jakoś nie trafiał do mnie język podręcznikowy
ethanak pisze:
7 sie 2018, 14:24
Na czym polega to złe doświadczenie? Co się stało jeśli millis() umieściłeś w funkcji i w czym poprawiło to działanie umieszczenia millis() w bloku np. if? Jakoś nie mogę sobie tego wyobrazić...
Funkcje wykorzystujące czas zwykle się nie wykonywały tak jak należy, to samo jeśli było w nich wiele instrukcji.
Wysyłając kilka SMS do wielu odbiorców muszę robić przerwy co najmniej 5s miedzy każdym z nich, w funkcji program wykonywał się nie zwracajac uwagi na czas przez co wiekszosć SMS nie była wysłana.
ethanak pisze:
7 sie 2018, 14:24
Co do reserve... a koniecznie chcesz używać klasy String? Do czego? Podaj powód, dla którego nie wystarczą konstrukcje które nie wymagają dynamicznych przydziałów pamięci.
nie koniecznie, ale jest dla mnie łatwiej (byłoby gdyby działało jak należy)
ethanak pisze:
7 sie 2018, 14:24
Co do amatorskiego zajmowania się elektroniką:

Ja się amatorsko zajmuję hodowlą jeżyn w ogródku, i nie bardzo widzę korelację między hodowlą jeżyn a pisaniem programów na Arduino. Możesz wyjaśnić, co ma do rzeczy amatorskie zajmowanie się elektroniką z pisaniem programów na cokolwiek?
przyznam, że chwilę się zastanawiałem o co chodzi, ale ok, ja wrzucam arduino i elektronikę do jednego worka
ethanak pisze:
7 sie 2018, 14:24
Pytałeś dlaczego stos (stack) się nie fragmentuje a sterta (heap) może... a próbowałeś przeczytać na ten temat coś więcej niż artykuł na pudelku czy dyskusję Antka Emigranta na onecie? Trochę samodzielności, please... nikt tu nie będzie robić copy/paste z Wikipedii tylko dlatego że Ci się nie chce!
Rzeczywiście jest na wikipedii.

Co do stylu Twojej odpowiedzi i nie tylko Twojej, drobna uwaga. W internecie znajdzie się wszystko to prawda, ale wśród sensownych informacji jest masa bzdur, czasem nie jest łatwo się zorientować z czym mamy do czynienia, szczególnie jeśli jestem początkujący w temacie. Wiele opracowań traktuje temat wybiórczo, pomijając według mnie najważniejsze informacje, np jest podane: unikaj czegoś tam, albo nie wolno tego, nie dając alternatywy i nie podając przyczyny. Dlatego pytam się na forum zdając się na doświadczenie innych, a przeglądając je od wczoraj znalazłem odpowiedzi typu: wiem ale nie powiem - domyśl się, albo podajac link do google.
Myślę, że na prawdę osoba decydująca się na zarejestrowanie i napisanie posta próbowała znaleźć rozwiązanie swojego problemu i to nie na pudelku czy onecie. Widocznie dalej ma wątpliwości. Jesli jest taki problem odpowiedzieć na te pytania to po co dajecie się rejestrować wszystkim jak leci, zróbcie forum dla specjalistów, tylko z polecenia, to nie będzie głupich pytań. A tak to trzeba z góry przepraszać, że się w ogóle jest, tłumaczyć, że się szukało ale nie znalazło a i tak połowa podeśle link do google, mało imponujące bo tyle to i 3 letnie dziecko potrafi zrobic.

Znając życie tą drobną uwagą narobie sobie wrogów na forum, albo dostanę bana i będzie po problemie.

Nie mniej jestem wdzięczny za Twoją odpowiedź, zapewne pozwoli mi rozwiązać problem i nie popełniac go w przyszłości
Ostatnio zmieniony 7 sie 2018, 15:19 przez pawel_123, łącznie zmieniany 1 raz.
Awatar użytkownika
ethanak
Złota rączka
Posty: 784
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Zawieszające sie Arduino

Post autor: ethanak » 7 sie 2018, 15:06

Co do języka podręcznikowego: też tego nie cierpię, ale potraktuj to jako zło konieczne.
Co do funkcji, wysyłania sms-ów co ileś tam sekund/minut/dni: polecam kurs Arduino.
Co do stringów, malloców i tym podobnmych wydumek: są fajne, ale dopóki siedzisz na Arduino radzę zapomnieć o ich istnieniu. Dlaczego? A np. dlatego. Najważniejsze jest jedno zdanie:
unlike larger architectures, there is no hardware-supported memory management which could help in separating the mentioned RAM regions from being overwritten by each other.
Co do jeżyn i Arduino: ja kiedyś spróbowałem do jednego worka wrzucić jeżyny i maliny (akurat krzaczki rosną obok). Nie wiedziałem, że moja piękna żona dysponuje tak rozbudowanym zakresem inwektyw... wolę nie sprawdzać co by było, gdybym tak jeszcze Arduino wrzucił ;)
Odróżnij elektronikę (lutowanie drucików) od programowania (naciskanie klawiszy na klawiaturze w określonej kolejności).
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
Slawek
Starszy majsterkowicz
Posty: 455
Rejestracja: 29 mar 2015, 15:05

Re: Zawieszające sie Arduino

Post autor: Slawek » 9 sie 2018, 19:12

Nie dostaniesz bana, forum jest dla użytkowników na każdym etapie wiedzy a nie tylko dla np. akademickich teoretyków traktujących innych w relacji profesor/student.

Pozdr
ODPOWIEDZ

Strony partnerskie: