SSD1306 Now with 64x48 for D1 Mini Oled Shield [SOLVED]

Posted on
  • I need your help with the SSD1306 driver for the ESP8266 D1.Mini (great little device with MANY HATS that stack up)

    The issue is the text DOES show up but of course it's line up wrong. BUT more importantly and get double height when trying the same with 64x48 from WEMOS which has a wonderful kit with the OLED and Two buttons all through I2C (or SPI)

    I'm aware that I have to modify the http://www.espruino.com/modules/SSD1306.js module and change the OLED_WIDTH and pass the valid 48 height. but I know there must be other changes.
    As you can see from the screenshot below. it's offset is off (easy to fix) but I'm wondering why the double-scan style font?

    Any help would be appreciated. and yes. I went through all the SSD1306 posts. but none were working with this new design.

    I DID get the SSD1306 drivers to work out of the box on this on the ESP8266 with 128x32 integrated OLED From TTGO and HELTEC
    https://www.banggood.com/LILYGO-TTGO-ESP8266-0_91-Inch-OLED-Display-Module-For-Arduino-Nodemcu-p-1205904.html

    function start(){
      g.clear();
      g.drawString("Hello",0,0);
        g.drawLine(0, 30, g.getWidth(), 30);
      g.setFontVector(20);
      g.drawString("I love Lily",0,7);
      g.flip();
    }
    
    // HELTEC 128x32
    //let SCL = D5;
    //let SDA = D4;
    
    //D1.Mini
    let SCL = D1;
    let SDA = D2;
    
    // I2C
    I2C1.setup({scl:D5,sda:D4});
    var g = require("SSD1306").connect(I2C1, start, { height : 32 });
    

  • Thank you @MaBe
    That gave me the values I was looking for. I knew that all that needed to change the values of the initCmds variable from the original 1306 module http://www.espruino.com/modules/SSD1306.js
    There was also the initCmds[15] change when initializing that I needed to update. My new driver can be found at: https://github.com/bocajs/NodeBotDays/blob/master/Espruino/ssd1306.js

    The working code from: https://github.com/bocajs/NodeBotDays/blob/master/Espruino/oled.js

    function start(){
      g.clear();
      g.drawString("Hello",35,0);
        g.drawLine(35, 20, g.getWidth(), 20);
      g.setFontVector(10);
      g.drawString("1234567890",20,7);
      g.drawString("1234567890",20,22);
      g.drawString("1234567890",20,35);
      g.flip();
    }
    
    // HELTEC 128x32
    /*
    let SCL = D5;
    let SDA = D4;
    I2C1.setup({scl:SCL,sda:SDA});
    var g = require("ssd1306").connect(I2C1, start, { height : 32 });
    */
    
    //D1.Mini OLED 64x48
    let SCL = D1;
    let SDA = D2;
    I2C1.setup({scl:SCL,sda:SDA});
    var g = require("https://raw.githubusercontent.com/bocajs/NodeBotDays/master/Espruino/ssd1306.js").connect(I2C1, start, { height : 48 });
    
    

    BUT...
    As you can see from the code. I did NOT change the width. I left it at 128. INSTEAD of 64.
    Everything is shifted over to the left. so to make the text be lined up I have to start it as if it's 30 pixels to the RIGHT.

    What value could be causing this?

  • @Gordon
    How can I contribute to the next release of the ssd1306.js with code that will work on all the other 1306 leds but ADD the 64x48 resolution?

  • Everything is shifted over to the left. so to make the text be lined up I have to start it as if it's 30 pixels to the RIGHT.What value could be causing this?

    It is this line https://github.com/bocajs/NodeBotDays/blob/master/Espruino/ssd1306.js#L54 you need to start and end it on right column, e.g. 31,95

  • To contribute you can just do it through GitHub... There'll be tutorials online but basically you just fork https://github.com/espruino/EspruinoDocs, replace the version of the file on there with the updated file, then issue a pull request - and as long as the '.md' file contains a note about the feature and it's not going to break code for anyone else then I can pull it in.

  • @MaBe - I don't know what the value but you can see 62 that it's height>>3 already. What's this value suppose to be?

    @fanoush - So are you saying that instead of 1 to 64 I just do everything: 30-94? I think there's something off. I mean I could just think of it like that but obviously it's ignoring the problem.

    ALSO changing the WIDTH simply cuts the screen in the middle. So obviously there still needs to be a shift to the right.

    where would that be? Any help would be appriciated.

    @Gordon Once I have this done I'll submit a change that will NOT affect any of the existing resolutions but also ADD this one.
    (I'll probably make some of the fields like WIDTH to be able to be passed. that will help)

  • No, you need to fix that line I linked so it does not start at zero and end at 127. Then you can draw at zero and that line will take care of moving it where it belongs. The SSD1306 controller works with 128pixel width so smaller displays show just some subset of available memory, typically in the middle, so when sending data the destination column should be e.g. 31, not 0. Then you must also reduce the WIDTH down from 128 to match width of that 31-95 window (=64).

  • @fanoush
    You explained this very well.
    I made the changes and I'm experiencing a shifting every couple of pixels.
    Any advice?

  • Hard to guess without seeing the code. When in WebIDE you may dump the Graphics object via oled.dump() method (it will show as picture in the IDE) so you can make sure the framebuffer data is OK (and e.g. width is really 64, not more), then if data is OK it is either in flip command sending (too many or too few?) data or can be also in display initialization.

  • 1) I've changed the WIDTH to 64 (even tried 128)
    2) changed the line you suggested (which made sense) to 31-94 in hex of course.
    Nothing changed.

    var C = {
        OLED_WIDTH                 : 64,
        OLED_CHAR                  : 0x40,
        OLED_CHUNK                 : 64
       };
       
       // commands sent when initialising the display
       var extVcc=false; // if true, don't start charge pump 
       var initCmds = new Uint8Array([
        0xAE, // 0 disp off
        0xD5, // 1 clk div
        0x80, // 2 suggested ratio
        0xA8, 63, // 3 set multiplex, height-1
        0xD3,0x0, // 5 display offset
        0x40, // 7 start line
        0x8D, extVcc?0x10:0x14, // 8 charge pump (need 0x14)
        0x20, 0x00, // 10 memory mode
        0xA1,  // 12 seg remap 1 (screen orientation)
        0xC8, // 13 comscandec () screen orientation change to INC to flip)
        0xDA, 0x12, // 14 set compins, height==64 ? 0x12:0x02,
        0x81, extVcc?0x9F:0xCF, // 16 set contrast //0x8F
        0xD9, extVcc?0x22:0xF1, // 18 set precharge
        0xDB, 0x40, // 20 set vcom detect
        0xA4, // 22 display all on
        0xA6, // 23 display normal (non-inverted)
        0xAF // 24 disp on
    ]);
       // commands sent when sending data to the display
       var flipCmds = [
            0x21, // columns
            0x20, 0x62,
            0x22, // pages
            0,6 /* (height>>3)-1 */];
       function update(options) {
         if (options) {
           if (options.height) {
             initCmds[4] = options.height-1;
             initCmds[15] = options.height==64 || options.height== 48 ? 0x12 : 0x02;
             flipCmds[5] = (options.height>>3)-1;
           }
           if (options.contrast!==undefined) initCmds[17] = options.contrast;
         }
       }
       
       
       connect = function(i2c, callback, options) {
         update(options);
         var oled = Graphics.createArrayBuffer(C.OLED_WIDTH,initCmds[4]+1,1,{vertical_byte : true});
       
         var addr = 0x3C;
         if(options) {
           if (options.address) addr = options.address;  
           // reset display if 'rst' is part of options 
           if (options.rst) digitalPulse(options.rst, 0, 10); 
         }
         
         setTimeout(function() {
           // configure the OLED
           initCmds.forEach(function(d) {i2c.writeTo(addr, [0,d]);});
         }, 50);
       
         // if there is a callback, call it now(ish)
         if (callback !== undefined) setTimeout(callback, 100);
       
         // write to the screen
         oled.flip = function() { 
           // set how the data is to be sent (whole screen)
           flipCmds.forEach(function(d) {i2c.writeTo(addr, [0,d]);});
           var chunk = new Uint8Array(C.OLED_CHUNK+1);
       
           chunk[0] = C.OLED_CHAR;
           for (var p=0; p<this.buffer.length; p+=C.OLED_CHUNK) {
             chunk.set(new Uint8Array(this.buffer,p,C.OLED_CHUNK), 1);
             i2c.writeTo(addr, chunk);
           } 
         };
       
         // set contrast, 0..255
         oled.setContrast = function(c) { i2c.writeTo(addr, 0, 0x81, c); };
       
         // set off
         oled.off = function() { i2c.writeTo(addr, 0, 0xAE); };
       
         // set on
         oled.on = function() { i2c.writeTo(addr, 0, 0xAF); };
       
         // return graphics
         return oled;
       };
    
    
    
    function start(){
      g.clear();
      g.drawString("Hello",0,0);
      g.drawLine(0, 20, g.getWidth(), 20);
      g.setFontVector(10);
      g.drawString("123456789",0,7);
      g.drawString("123456789",0,22);
      g.drawString("123456789",0,35);
      g.flip();
    }
    // HELTEC 128x32
    /*
    let SCL = D5;
    let SDA = D4;
    I2C1.setup({scl:SCL,sda:SDA});
    var g = require("SSD1306").connect(I2C1, start, { height : 32 });
    */
    //D1.Mini OLED 64x48
    let SCL = NodeMCU.D1;
    let SDA = NodeMCU.D2;
    I2C1.setup({scl:SCL,sda:SDA});
    var g = connect(I2C1,start, { height : 48 });
    
  • changed the line you suggested (which made sense) to 31-94 in hex of course.

    Actually I suggested 31,95 (0x1f,0x5f) and now I see you even have 0x20, 0x62 there which is width of 66, not 64. BTW, the original was 127 (not 128). Looks like you simply don't trust odd numbers? ;-)

  • @fanoush you were (of course) correct. My code looks now like this and works flawlessly.

    I'm going to post a modified version of the SSD1603.js module to github for @gordon with full compatibility with this new resolution as well as the other versions of course.

    var C = {
        OLED_WIDTH                 : 64,
        OLED_CHAR                  : 0x40,
        OLED_CHUNK                 : 128
       };
       
       // commands sent when initialising the display
       var extVcc=false; // if true, don't start charge pump 
       var initCmds = new Uint8Array([
        0xAE, // 0 disp off
        0xD5, // 1 clk div
        0x80, // 2 suggested ratio
        0xA8, 63, // 3 set multiplex, height-1
        0xD3,0x0, // 5 display offset
        0x40, // 7 start line
        0x8D, extVcc?0x10:0x14, // 8 charge pump (need 0x14)
        0x20, 0x00, // 10 memory mode
        0xA1,  // 12 seg remap 1 (screen orientation)
        0xC8, // 13 comscandec () screen orientation change to INC to flip)
        0xDA, 0x12, // 14 set compins, height==64 ? 0x12:0x02,
        0x81, extVcc?0x9F:0xCF, // 16 set contrast //0x8F
        0xD9, extVcc?0x22:0xF1, // 18 set precharge
        0xDB, 0x40, // 20 set vcom detect
        0xA4, // 22 display all on
        0xA6, // 23 display normal (non-inverted)
        0xAF // 24 disp on
    ]);
       // commands sent when sending data to the display
       var flipCmds = [
            0x21, // columns
            0x20,0x5f,
            0x22, // pages
            0,7 /* (height>>3)-1 */];
       function update(options) {
         if (options) {
           if (options.height) {
             initCmds[4] = options.height-1;
             initCmds[15] = options.height==64 || options.height== 48 ? 0x12 : 0x02;
             flipCmds[5] = (options.height>>3)-1;
           }
           if (options.contrast!==undefined) initCmds[17] = options.contrast;
         }
       }
    
    
     
    function start(){
      g.clear();
      g.drawString("Hello",0,0);
      g.drawLine(0, 20, g.getWidth(), 20);
      g.setFontVector(10);
      g.drawString("123456789",0,7);
      g.drawString("123456789",0,22);
      g.drawString("123456789",0,35);
      g.flip();
    }
    
    //D1.Mini OLED 64x48
    let SCL = NodeMCU.D1;
    let SDA = NodeMCU.D2;
    I2C1.setup({scl:SCL,sda:SDA});
    var g = connect(I2C1,start, { height : 48 });  
    

  • Great, you solved it - Thanks for the PR

  • @Gordon
    PR Request for the next version of Espruino as you requested:
    https://github.com/espruino/EspruinoDocs/pull/522

    EDITED
    Thank you for accepting this PR. It's an honor to be an ant on top of a giant.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

SSD1306 Now with 64x48 for D1 Mini Oled Shield [SOLVED]

Posted by Avatar for DamianMontero @DamianMontero

Actions