Help to get ss_oled library to display bitmap

I am working on a project that uses two 128x64 OLEDs. I am using the multi-OLED library from Larry Bank. I have the work done for the first OLED at address 0x3C. I must display a static bitmap on the second OLED at address 0x3D. When looking into the library examples there is an animation and a graphic where lines and other shapes are drawn, but for ease of updating, I want to use a single bitmap.

What I am looking for is help to understand what I need to change in this block to display the image. "rc = oledInit(&ssoled[1], MY_OLED2, 0x3D, FLIP180, INVERT, 1, SDA_PIN, SCL_PIN, RESET_PIN, 400000L); // Display 2 initialize
if (rc != OLED_NOT_FOUND)
{
//fill display 2
oledFill(&ssoled[1], 0, 1);
oledSetTextWrap(&ssoled[1], 1);
oledWriteString(&ssoled[1], 0,9,1,(char *)"Display 2", FONT_NORMAL, 0, 1);

}"

this is the loop that displays the bitmap, I am at a loss as to how to integrate it into the ss_oled display statement.

" // picture loop
u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
"

//
// Small Simple OLED library multi-display demo
// By Larry Bank
// Mod by Zef D
// Started on 12.15.2023
//
#include <ss_oled.h>
#include <AHTxx.h>
#include "U8glib.h"

#define SDA_PIN A4
#define SCL_PIN A5
// Set this to -1 to disable or the GPIO pin number connected to the reset
// line of your display if it requires an external reset
#define RESET_PIN -1
// don't rotate the display
#define FLIP180 0
// don't invert the display
#define INVERT 0
// OLED1 address 0x3C
#define MY_OLED1 OLED_128x64
//OLED2 address 0x3D
#define MY_OLED2 OLED_128x64
// AHT21 address 0x38

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);  // Display which does not send ACK

float ahtValue1;    //to store Temp result
float ahtValue2;   //to store humidity result

AHTxx aht20(AHTXX_ADDRESS_X38, AHT2x_SENSOR); //sensor address, sensor type
  byte celsius = 26;
  byte fahrenheit = (celsius * 9) / 5 + 32;
  byte humidity =  ahtValue2;

// 2 copies of the SSOLED structure. Each structure is about 56 bytes
SSOLED ssoled[2];

#define tracking_width 128
#define tracking_height 64


static unsigned char tracking_bits[] U8G_PROGMEM = {
   
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x10, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x80,
   0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80,
   0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x08, 0x00, 0x00, 0x20, 0x00, 0xff, 0x7f, 0x00, 0x02, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0xff, 0x81,
   0xc0, 0x7f, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
   0x00, 0xe0, 0x01, 0x80, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00,
   0x00, 0x00, 0x40, 0x00, 0x00, 0x5c, 0x00, 0x80, 0x00, 0x00, 0x1d, 0x00,
   0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x83, 0x00, 0x80,
   0x00, 0x80, 0xe0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
   0x70, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x07, 0x40, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x02, 0x18, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x0c,
   0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x01, 0x80,
   0x00, 0x40, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88,
   0x00, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, 0x60, 0x00, 0x00,
   0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x02, 0x80,
   0x00, 0x20, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
   0x00, 0x00, 0x06, 0x80, 0x00, 0x30, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x04, 0x80, 0x00, 0x10, 0x00, 0x80,
   0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x01, 0x00, 0x04, 0x80,
   0x00, 0x10, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
   0x02, 0x00, 0x08, 0x80, 0x00, 0x08, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00,
   0x00, 0x00, 0x70, 0x00, 0x04, 0x00, 0x08, 0x80, 0x00, 0x08, 0x00, 0x10,
   0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x80,
   0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
   0x10, 0x00, 0x10, 0x80, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00,
   0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x10, 0x80, 0x00, 0x04, 0x00, 0x02,
   0x00, 0x10, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00, 0x40, 0x00, 0x30, 0x80,
   0x00, 0x06, 0x00, 0x01, 0x00, 0x20, 0xc0, 0x00, 0x00, 0x06, 0x01, 0x00,
   0x80, 0x00, 0x20, 0x80, 0x00, 0x02, 0x80, 0x00, 0x00, 0x40, 0x30, 0x00,
   0x00, 0x98, 0x01, 0x00, 0x00, 0x01, 0x40, 0x80, 0x00, 0x01, 0x40, 0x00,
   0x00, 0xc0, 0x0c, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x40, 0x80,
   0x00, 0x01, 0x20, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00,
   0x00, 0x04, 0x40, 0x80, 0x00, 0x01, 0x10, 0x00, 0x00, 0xf0, 0x01, 0x00,
   0x00, 0x20, 0x0c, 0x00, 0x00, 0x08, 0x80, 0x80, 0x80, 0x00, 0x08, 0x00,
   0x00, 0x18, 0x02, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x10, 0x80, 0x81,
   0xc0, 0x00, 0x04, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x10, 0xc0, 0x00,
   0x00, 0x20, 0x00, 0x81, 0x40, 0x00, 0x02, 0x00, 0x80, 0x01, 0x04, 0x00,
   0x00, 0x08, 0x00, 0x07, 0x00, 0x40, 0x00, 0x81, 0x40, 0x00, 0x01, 0x00,
   0x70, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x80, 0x00, 0x81,
   0x40, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x70,
   0x00, 0x00, 0x01, 0x83, 0x60, 0x40, 0x00, 0x00, 0x07, 0x00, 0x10, 0x00,
   0x00, 0x04, 0x00, 0x80, 0x01, 0x00, 0x02, 0x82, 0x20, 0x20, 0x00, 0xc0,
   0x00, 0x00, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x04, 0x84,
   0x10, 0x10, 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x02, 0x00, 0x00,
   0x38, 0x00, 0x08, 0x84, 0x10, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x20, 0x00,
   0x00, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x10, 0x84, 0x10, 0x04, 0xc0, 0x01,
   0x00, 0x00, 0x60, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x20, 0x88,
   0x08, 0x02, 0x60, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00,
   0x00, 0x1c, 0x40, 0x98, 0x0c, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x40, 0x00,
   0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x80, 0x90, 0x84, 0x00, 0x07, 0x00,
   0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x91,
   0x44, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00,
   0x00, 0x00, 0x06, 0xa2, 0x22, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
   0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xa4, 0x12, 0x1c, 0x00, 0x00,
   0x00, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xa8,
   0x8a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0xd3, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
   0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x1b, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
   0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xfc, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
   0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
   0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00 };



