Datasect overschrijdt beschikbare ruimte op bord

Dit topic is gesloten

Ik ben onlangs een klein spel aan het maken en ik wil Arduino uno gebruiken om het te doen. Mijn code compileert zonder problemen, maar als ik hem upload krijg ik een fout zoals op de foto, komt het omdat ik te veel variabelen gedefinieerd heb?
Kan iemand mij vertellen hoe ik dit kan oplossen?

c code:

Arduino:1.8.12 (Windows 10), Development board: "Arduino Uno"

The project uses 6336 bytes, which occupies (19%) of the program storage space. The maximum is 32256 bytes. data section exceeds available space in board

Global variables used 3046 bytes, (148%) of dynamic memory, leaving -998 bytes for local variables. The maximum is 2048 bytes.
There is not enough memory; visit the following URL to follow the instructions to reduce memory usage.
http://www.arduino.cc/en/Guide/Troubleshooting#size
Error while compiling for development board Arduino Uno.

Turn on in File -> Preferences
"Show detailed output during compilation" option
This report will contain more information.

Meer info zou handig zijn, maar dit is duidelijk

c code:

Global variables used 3046 bytes, (148%) of dynamic memory, leaving -998 bytes for local variables. The maximum is 2048 bytes.
There is not enough memory

Je zal het aantal variabelen moeten verminderen. Of dat mogelijk is hangt af van je programma.

Damn the torpedoes, full speed ahead!

Je atmega328 CPU heeft 2k aan RAM aan boord. Jij hebt kennelijk "grote datastructuren" gedeclareerd die samen ongeveer 3k aan RAM gebruiken. Dat past niet.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

je hebt inderdaad te weinig RAM.
Of eerder denk ik dat je teveel RAM onnodig declareert.

als je geen bezwaar hebt om je code te delen kunnen we je hier wel mee op weg helpen.

Dat kun je waarschijnlijk oplossen door tekst strings te verhuizen naar Flash.

Dus ipv

code:


   serial.println("Text uit SRAM");

kun je dit doen:

code:


   serial.println(F("Text uit Flash"));

Door de tekst tussen een F() te zetten verhuist die naar flash geheugen.

Dat werkt voor alle functies die afgeleid zijn van 'printable', dat zijn de meeste functies die teksten printen en naar displays sturen.

[Bericht gewijzigd door deKees op 24 september 2021 11:31:34 (19%)

Arco

Special Member

Voorgeprogrammeerde tekst zit altijd al in flash. (hoe wou je die anders bewaren bij stroomuitval?)
Je kunt meer locale variabelen toepassen, die komen na gebruik weer vrij...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Wat ook kan helpen voor de arduino-programmeurs is het gebruik van '#define' ipv alle constanten in een variabele te steken. Dat laatste is om een of andere rede vrij gangbaar binnen de arduino-community en heb ik ook moeten afleren. :)

Als voorbeeld ergens van het www geplukt:

c code:


/***********************************************************
File name:   01_blinkingLed.ino
Description: LED blinks ON and OFF.
Website: www.quadstore.in
***********************************************************/
int ledPin=8; //definition digital 8 pins as pin to control the LED
void setup()
{
    pinMode(ledPin,OUTPUT);    //Set the digital 8 port mode, OUTPUT: Output mode
}
void loop()
{  
    digitalWrite(ledPin,HIGH); //HIGH is set to about 5V PIN8
    delay(1000);               //Set the delay time, 1000 = 1S
    digitalWrite(ledPin,LOW);  //LOW is set to about 5V PIN8
    delay(1000);               //Set the delay time, 1000 = 1S
} 

Heb ik leren herschrijven als:

c code:


/***********************************************************
File name:   01_blinkingLed.ino
Description: LED blinks ON and OFF.
Website: www.quadstore.in
***********************************************************/
#define ledPin 8 //definition digital 8 pins as pin to control the LED
void setup()
{
    pinMode(ledPin,OUTPUT);    //Set the digital 8 port mode, OUTPUT: Output mode
}
void loop()
{  
    digitalWrite(ledPin,HIGH); //HIGH is set to about 5V PIN8
    delay(1000);               //Set the delay time, 1000 = 1S
    digitalWrite(ledPin,LOW);  //LOW is set to about 5V PIN8
    delay(1000);               //Set the delay time, 1000 = 1S
} 

Zie de regel boven 'void setup()' in beide stukjes code

