Zgodnie z dokumentacją Arduino, ATmega328 ma 32 KB pamięci Flash dla bootloadera + przesłanego szkicu i tylko 2 KB SRAM dla danych wykonawczych. ATmega2560 ma znacznie więcej, w sumie odpowiednio 256 KB i 8 KB.
W obu przypadkach limity te wydają się raczej niewielkie, zwłaszcza w porównaniu z urządzeniami konsumenckimi o podobnych rozmiarach, takimi jak smartfony.
Co możesz zrobić, jeśli zabraknie? Np. Jeśli twój szkic jest zbyt duży lub potrzebujesz przetworzyć dużo danych (takich jak łańcuchy) w czasie wykonywania? Czy jest jakiś sposób na rozszerzenie Flasha lub SRAM?
flash
sketch-size
Peter Bloomfield
źródło
źródło
Odpowiedzi:
Optymalizacja
Programowanie niskopoziomowe dla systemów wbudowanych różni się zupełnie od programowania dla urządzeń ogólnego przeznaczenia, takich jak komputery i telefony komórkowe. Wydajność (pod względem prędkości i przestrzeni) jest znacznie ważniejsza, ponieważ zasoby są na wagę złota. Oznacza to, że pierwszą rzeczą do zrobienia, jeśli zabraknie Ci miejsca, jest sprawdzenie, które części kodu możesz zoptymalizować.
Jeśli chodzi o zmniejszenie wykorzystania przestrzeni programowej (Flash), rozmiar kodu może być dość trudny do optymalizacji, jeśli nie masz doświadczenia lub jeśli jesteś bardziej przyzwyczajony do programowania na komputerach stacjonarnych, które zwykle nie potrzebują tej umiejętności. Niestety, nie istnieje podejście oparte na „magicznej kuli”, które działałoby we wszystkich sytuacjach, chociaż pomaga, jeśli poważnie zastanawiasz się, co naprawdę musi mieć szkic . Jeśli funkcja nie jest potrzebna, wyjmij ją.
Czasami pomocne jest również określenie, gdzie wiele części kodu jest takich samych (lub bardzo podobnych). Możesz je skondensować w funkcje wielokrotnego użytku, które można wywoływać z wielu miejsc. Należy jednak pamiętać, że czasami próba uczynienia kodu zbyt wielokrotnego użytku w rzeczywistości powoduje, że jest on bardziej szczegółowy. Jest to trudna równowaga do uderzenia, która zwykle towarzyszy ćwiczeniom. Pomocne może być poświęcenie czasu na sprawdzenie, jak zmiany kodu wpływają na dane wyjściowe kompilatora.
Optymalizacja danych wykonawczych (SRAM) jest nieco łatwiejsza, gdy się do tego przyzwyczaisz. Bardzo częstym problemem dla początkujących programistów jest używanie zbyt dużej ilości danych globalnych. Wszystko zadeklarowane w zasięgu globalnym będzie istniało przez cały okres istnienia szkicu, i to nie zawsze jest konieczne. Jeśli zmienna jest używana tylko w obrębie jednej funkcji i nie musi trwać między wywołaniami, należy uczynić ją zmienną lokalną. Jeśli wartość musi być dzielona między funkcje, zastanów się, czy możesz przekazać ją jako parametr zamiast uczynić ją globalną. W ten sposób będziesz używał SRAM dla tych zmiennych tylko wtedy, gdy ich potrzebujesz.
Kolejnym zabójcą używanym przez SRAM jest przetwarzanie tekstu (np. Używanie
String
klasy). Ogólnie rzecz biorąc, w miarę możliwości należy unikać wykonywania operacji na łańcuchach. To ogromne wieprze pamięci. Na przykład, jeśli wysyłasz dużo tekstu do numeru seryjnego, użyj wielu wywołańSerial.print()
zamiast zamiast konkatenacji ciągów. Spróbuj również zmniejszyć liczbę literałów łańcuchowych w kodzie, jeśli to możliwe.Jeśli to możliwe, unikaj rekurencji. Za każdym razem, gdy wykonuje się wywołanie rekurencyjne, poziom stosu jest wyższy. Zamiast tego przekształć swoje funkcje rekurencyjne na iteracyjne.
Użyj EEPROM
EEPROM służy do długoterminowego przechowywania rzeczy, które zmieniają się tylko sporadycznie. Jeśli potrzebujesz użyć dużych list lub tabel przeglądowych stałych danych, rozważ wcześniejsze zapisanie ich w EEPROM i wyciąganie tylko tego, czego potrzebujesz.
Oczywiście pamięć EEPROM ma jednak dość ograniczony rozmiar i prędkość oraz ma ograniczoną liczbę cykli zapisu. Nie jest to świetne rozwiązanie dla ograniczeń danych, ale może wystarczyć, aby zmniejszyć obciążenie pamięci Flash lub SRAM. Jest również całkiem możliwe połączenie z podobną pamięcią zewnętrzną, taką jak karta SD.
Rozszerzenie
Jeśli wyczerpałeś wszystkie inne opcje, rozszerzenie może być możliwe. Niestety, rozszerzenie pamięci Flash w celu zwiększenia przestrzeni programu nie jest możliwe. Jednakże, to jest możliwe, aby rozwinąć SRAM. Oznacza to, że możesz być w stanie zmienić swój szkic, aby zmniejszyć rozmiar kodu kosztem zwiększenia rozmiaru danych.
Zdobywanie większej ilości pamięci SRAM jest w rzeczywistości dość proste. Jedną z opcji jest użycie jednego lub więcej układów 23K256 . Są one dostępne za pośrednictwem SPI, a biblioteka SpiRAM pomaga ci z nich korzystać. Uważaj tylko, że działają przy napięciu 3,3 V, a nie 5 V.
Jeśli używasz Mega, możesz alternatywnie uzyskać tarcze rozszerzające SRAM od Lagrangian Point lub Rugged Circuits .
źródło
Kiedy prześlesz swój kod do Arduino, powiedz na przykład Uno, powie ci ile bajtów zużywa z dostępnych 32K. Tak dużo masz pamięci flash (pomyśl o dysku twardym komputera). Podczas gdy twój program działa, używa tak zwanej SRAM i jest go znacznie mniej.
Czasami zauważysz, że twój program zachowuje się dziwnie w miejscu, którego nawet nie dotykałeś od dłuższego czasu. Możliwe, że ostatnie zmiany spowodowały brak pamięci (SRAM). Oto kilka wskazówek, jak zwolnić część pamięci SRAM.
Przechowywanie ciągów we Flashu zamiast SRAM.
Jedną z najczęstszych rzeczy, które widziałem, jest brak pamięci w układzie, ponieważ jest za dużo długich łańcuchów.
Użyj tej
F()
funkcji, gdy używasz ciągów znaków, aby były one przechowywane we Flashu zamiast w pamięci SRAM, ponieważ masz ich znacznie więcej.Użyj odpowiednich typów danych
Możesz zapisać bajt, przełączając z
int
(2 bajty) nabyte
(1 bajt). Bez znaku bajt da ci 0-255, więc jeśli masz liczby, które nie przekraczają 255, zapisz bajt!Skąd mam wiedzieć, że kończy mi się pamięć?
Zwykle obserwujesz, jak twój program zachowuje się dziwnie i zastanawiasz się, co poszło nie tak ... Nie zmieniłeś niczego w kodzie w pobliżu punktu, w którym się psuje, więc co daje? Brakuje pamięci.
Istnieje kilka funkcji informujących o ilości dostępnej pamięci.
Dostępna pamięć
źródło
F()
jest to funkcja specyficzna dla Arduino, czy jest w bibliotekach AVR? MożeszPROGMEM const ...
również wspomnieć o tym .Oprócz tego, co powiedzieli inni (na co się całkowicie zgadzam), radziłbym przeczytać ten artykuł adafruitowy o pamięci; jest dobrze napisany, wyjaśnia wiele rzeczy na temat pamięci i dostarcza wskazówek, jak ją zoptymalizować.
Pod koniec czytania myślę, że uzyskałbyś dość kompletną odpowiedź na swoje pytanie.
Podsumowując, masz 2 możliwe cele optymalizacji (w zależności od tego, gdzie znajdują się problemy z pamięcią):
F()
makra)Opisano także dodatkowe podejście do zmniejszenia zużycia pamięci SRAM (ale rzadko stosowane, ponieważ jest nieco ciężkie podczas kodowania i niezbyt wydajne), polega na użyciu pamięci EEPROM do przechowywania danych zbudowanych przez program, ale nie jest używane później, gdy pewne warunki występują, gdy dane mogą zostać ponownie załadowane z EEPROM.
źródło
W przypadku braku miejsca na dysku są dwie rzeczy do zrobienia:
Istnieje wiele wskazówek online, jak zrobić to pierwsze (a dla zdecydowanej większości rzeczy, które ludzie robią z Arduino, wbudowana pamięć jest więcej niż wystarczająca po „optymalizacji”). Więc skupię się na drugim:
Istnieją 3 rzeczy, które zużywają flash lub SRAM; każdy potrzebuje nieco innego podejścia do dodawania pamięci:
zmienne przechowywanie: możliwe jest rozszerzenie SRAM, jak już wskazała sachleen. SRAM, FRAM i NVSRAM są odpowiednie dla szybko zmieniających się zmiennych. (Chociaż w zasadzie można użyć pamięci flash do przechowywania zmiennych, musisz jednak martwić się o zużycie lampy błyskowej). SPI (protokół szeregowy) jest najłatwiejszy do połączenia z Arduino. Biblioteka SpiRAM współpracuje z Microchip 23K256 szeregowym układzie SRAM. Układ szeregowy FRAM Ramtron FM25W256 (obecnie należący do Cypress) również korzysta z SPI. Cypress CY14B101 NVSRAM wykorzystuje również SPI. Itp.
ciągłe dane, które muszą znajdować się przy następnym włączeniu zasilania: jest to prawie tak proste, jak rozszerzenie SRAM. Istnieje wiele zewnętrznych urządzeń pamięci EEPROM, FRAM, NVSRAM i FLASH . Obecnie najniższy koszt w przeliczeniu na MB to karty flash SD (dostępne za pośrednictwem SPI). Ramtron FM25W256 (patrz wyżej), Cypress CY14B101 (patrz wyżej) itp. Mogą również przechowywać stałe dane. Wiele osłon rozszerzających zawiera gniazdo kart SD, a kilka bibliotek i samouczków obsługuje odczytywanie i zapisywanie na kartach (flash) SD. (Nie możemy do tego użyć SRAM, ponieważ SRAM zapomina o wszystkim, gdy kończy się zasilanie).
kod wykonywalny: Niestety, rozszerzenie pamięci Flash Arduino w celu zwiększenia przestrzeni programowej nie jest możliwe. Jednak programiści zawsze mogą refaktoryzować szkic, aby zmniejszyć rozmiar kodu kosztem zwiększenia rozmiaru danych i spowolnienia jego działania. (Teoretycznie można posunąć się do przetłumaczenia całego szkicu na jakiś interpretowany język, zapisać tę wersję szkicu na karcie SD, a następnie napisać tłumacza dla tego języka, który działa na Arduino, aby pobrać i wykonać instrukcje z Karta SD - dalej na Arduino , tłumacz BASIC, tłumacz Tom Napier Picaro, język specyficzny dla aplikacji itp.).
źródło