void draw(void) {
  // graphic commands to redraw the complete screen should be placed here 
  u8g.drawXBMP( 0, 0, tracking_width, tracking_height, tracking_bits); 
  
}

void setup() {

int rc;
// The I2C SDA/SCL pins set to -1 means to use the default Wire library
// If pins were specified, they would be bit-banged in software
//
// oledInit(SSOLED *, type, oled_addr, rotate180, invert, bWire, SDA_PIN, SCL_PIN, RESET_PIN, speed)

rc = oledInit(&ssoled[0], MY_OLED1, 0x3C, FLIP180, INVERT, 1, SDA_PIN, SCL_PIN, RESET_PIN, 400000L); // Display 1 initialize
  if (rc != OLED_NOT_FOUND)

rc = oledInit(&ssoled[1], MY_OLED2, 0x3D, FLIP180, INVERT, 1, SDA_PIN, SCL_PIN, RESET_PIN, 400000L); // Display 2 initialize
  if (rc != OLED_NOT_FOUND)
  {
    //fill display 2
    oledFill(&ssoled[1], 0, 1);
    oledSetTextWrap(&ssoled[1], 1);
    oledWriteString(&ssoled[1], 0,9,1,(char *)"Display 2", FONT_NORMAL, 0, 1);

  }

  Serial.begin(9600);  // start serial monitor data

  Serial.println(); // print space
  
  while (aht20.begin() != true)
  {
    Serial.println(F("AHT2x not connected or fail to load calibration coefficient")); //(F()) save string to flash & keeps dynamic memory free

    delay(5000);
  }

  //Serial.println(F("AHT20 OK"));

  //Wire.setClock(400000); //experimental I2C speed! 400KHz, default 100KHz  
  //oledSetBackBuffer(&ssoled, ucBackBuffer);  
} /* setup() */

