0.96" OLED Displays

All things Arduino!
Post Reply
Eric
Posts: 316
Joined: Fri Feb 21, 2014 4:52 pm

0.96" OLED Displays

Post by Eric »

Finally had some time to make a video on these and thought I would quickly share some of the basic code in case others need it. The only hiccup is you need the right I2C address for your display and that could vary. Simply use the I2C scanner sketch from the examples (Google if you don't have it for some reason) and you can get your address to input in the code.

You need the Adafruit libraries listed for these but that is easy to download. their example sketch works good and will give you more ideas.

Here is my really basic Nokia 5110 scope ported over to the OLED (it needs some scaling done)

Code: Select all

/*********************************************************************
Erics basic OLED Scope

My Youtube Channel  : http://www.youtube.com/user/Shadow5549
More info found at http://www.mkme.org

Erics 0.96" OLED Example using Adafruit Library

0X3C is address for cheap ebay units
Used I2C Scanner to find address
SDA connected to pin Analog 4
SCL connected to pin Analog 5

From original code:
This is an example for our Monochrome OLEDs based on SSD1306 drivers

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/category/63_98

This example is for a 128x64 size display using I2C to communicate
3 pins are required to interface (2 I2C and one reset)

Adafruit invests time and resources providing this open source code, 
please support Adafruit and open-source hardware by purchasing 
products from Adafruit!

Written by Limor Fried/Ladyada  for Adafruit Industries.  
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/

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

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

//Analog Pins
int channelAI = A0;      // probe
int delayAI = A1;       // delay potentiometer
float delayVariable =5; // 10 seems good for decent update- bit fast
float scale = 0;
int xCounter = 0;
int yPosition = 0;
int readings[85];
int counter = 0;

void setup()   {                
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  // init done
  
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();

  // draw a single pixel
  display.drawPixel(10, 10, WHITE);
  // Show the display buffer on the hardware.
  // NOTE: You _must_ call display after making any drawing commands
  // to make them visible on the display hardware!
  display.display();
  delay(2000);
  display.clearDisplay();

}


void loop() 
{
display.setTextColor(WHITE);  
//delayVariable = analogRead(delayAI);
  //delayVariable = (delayVariable/10);
  scale = 47.0/1023.0; 
  // commented out above delay items as no pot/encoder installed yet
  
  
  //record readings
  for(xCounter = 0; xCounter < 85; xCounter += 1)
    {                                 
      yPosition = analogRead(channelAI);
      readings[xCounter] = (yPosition*scale);
      delay (delayVariable);
    }
  
  display.clearDisplay();

  //Draw Voltage Ref Lines
  display.drawLine( 10, 0, 10, 47, WHITE);
  display.drawLine( 5, 47-(.166 *1023.0 * scale), 10, 47-(.166 *1023.0 * scale), WHITE);
  display.drawLine( 0, 47-(.33 *1023.0 * scale), 10, 47-(.33 *1023.0 * scale), WHITE);
  display.drawLine( 5, 47-(.5 *1023.0 * scale), 10, 47-(.5 *1023.0 * scale), WHITE);
  display.drawLine( 0, 47-(.66 *1023.0 * scale), 10, 47-(.66 *1023.0 * scale), WHITE);
  display.drawLine( 5, 47-(.84 *1023.0 * scale), 10, 47-(.84 *1023.0 * scale), WHITE);

  for(xCounter = 0; xCounter < 85; xCounter += 1)
    {
       display.drawPixel(xCounter, 47-readings[xCounter], WHITE);
       if(xCounter>1){
         display.drawLine(xCounter-1, 47-readings[xCounter-1], xCounter, 47-readings[xCounter], WHITE);
       }
    }
  
  display.display();     
} 


Here is a different version I found online. Source and info are commented in the code:

Code: Select all

/*
My Youtube Channel  : http://www.youtube.com/user/Shadow5549
More info found at http://www.mkme.org

Eric Notes:  Unknown how well or why this functions the way it does
Shows odd waveform(s) when monitoring a floating or semi floating pin.  weird.
Fits screen better than adapted 5110 code

Original Code:
This is set up to use a 128x64 I2C screen, as available
here: http://www.banggood.com/buy/0-96-oled.html
For wiring details see http://youtu.be/XHDNXXhg3Hg
*/

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

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

/********************************************/

#define CHARWIDTH           5
#define CHARHEIGHT          8
#define AXISWIDTH           (2 + 1)                   // axis will show two-pixel wide graph ticks, then an empty column
#define VISIBLEVALUEPIXELS  (128 - AXISWIDTH)         // the number of samples visible on screen
#define NUMVALUES           (2 * VISIBLEVALUEPIXELS)  // the total number of samples (take twice as many as visible, to help find trigger point

#define TRIGGER_ENABLE_PIN       2  // set this pin high to enable trigger
#define SCREEN_UPDATE_ENABLE_PIN 3  // set this pin high to freeze screen

byte values[NUMVALUES];           // stores read analog values mapped to 0-63
int pos = 0;                      // the next position in the value array to read
int count = 0;                    // the total number of times through the loop
unsigned long readStartTime = 0;  // time when the current sampling started
int sampleRate = 1;              // A value of 1 will sample every time through the loop, 5 will sample every fifth time etc.

/********************************************/

// Draws a printf style string at the current cursor position
void displayln(const char* format, ...)
{
  char buffer[32];
  
  va_list args;
  va_start(args, format);
  vsprintf(buffer, format, args);
  va_end(args);
  
  int len = strlen(buffer);
  for (uint8_t i = 0; i < len; i++) {
    display.write(buffer[i]);
  }
}

// Draws the graph ticks for the vertical axis
void drawAxis()
{  
  // graph ticks
  for (int x = 0; x < 2; x++) {
    display.drawPixel(x,  0, WHITE);
    display.drawPixel(x, 13, WHITE);
    display.drawPixel(x, 26, WHITE);
    display.drawPixel(x, 38, WHITE);
    display.drawPixel(x, 50, WHITE);
    display.drawPixel(x, 63, WHITE);  
  }
}

// Draws the sampled values
void drawValues()
{
  int start = 0;
  
  if ( digitalRead(TRIGGER_ENABLE_PIN) ) {
    // Find the first occurence of zero
    for (int i = 0; i < NUMVALUES; i++) {
      if ( values[i] == 0 ) {
        // Now find the next value that is not zero
        for (; i < NUMVALUES; i++) {
          if ( values[i] != 0 ) {
            start = i;
            break;
          }
        }
        break;
      }
    }    
    // If the trigger point is not within half of our values, we will 
    // not have enough sample points to show the wave correctly
    if ( start >= VISIBLEVALUEPIXELS )
      return;
  }
  
  for (int i = 0; i < VISIBLEVALUEPIXELS; i++) {
    display.drawPixel(i + AXISWIDTH, 63 - (values[i + start]), WHITE);
  }
}

// Shows the time taken to sample the values shown on screen
void drawFrameTime(unsigned long us)
{
  display.setCursor(9 * CHARWIDTH, 7 * CHARHEIGHT - 2); // almost at bottom, approximately centered
  displayln("%ld us", us);
}

/********************************************/

void setup() {

  // Set up the display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Initialize with the I2C addr 0x3D (for the 128x64)
  display.setTextColor(WHITE);

  pinMode(TRIGGER_ENABLE_PIN, INPUT);
  pinMode(SCREEN_UPDATE_ENABLE_PIN, INPUT);
}

/********************************************/

void loop() {
  
  // If a sampling run is about to start, record the start time
  if ( pos == 0 )
    readStartTime = micros();
  
  // If this iteration is one we want a sample for, take the sample
  if ( (++count) % sampleRate == 0 )
    values[pos++] = analogRead(0) >> 4; // shifting right by 4 efficiently maps 0-1023 range to 0-63

  // If we have filled the sample buffer, display the results on screen
  if ( pos >= NUMVALUES ) {
    // Measure how long the run took
    unsigned long totalSampleTime = (micros() - readStartTime) / 2;     // Divide by 2 because we are taking twice as many samples as are shown on the screen
 
    if ( !digitalRead(SCREEN_UPDATE_ENABLE_PIN) ) {
      // Display the data on screen   
      display.clearDisplay();
      drawAxis();
      drawValues();
      drawFrameTime(totalSampleTime);
      display.display();
    }
       
    // Reset values for the next sampling run
    pos = 0;
    count = 0;
  }
}
Enjoy!
I make videos and content on all things electronics, 3D printing and DIY
http://www.mkme.org
https://www.youtube.com/mkmeorg
Glytch
Posts: 26
Joined: Mon Feb 16, 2015 8:55 pm
Location: Missouri, US
Contact:

Re: 0.96" OLED Displays

Post by Glytch »

I absolutely love these little displays. So cheap, but so much potential. I've got a few projects in mind, anything from a small cheap "smart watch" and even a google glass style display for real-time data monitoring. May integrate a personal sensor network,something like the GSG may get involved. (Gas Sensor Grenade for those of you who havent heard it put that way yet ;) ) I'm getting a second Antminer S3 this week, but after that, I will be spending some money on some Arduino bits and bobs to tinker with. Keep up the good work Eric!
I make things, I break things, and cause all around chaos.
My Website: http://glytchtech.com
My Youtube: http://youtube.com/c/glytch
Post Reply