Display OLED SSD1306 e SSH1106 utilizzo memoria

Ciao a tutti,

ho provato a fare numerose ricerche ma non sono riuscito a dare una risposta ad una domanda che mi assilla da settimane.

Sto cercando di capire le differenze fra i drivers dei due display Oled SD1306 e SH1106 e rispettive librerie.
Quella per il display SSH1106 di fatto è una libreria Adafruit_SSD1306 modificata.

Vengo alla domanda: come mai lo stesso identico sketch occupa una cosiderevole quantità di ram in più in base al tipo di display?

In pratica ho due display, uno da 1,3 inch 128x64 che fuziona solo con la SH1106, e un altro da 0,96 inch bicolore 128x64 che funziona con tutte e due le librerie.

Qui sotto le quantità di memoria utilizzata caricando lo stesso sketch sullo stesso identico hardware:

  • Con la libreria Adafruit_SSD1306 e display da 0,96 inch
    Program memory used 27318 byte (85%)
    Dynamic memory used 534 (26%)

  • Con la libreria Adafruit_SH1106 e display da 0,96 inch
    Program memory used 26664 byte (83%)
    Dynamic memory used 1547 (76%)

In pratica la SH1106 a fronte di un -2% di memoria flash, occupa un sostanzioso +50% di ram, quasi la metà della ram di Arduino, cosa che ovviamente costringe a ridurre il numero di variabili globali utilizzabili.

Leggendo su vari forum mi è sembrato di capire che la SSD1306 alloca il buffer per il display al runtime mentre la SH1106 lo alloca all'atto della compilazione. Tuttavia non mi è ben chiara la differenza di ben 1013 byte fra le due.
Si tratta di una differenza dovuta proprio al diverso modo di allocazione della memoria delle due librerie?

Qualcuno riesce a dargli una spiegazione?
Grazie

Se la libreria alloca ram sufficente per TUTTO il display, che poi tu ne usi uno schermo o una riga poco importa ... la risoluzione e' maggiore, quindi piu pixel, quindi piu memoria allocata :wink:

Infatti non cambia la risoluzione, cambiano le dimensioni ma il numero di pixel è uguale.
Inoltre ho anche specificato: "stesso identico hardware".

Allora cambiera' la logica di funzionamento della libreria ... o del controller ... pensavo che avessi un display con risoluzione maggiore essendo piu grande ...

EDIT: no, ho dato un'occhiata al volo (ma solo al volo) ai due datasheet pensando che richiedessero diverse dimensioni di memoria, ma non sembra ... ok, il controller SH1106 gestisce 132x64, mentre SSD1306 e' 128x64, ma non sembra proprio che una differenza cosi piccola possa giustificare tutta quella RAM in piu ... quindi probabilmente dipende dalla libreria ... ma qui non saprei come ...

Con il SSD1306 puoi evitare di allocare in RAM un buffer e gestire, con un po' più di codice, tutto senza buffer, l'altro non lo conosco così bene, ma probabilmente usa un buffer in SRAM ... ::slight_smile:

Guglielmo

Un buffer che è lungo più o meno quanto la differenza di utilizzo riscontrata (1024 byte con display 128*64).

https://github.com/davidperrenoud/Adafruit_SH1106/

Trovato l'inghippo.

Come avevo letto in giro, le due librerie allocano il frame buffer in modo differente, ma ai fini della occupazione di ram sono equivalenti.

Flash su Arduino Uno:

SSD1306

Lo sketch usa 14930 byte (48%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 567 byte (27%) di memoria dinamica, lasciando altri 1481 byte liberi per le variabili locali. Il massimo è 2048 byte.
avrdude: writing flash (14930 bytes):

SH1106

Lo sketch usa 13142 byte (42%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 1584 byte (77%) di memoria dinamica, lasciando altri 464 byte liberi per le variabili locali. Il massimo è 2048 byte.
avrdude: writing flash (13142 bytes):

Se si esegue lo sketch che allego il risultato al runtime è quasi identico:

  • 464 byte liberi per la SH1106
  • 455 byte liberi per la SSD1306.

Il display da 0,96 pollici bicolore giallo/azzuro di cui dispongo funziona con tutte e due le librerie.
L'altro da 1,3 pollici invece funziona soltanto con la SH1106.

//************************************************************************
// This example investigate on amount of ram used by oled display device
// Monochrome OLEDs based on SSD1306 drivers
// Monochrome OLEDs based on SH1106 drivers
//************************************************************************

// Uncomment only one display type
#define DISPLAY_TYPE_SH1106
//#define DISPLAY_TYPE_SSD1306

#include <Wire.h>

#define OLED_RESET       -1   // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C

#ifdef DISPLAY_TYPE_SSD1306
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH    128
#define SCREEN_HEIGHT    64
#define POWERMODE      SSD1306_SWITCHCAPVCC
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
char DISPLAY_TYPE[] = "SD1306";
#endif

#ifdef DISPLAY_TYPE_SH1106
#include <Adafruit_SH1106.h>
#define POWERMODE      SH1106_SWITCHCAPVCC
Adafruit_SH1106 display(OLED_RESET);
char DISPLAY_TYPE[] = "SH1106";
#endif

#define SMALL 1
#define BIG   2
int ramBefore = 0;
int ramAfter = 0;

void setup() {
  display.clearDisplay();

  Serial.begin(9600);
  Serial.print(F("\n--------------------------------------\n"));
  Serial.print(F("Whit library: "));
  Serial.println(DISPLAY_TYPE);
  Serial.print(F("--------------------------------------\n"));
  ramBefore = getFreeRam() + 14;
  Serial.print(F("Free ram before display init:\t")); Serial.println(ramBefore);
  //------------------------------------------------------------
  // Display initialization
  //------------------------------------------------------------
  display.begin(POWERMODE, SCREEN_ADDRESS);
  //------------------------------------------------------------
  ramAfter = getFreeRam() + 14;
  Serial.print(F("Free ram after display init:\t")); Serial.println(ramAfter);
}

void loop() {

  char ram[10];
  delay(3000);
  display.clearDisplay();
  displayText(25, 1, DISPLAY_TYPE, WHITE, BLACK, BIG);
  displayText(15, 30, "FREE RAM", WHITE, BLACK, BIG);

  delay(3000);
  display.clearDisplay();
  displayText(25, 1, "BEFORE", WHITE, BLACK, BIG);
  displayText(38, 18, "INIT", WHITE, BLACK, BIG);
  itoa(ramBefore, ram, 10);
  displayText(5, 40, ram, WHITE, BLACK, BIG);
  displayText(60, 40, "bytes", WHITE, BLACK, BIG);

  delay(3000);
  display.clearDisplay();
  displayText(28, 1, "AFTER", WHITE, BLACK, BIG);
  displayText(38, 18, "INIT", WHITE, BLACK, BIG);
  itoa(ramAfter, ram, 10);
  displayText(10, 40, ram, WHITE, BLACK, BIG);
  displayText(60, 40, "bytes", WHITE, BLACK, BIG);
}


void displayText(byte x, byte y, const char *str, byte foreColor, byte backColor, byte textSize) {
  display.setTextSize(textSize);
  display.setTextColor(foreColor, backColor);
  display.setCursor(x, y);
  display.print(str);
  display.display();
}

int getFreeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval) ;
}

Nota: ho aggiunto 14 ai bytes restituiti dalla funzione getFreeRam() (trovata sul web) in quanto questa restituisce un valore inferiore di 14 byte rispetto a quanto indicato all'IDE.

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