[Bericht gewijzigd door Shock6805 op 24 september 2021 12:05:07 (78%)

Als je maar genoeg geinteresseerd ben, verwondert heel de wereld.
Arco

Special Member

Vaste waardes definieer je toch altijd al als constante? (dus die komt sowieso in flash terecht)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
eSe

Honourable Member

Voorgeprogrammeerde tekst zit altijd al in flash. (hoe wou je die anders bewaren bij stroomuitval?)

Yep, maar... bij het opstarten word de "voorgeprogrammeerde text" en "constanten" (uit het 1ste voorbeeld van Shock6805) die gedeclareerd worden in ram overgeschreven. Als je de strings en dergelijke gebruikt zoals deKees voorstelt (en #define's) word er niets naar ram geschreven en worden deze constanten direct uit flash gelezen.

Groetjes,
eSe

CChheecckk yyoouurr dduupplleexx sswwiittcchh..

Arco,

Wat bedoel je juist? Binnen de arduino-community is het heel gewoon om bv.

c code:

double pi = 3.14159265;

te doen i.p.v.

c code:

#define pi 3.14159265

ik heb mij laten vertellen dat in het eerste geval de constante (die je voor de leesbaarheid een naam wilt geven) in het ram terecht komt, terwijl in het tweede geval de compiler alle instanties van 'pi' vervangt door '3.14159265'. Op die manier wordt daar geen ram aan vervuild. Optie twee is 'zoals het hoort' en ook wat jij volgens mij bedoelt. Optie 1 komt verrassend vaak voor in arduino sketches.

Of het moet zijn dat die arduino compiler slim genoeg is om optie 1 zelf om te zetten naar optie 2. Dan geldt mijn opmerking niet natuurlijk.

Als je maar genoeg geinteresseerd ben, verwondert heel de wereld.

Vaste waardes definieer je toch altijd al als constante? (dus die komt sowieso in flash terecht)

Nee, zo werkt dat niet.

Bijv

code:


   const char MyString[12] = "Test";

Dan wordt er een string van 12 bytes aangemaakt in Sram, en de tekst wordt tijdens opstarten vanuit Flash naar Sram gecopieerd.

En dat gebeurt ook bij

code:


   serial.print("Tekst");

Want de benodigde code is anders voor tekst uit SRAM en voor tekst uit Flash. De serial.print("Tekst") funktie kan alleen SRAM tekst printen.

De serial.print(F("text")); is een andere funktie die tekst uit Flash print.

PS.
Bovenstaande geldt alleen voor AVR 8-bit processors (zoals de meeste arduino's) en is een gevolg van de aparte adres ruimtes voor SRAM en flash. (Wat mij betreft een dikke blunder in het ontwerp van de AVR instruktie-set die al veel ellende heeft veroorzaakt).

@shock6805

De moderne compilers zijn vaak veel slimmer dan de gemiddelde programmeur (wel afhankelijk van instellingen). Er wordt niks verspild en code wordt geoptimaliseerd. Ongebruikte code wordt niet gecompileerd en gebruikt dus ook geen ruimte.

Dus #define levert geen ruimte-winst op en heeft alleen nog maar nadelen, afgezien van een paar heel speciale gevallen.

Arco

Special Member

De intelligentie van compilers is soms ook wel ergerlijk:

Als ik een constante definieer in flash op een vaste locatie, dan stript de compiler die er altijd uit indien niet gebruikt...:(
(zelfs met optimization leven 0. Compiler sloopt gewoon alles wat niet gebruikt is eruit...)

Ben dan verplicht om een dummy read te doen zodat de compiler denkt dat de constante gebruikt wordt...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Aha, dat is goed om te weten. Ik begrijp wel dat je dan expliciet 'const double pi = 3.14159265' moet gebruiken en niet gewoon 'double pi = 3.14159265'? Of maakt ook dat weinig meer uit? Wat zijn dan de nadelen van #define waardoor die minder gewenst is?

@Arco

Nu ben ik wel nieuwsgierig waarom je een constante in je flash zo willen hebben die niet gebruikt wordt?

Als je maar genoeg geinteresseerd ben, verwondert heel de wereld.
Arco

Special Member

Voor een bootloader. Dan kan het door de bootloader geladen programma het versienummer van de bootloader uitlezen...
(wordt dus eigenlijk alleen door een ander programma gebruikt... ;) )

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Nadeel van een #define is dat die geprocessed wordt door de pre-compiler. Overal waar 'pi' staat wordt dat vervangen door '3.141592654'.

De echte compiler krijgt de #define nooit te zien, en ook de 'pi' niet. Die ziet alleen het getal. Het grootste probleem daarbij is dat de type-controle van de compiler buitenspel wordt gezet. Dat gaat vaak wel goed, maar niet altijd.

Op 24 september 2021 13:57:30 schreef Shock6805:
Aha, dat is goed om te weten. Ik begrijp wel dat je dan expliciet 'const double pi = 3.14159265' moet gebruiken en niet gewoon 'double pi = 3.14159265'?

Als je "const" er bij zet, dan weet de compiler dat die nooit meer verandert. Dus op processoren waarbij dat kan (STM32 / ARM bijvoorbeeld) komt die constante dan gewoon in flash te staan en wordt niet naar RAM gecopieerd. Bij "double pi = 3.14159265;" wordt de variabele (samen met alle andere geinitializeerde variabelen) uit een stuk flash naar RAM gecopieerd.

Dus zet het er nu vast bij. Programmeer je vandaag nog op AVR: Helaas, daar maakt het niet uit.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Op 24 september 2021 11:27:53 schreef deKees:
Dat kun je waarschijnlijk oplossen door tekst strings te verhuizen naar Flash.

Dus ipv

code:


   serial.println("Text uit SRAM");

kun je dit doen:

code:


   serial.println(F("Text uit Flash"));

Deze methode is geweldig en het werkte.

Bedankt voor jullie antwoorden, ik heb het probleem opgelost met F(). Het probleem ontstaat doordat mijn LCD zijn eigen instructieset heeft, een erg lange dus die neemt te veel geheugen in beslag.

Hier is een deel van de code nadat ik het gewijzigd heb.

c code:

Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image2\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image3\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image4\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image5\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image6\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image7\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image8\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image9\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image10\",\"image\":\"bai\"}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif4\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif5\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif6\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif7\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif8\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif9\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif10\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif11\",\"visible\":false}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button9\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button8\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button7\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button6\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button5\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button4\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button3\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button2\",\"enable\":true}>ET"));
            Serial.println(F("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button1\",\"enable\":true}>ET"));
PE9SMS

Special Member

Daar staat een heleboel keer dezelfde data. Dat kun je slimmer doen om zo veel geheugen te besparen.

This signature is intentionally left blank.

Dit topic is gesloten