loading

In this instructable I will show you how to connect and test a 0.96" i2c OLED display module to an arduino.

Parts:

  • Breadboard and hookup wires
  • Arduino (using a nano v3 5v 16mhz clone in this case)
  • External power supply (regulated 5v)
  • The OLED i2c display

I bought my display around 6 months ago, and I can’t seem to find the exact display on ebay now, but searching for “0.96 ssd1306 i2c OLED” shows a whole lot of similar displays. Other sites, like adafruit, got the same displays if you prefer to shop there.

Step 1: Connecting Your Display

The display is connected by utilizing the i2c pins on your arduino.

Which pins to use for this differs on some arduino models, but on the UNO and NANO you use pin A4 (SDA) and A5 (SCL). If you’re using another arduino, google the pinout and look for SDA and SCL pins. (For example, google “arduino mega pinout”, and check the images).

I first attempted to power my display from my arduinos 5v. This worked, but only halfway – the display fired up, and started cycling the demos in the sketch we will see later on, and then froze after a few seconds.

I then powered my display from my external 5v supply (with common ground to the arduino), which did the trick – the display is now working properly.

The connections from the display:

  • VCC to external 5v
  • GND to external GND
  • SCL to arduino pin A5 (or the SCL pin for your arduino)
  • SDA to arduino pin A4 (or the SDA pin for your arduino)
  • arduino GND pin to external psu GND

Arduino is connected to the computer via an USB cable. The USB powers the arduino.

Step 2: I2c Scanner

To start out, we need to find out the i2c address of the display. To
accomplish this, I use a quick i2c scanner uploaded to the arduino. The scanner code can be found on http://playground.arduino.cc/Main/I2cScanner.
Copy and paste the code into your arduino IDE, build and upload, and fire up your serial monitor. If your display are connected, powered and working, you will get an address back from the scanner (in serial monitor). My display shows up at address 0x3C.

Step 3: Libraries

