nodemcu / nodemcu-firmware

Lua based interactive firmware for ESP8266, ESP8285 and ESP32
https://nodemcu.readthedocs.io
MIT License
7.64k stars 3.12k forks source link

Can't use 128x32 I2C display drivers from u8g2 library #2713

Closed poorandunlucky closed 5 years ago

poorandunlucky commented 5 years ago

8<------------------------ BUG REPORT -----------------------------------------

Expected behavior

I have a 0.91" 128 x 32 monochrome OLED display that works with the default ssd1306_i2c_128x64 driver, however, it doesn't work with drivers for its size whether the ssd1306_i2c_128x32_univision, ssd1305_i2c_128x32_noname, or the uc1601_i2c_128x32 (there are only 3 drivers for 128 x 32 I2C devices).

Actual behavior

Trying to use the appropriate drivers (after enabling them in u8g2_displays.h) yields:

display_test.lua:13: attempt to call field 'ssd1305_i2c_128x32_noname' (a nil value)

Using the 128x64 driver makes so only 1/3 pixels is displayed, I think... 6 px font becomes 3 px high...

Test code

u8g2_displays.h

#ifndef _U8G2_DISPLAYS_H
#define _U8G2_DISPLAYS_H

#define U8G2_DISPLAY_TABLE_ENTRY(function, binding)

// ***************************************************************************
// Enable display drivers
//
// Uncomment the U8G2_DISPLAY_TABLE_ENTRY for the device(s) you want to
// compile into the firmware.
// Stick to the assignments to *_I2C and *_SPI tables.

#ifndef U8G2_DISPLAY_TABLE_I2C_EXTRA

// I2C based displays go into here:
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1610_i2c_ea_dogxl160_f, uc1610_i2c_ea_dogxl160) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1325_i2c_nhd_128x64_f, ssd1325_i2c_nhd_128x64) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_64x48_er_f, ssd1306_i2c_64x48_er) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1608_i2c_erc24064_f, uc1608_i2c_erc24064) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7588_i2c_jlx12864_f, st7588_i2c_jlx12864) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_i2c_128x64_noname0_f, ssd1309_i2c_128x64_noname0) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_i2c_ea_dogxl240_f, uc1611_i2c_ea_dogxl240)
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1305_i2c_128x32_noname_f, ssd1305_i2c_128x32_noname) \
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x32_univision_f, ssd1306_i2c_128x32_univision) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1608_i2c_240x128_f, uc1608_i2c_240x128) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ld7032_i2c_60x32_f, ld7032_i2c_60x32) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_i2c_ew50850_f, uc1611_i2c_ew50850) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1604_i2c_jlx19264_f, uc1604_i2c_jlx19264)
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1601_i2c_128x32_f, uc1601_i2c_128x32) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_i2c_128x64_vcomh0_f, sh1106_i2c_128x64_vcomh0) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_96x16_er_f, ssd1306_i2c_96x16_er) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1106_i2c_128x64_noname_f, sh1106_i2c_128x64_noname) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_i2c_64x128_f, sh1107_i2c_64x128) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_i2c_seeed_96x96_f, sh1107_i2c_seeed_96x96) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1107_i2c_128x128_f, sh1107_i2c_128x128) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1108_i2c_160x160_f, sh1108_i2c_160x160) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_sh1122_i2c_256x64_f, sh1122_i2c_256x64) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_vcomh0_f, ssd1306_i2c_128x64_vcomh0) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1309_i2c_128x64_noname2_f, ssd1309_i2c_128x64_noname2) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_alt0_f, ssd1306_i2c_128x64_alt0) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1611_i2c_ea_dogm240_f, uc1611_i2c_ea_dogm240) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1326_i2c_er_256x32_f, ssd1326_i2c_er_256x32 )\
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_i2c_seeed_96x96_f, ssd1327_i2c_seeed_96x96) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_i2c_ea_w128128_f, ssd1327_i2c_ea_w128128) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1327_i2c_midas_128x128_f, ssd1327_i2c_midas_128x128) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st7567_i2c_64x32_f, st7567_i2c_64x32) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx256128_f, st75256_i2c_jlx256128) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx256160_f, st75256_i2c_jlx256160) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx240160_f, st75256_i2c_jlx240160) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx25664_f, st75256_i2c_jlx25664) \
//  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_st75256_i2c_jlx172104_f, st75256_i2c_jlx172104) \

