128x64 monochome with SH1106 driver

Hello,

I bought some of these displays. I use the U8x8lib.h library for them. It works fine in text mode , but the library is missing a function to display bitmaps (generally drawBitmap or drawXBMP). The function exist for a dozen of drivers, but not for HC1105, is there anybody aware of a workaround?

U8g2lib handles text, graphics, bitmaps, … and supports many display controllers e.g. SH1106

If you prefer Adafruit_GFX style methods there are suitable libraries too.

David

I don’t know this library. As said, U8x8lib supports U8x8lib, but not all methods, for instance drawBitmap and drawXBMP are not implemented for SH1106.

I’m going to have a look to Adafruit_GFX, thanks for that.

U8g2lib is written by Oliver. The same person who wrote U8x8lib.

Run the IDE Library Manager and look for SH1106

David.

Just tried to use U8g2lib. Here is the of compilation report. Last line is explicit.

/home/pfeuh/Documents/sources/C_language/arduino/_project/LFOx4int/LFOx4int.ino: In function ‘void printShape()’:
LFOx4int:157:13: error: ‘class U8X8_SH1106_128X64_NONAME_HW_I2C’ has no member named ‘drawBitmap’; did you mean ‘drawTile’?

  • display.drawBitmap(16, 0, bmpSinusTable, 64, 64, 1);*
    
  •         ^~~~~~~~~~*
    
  •         drawTile*
    

*Utilisation de la bibliothèque U8g2 version 2.28.10 dans le dossier: /home/pfeuh/snap/arduino/50/Arduino/libraries/U8g2 *
*Utilisation de la bibliothèque SPI version 1.0 dans le dossier: /snap/arduino/50/hardware/arduino/avr/libraries/SPI *
*Utilisation de la bibliothèque Wire version 1.0 dans le dossier: /snap/arduino/50/hardware/arduino/avr/libraries/Wire *
exit status 1
‘class U8X8_SH1106_128X64_NONAME_HW_I2C’ has no member named ‘drawBitmap’; did you mean ‘drawTile’?

There is a drawBitmap() but it is limited to drawing from SRAM. See u8g2reference · olikraus/u8g2 Wiki · GitHub

He prefers drawXBM() which has methods for Flash and SRAM.

Current Adafruit_GFX style libraries have several drawBitmap() methods.
A hardware library that inherits from Adafruit_GFX gets all the current features.
Some hardware libraries implement native “compatible” GFX functions instead of inheritance. This often means that they miss some newer GFX features.

David.

Thanks for all, David, but I give up. I’ve tried the example given by Oliver, but always the same result, no member named drawBitmap, drawXBM nor drawXBMP.

Having a look at source code, there is really a lot of precompiler directives, almost one #ifdef per driver, so I’ve spent enough time, I’m going to find another solution.

It looks as if you have a 64x64 monochrome bitmap.
You want to display it at coordinates (16, 0)
Using (1) WHITE as foreground colour.

U8g2lib has:

void U8G2::drawBitmap(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t cnt, u8g2_uint_t h, const uint8_t *bitmap)

which does not have a foreground colour argument (and different argument order)

so you would use:

display.drawBitmap(16, 0, 64/8, 64, bmpSinusTable);

U8g2lib expects bmpSinusTable to be stored in SRAM.

U8x8lib does not seem to have any drawBitmap() at all from https://github.com/olikraus/u8g2/wiki/u8x8reference

Personally, I am happier with Adafruit_GFX class methods. But U8x8 and U8g2 support a wide range of display hardware.

You can try GitHub - prenticedavid/Adafruit_SH1106_kbv: SH1106 oled driver library for monochrome 128x64 and 128x32 displays
It is not a public library supported by IDE Library Manager. But it should give you regular Adafruit_GFX functionality.

Note that the Adafruit libraries steal 1024 bytes of SRAM at runtime. You must be careful with a Uno.

David.

That’s exactly what I wrote. But I don’t know how to say more clearly that this function doesn’t exist for the SH1106 driver, nor in U8g2lib, nor in U8x8. FOr the rest, you’re totally right, 64x64 pixels, monochrome and stored in sram. Here is the code.testOldGraphix2.ino (4.0 KB)

I built for U8g2 and ran it on a Uno with a 128x64 SH1106 display.

#include <U8g2lib.h>
U8G2_SH1106_128X64_NONAME_1_HW_I2C display(U8G2_R0); //small buffer

#include "bmpSinusTable.h"  //in SRAM

#define DISPLAY_MSEC_DURATION 2000

unsigned long int milestone;

