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


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Zmniejszenie rozmiaru projektu
#1
Witam
Udało mi się uruchomić cyfrowy termometr z dwoma czujnikami DS18B20 i wyświetlaczem OLED.
Napotkałem jednak kolejny problem. Mianowicie kod zajmuje zbyt dużo miejsca w pamięci kontrolera. O ile na Arduino UNO nie ma problemów z pamięcią o tyle na Arduino Nano (Atmega 168) brakuje pamięci. Czy jest jakaś możliwość zmniejszenia rozmiaru kodu? Usunięcie zbędnych danych z wykorzystanych bibliotek? Chciałbym, aby jakoś udało się zmieścić ten program na Arduino NANO, ponieważ z założenia miało to wszystko zostać zamknięte w jak najmniejszej obudowie. Jeżeli jednak zajdzie taka potrzeba, będę zmuszony zakupić Arduino NANO z Atmegą 328. Jednak warto spróbować zmniejszyć kod i czegoś się przy okazji nauczyć Wink
W razie potrzeby zamieszczam kod:
Kod:
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DS18B20.h>
#define ONEWIRE_PIN 2
#define SENSORS_NUM 2
#define OLED_RESET LED_BUILTIN
const byte address[SENSORS_NUM][8] PROGMEM = {
 0x28, 0xB1, 0x6D, 0xA1, 0x3, 0x0, 0x0, 0x11, ///////adres czujnika 1
 0x28, 0x87, 0x6A, 0xA1, 0x3, 0x0, 0x0, 0x1F  ///////adres czujnika 2
};
OneWire onewire(ONEWIRE_PIN);
DS18B20 sensors(&onewire);
Adafruit_SSD1306 display(OLED_RESET);
const uint8_t logo [] PROGMEM = {
dane hex logo
};
const uint8_t ramka [] PROGMEM = {
dane hex ramki
};
void setup() {
 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
 display.clearDisplay();
 display.drawBitmap(0, 0, logo, 128, 64, 1);
 display.display();
 delay(5000);
 display.clearDisplay();
 sensors.begin();
 sensors.request();
 }
void loop() {
 if (sensors.available())
 {
   for (byte i=0; i<SENSORS_NUM; i++)
   {
     float temperature = sensors.readTemperature(FA(address[i]));
     display.drawBitmap(0, 0, ramka, 128, 64, 1);
     display.display();
     display.setTextColor(WHITE);
     display.setCursor(22,30);
     display.println(temperature);
     display.setTextColor(WHITE);
     display.setCursor(73,30);
     display.println(temperature);
}
   }

   sensors.request();
 }

Jedyne, co przychodzi mi do głowy, to możliwość usunięcia "logo" i przeniesienia go do biblioteki adafruit, chociaż wątpię, czy zmieni to rozmiar.
Za wszystkie pomocne odpowiedzi z góry dziękuję Smile
 
Odpowiedź
#2
Ta biblioteka do oleda buforuje cały ekran w RAM, a po zakończeniu ustawiania co ma być na ekranie wyrzuca cały ekran (bufor w RAM) na OLED. Niestety zajmuje to 1kb pamięci RAM. Nie użyjesz tego z prockiem, który ma tylko 1kb RAM (Atmega 168 lub 88).
Albo kup sobie NANO z 328, alb PRO MINI 328 (mniejsze zużycie prądu, potrzebna osobna przejściówka USB-UART do programowania) albo zastosuj inną bibliotekę, która wysyła ekran po kawałeczku. Jest tu wśród moich postów załączona ssd1306 ascii https://forum.arduinopolska.pl/watek-ard...ight=ascii , lub coś w ten deseń. Ewentualnie użyj oleda 128x32 jeśli wystarczy Ci 512b RAM na resztę i flash 16kb jest OK.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
(03-09-2018, 18:52)ArduinoNewbie napisał(a): Mianowicie kod zajmuje zbyt dużo miejsca w pamięci kontrolera.

W Arduinowskich bibliotekach dla wyświetlaczy graficznych, jest logo, które zajmuje niepotrzebne flash. Znajdź w bibliotece bufor ekranu, będzie zadeklarowany mniej więcej tak:
uint8_t static bufor_wyswietlacza[SZEROKOSC*WYSOKOSC/8] = { 0x ........ };
Wywal te { 0x ........ } i zyskasz trochę flash.
 
Odpowiedź
#4
Niestety, po usunięciu buforu z bibliotek nadal brakuje miejsca. 
Kod:
Szkic używa 16474 bajtów (114%) pamięci programu. Maksimum to 14336 bajtów.

Zmienne globalne używają 1564 bajtów (152%) pamięci dynamicznej, pozostawiając -540 bajtów dla zmiennych lokalnych. Maksimum to 1024 bajtów.
Wygląda na to, że muszę kupić NANO V3 z Atmegą 328
 
Odpowiedź
#5
(04-09-2018, 06:23)ArduinoNewbie napisał(a): Niestety, po usunięciu buforu z bibliotek nadal brakuje miejsca. 
Kod:
Szkic używa 16474 bajtów (114%) pamięci programu. Maksimum to 14336 bajtów.

Zmienne globalne używają 1564 bajtów (152%) pamięci dynamicznej, pozostawiając -540 bajtów dla zmiennych lokalnych. Maksimum to 1024 bajtów.

Te 14% łatwo byłoby zyskać ale 152 już nie, bo kosztem skomplikowania programu czyli pamięci flash.
Praktyka nauczyła mnie, aby program wykorzystywał mniej niż 50% zasobów pamięci programu i danych. Jeśli pierwsza wersja zajmuje więcej niż 60% to bardzo prawdopodobne, że finalna zajmie prawie całą lub jej zabraknie.