#define U8G2_DISPLAY_TABLE_I2C \
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \

#else

// I2C displays can be defined in an external file.
#define U8G2_DISPLAY_TABLE_I2C \
   U8G2_DISPLAY_TABLE_I2C_EXTRA

#endif

#endif /* _U8G2_DISPLAYS_H */

display_test.lua

-- display_test.lua
-- Tests with monochrome 128x32 I2C OLED using u8g2 library

id  = 0
sda = 2
scl = 1
sla = 0x3c
i2c.setup(id, sda, scl, i2c.SLOW)

disp = u8g2.ssd1306_i2c_128x32_univision(id, sla)

disp:setFont(u8g2.font_synchronizer_nbp_tf)
-- Default: font_6x10_tf)

disp:clearBuffer()

disp:setFontMode(0);
disp:setDrawColor(1);

disp:setFontDirection ( 0 )

disp:drawUTF8 ( 0, 16, "Test" )

disp:sendBuffer()

NodeMCU version

2.2.1 Master

Hardware

ESP8266MOD on a dev board, connected to a generic I2C OLED.

8<------------------------ END BUG REPORT -------------------------------------

sonaux commented 5 years ago

Instructions in the u8g2_displays.h are actually a bit misleading and should be:

// Uncomment the U8G2_DISPLAY_TABLE_ENTRY for the device(s) you want to // compile into the firmware and place it in the corresponding table.

Try this:

#define U8G2_DISPLAY_TABLE_I2C \
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1305_i2c_128x32_noname_f, ssd1305_i2c_128x32_noname) \
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x32_univision_f, ssd1306_i2c_128x32_univision) \
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_uc1601_i2c_128x32_f, uc1601_i2c_128x32) \

#else

Keep empty line before #else statement, because \ symbol is used to split #define statement across several lines.

poorandunlucky commented 5 years ago

@sonaux Thank you very much, that worked...

`// I2C displays can be defined in an external file.

define U8G2_DISPLAY_TABLE_I2C \

U8G2_DISPLAY_TABLE_I2C_EXTRA`

What is this for, then? I thought it would override the default display driver selection if any lines were uncommented in U8G2_DISPLAY_TABLE_I2C_EXTRA...

I spent so much time on this, it's incredible... -_- I tried putting the variable up, but not the values down... I probably had a syntax error somewhere, so I still couldn't load the driver, and ended-up here...

Michal78S commented 5 years ago

The latest "dev" issue puts display name with "xxx" into firmware so there is no chance to put correct name to the: disp = u8g2.ssd1306_i2c_128x64_noname(id, sla)" The "master" release works perfectly.

marcelstoer commented 5 years ago

What is this for, then?

@poorandunlucky take a look at the big picture without the commented lines.

#ifndef U8G2_DISPLAY_TABLE_I2C_EXTRA

#define U8G2_DISPLAY_TABLE_I2C \
  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \

#else

// I2C displays can be defined in an external file.
#define U8G2_DISPLAY_TABLE_I2C \
   U8G2_DISPLAY_TABLE_I2C_EXTRA

#endif

That basically means: "if U8G2_DISPLAY_TABLE_I2C_EXTRA is not defined anywhere (e.g. external file) then set U8G2_DISPLAY_TABLE_I2C inline here. Otherwise, use U8G2_DISPLAY_TABLE_I2C_EXTRA for U8G2_DISPLAY_TABLE_I2C as defined elsewhere".

marcelstoer commented 5 years ago

@Michal78S I don't understand what you mean, sorry. If you think there is a (new) bug in the firmware please create a separate issue.