Vettore bidimensionale vs OLED SH1106

salve a tutti.
C'è una cosa che non riesco a spiegarmi.
In un mio progetto avevo dei malfunzionamenti random, ogni tanto, subito dopo il loader il sistema andava in crash.
A forza di semplificazioni/eliminazione parti di codice, ho scoperto che:

  • se nel progetto includo la libreria Adafruit_SH1106G
  • ci sono due for ( ; ; ), uno per valorizzare gli elementi e l'altro per visualizzarne il contenuto
  • se si superano i 31 come elementi nel vettore
  • il sistema si blocca.

Senza la libreria Adafruit_SH1106G va sempre bene, ho provato fino a 200 elementi.

Un altro modo per farlo funzionare è quello di fare un unico for( ; ; ) per valorizzare e visualizzare.

Uso un Arduino UNO R3, ho provato con IDE 1.8 ed anche 2.0, stessi risultati.
Allego il progetto ridotto ai minimi termini:

//#define __PRINT    oled.print
#define __PRINT     Serial.println
// #define __PRINT    ;

#define __OLED

//----per display OLED SH1106/SSD1306------------------------------------------------
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#define i2c_Address 0x3c
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

#ifdef __OLED
Adafruit_SH1106G oled = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#endif
//----fine display OLED SH1106/SSD1306--------------------------------------------------

#define MAX_BLK 150                                // ???????????????????????????????
#define N_PAR   8
unsigned char  sBlocco_AUT[MAX_BLK][N_PAR] = {0};


/////////////////////////////////////////////////////////////////////////////////////
// 
/////////////////////////////////////////////////////////////////////////////////////
void setup() 
{
char  sApp[20];
unsigned int i;
	Serial.begin(115200);
	pinMode(LED_BUILTIN, OUTPUT);

	InitOLED();

  for (i=0; i<(MAX_BLK); i++)
  {
    sBlocco_AUT[i][0] = i;                          // ????????????
  }
  for (i=0; i<(MAX_BLK); i++)
  {
//    sBlocco_AUT[i][0] = i;                        // ????????????
    sprintf(sApp, "%06d ", sBlocco_AUT[i][0]);
    __PRINT(sApp);
  }
#ifdef __OLED
  oled.display();
#endif
} 



///////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////
void loop() 
{
  delay(100);
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}




///////////////////////////////////////////////////////////////////
// inizializza display OLED SH1106
///////////////////////////////////////////////////////////////////
void  InitOLED(void)
{
#ifdef __OLED
	delay(250);                             // wait for the OLED to power up
	if(!oled.begin(i2c_Address, true)) 
	{
		Serial.print(F("SH1106 allocation failed") );
		for(;;)
      ;
	}
  oled.display();
  delay(2000);
  oled.clearDisplay();
  oled.setTextSize(1);
  oled.setCursor(0, 10);
  oled.setTextColor(SH110X_WHITE);
  oled.display();
#endif
}

Nel codice ho evidenziato con // ?????? i punti "critici".
Se qualcuno ha tempo/voglia di verificare ....

Ho notato anche che il compilatore si comporta in modo differente a seconda che nel codice ci siano uno o due for( ; ; ):
- **con unico for()** lo spazio occupato dalle variabili globali è sempre di **600bytes** anche se è presente un solo elemento (?).
- **con due for()**  lo spazio occupato varia a seconda del numero degli elementi presenti nel vettore (ovviamente).

grazie

Ma sei sicuro che includendo la lib e mettendo 150 elementi non vai fuori dalla memoria SRAM disponibile ?
La cosa dei due for o uno unico mi pare molto strana.

no no,
non si va fuori lo tengo d'occhio:

  • con un solo for ( ; ; ) sono sempre 600bytes di RAM occupati
  • con due for( ; ; ) sono 1800bytes di RAM occupati (87%)
    Oltretutto anche perché il compilatore non lo permette, non termina la compilazione con una diagnostica in chiaro sul superamento dei limiti

... che è TROPPO ... il compilatore tiene conto solo della memoria allocata staticamente, ma NON sa nulla di quella che viene allocata dinamicamente (es. le variabili locali che finiscono nello stack).

Su Arduino UNO, che ha solo 2KB di SRAM ... 1800 bytes di memoria statica sono l'anticamera di possibili problemi e crash di sistema ... :roll_eyes:

Guglielmo

grazie Guglielmo, l'ho imparato a mie spese :sweat_smile:
In realtà 150 l'avevo messo per trovare un limite.
Già con 50 elementi nel vettore ( e 50% di SRAM occupati) il problema si presenta.
E comunque l'unica allocazione dinamica credo che sia quella del .begin() per OLED.

ciao nid69ita.
In questi giorni ho fatto un pò di ricerche/prove.
Ho utilizzato sempre uno sketch con un vettore di 50 elementi (50*8=400bytes).
Ho utilizzato due tools AVR:
avr-size.exe e avr-readelf.exe.

AVR-SIZE.EXE produce questo:

  • con OLED e 2 for(..): text=14612 data=170 bss=828 (data+bss=998 confermati dal compilatore)
  • con OLED e 1 for (...): text=14568 data=170 bss=428 (data+bss=598 confermati dal copilatore)

AVR-READELF che visualizza i dati contenuti nel file .elf: ci sono delle differenze nei 2 files prodotti nei due casi (2 for(..) e 1 for(..) ).
Infatti ci sono rispettivamente 248entry nell'uno e 249 nell'altro.
Per me è difficile/impossibile interpretare profondamente il contenuto dei 2 files ottenuti.
Utilizzando WinMerge, la cosa che si vede subito è che nella "Symbol table" (.symtab) generata dal sorgente con 1 for(...) (e funzionante) NON c'è il vettore sBlocco_AUT.
Al contrario, nella .symtab generata dal file con 2 for(...) e non funzionante, c'è mappato il vettore sBlocco_AUT.
Non saprei come interpretarlo.
Se ti può essere d'aiuto ho i due .elf generati ed anche i due files esportati, relativi al loro contenuto.
Non è che cortesemente potresti eseguire una prova pratica?
Serve solo un Arduino UNO R3 e quelle poche righe di codice che ho già postato.
A volte mi passa anche per la testa che possa essere un problema HW (SRAM / FLASH) ma purtroppo in questo momento ho un solo Arduino UNO, non posso fare la controprova.

Che tu sappia, esistono dei FW/SKETCH per eseguire un check dell'hw di una scheda?
Nel forum non li ho trovati e neppure in rete.
grazie
claudio

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.