void showWaveform()
{
    display.firstPage();
    do {
        display.drawBitmap( 16, 0, 8, 64, bmpSinusTable);
    } while ( display.nextPage() );
}

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    milestone = millis();

    display.begin();
}

void loop()
{
    if (milestone <= millis())
    {
        showWaveform();
        milestone += DISPLAY_MSEC_DURATION;
    }

    // led blinks as CPU_RUN indicator
    if (millis() & 0x200)
        digitalWrite(LED_BUILTIN, 0);
    else
        digitalWrite(LED_BUILTIN, 1);
}

and wrote the equivalent for Adafruit_SH1106_kbv library:

#include <Wire.h>
#include "Adafruit_SH1106_kbv.h"
Adafruit_SH1106_kbv display(128, 64, &Wire);
#include "bmpSinusTable.h"

#define DISPLAY_MSEC_DURATION 2000

unsigned long int milestone;

void showWaveform()
{
    display.clearDisplay();
    display.drawBitmap( 16, 0, bmpSinusTable, 64, 64, WHITE);
    display.display();
}

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    milestone = millis();

    display.begin(SH1106_SWITCHCAPVCC, 0x3C);
}

void loop()
{
    if (milestone <= millis())
    {
        showWaveform();
        milestone += DISPLAY_MSEC_DURATION;
    }
    // led blinks as CPU_RUN indicator
    if (millis() & 0x200)
        digitalWrite(LED_BUILTIN, 0);
    else
        digitalWrite(LED_BUILTIN, 1);
}

Note that Adafruit_GFX style libraries allow you to display bitmap in PROGMEM. Also with different foreground and background colours e.g.

    display.drawBitmap( 16, 0, bmpSinusTable, 64, 64, BLACK, WHITE);

You make my day, I’ve copy-paste your first version, it works on my system. But for your second version, which is the one I would like to use because my bitmaps are in program memory, I don’t find the Adafruit_SH1106_kbv library, the Arduino IDE library manager doesn’t show it.

I just got it on Github, and it works as I expect, a big thumb up for you! Cherry on the pie, this driver doesn’t seem to have the 1kbyte of buffer in sram.

Yes, it will still allocate 1024 bytes of SRAM for the 128x64 buffer. Just make sure that 1024 is available at build time e.g. for SRAM image

Sketch uses 13774 bytes (42%) of program storage space. Maximum is 32256 bytes.

Global variables use 860 bytes (41%) of dynamic memory, leaving 1188 bytes for local variables. Maximum is 2048 bytes.

and for PROGMEM image:

const static unsigned char PROGMEM bmpSinusTable[] = 
Sketch uses 13774 bytes (42%) of program storage space. Maximum is 32256 bytes.
Global variables use 348 bytes (16%) of dynamic memory, leaving 1700 bytes for local variables. Maximum is 2048 bytes.

Ouch. This Forum software is a nightmare.

However the SRAM version says 1188 bytes of SRAM. i.e. 1188 - 1024 = 164. Which is very risky.
The PROGMEM version is 1700 - 1024 = 674. Which is much safer.

David.

David, despite the name of the lib (U8x8), I haven’t found any font in 8x8 pixels, like these for vintage computers… Am I wrong?

Using the lib’s font closer to 16x16 used in examples, it seems that it’s a little bit too big in width, lines 2 and 3 have some pixels (only last pixel column, I suppose) at the start of the following line.

#include <Arduino.h>

#include <U8x8lib.h>

U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

void setup(void)
{
    pinMode(LED_BUILTIN, OUTPUT);
    u8x8.begin();
    u8x8.setCursor(0, 0);
    u8x8.setFont(u8x8_font_px437wyse700b_2x2_r);  
    u8x8.clear();
    u8x8.print(F("01234567\n"));
    u8x8.print(F("10123456\n"));
    u8x8.print(F("12012345\n"));
    u8x8.print(F("12301234\n"));
}

void loop()
{
    if(millis() & 0x200)
        digitalWrite(LED_BUILTIN, 0);
    else
        digitalWrite(LED_BUILTIN, 1);
}

Hello,

I’ve got many problems attempting to mix bitmaps and text. I also gave a lot of time trying to understand the adafruit GFX library. I came to the conclusion that I probably have to write my own minimalist driver.

I have understood (I hope I’m not wrong) that most of methods works with the 1k ram buffer and the method .display() copies the ram to the display().

I haven’t found the code of this command .display(), do you know something about it? Ideally, I miss 2 methods: Display initialization and sending of one byte to the display.

I professionally wrote some code (drivers and applications) before my retirement, including this one.

LCDpfeuh

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