In this instructable I am using the arduino IDE (http://arduino.cc) and libraries from adafruit downloaded via github.
Link to the libraries:

I will assume you know how to download and install libraries in your arduino IDE. If not, there are tons of nice tutorials/instructions out there on how to get started with the arduino IDE and libraries.

Both libraries below needs to be installed before you are able to continue with this instructable.

https://github.com/adafruit/Adafruit_SSD1306 (SSD1306 library)

https://github.com/adafruit/Adafruit-GFX-Library (GFX library)

Step 4: Test Sketch

Now that we know our displays i2c address, we can open the example sketch in our adafruit ssd1306 library.
In your arduino IDE, check your examples menu and locate the 128×64 i2c sketch found under Adafruit SSD1306 (as shown in the picture).
Change the address of the display to whatever the scanner told you, in my case 3x0C.

Compile and upload to your arduino, give it a second, and the display should fire up and show some different display modes.

The demo sketch ends with stars that continues to fall forever. You can copy-paste from the demo sketch to use the display modes that fits your needs.

<p>Great tutorial. Thank you very much. Mine works perfectly now!</p>
<p>Thanks for the lesson, I butchered the provided code and mashed it up with code for reading a AM2302 temp sensor .... now I have something practical...a digital readout of temp and humidity. Make sure you get the right I2c address. way cool.</p><p><br><em>#include &lt;SPI.h&gt;<br>#include &lt;Wire.h&gt;<br>#include &quot;DHT.h&quot;<br>#include &lt;Adafruit_SSD1306.h&gt;</em></p><p><em>#define OLED_RESET 4<br>#define DHTPIN 2<br>#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321<br>DHT dht(DHTPIN, DHTTYPE);<br>Adafruit_SSD1306 display(OLED_RESET);</em></p><p><br><em>void setup() { <br> Serial.begin(9600);<br> display.begin(SSD1306_SWITCHCAPVCC, 0x3C); <br> dht.begin();<br>}</em></p><p><em>void loop() {</em></p><p><em> int h = dht.readHumidity();</em></p><p><em> // Read temperature as Fahrenheit (isFahrenheit = true)<br> int f = dht.readTemperature(true);</em></p><p><em> display.clearDisplay(); <br> display.setTextSize(2);<br> display.setTextColor(WHITE);<br> display.setCursor(0,0);<br> display.print(&quot;TEMP &quot;); display.print(f); display.println(&quot;F&quot;);<br> display.setTextSize(2);<br> display.setTextColor(WHITE); <br> display.print(&quot;Humid: &quot;); display.print(h); display.println(&quot;%&quot;);<br> display.display();<br> delay(10000);<br> </em></p><p><em>}</em></p>
<p>I want to use your code to read the temp sensor but i am getting an error when i try to compile. any ideas? i did grab the DHT.h code from here - <a href="http://playground.arduino.cc/Main/DHT11Lib" rel="nofollow">http://playground.arduino.cc/Main/DHT11Lib</a> </p>
<p>a common compile error (for me anyway) is caused by not selecting the right board in the tools&gt;board&gt;boardmanager menu.</p><p>are you getting a specific error?</p>
<p>Thanks for the guide!</p><p>I got the code working (had the height problem in the library). And the nano seems to happily take the code. But there is no sign of life from the display. Should it give some sign of life when powered on or does it need to be correctly wired and programed to even light up?</p><p>Im worried that my display is a doa, or should I give it some time and search for errors?</p><p>BTW: my display are labeled SCK instead of SCL, other than that compleatly identical to the example. (It is labeled SCL on ebay where I bought it).</p>
<p>i read somewhere this is issue of buffering, check adafruit forums.</p>
<p>If you're seeing every second line as blank, like I was, you need to edit the library file to uncomment:</p><p><br>`#define SSD1306_128_64`<br><br>and comment out<br><br>`// #defineSSD1306_128_32`</p><p><br>https://github.com/adafruit/Adafruit_SSD1306/blob/...</p>
<p>sadness not working for me, used correct settings, but still seconds lines blank like interlacing efect</p><p>#define SSD1306_128_64<br>// #define SSD1306_128_32<br>// #define SSD1306_96_16</p>
<p>Why you don't need any pull-up resistors?</p>
<p>Hello there</p><p>It's an awesome tutorial.</p><p>I want to know in the basic code of testing the 128x32 i2c display they are using reset pin. But there is no reset pin on my OLED display.</p><p>Second, I got the flickering display even after giving the external 5V. </p><p>What should I do??</p><p>Thanks</p>
<p>Tie both GNDs together on the nano. </p>
<p>The lack of the reset pin seams to be normal.</p><p>But this instruction is wrong. You shouldn't let the example code using pin4 as a non-connected reset pin. Instead you should modify the example not using any parameters while constructing the display. (This will lead to a default value -1 to be set as reset pin, and it is handled by the Adafruite driver.)</p><p>Also worth to mention that there are SPI-ready versions of this display board, that are also supported by the Adafruite driver. (Buy Adafruite products to support them developing drivers!)</p>
<p>it took me 2 days to get it working but it now works great. FYI, the 2 god connections on the nano are not the same. The one between RST and D2 works great. The one on the other side does not, impedance is too high on my Chinese clone. Tie the 2 together and all is well. That little lesson cost me a lot of time.</p>
<p>Works. Great primer.</p>
<p>This is the very first thing I've made with the arduino, the steps were easy, even though I've never tinkered with this before. Thank you.</p>
<p>thanks fore help withe the display.</p><p>this work great.</p><p>i needed this to my stopwatch projekt </p>
<p>Making a marauders map for myself, thanks to you, easily got started with the display.</p>
<p>There's a typo in Step 4 &gt;&gt;3x0C should be 0x3C (as per the scan in step 2)</p>
<p>I took this one step further and added the HC-SR04. I have it outputting the average distance readings to the screen, as well as serial monitor. Thanks for the help!</p><p>[code]</p><p>#include &lt;SPI.h&gt;</p><p>#include &lt;Wire.h&gt;</p><p>#include &lt;Adafruit_GFX.h&gt;</p><p>#include &lt;Adafruit_SSD1306.h&gt;</p><p>#define OLED_RESET 4</p><p>Adafruit_SSD1306 display(OLED_RESET);</p><p>// Pins</p><p>const int TRIG_PIN = 11;</p><p>const int ECHO_PIN = 12;</p><p>// Anything over 400 cm (23200 us pulse) is &quot;out of range&quot;</p><p>const unsigned int MAX_DIST = 23200, MIN_DIST = 150;</p><p>float avgDist = 0, dist, cm,inches;</p><p>int pingCount,avgCount;</p><p>unsigned long pulse_width;</p><p>void setup() {</p><p> //lcd.Begin(16,2)</p><p> // The Trigger pin will tell the sensor to range find</p><p> pinMode(TRIG_PIN, OUTPUT);</p><p> digitalWrite(TRIG_PIN, LOW);</p><p> // We'll use the serial monitor to view the sensor output</p><p> Serial.begin(9600);</p><p> // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)</p><p> display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)</p><p> // init done</p><p> // Show image buffer on the display hardware.</p><p> // Since the buffer is intialized with an Adafruit splashscreen</p><p> // internally, this will display the splashscreen.</p><p> display.display();</p><p> delay(2000);</p><p> // Clear the buffer.</p><p> display.clearDisplay();</p><p> // draw a single pixel</p><p> display.drawPixel(10, 10, WHITE);</p><p> // Show the display buffer on the hardware.</p><p> // NOTE: You _must_ call display after making any drawing commands</p><p> // to make them visible on the display hardware!</p><p> display.display();</p><p> delay(2000);</p><p> display.clearDisplay();</p><p>}</p><p>void loop() {</p><p> unsigned long t1;</p><p> unsigned long t2;</p><p> // Hold the trigger pin high for at least 10 us</p><p> digitalWrite(TRIG_PIN, HIGH);</p><p> delayMicroseconds(10);</p><p> digitalWrite(TRIG_PIN, LOW);</p><p> // Wait for pulse on echo pin</p><p> // while ( digitalRead(ECHO_PIN) == 0 );</p><p> pulse_width = pulseIn(ECHO_PIN,HIGH);</p><p> // Calculate distance in centimeters and inches. The constants</p><p> // are found in the datasheet.</p><p> cm = (pulse_width*0.034)/2;// / 58.0;</p><p> inches = (pulse_width*0.0133)/2; // 148.0;</p><p> pingCount++;</p><p> //set average distance and reset it every x pings</p><p> if(pingCount&gt;10){</p><p> dist=inches;</p><p> pingCount= 1;</p><p> }</p><p> else {</p><p> dist= dist+inches++;</p><p> avgDist = dist/pingCount;</p><p> }</p><p> if(pingCount==10){</p><p> printReadings();</p><p> }</p><p> if (avgDist &lt; 10){</p><p> // playTone(); //previously had it play tones over a piezo based on distance from the sensor</p><p> }</p><p> else {</p><p> // noTone(piezo);</p><p> }</p><p> // Wait at least 60ms before next measurement</p><p> delay(60);</p><p>}</p><p>void printReadings()</p><p>{</p><p> // Print out results</p><p> if ( pulse_width &gt; MAX_DIST ) {</p><p> Serial.println(&quot;Out of range&quot;);</p><p> display.setTextSize(1);</p><p> display.setTextColor(WHITE);</p><p> display.setCursor(0,0);</p><p> display.println(&quot;Out of range&quot;);</p><p> display.display(); </p><p> } </p><p> else if (pulse_width &lt;MIN_DIST) { </p><p> display.print(pulse_width);</p><p> Serial.println(&quot;Object to close!!&quot;) ;</p><p> display.setTextSize(1);</p><p> display.setTextColor(WHITE);</p><p> display.setCursor(0,0);</p><p> display.println(&quot;Object to close!!&quot;);</p><p> display.display();</p><p> }</p><p> else {</p><p> Serial.print(pingCount);</p><p> Serial.print(&quot; pc \t&quot;);</p><p> Serial.print(avgDist);</p><p> Serial.print(&quot; avgInch \t&quot;);</p><p> Serial.print(cm);</p><p> Serial.print(&quot; cm \t&quot;);</p><p> Serial.print(inches);</p><p> Serial.println(&quot; in&quot;);</p><p> display.setTextSize(1);</p><p> display.setTextColor(WHITE);</p><p> display.setCursor(0,0);</p><p> display.print(pingCount);</p><p> display.print(&quot; pc \t&quot;);</p><p> display.print(avgDist);</p><p> display.print(&quot; avgInch \t&quot;);</p><p> display.print(cm);</p><p> display.print(&quot; cm \t&quot;);</p><p> display.print(inches);</p><p> display.println(&quot; in&quot;);</p><p> display.display(); </p><p> }</p><p> delay(1000);</p><p> display.clearDisplay();</p><p>}</p><p>[/code]</p><p>[code]</p>
<p>Very Cool. Thank you for sharing!</p>
<p>Good work! Nice to get an ebay impulse purchase going so easily. Many thanks!</p>
<p>Very clear instructions and could make it in less than 5 minutes. Thanks a lot</p>
<p>Just did it. Thanks for the information. You are spot on about the address 0x3C.</p><p>One more thing: there is a glitch in the 128x64 i2c example, before the Setup section, there is a static char bitmap. You must add const on the line just before static in order for it to compile. The error message is pretty clear but it bears mentioning.</p><p>Keep up the good work!</p><p>I really want to see more ways to use this display. There seems to me no real manual..</p>
<p>It works!</p>
<p>Great, you can find different color and sizes in this amazon store</p><p>https://www.amazon.com/s/ref=nb_sb_noss?url=me%3DA28JUS3SJ1A0RV&amp;field-keywords=0.96</p>
<p>Great instructions! Everything working fine ;) (header issue was easy to fix indeed). </p><p>Does anyone know of instructions to get the special features like battery strength etc going? </p>
<p>Hi, build this, great.</p><p>i found a tool to transfer an picture to binary code here: <a href="https://www.instructables.com/id/How-to-use-OLED-display-arduino-module/" rel="nofollow">https://www.instructables.com/id/How-to-use-OLED-di...</a></p><p>but this did&acute;t work in this sketch.</p><p>How can i transfer an picture to binary code for this sketch?</p><p>Thanxs, Duffy</p><p>b</p>
<p>0x3C is pretty much the standard for these displays o in most cases the I2C scanner wouldn't be necessary. Wont hurt to make sure though</p>
<p>I had some other problems not addressed in the guide, but I couldn't have done it without your help! I had to change the names of the adafruit libraries because they contained non alphabetic characters, ie - and _. The .h file in the SSD library also had the wrong height around line 70 or so. I opened the file in notepad++ and was able to uncomment the correct 128x64 declaration and remove the 128x32 one. Also I got a compilation error saying all sorts of objects in the &quot;Robot Control&quot; library were not declared. I have no idea why that happened, but I just took RobotControl out of the libraries folder and that problem was solver. The last error I had was that the program could not find the fillCircle class, even though the GFX library was included. To fix this I clicked sketch, then add library and re-added the GFX library, which add this line to the code: </p><p>#include &lt;gfxfont.h&gt;</p>
<p>It works! I had to alter the .h file too, but that was it :-)</p>
<p>I got it to work. But I have a questions.</p><p>1My display the top 1/3 displays yellow and the bottom 2/3 displays blue. How do I fix it? Is it defective?</p>
<p>Nothing's wrong, thats just the way the display was made. Assuming that you bought this off eBay. The top yellow bar is for a status bar, battery level, clock, etc... The same stuff as in an MP3 player. Good luck!</p>
<p>It's not defective. Some displays are designed to have a different color in the top part. It's not possible to change the colors, they are designed that way to be used in specific applications (an old cel phone top bar, for example).</p>
<p>Your display is not defective. Many displays have different color <strong>LED's</strong> in the upper portion of the screen, I do not know of a way to change this.</p>
Hi, cool that you got it working, but I must admit I haven't seen that behavior before, so I don't know how to help you out. Good luck tho! :)
<p>You said: &quot;I first attempted to power my display from my arduinos 5v. This <br>worked, but only halfway &ndash; the display fired up, and started cycling the<br> demos in the sketch we will see later on, and then froze after a few <br>seconds. </p><p>I then powered my display from my external 5v supply <br>(with common ground to the arduino), which did the trick &ndash; the display <br>is now working properly&quot;.</p><p>This is somewhat strange ... some of the replyers have no problem with powering from the arduinos 5V? </p>
<p>Maybe they are plugging into usb 3.0 while he is using USB 2.0 which only supplies half the current of 3.0</p>
I'm really not sure, but it might be related to the fact that I was using a nano clone (not genuine arduino), which might have a different voltage regulator, or maybe a partly broken one? I'm also considering if the lack of pull-up resistors on the i2c-line could be the reason, even thought when I changed PSU it worked fine.
<p>The 0.08W claim for the OLED would mean it could take a maximum of around 25mA with 3.3V and less than 20mA with 5V.</p><p>I can't measure my OLED since it's soldered onto my arduino now, but I'm using SPI, which works without issues. I2C would be better, when having multiple devices, but you do need to use pull ups and set up addresses.</p><p>Pull up resistors might be the answer, for sure. Not sure if the OLED device has built in pull-ups, but you could try adding 10k ones, and see weather it makes a difference. Or if the 5V line is too noisy, add a small uF capacitor between the 5V and GND to keep the noise down.</p><p>It's quite difficult to make a crap arduino clone, so that's never been a problem for me. As long as you can run blink on it, it should pretty much do everything else too. </p><p>I'd like to know if you find the fix! =)</p>
<p>The display uses minimalistic current, and powering even from an arduino digital pin probably works, so naturally the 5V regulated or VCC would work perfect from USB 2.0. </p><p>I think Steven is correct and I'd suspect glitchy wiring if the screen froze. Probably lost the i2c mid process, and nothing to do with the power.</p><p>There's NO need to use external power for this OLED screen!</p>
<p>A faulty wire could certainly explain it, as well as a bugged clone can - might be both. Anyway, not stating you need an external supply, but I indeed did with this setup. Have you measured the current draw on the display?</p>
<p>That might also be something to consider - when I changed power supply, I didn't power the display from USB anymore, which might explain the change in behaviour.</p>
<p>THANKY MANKY awesoe explanation !!</p>
<p>Thanks, glad it could help!</p>
<p>Nice guide! I also had to change the address and comment out the correct display in the .h file but other than that everything worked great! Many Thanks!!</p>
<p>Thanks for the feedback! :)</p>
<p>I've been working on a smartwatch project and i have the clock working but how do I make it so I can increase the hours or minutes by pressing a tactile button please answer thank you in advance </p><p>Here is the code:</p><p>#include &lt;SPI.h&gt;</p><p>#include &lt;Wire.h&gt;</p><p>#include &lt;Adafruit_GFX.h&gt;</p><p>#include &lt;Adafruit_SSD1306.h&gt;</p><p>#define OLED_RESET 4</p><p>Adafruit_SSD1306 display(OLED_RESET);</p><p>#define NUMFLAKES 10</p><p>#define XPOS 0</p><p>#define YPOS 1</p><p>#define DELTAY 2</p><p>int hours = 0;</p><p>int mins = 0;</p><p>int secs = 0;</p><p>void setup() {</p><p> pinMode(2,INPUT);</p><p> Serial.begin(9600);</p><p>display.begin(SSD1306_SWITCHCAPVCC, 0x3C);</p><p>display.display();</p><p>delay(1);</p><p>display.clearDisplay();</p><p>}</p><p>void loop() {</p><p> // put your main code here, to run repeatedly:</p><p> delay(1000);</p><p> display.setCursor(0,0);</p><p> display.clearDisplay();</p><p> display.setTextSize(2);</p><p> display.setTextColor(WHITE);</p><p> display.println(secs);</p><p> display.setCursor(23,0);</p><p> display.println(&quot;:&quot;);</p><p> display.setCursor(34,0);</p><p> display.println(hours);</p><p> display.setCursor(58,0);</p><p> display.setTextSize(1);</p><p> display.println(mins);</p><p> display.display();</p><p> mins++;</p><p> if(mins &gt; 59)</p><p> {</p><p> hours++;</p><p> mins = 0;</p><p> } </p><p> if(hours &gt; 59)</p><p> {</p><p> secs++;</p><p> hours = 0;</p><p> } </p><p> if(secs &gt; 24)</p><p> {</p><p> hours = 0;</p><p> secs = 0;</p><p> mins = 0; </p><p>}</p>
<p>Just what I needed to get another step of my &quot;project&quot; done...</p>
<p>Thanks! With the few changes mentioned (oled address and library panel size), it worked without problems.</p>
<p>Followed your nice instructable to test 2 i2c 128x64 displays I bought. Worked like a charm!</p>

About This Instructable

209,626views

113favorites

Bio: Computer geek who stumbled upon arduino and electronics in general a while ago.
More by Jean0x7BE:AC light 433 mhz radio controlled timer with arduino OLED i2c display with arduino 
Add instructable to: