0

Devices used It's about these devices:

Devices


Quick scheme (how I connected those)

enter image description here


Got the wiring info from the TinyWire library

TinyWire


Program I use (also many different examples tried but no luck):

#include <Wire.h>

//~ DEFINES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Some defines for the SSD1306 controller driving a 128x64 resolution OLED display
// PART     - http://www.simplelabs.co.in/content/96-blue-i2c-oled-module
// DATASHEET  - https://www.adafruit.com/datasheets/SSD1306.pdf

// The Slave Address (SLA) of the OLED controller - SSD1306 - is 0x3C 
// The LSB is supposed to be the mode. Since we are only going to WRITE to the OLED, the LSB is going to be 0
// SLA (0x3C) + WRITE_MODE (0x00) =  0x78 (0b01111000)
#define OLED_I2C_ADDRESS   0x3C

// The SSD1306 datasheet (pg.20) says that a control byte has to be sent before sending a command
// Control byte consists of 
// bit 7    : Co   : Continuation bit - If 0, then it assumes all the next bytes are data (no more control bytes).
//        :    You can send a stream of data, ie: gRAM dump - if Co=0
//        :        For Command, you'd prolly wanna set this - one at a time. Hence, Co=1 for commands
//        :    For Data stream, Co=0 :)
// bit 6      : D/C# : Data/Command Selection bit, Data=1/Command=0
// bit [5-0]  : lower 6 bits have to be 0
#define OLED_CONTROL_BYTE_CMD_SINGLE  0x80
#define OLED_CONTROL_BYTE_CMD_STREAM  0x00
#define OLED_CONTROL_BYTE_DATA_STREAM 0x40

// Fundamental commands (pg.28)
#define OLED_CMD_SET_CONTRAST     0x81  // follow with 0x7F
#define OLED_CMD_DISPLAY_RAM      0xA4
#define OLED_CMD_DISPLAY_ALLON      0xA5
#define OLED_CMD_DISPLAY_NORMAL     0xA6
#define OLED_CMD_DISPLAY_INVERTED     0xA7
#define OLED_CMD_DISPLAY_OFF      0xAE
#define OLED_CMD_DISPLAY_ON       0xAF

// Addressing Command Table (pg.30)
#define OLED_CMD_SET_MEMORY_ADDR_MODE 0x20  // follow with 0x00 = HORZ mode = Behave like a KS108 graphic LCD
#define OLED_CMD_SET_COLUMN_RANGE   0x21  // can be used only in HORZ/VERT mode - follow with 0x00 + 0x7F = COL127
#define OLED_CMD_SET_PAGE_RANGE     0x22  // can be used only in HORZ/VERT mode - follow with 0x00 + 0x07 = PAGE7

// Hardware Config (pg.31)
#define OLED_CMD_SET_DISPLAY_START_LINE 0x40
#define OLED_CMD_SET_SEGMENT_REMAP    0xA1  
#define OLED_CMD_SET_MUX_RATIO      0xA8  // follow with 0x3F = 64 MUX
#define OLED_CMD_SET_COM_SCAN_MODE    0xC8  
#define OLED_CMD_SET_DISPLAY_OFFSET   0xD3  // follow with 0x00
#define OLED_CMD_SET_COM_PIN_MAP    0xDA  // follow with 0x12

// Timing and Driving Scheme (pg.32)
#define OLED_CMD_SET_DISPLAY_CLK_DIV  0xD5  // follow with 0x80
#define OLED_CMD_SET_PRECHARGE      0xD9  // follow with 0x22
#define OLED_CMD_SET_VCOMH_DESELCT    0xDB  // follow with 0x30

// Charge Pump (pg.62)
#define OLED_CMD_SET_CHARGE_PUMP    0x8D  // follow with 0x14

// NOP
#define OLED_CMD_NOP          0xE3

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// Box pattern
uint8_t pattern1[] = {
  0x00,0x7E,0x42,0x42,0x42,0x42,0x7E,0x00,
  0x00,0x7E,0x42,0x42,0x42,0x42,0x7E,0x00
  };

// Cross weave pattern
uint8_t pattern2[] = {
  0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81,
  0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81
  };

void setup()   {                
  // Init the OLED controller
  OLED_init();
}

void loop() {
  // I2C
  Wire.beginTransmission(OLED_I2C_ADDRESS);
  Wire.write(OLED_CONTROL_BYTE_CMD_STREAM);
  Wire.write(OLED_CMD_SET_COLUMN_RANGE);
  Wire.write(0x00);
  Wire.write(0x7F);
  Wire.write(OLED_CMD_SET_PAGE_RANGE);
  Wire.write(0);
  Wire.write(0x07);
  Wire.endTransmission();

  for(uint16_t i=0;i<1024;i++){
    Wire.beginTransmission(OLED_I2C_ADDRESS);
    Wire.write(OLED_CONTROL_BYTE_DATA_STREAM);
      for (uint8_t x=0; x<16; x++) {  
      // Wire.write(0b11000001);  
      // Wire.write(0x81);  
      // Wire.write(0x02);
      Wire.write(pattern1[x]);
      // Wire.write(pattern2[x]); 
      i++;
      }
      i--;
      Wire.endTransmission();   
  }

    delay(5000);

}


void OLED_init() {
  // Init the I2C interface (pins A4 and A5 on the Arduino Uno board) in Master Mode.
  Wire.begin();
  // keywords:
  // SEG = COL = segment = column byte data on a page
  // Page = 8 pixel tall row. Has 128 SEGs and 8 COMs
  // COM = row

  // Begin the I2C comm with SSD1306's address (SLA+Write)
  Wire.beginTransmission(OLED_I2C_ADDRESS);

  // Tell the SSD1306 that a command stream is incoming
  Wire.write(OLED_CONTROL_BYTE_CMD_STREAM);

  // Follow instructions on pg.64 of the dataSheet for software configuration of the SSD1306
  // Turn the Display OFF
  Wire.write(OLED_CMD_DISPLAY_OFF);
  // Set mux ration tp select max number of rows - 64
  Wire.write(OLED_CMD_SET_MUX_RATIO);
  Wire.write(0x3F);
  // Set the display offset to 0
  Wire.write(OLED_CMD_SET_DISPLAY_OFFSET);
  Wire.write(0x00);
  // Display start line to 0
  Wire.write(OLED_CMD_SET_DISPLAY_START_LINE);

  // Mirror the x-axis. In case you set it up such that the pins are north.
  // Wire.write(0xA0); - in case pins are south - default
  Wire.write(OLED_CMD_SET_SEGMENT_REMAP);

  // Mirror the y-axis. In case you set it up such that the pins are north.
  // Wire.write(0xC0); - in case pins are south - default
  Wire.write(OLED_CMD_SET_COM_SCAN_MODE);

  // Default - alternate COM pin map
  Wire.write(OLED_CMD_SET_COM_PIN_MAP);
  Wire.write(0x12);
  // set contrast
  Wire.write(OLED_CMD_SET_CONTRAST);
  Wire.write(0x7F);
  // Set display to enable rendering from GDDRAM (Graphic Display Data RAM)
  Wire.write(OLED_CMD_DISPLAY_RAM);
  // Normal mode!
  Wire.write(OLED_CMD_DISPLAY_NORMAL);
  // Default oscillator clock
  Wire.write(OLED_CMD_SET_DISPLAY_CLK_DIV);
  Wire.write(0x80);
  // Enable the charge pump
  Wire.write(OLED_CMD_SET_CHARGE_PUMP);
  Wire.write(0x14);
  // Set precharge cycles to high cap type
  Wire.write(OLED_CMD_SET_PRECHARGE);
  Wire.write(0x22);
  // Set the V_COMH deselect volatage to max
  Wire.write(OLED_CMD_SET_VCOMH_DESELCT);
  Wire.write(0x30);
  // Horizonatal addressing mode - same as the KS108 GLCD
  Wire.write(OLED_CMD_SET_MEMORY_ADDR_MODE);
  Wire.write(0x00);
  // Turn the Display ON
  Wire.write(OLED_CMD_DISPLAY_ON);

  // End the I2C comm with the SSD1306
  Wire.endTransmission();
}

Source: https://github.com/SonalPinto/Arduino_SSD1306_OLED/blob/master/oled_test/oled_test.ino


Other examples I have been tried:


Question

What could be wrong, do I miss something inhere? Wires seems to be OK, do I use the correct pins (sometimes a little confusing on Attiny85, digital versus analog)? Tried also another OLED_I2C_ADDRESS, 0x3D instead of 0x3C but no luck at all. Tried both screen and both remain black.

2

2 Answers 2

3

With I2C you always need pull up resistors on the data lines, otherwise nothing works. Normally ones around 4.7K for a Uno, not sure what they should be for a Tiny.

If you are unsure about the I2C address get "I2CScanner" (An Arduino program) and that will tell you.

1
  • 1
    Ah, this is useful info, thanks! Got no 4,7K resistors but desoldered two from a spare board and guess what..... It works like a charm! Thank you very much for the execellent info. I'm happy, thumbs up!
    – Codebeat
    Feb 5, 2017 at 4:39
0

Hmm not strictly true I've currently got mine working without resistors, and the screens I get often do work without them, for example the Arduino Nano and ESP8266/NodeMCU I have used without resistors.

I had a bit of a pain with this board, the drivers for Windows originaly not working or detecting the board correctly and then the board not seeing the OLED mine is the 128x32 version. I edited the code to reflect the screen size in the DigiSparkOLED.cpp

0xA8, 0x1F,      // Set multiplex ratio(1 to 64)

And change:

0xDA, 0x12,      // Set com pins hardware configuration   

To:

0xDA, 0x02,      // Set com pins hardware configuration   

Also on several sites it does say to use PINS SCL on P5 and SDA on P2 so if its not working maybe try that pinout. I used the one mentioned above and the I2C scanner is now seeing it on address 0x3C (I wouldn't try changing the address in my experience the pinout will be wrong)

Do your usual checks to see if the screen is drawing power on all lines with a multimeter, also run I2C Scanner program to see if it sees anything and if not then try the alternative pinout.

2
  • ESP8266/NodeMCU is another puppy comparing to the Attiny85, Attiny is very basic and limited. However it might work now, it can change when connecting more i2c peripherals or using longer wires. Also the pin versus GPIO naming isn't the same, see also: github.com/esp8266/Arduino/blob/master/variants/nodemcu/… . About the display, used a 128x64 oled and it feels very buggy, especially at boot, sometimes it works, sometimes it don't. The ESP8266 is very picky on timing. See my topic on this on stackoveflow when it is using the wire library:
    – Codebeat
    Jan 28, 2018 at 3:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.