void loop() {

 // u8g.firstPage();  
  //do {
  //  draw();
 // } while( u8g.nextPage() );

 ahtValue1 = aht20.readTemperature(); //read 6-bytes via I2C, takes 80 milliseconds 
 humidity = aht20.readHumidity(AHTXX_USE_READ_DATA); //use 6-bytes from temperature reading, takes zero milliseconds!!!  
  {
    char szString1[16];
    char szString2[16];
    sprintf(szString1,"%d", fahrenheit);
    sprintf(szString2,"%d", humidity);
    
    // Line one
    oledFill(&ssoled[0], 0, 1);
    oledWriteString(&ssoled[0], 0,0,0,(char *)" Out: ", FONT_NORMAL, 0, 1);
    oledWriteString(&ssoled[0], 0,50,0,(szString1), FONT_NORMAL, 0,1);
    oledWriteString(&ssoled[0], 0,66,0,(char *)"F", FONT_NORMAL, 0, 1);
    oledWriteString(&ssoled[0], 0,90,0,(szString2), FONT_NORMAL, 0,1);
    oledWriteString(&ssoled[0], 0,105,0,(char *)"%", FONT_NORMAL, 0, 1);

    // Line two
    //oledFill(&ssoled[0], 0, 1);
    oledWriteString(&ssoled[0], 0,0,2,(char *)"Helm: ", FONT_NORMAL, 0, 1);
    oledWriteString(&ssoled[0], 0,50,2,(char *)"25F", FONT_NORMAL, 0, 1);
    oledWriteString(&ssoled[0], 0,90,2,(char *)"70%", FONT_NORMAL, 0, 1);
    //oledWriteString(&ssoled[0], 0,0,4, szString, FONT_NORMAL, 0,1);

    // Line three
    //oledFill(&ssoled[0], 0, 1);
    oledWriteString(&ssoled[0], 0,0,4,(char *)"Cool: ", FONT_NORMAL, 0, 1);
    oledWriteString(&ssoled[0], 0,50,4,(char *)"ON/Off", FONT_NORMAL, 0, 1);
    //oledWriteString(&ssoled[0], 0,0,4, szString, FONT_NORMAL, 0,1);

    // Line four
    //oledFill(&ssoled[0], 0, 1);
    oledWriteString(&ssoled[0], 0,0,6,(char *)"Fan: ", FONT_NORMAL, 0, 1);
    oledWriteString(&ssoled[0], 0,50,6,(char *)"100%", FONT_NORMAL, 0, 1);
    //oledWriteString(&ssoled[0], 0,0,4, szString, FONT_NORMAL, 0,1);
 
  }
  Serial.print(F("Temperature: "));
  
  if (ahtValue1 != AHTXX_ERROR) //AHTXX_ERROR = 255, library returns 255 if error occurs
  {
    
    Serial.print(fahrenheit);
    Serial.println(F("F"));
    Serial.print(ahtValue1);
    Serial.println(F("C"));

  }
  else
  {
    printStatus(); //print temperature command status
  }
   //humidity = aht20.readHumidity(AHTXX_USE_READ_DATA); //use 6-bytes from temperature reading, takes zero milliseconds!!!
  Serial.print(F("Humidity...: "));
  
  if (ahtValue2 != AHTXX_ERROR) //AHTXX_ERROR = 255, library returns 255 if error occurs
  {
    Serial.print(humidity);
    Serial.println(F("%"));
    Serial.println();
  }
  else
  {
    printStatus(); //print temperature command status not humidity!!! RH measurement use same 6-bytes from T measurement
  }

  delay(5000); //recomended polling frequency 8sec..30sec



} /* loop() */

void printStatus()
{
  switch (aht20.getStatus())
  {
    case AHTXX_NO_ERROR:
      Serial.println(F("no error"));
      break;

    case AHTXX_BUSY_ERROR:
      Serial.println(F("sensor busy, increase polling time"));
      break;

    case AHTXX_ACK_ERROR:
      Serial.println(F("sensor didn't return ACK, not connected, broken, long wires (reduce speed), bus locked by slave (increase stretch limit)"));
      break;

    case AHTXX_DATA_ERROR:
      Serial.println(F("received data smaller than expected, not connected, broken, long wires (reduce speed), bus locked by slave (increase stretch limit)"));
      break;

    case AHTXX_CRC8_ERROR:
      Serial.println(F("computed CRC8 not match received CRC8, this feature supported only by AHT2x sensors"));
      break;

    default:
      Serial.println(F("unknown status"));    
      break;
  }
}

To display a static bitmap on the second OLED (with address 0x3D) using the ss_oled library, you can do this directly with the oledWriteBitmap function provided by the ss_oled library. It seems that you are including the U8glib.h which is not necessary if you're using ss_oled.

Here's how you can integrate your bitmap data and display it on the second OLED:

First, make sure the bitmap data is in a format compatible with ss_oled (usually a byte array).

Then, in your setup or wherever you wish to display the bitmap, after initializing the second OLED, you could use oledWriteBitmap to display your bitmap. The oledWriteBitmap function takes the OLED index, starting x and y positions, width and height of the bitmap, and the bitmap data.

A short example based on your code:

int rc;
rc = oledInit(&ssoled[1], MY_OLED2, 0x3D, FLIP180, INVERT, 1, SDA_PIN, SCL_PIN, RESET_PIN, 400000L); 
if (rc != OLED_NOT_FOUND)
{
  oledFill(&ssoled[1], 0, 1); // Clear the display
  // Now draw the bitmap
  oledWriteBitmap(&ssoled[1], 0, 0, tracking_width, tracking_height, tracking_bits);
  oledDisplay(&ssoled[1]);
}

Make sure to replace tracking_bits with the name of your actual bitmap array if it's different.

The oledDisplay function may not be necessary depending on how the library is set up, as some libraries automatically push changes to the display when drawing functions are called.

You should remove the U8glib.h related code if you are not using that library,

Thanks to all the help, I have been in contact with the library developer Larry Bank. He tells me that the library ss_oled has been retired and replaced by the OneBitDisplay library.

And that oledWriteBitmap, and oledDisplay is not part of the library.
ZefD

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