ThingPulse / esp8266-oled-ssd1306

Driver for the SSD1306 and SH1106 based 128x64, 128x32, 64x48 pixel OLED display running on ESP8266/ESP32
https://thingpulse.com
Other
2.03k stars 643 forks source link

Does not run on Wemos D1 mini with SSD1306 128x64 #240

Closed emilekm2142 closed 5 years ago

emilekm2142 commented 5 years ago

Hi. I have this board - https://wiki.wemos.cc/products:d1:d1_mini It's D1 pin is labeled as SCL and D2 as SDA. I also have a 128x64 screen with SSD1306 driver. I followed the guide here -> http://automatedhome.party/2017/04/17/connect-an-inexpensive-oled-display-to-a-esp8266wemos-d1-mini/ and made it work. After that I had realized that Adafruit library is very slow and poor.

I tried to run this library but did not succeed. Every single pin setting I had tried came out wrong SSD1306Wire display(0x3c, 4, 5); SSD1306Wire display(0x3c, D2, D1); SSD1306Wire display(0x3c, D1, D2); SSD1306Wire display(0x3c, D3, D5); Changing 0x3c to 0x3d did not work either. In all these cases nothing happens, just as if the pins were set up wrong :/

But Adafruit library did work. Does anyone know what is going on?

reivaxy commented 5 years ago

Hi, it's working for me with 0x3c, D2, D1 Are you using the exact same screen that was working wirth the Adafruit library? Check its corners, if they are broken, your screen may be dead. Can you try it again with the lib that was working? Do you have other devices on the same I2C bus?

emilekm2142 commented 5 years ago

Exactly the same device in both cases. I just change the sketches are are running :/. Adafruit works everytime.

stirobot commented 5 years ago

I also have a D1 and have it working (https://github.com/stirobot/oledBoostGaugeWithNeopixel/blob/master/oledBoostGaugeWithNeopixel.ino) (The sensor is not working by the way because it expects 5V not 3.3V).

SSD1306 display(0x3c, 5, 4); //put it on the gpio pins D1 and D2

reivaxy commented 5 years ago

@emilekm2142 it must be something else in your code then. What do you do after SSD1306Wire display(0x3c, 4, 5);

emilekm2142 commented 5 years ago

Just an unedited SSD1306SimpleDemo

// Include the correct display library
// For a connection via I2C using Wire include
#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"`
// For a connection via I2C using brzo_i2c (must be installed) include
// #include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
// #include "SSD1306Brzo.h"
// #include "SH1106Brzo.h"
// For a connection via SPI include
// #include <SPI.h> // Only needed for Arduino 1.6.5 and earlier
// #include "SSD1306Spi.h"
// #include "SH1106SPi.h"

// Include custom images
#include "images.h"

// Initialize the OLED display using SPI
// D5 -> CLK
// D7 -> MOSI (DOUT)
// D0 -> RES
// D2 -> DC
// D8 -> CS
// SSD1306Spi        display(D0, D2, D8);
// or
// SH1106Spi         display(D0, D2);

// Initialize the OLED display using brzo_i2c
// D3 -> SDA
// D5 -> SCL
 //SSD1306Brzo display(0x3d, D2, D1);
// or
// SH1106Brzo  display(0x3c, D3, D5);

// Initialize the OLED display using Wire library
SSD1306Wire  display(0x3c, 5, 4); //Nothing helps here

// SH1106 display(0x3c, D3, D5);

#define DEMO_DURATION 3000
typedef void (*Demo)(void);

int demoMode = 0;
int counter = 1;

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  // Initialising the UI will init the display too.
  display.init();

  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);

}

void drawFontFaceDemo() {
    // Font Demo1
    // create more fonts at http://oleddisplay.squix.ch/
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.setFont(ArialMT_Plain_10);
    display.drawString(0, 0, "Hello world");
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 10, "Hello world");
    display.setFont(ArialMT_Plain_24);
    display.drawString(0, 26, "Hello world");
}

void drawTextFlowDemo() {
    display.setFont(ArialMT_Plain_10);
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.drawStringMaxWidth(0, 0, 128,
      "Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore." );
}

void drawTextAlignmentDemo() {
    // Text alignment demo
  display.setFont(ArialMT_Plain_10);

  // The coordinates define the left starting point of the text
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(0, 10, "Left aligned (0,10)");

  // The coordinates define the center of the text
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 22, "Center aligned (64,22)");

  // The coordinates define the right end of the text
  display.setTextAlignment(TEXT_ALIGN_RIGHT);
  display.drawString(128, 33, "Right aligned (128,33)");
}

void drawRectDemo() {
      // Draw a pixel at given position
    for (int i = 0; i < 10; i++) {
      display.setPixel(i, i);
      display.setPixel(10 - i, i);
    }
    display.drawRect(12, 12, 20, 20);

    // Fill the rectangle
    display.fillRect(14, 14, 17, 17);

    // Draw a line horizontally
    display.drawHorizontalLine(0, 40, 20);

    // Draw a line horizontally
    display.drawVerticalLine(40, 0, 20);
}

void drawCircleDemo() {
  for (int i=1; i < 8; i++) {
    display.setColor(WHITE);
    display.drawCircle(32, 32, i*3);
    if (i % 2 == 0) {
      display.setColor(BLACK);
    }
    display.fillCircle(96, 32, 32 - i* 3);
  }
}

void drawProgressBarDemo() {
  int progress = (counter / 5) % 100;
  // draw the progress bar
  display.drawProgressBar(0, 32, 120, 10, progress);

  // draw the percentage as String
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 15, String(progress) + "%");
}

void drawImageDemo() {
    // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html
    // on how to create xbm files
    display.drawXbm(34, 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits);
}

Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, drawRectDemo, drawCircleDemo, drawProgressBarDemo, drawImageDemo};
int demoLength = (sizeof(demos) / sizeof(Demo));
long timeSinceLastModeSwitch = 0;

void loop() {
  // clear the display
  display.clear();
  // draw the current demo method
  demos[demoMode]();

  display.setTextAlignment(TEXT_ALIGN_RIGHT);
  display.drawString(10, 128, String(millis()));
  // write the buffer to the display
  display.display();

  if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) {
    demoMode = (demoMode + 1)  % demoLength;
    timeSinceLastModeSwitch = millis();
  }
  counter++;
  delay(10);
}

Images.h

#define WiFi_Logo_width 60
#define WiFi_Logo_height 36
const uint8_t WiFi_Logo_bits[] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
  0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
  0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
  0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF,
  0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00,
  0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C,
  0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00,
  0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C,
  0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00,
  0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C,
  0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00,
  0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C,
  0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00,
  0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F,
  0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00,
  0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF,
  0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00,
  0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
  0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

Though, in Adafruit's demo ( https://github.com/adafruit/Adafruit_SSD1306/blob/master/examples/ssd1306_128x32_i2c/ssd1306_128x32_i2c.ino) I had to replace

 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

with

display.begin();

To make it work. Leaving it unedited did not result in "SSD1306 allocation failed" being printed. It seemed as if the display was not initialized correctly because nothing happened, yet the program continued execution. With only display.begin() it is working.

reivaxy commented 5 years ago

It's totally working for me with SSD1306Wire display(0x3c, 0, 2); 20190326_184731-_1024

Oh but I'm using an older release of the library, 3.2.7

bigStanS commented 5 years ago

This works for me on all of my WeMos's including D1 mini. on pins D1 & D2 See https://www.teachmemicro.com/nodemcu-pinout/ how D1 maps to GPIO5 & D2 maps to GPIO4 Hope this helps.

#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
// All 3 of the following statements are valid & work!
//SSD1306  display(0x3c, 4, 5);   //display(I2C address, SDA, SCL) 
SSD1306  display(0x3c, SDA, SCL);   //display(I2C address, SDA, SCL) 
//SSD1306  display(0x3c, D4, D3);   //display(I2C address, SDA, SCL) 

void setup() {
  // Initialising the UI will init the display too.
  display.init();

  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 0, "Hello world");
  display.setFont(ArialMT_Plain_16);
  display.drawString(0, 10, "Hello world");
  display.setFont(ArialMT_Plain_24);
  display.drawString(0, 26, "Hello world");

// write the buffer to the display
  display.display();
}

void loop() {
  // put your main code here, to run repeatedly:
}
Craig1516 commented 5 years ago

@emilekm2142 Did you ever get the SSD1306 Wemos D1 project working? I have had the same problem. Others seem to have it solved? Using Arduino's i2c_scanner.ino I was finally able to see one I2C device on address 3C. Been working on this all day and have tried several SSD1306's, several D1 Mini's, and even tried a bare ESP12F. Then I used different power supplies as the ESP's are finicky about power. Nothing. Frustrating.

Craig1516 commented 5 years ago

Solved my problem. Hope this helps others. There were several things I learned from this forum above (thanks everybody). Here is what I learned:

  1. Several of the SSD1306 screens are bad. Out of 6 i purchased, two were bad. One was my fault (reverse power I think), and the other one had never been opened.
  2. Two critical changes to the program were needed. One was the I2C address of the screens that worked are 0x3C, not 0x3D. I am using the 128X64 cheap OLEDs.
  3. The second program change was #define OLED_RESET -1 //4. Altered 4 to -1. These changes should be made to any program to follow.

Today's problems were a comedy of these errors but once I got one screen/ESP/program working then I was able to test all screens, several wemos d1 mini boards, stand alone ESP12F chip, another development board and my IDE to make sure they all work. It has been a long day. I hope this helps save other readers some time.

emilekm2142 commented 5 years ago

I could not get mine to work. Getting a new display and a new esp solved the problem. It is up to one's luck I think :<

Craig1516 commented 5 years ago

Thanks for the reply. Finally, I did get mine to work – I think I had a bum display and that cost me most of the day! I documented my finding on the forum for others. But the main problem was that 2 of 6 of my displays were not working. You are right, it is up to one’s luck. But once I got a working set I was able to verify and test the esp’s and the ssd1306’s. I threw the bad ones away!

RevoluPowered commented 5 years ago

Had the same issue, turns out that using D0, D1, Dpin pin mappings causes the lib to die for some reason.

Whereas I used the direct GPIO pin numbers.

I changed SSD1306Wire display(0x3c, D3, D5);

to SSD1306Wire display(0x3c, 14, 0);

on my board there is apparently a pull up on 0 but it didn't break the display.

I tried several I2C libraries, had no luck until I did this.

Craig1516 commented 5 years ago

Gordon, glad you found something that works. In my case I know the library pin assignments were okay because some displays worked... some didn't. I used the same ESP and same sketch to drive the SSD1306's.

colesnicov commented 5 years ago

@emilekm2142, Close The Issue please!

emilekm2142 commented 5 years ago

Had the same issue, turns out that using D0, D1, Dpin pin mappings causes the lib to die for some reason.

Whereas I used the direct GPIO pin numbers.

I changed SSD1306Wire display(0x3c, D3, D5);

to SSD1306Wire display(0x3c, 14, 0);

on my board there is apparently a pull up on 0 but it didn't break the display.

I tried several I2C libraries, had no luck until I did this.

@RevoluPower You are great! Your solution worked!

wavesailor commented 5 years ago

@bigStanS solution worked for me.

But this also worked for me using a different method:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(-1);

void setup() {
  Serial.begin(115200);
  // initialize with the I2C addr 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 

  display.clearDisplay();
  //display.setColor(WHITE);
  display.drawLine(0, 0, 128, 64, SSD1306_WHITE);
  display.drawLine(0, 64, 128, 0, SSD1306_WHITE);
  display.display();

}

void loop() {

}
Lesyk15 commented 3 years ago

Go home ESP you are drunk. I came here to find out why my display doesn't work. Tried several solutions mentioned here but with no success. However, during the last attempt to make things work, I forgot to change my wiring, but it turned out that this mistake led to the solution of my problem. Despite declaring pins D4 and D3 for my SDA and SCL my wires are connected to D1 and D2 and it works. When I plug my wires to pin D4 and D3 my display does not work as same as setting pins D1 and D2 in my source code. Weird!

// Pins
#define SDA D4
#define SCL D3
#define I2C 0x3C

// Create display
SSD1306 display(I2C, SDA, SCL);

image

julienlev commented 3 years ago

Go home ESP you are drunk.

Thank you for your post, my setup was not working on default SDA and SCL pins, but when I changed to D4 and D3 it worked, even if it's physically connected to D1a nd D2.