Sens walki o zyskanie 10 czy 20% była 20 lat temu gdy nie było większej wersji (np ponad 64kB 8051, czy ponad 8, później 12 8051 z EEPROM).

Twój program zmieści się w 32kB flash i 2kB RAM ale zajęte będzie 75% RAM. Praktyka wykazuje (dla ram do 2kB), że RAM można zając w  70..80% bo gdzieś musi mieścić się stos i sterta. Jesteś na granicy. Ponadto używasz wyświetlacza graficznego, a grafika swoje zajmuje. Mając tylko 32kb może okazać się, że w przyszłości nie dodasz kolejnych obrazków. W razie czego nie wymienisz uC z Mega328 na Mega648 bo puki co taki nie istnieje.
Dlatego do projektu użyłbym uC z min 64kB Flash i min 4kB RAM. W praktyce, tego typu projekty realizowałem na:
Mega664(64kB/4kB), Mega1284 (128kB/20kB), STM32F103C8T6 (64kB/20kB), STM32F103RBxx (128kB/20kB) i jeśli nie chcesz, za jakiś czas walczyć o każdy bajt, użyj coś większego niż Mega328. Pamiętaj też, że jedną z największych wad AVR jest mała ilość RAM. Sensowna praca z nim jest możliwa gdy masz 8 lub więcej RAM, czyli na Mega1284, Mega1281, M1280, M2561, M2560.
 
Odpowiedź
#6
Tak z ciekawości.
Co to jest: dane hex logo, oraz dane hex ramki? Dla czego nie ma ich definicji?
I w jaki sposób ten kod w ogóle się kompiluje?
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#7
Jak przy okazji chcesz się czegoś nauczyć to zerknij do biblioteki ASCII. Bez wodotrysków monitor "pieczarek garażowych" chodzi sobie na Atmega88.

Jeśli walczysz o miejsce w kodzie to używając już I2C do Oleda można poszukać również czujników na I2C, żeby nie dodawać kodu do kolejnej magistrali danych.

Załączony kod się nie kompilował, po usunięciu tych definicji z progmem oraz reszty z nimi związanej i tak nie zmniejszy się odpowiednio ilość zajętego RAM, bo biblioteka OLED od AdaFruit od razu zjada 1kb+, >100%. Ta biblioteka nie nadaje się do niczego poniżej 2kb RAM. Z połówką ekranu można powalczyć.

Oledem można się bawić już na Attiny: https://www.instructables.com/id/ATTiny8...at-Things/ , bouncing ball mieści się do attiny25. Jeśli np. faktycznie potrzebujesz coś co zajmuje mało miejsca...
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#8
Projekt mieści się na Atmedze 328 (na Arduino UNO, lecz jest ono za duże do tego projektu). Raczej nie będę nic więcej modyfikował w tym projekcie, więc Atemga 328 powinna wystarczyć. Dzięki za wszystkie odpowiedzi Smile
 
Odpowiedź
#9
(04-09-2018, 16:48)ArduinoNewbie napisał(a): Projekt mieści się na Atmedze 328
W pamięci programu tak bo nie widzę obsługi błędów. Zewrzyj 1-Wire do masy, jaki jest rezultat? To samo z I2C, co się dzieje? Odłącz termometry, jaka temperatura się wyświetla? Czy nie powinien to być komunikat o braku czujnika a nie kosmiczna temperatura?
Czy nie uważasz, ze dobrze napisany program powinien reagować na błędy? Czy nie powinien mieć włączonego watchdoga? Czy nie powinien, jeśli jest taka możliwość, wysyłać informacji diagnostycznych na np USART (przykładowo o resecie uC i przyczynie resetu, o wykryciu bądź nie wyświetlacza). Czy zamiast delay 5 sekund uC nie powinien być usypiany aby pobierać mniej energii i generować mniejsze zakłócenia EMI?

Już na początku kodu masz wpadkę:
Kod:
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
Nie sprawdzasz czy wyświetlacz został wykryty tylko zaraz po inicjalizacji
Kod:
display.clearDisplay();
display.drawBitmap(0, 0, logo, 128, 64, 1);
display.display();
Dlaczego zakładasz, że wyświetlacz NA PEWNO JEST podłączony? W czasie działania programu także powinieneś to sprawdzać i w razie czego sygnalizować błędy.
Zrób tez mały eksperyment, odłącz rezystory podciągające I2C. Jak zachowa się program? Na 99% zawiśnie. Czy tak powinno być?
nie pamiętam czy SSD1306 może zablokować w pewnych sytuacjach I2C ale NA PEWNO, nie masz mechanizmu, który w takiej sytuacji "ożywia" magistralę. Program zawiśnie i reset nie pomoże (przynajmniej nie jeden), trzeba będzie odłączyć zasilanie jak w Windows. Chcesz robić konkurencję firmie Micro$oft?

Jestem przekonany, że gdy napiszesz ten program "po bożemu" to zacznie brakować pamięci programu.
Jestem także przekonany, że w kilka sekund potrafię program w postaci w jakiej teraz jest doprowadzić do nieprzewidywalnego zachowania (nieprawdziwe temperatury, zawieszanie).


Sprawdź też ile tak naprawdę masz wolnej pamięci RAM.


PS
Gdyby to była praca końcowa w technikum, to za taki program, ocena dopuszczająca z dwoma minusami. A wystarczy poświęcić jeden czy dwa dni aby było 4..5.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości