Re: Blue OLED 16x2 Display not acting like LCD Versions

by erikroby on Thu Aug 16, 2012 12:43 am

I haven't tested it yet, but it looks like a library update was posted:

https://github.com/ladyada/Adafruit_CharacterOLED

http://adafruit.com/products/823
erikroby
 
Posts: 5
Joined: Mon Jun 04, 2012 2:17 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by techman on Thu Aug 16, 2012 7:52 pm

The new library seems to work. I thought it failed one time, but it worked every other time. I am trying to modify the library to add support for the lcd backpack.

-tim
techman
 
Posts: 4
Joined: Sun Jun 10, 2012 7:10 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by rustybikes on Mon Aug 27, 2012 3:39 pm

I know I'm late to the party here, but I have also seen the problem where line 0 and 1 get swapped. Adding another data-point, the behaviour is different when powered via USB vs. external. It's been a while since I poked at this, but IIRC, on USB they're reversed. On external, they display as intended. Or maybe the other way round. I don't remember.

@techman - did you ever get the backpack working? I've a project that really really needs OLED, but I'm limited to SPI (maybe i2c) by the number of pins used on the Ardu by the shield in use.
rustybikes
 
Posts: 10
Joined: Sun Jul 15, 2012 1:25 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by techman on Mon Aug 27, 2012 11:18 pm

rustybikes wrote:I know I'm late to the party here, but I have also seen the problem where line 0 and 1 get swapped. Adding another data-point, the behaviour is different when powered via USB vs. external. It's been a while since I poked at this, but IIRC, on USB they're reversed. On external, they display as intended. Or maybe the other way round. I don't remember.

@techman - did you ever get the backpack working? I've a project that really really needs OLED, but I'm limited to SPI (maybe i2c) by the number of pins used on the Ardu by the shield in use.


Yes I was able to get it working with the backpack. I took the adafruit_LiquidCrystal library, made the write4bits public, and added the following. It's was brute force.

The issue is the backpack does not implement the r/w line, so I was not able to completely implement the complete library as provided above. However it seems to work once the lcd is properly started up.

Code: Select all | TOGGLE FULL SIZE
void setup(void) {
    lcd.begin(16,2);               // initialize the lcd
   
  // Initialization sequence is not quite as documented by Winstar.
  // Documented sequence only works on initial power-up.  An additional
  // step is required to handle a warm-restart.
  //
  // In the data sheet, the timing specs are all zeros(!).  These have been tested to
  // reliably handle both warm & cold starts
  //

  lcd.write4bits(0x03);  // Missing step from doc. Thanks to Elco Jacobs
  delayMicroseconds(5000);
  lcd.write4bits(0x02);
  delayMicroseconds(5000);
  lcd.write4bits(0x02);
  delayMicroseconds(5000);
  lcd.write4bits(0x08);
   
  delayMicroseconds(5000);
 
  lcd.command(0x08);   // Turn Off
  delayMicroseconds(5000);
  lcd.command(0x01);   // Clear Display
  delayMicroseconds(5000);
  lcd.command(0x06);   // Set Entry Mode
  delayMicroseconds(5000);
  lcd.command(0x02);   // Home Cursor
  delayMicroseconds(5000);
  lcd.command(0x0C);   // Turn On - enable cursor & blink
  delayMicroseconds(5000);
 
   
  lcd.home();
  lcd.print("Booting...");
  delay(1000);
  lcd.print("Booted...");
}


-tim
techman
 
Posts: 4
Joined: Sun Jun 10, 2012 7:10 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by rustybikes on Wed Aug 29, 2012 12:20 pm

Yes I was able to get it working with the backpack. I took the adafruit_LiquidCrystal library, made the write4bits public, and added the following. It's was brute force.


Well, it's a kind of progress, I guess...

Following your lead, I modified the Adafruit_LiquidCrystal library (provided in this thread) to let write4bits be public, and used your sample above to modify the HelloWorld_SPI example included in the library:

Code: Select all | TOGGLE FULL SIZE
/*
 Demonstration sketch for Adafruit i2c/SPI LCD backpack
 using 74HC595 SPI expander
 ( http://www.ladyada.net/products/i2cspilcdbackpack/index.html )

 This sketch prints "Hello World!" to the LCD
 and shows the time.
 
  The circuit:
 * 5V to Arduino 5V pin
 * GND to Arduino GND pin
 * CLK to Digital 2
 * DAT to Digital 3
 * LAT to Digital 4
*/


// include the library code:
#include "Wire.h"
#include "LiquidCrystal.h"

// Connect via SPI. Data pin is #3, Clock is #2 and Latch is #4
LiquidCrystal lcd(3, 2, 4);

void setup() {
  // set up the LCD's number of rows and columns:
    lcd.begin(16,2);               // initialize the lcd
   
  // Initialization sequence is not quite as documented by Winstar.
  // Documented sequence only works on initial power-up.  An additional
  // step is required to handle a warm-restart.
  //
  // In the data sheet, the timing specs are all zeros(!).  These have been tested to
  // reliably handle both warm & cold starts
  //
 
  lcd.write4bits(0x03);  // Missing step from doc. Thanks to Elco Jacobs
  delayMicroseconds(5000);
  lcd.write4bits(0x02);
  delayMicroseconds(5000);
  lcd.write4bits(0x02);
  delayMicroseconds(5000);
  lcd.write4bits(0x08);
   
  delayMicroseconds(5000);
 
 
  lcd.command(0x08);   // Turn Off
  delayMicroseconds(5000);
  lcd.command(0x01);   // Clear Display
  delayMicroseconds(5000);
  lcd.command(0x06);   // Set Entry Mode
  delayMicroseconds(5000);
  lcd.command(0x02);   // Home Cursor
  delayMicroseconds(5000);
  lcd.command(0x0C);   // Turn On - enable cursor & blink
  delayMicroseconds(5000);
 
  lcd.home();
  lcd.print("Booting...");
  delay(1000);
  lcd.print("Booted...");
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis()/1000);

  lcd.setBacklight(HIGH);
  //delay(500);    // Seizure-inducing. Plus, it's not needed for OLED.
  //lcd.setBacklight(LOW);
  //delay(500);
}


Obviously, it compiles and transfers to the Ardu (I'm using an UNO, FYI), but the results are not exactly useable.

Image

I call it progress, 'cos I get more than a single "H" now, and I do see the pattern shift every second as the loop() runs, but I'm not quite "there" yet. FWIW, the LCD works fine with the unmodified example sketch, but it also displays garbage with the additions you posted, so it's clearly doing something.

Maybe something'll happen if I poke around at the timings even further. I'm new enough to this scene that I'll probably cause more harm than good, but that's what backups are for.. :)
rustybikes
 
Posts: 10
Joined: Sun Jul 15, 2012 1:25 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by adafruit_support_bill on Wed Aug 29, 2012 12:28 pm

These displays are tricky to work with. I've got them to work without using the R/W line, but not very consistently. And once they get out of sync, the only way to reliably recover is to power cycle them.
User avatar
adafruit_support_bill
 
Posts: 28171
Joined: Sat Feb 07, 2009 9:11 am

Re: Blue OLED 16x2 Display not acting like LCD Versions

by rustybikes on Fri Aug 31, 2012 1:15 pm

adafruit_support wrote:These displays are tricky to work with. I've got them to work without using the R/W line, but not very consistently. And once they get out of sync, the only way to reliably recover is to power cycle them.


Quoted for truth. These little OLED 16x2's are great when you get them to work correctly (i.e. not SPI/i2c), but they are only "mostly" HD44780-compatible.

I don't want to further derail the thread, but I thought I'd report progress on my project. I didn't mention it the other day, but it's the beginning of a car-computer based on the CAN-BUS shield from SparkFun. Until I figured out the OLED, I popped one of the LCDs on. I had been using a red-on-black LCD, but switched to white-on-blue. That improved the readability rather dramatically, plus (big win) I've tweaked the code to allow me to set the backlight level using the joystick, so it's actually better than OLED, especially for night-drives.

One of my next projects is to use an Ardu with a GPS receiver as a bicycle computer. In that context, I still think OLED would be more suitable. Plus, I'll play with the LINE0/LINE1 reversal behaviour some more. Maybe I'll even stop derailing the thread and contribute something on-topic... :)
rustybikes
 
Posts: 10
Joined: Sun Jul 15, 2012 1:25 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by uhclem on Fri Sep 07, 2012 8:17 pm

My attempt at modifying the Adafruit_CharLCD.py library for the Pi. It's not working any better than the original and I am not sure why. The linefeeds seem to be ignored and the characters are too close to each other. I've got the r/w pin grounded since in the Arduino library it never seems to leave the LOW state.

Code: Select all | TOGGLE FULL SIZE
#!/usr/bin/python

#
# based on code from lrvick and LiquidCrystal
# lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py
# LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp
#
# Changes based on the Adafruit_CharacterOLED library

import RPi.GPIO as GPIO
from time import sleep

class Adafruit_CharLCD:

    # commands
    LCD_CLEARDISPLAY         = 0x01
    LCD_RETURNHOME         = 0x02
    LCD_ENTRYMODESET         = 0x04
    LCD_DISPLAYCONTROL         = 0x08
    LCD_CURSORSHIFT         = 0x10
    LCD_FUNCTIONSET         = 0x20
    LCD_SETCGRAMADDR         = 0x40
    LCD_SETDDRAMADDR         = 0x80

    # flags for display entry mode
    LCD_ENTRYRIGHT         = 0x00
    LCD_ENTRYLEFT         = 0x02
    LCD_ENTRYSHIFTINCREMENT     = 0x01
    LCD_ENTRYSHIFTDECREMENT     = 0x00

    # flags for display on/off control
    LCD_DISPLAYON         = 0x04
    LCD_DISPLAYOFF         = 0x00
    LCD_CURSORON         = 0x02
    LCD_CURSOROFF         = 0x00
    LCD_BLINKON         = 0x01
    LCD_BLINKOFF         = 0x00

    # flags for display/cursor shift
    LCD_DISPLAYMOVE         = 0x08
    LCD_CURSORMOVE         = 0x00

    # flags for display/cursor shift
    LCD_DISPLAYMOVE         = 0x08
    LCD_CURSORMOVE         = 0x00
    LCD_MOVERIGHT         = 0x04
    LCD_MOVELEFT         = 0x00

    # flags for function set
    LCD_8BITMODE         = 0x10
    LCD_4BITMODE         = 0x00
    LCD_2LINE             = 0x08
    LCD_1LINE             = 0x00
    LCD_5x10DOTS         = 0x04
    LCD_5x8DOTS         = 0x00


    def __init__(self, pin_rs=25, pin_e=24, pins_db=[23, 17, 21, 22]):

        self.pin_rs = pin_rs
        self.pin_e = pin_e
        self.pins_db = pins_db

        GPIO.setmode(GPIO.BCM)
        # set the control pins as outputs
        GPIO.setup(self.pin_e, GPIO.OUT)
        GPIO.setup(self.pin_rs, GPIO.OUT)
       
        # set the data pins as outputs
        for pin in self.pins_db:
            GPIO.setup(pin, GPIO.OUT)

        # pull the control pins low
        GPIO.output(self.pin_rs, False)
        GPIO.output(self.pin_e, False)

        # special setup sauce
        self.write4bits(0x03)
        self.delayMicroseconds(5000)
        self.write4bits(0x02)
        self.delayMicroseconds(5000)
        self.write4bits(0x02)
        self.delayMicroseconds(5000)
        self.write4bits(0x08)
        self.delayMicroseconds(5000)

        # turn off
        self.write4bits(0x08)
        self.delayMicroseconds(5000)
        # clear display
        self.write4bits(0x01)
        self.delayMicroseconds(5000)
        # set entry mode
        self.write4bits(0x06)
        self.delayMicroseconds(5000)
        # home cursor
        self.write4bits(0x02)
        self.delayMicroseconds(5000)
        # turn on - enable cursor and blink
        self.write4bits(0x0c)
        self.delayMicroseconds(5000)


    def begin(self, cols, lines):

        if (lines > 1):
            self.numlines = lines
            self.displayfunction |= self.LCD_2LINE
            self.currline = 0


    def home(self):

        self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero
        self.delayMicroseconds(2000) # this command takes a long time!

   
    def clear(self):

        self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display
        self.delayMicroseconds(2000)    # 2000 microsecond sleep, clearing the display takes a long time


    def setCursor(self, col, row):

        self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ]

        if ( row > self.numlines ):
            row = self.numlines - 1 # we count rows starting w/0

        self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))


    def noDisplay(self):
        """ Turn the display off (quickly) """

        self.displaycontrol &= ~self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)


    def display(self):
        """ Turn the display on (quickly) """

        self.displaycontrol |= self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)


    def noCursor(self):
        """ Turns the underline cursor on/off """

        self.displaycontrol &= ~self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)


    def cursor(self):
        """ Cursor On """

        self.displaycontrol |= self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)


    def noBlink(self):
        """ Turn on and off the blinking cursor """

        self.displaycontrol &= ~self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)


    def noBlink(self):
        """ Turn on and off the blinking cursor """

        self.displaycontrol &= ~self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)


    def DisplayLeft(self):
        """ These commands scroll the display without changing the RAM """

        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT)


    def scrollDisplayRight(self):
        """ These commands scroll the display without changing the RAM """

        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT);


    def leftToRight(self):
        """ This is for text that flows Left to Right """

        self.displaymode |= self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode);


    def rightToLeft(self):
        """ This is for text that flows Right to Left """
        self.displaymode &= ~self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)


    def autoscroll(self):
        """ This will 'right justify' text from the cursor """

        self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)


    def noAutoscroll(self):
        """ This will 'left justify' text from the cursor """

        self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)


    def write4bits(self, bits, char_mode=False):
        """ Send command to LCD """

        self.delayMicroseconds(1000) # 1000 microsecond sleep

        bits=bin(bits)[2:].zfill(8)

        GPIO.output(self.pin_rs, char_mode)

        for pin in self.pins_db:
            GPIO.output(pin, False)

        for i in range(4):
            if bits[i] == "1":
                GPIO.output(self.pins_db[::-1][i], True)

        self.pulseEnable()

        for pin in self.pins_db:
            GPIO.output(pin, False)

        for i in range(4,8):
            if bits[i] == "1":
                GPIO.output(self.pins_db[::-1][i-4], True)
        # added 50 us delay
        self.delayMicroseconds(50)
        self.pulseEnable()


    def delayMicroseconds(self, microseconds):
        seconds = microseconds / 1000000    # divide microseconds by 1 million for seconds
        sleep(seconds)


    def pulseEnable(self):
        GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)        # 1 microsecond pause - enable pulse must be > 450ns
        GPIO.output(self.pin_e, True)
        # changed to 50 us
        self.delayMicroseconds(50)        # 1 microsecond pause - enable pulse must be > 450ns
        GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)        # commands need > 37us to settle


    def message(self, text):
        """ Send string to LCD. Newline wraps to second line"""

        for char in text:
            if char == '\n':
                self.write4bits(0xC0) # next line
            else:
                self.write4bits(ord(char),True)


if __name__ == '__main__':

    lcd = Adafruit_CharLCD()

    lcd.clear()
    lcd.message("  Adafruit 16x2\n  Standard LCD")

uhclem
 
Posts: 46
Joined: Sun Jul 08, 2007 5:03 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by adafruit_support_bill on Sat Sep 08, 2012 6:08 am

I've got the r/w pin grounded since in the Arduino library it never seems to leave the LOW state.

As mentioned two posts up, you need to use the R/W line with these displays.
User avatar
adafruit_support_bill
 
Posts: 28171
Joined: Sat Feb 07, 2009 9:11 am

Re: Blue OLED 16x2 Display not acting like LCD Versions

by uhclem on Mon Sep 10, 2012 8:23 am

Ah there it is in Adafruit_CharacterOLED::waitForReady - it goes high there. I'll post the python code once I get it working.

Thanks! I can't wait to see this work. A regular LCD literally "pales" in comparison!
uhclem
 
Posts: 46
Joined: Sun Jul 08, 2007 5:03 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by uhclem on Thu Sep 13, 2012 10:14 pm

Not quite working. I get the feeling it's still not getting properly initialized. I'll see if I can catch the rw pin and d7 doing their thing (or not) on my scope.
0913122302.png
0913122302.png (415.99 KiB) Viewed 2395 times
uhclem
 
Posts: 46
Joined: Sun Jul 08, 2007 5:03 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by JD3 on Fri Sep 14, 2012 3:26 pm

Try including the wire library first.
Then include the LCD library.
Saw that on another website.......


#include <Wire.h>
#include <LiquidCrystal.h>
That little black caterpillar you just stepped on will set you back a few bucks....
JD3
 
Posts: 101
Joined: Sat Jul 28, 2012 7:01 am

Re: Blue OLED 16x2 Display not acting like LCD Versions

by uhclem on Fri Sep 14, 2012 9:10 pm

Getting pretty close:
0914122201.png
0914122201.png (367.71 KiB) Viewed 2375 times


On a cold power-up it does not work right but after that it does. I still have to figure out why there is no space between the characters. I think the other artifacts are due to a damaged display. I might have been too rough desoldering it from the serial backpack it came with.

Here's my code (don't forget this is python meant for python GPIO library on the Raspberry Pi):
Code: Select all | TOGGLE FULL SIZE
#!/usr/bin/python

#
# based on code from lrvick and LiquidCrystal
# lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py
# LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp
#

import RPi.GPIO as GPIO
from time import sleep

class Adafruit_CharOLED:
   
    # commands
    LCD_CLEARDISPLAY       = 0x01
    LCD_RETURNHOME       = 0x02
    LCD_ENTRYMODESET       = 0x04
    LCD_DISPLAYCONTROL       = 0x08
    LCD_CURSORSHIFT       = 0x10
    LCD_FUNCTIONSET       = 0x20
    LCD_SETCGRAMADDR       = 0x40
    LCD_SETDDRAMADDR       = 0x80
   
    # flags for display entry mode
    LCD_ENTRYRIGHT       = 0x00
    LCD_ENTRYLEFT       = 0x02
    LCD_ENTRYSHIFTINCREMENT    = 0x01
    LCD_ENTRYSHIFTDECREMENT    = 0x00
   
    # flags for display on/off control
    LCD_DISPLAYON       = 0x04
    LCD_DISPLAYOFF       = 0x00
    LCD_CURSORON       = 0x02
    LCD_CURSOROFF       = 0x00
    LCD_BLINKON       = 0x01
    LCD_BLINKOFF       = 0x00
   
    # flags for display/cursor shift
    LCD_DISPLAYMOVE       = 0x08
    LCD_CURSORMOVE       = 0x00
   
    # flags for display/cursor shift
    LCD_DISPLAYMOVE       = 0x08
    LCD_CURSORMOVE       = 0x00
    LCD_MOVERIGHT       = 0x04
    LCD_MOVELEFT       = 0x00
   
    # flags for function set
    LCD_8BITMODE       = 0x10
    LCD_4BITMODE       = 0x00
    LCD_2LINE          = 0x08
    LCD_1LINE          = 0x00
    LCD_5x10DOTS       = 0x04
    LCD_5x8DOTS       = 0x00
   
   
   
    def __init__(self, pin_rw=18, pin_rs=25, pin_e=24, pins_db=[23, 17, 21, 22]):
       
        self.pin_rw = pin_rw
        self.pin_rs = pin_rs
        self.pin_e = pin_e
        self.pins_db = pins_db
       
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.pin_rw, GPIO.OUT)
        GPIO.setup(self.pin_e, GPIO.OUT)
        GPIO.setup(self.pin_rs, GPIO.OUT)
       
        GPIO.output(self.pin_rs, False)
        GPIO.output(self.pin_e, False)
        GPIO.output(self.pin_rw, False)
       
        self.busy_pin = 22
       
        for pin in self.pins_db:
            GPIO.setup(pin, GPIO.OUT)
       
       
        # copied from Adafruit_CharacterOLED.cpp
        self.write4bits(0x03, True)
        self.delayMicroseconds(5000)
        self.write4bits(0x02, True)
        self.delayMicroseconds(5000)
        self.write4bits(0x02, True)
        self.delayMicroseconds(5000)
        self.write4bits(0x08, True)
        self.delayMicroseconds(5000)
       
        self.write4bits(0x08)
        self.delayMicroseconds(5000)
        self.write4bits(0x01)
        self.delayMicroseconds(5000)
        self.write4bits(0x06)
        self.delayMicroseconds(5000)
        self.write4bits(0x02)
        self.delayMicroseconds(5000)
        self.write4bits(0x0c)
        self.delayMicroseconds(5000)
       
        # self.write4bits(0x33) # initialization
        # self.write4bits(0x32) # initialization
        # self.write4bits(0x28) # 2 line 5x7 matrix
        # self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor
        # self.write4bits(0x06) # shift cursor right
        self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF
       
        self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS
        self.displayfunction |= self.LCD_2LINE
       
        """ Initialize to default text direction (for romance languages) """
        self.displaymode =  self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) #  set the entry mode
       
        self.clear()
   
   
    def begin(self, cols, lines):
       
        if (lines > 1):
            self.numlines = lines
          self.displayfunction |= self.LCD_2LINE
            self.currline = 0
   
    def waitForReady(self):
        self.busy = True
        GPIO.setup(self.busy_pin, GPIO.IN)
        GPIO.output(self.pin_rs, False)
        GPIO.output(self.pin_rw, True)
       
        while True:
            GPIO.output(self.pin_e, False)
            GPIO.output(self.pin_e, True)
           
            self.delayMicroseconds(10)
            self.busy = GPIO.input(self.busy_pin)
            GPIO.output(self.pin_e, False)
            self.pulseEnable()
            if (self.busy == False):
                break
       
        GPIO.setup(self.busy_pin, GPIO.OUT)
        GPIO.output(self.pin_rw, False)
   
   
    def home(self):
       
        self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero
        self.delayMicroseconds(2000) # this command takes a long time!
   
   
    def clear(self):
       
        self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display
        self.delayMicroseconds(2000)   # 2000 microsecond sleep, clearing the display takes a long time
   
   
    def setCursor(self, col, row):
       
        self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ]
       
        if ( row > self.numlines ):
            row = self.numlines - 1 # we count rows starting w/0
       
        self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))
   
   
    def noDisplay(self):
        """ Turn the display off (quickly) """
       
        self.displaycontrol &= ~self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
   
   
    def display(self):
        """ Turn the display on (quickly) """
       
        self.displaycontrol |= self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
   
   
    def noCursor(self):
        """ Turns the underline cursor on/off """
       
        self.displaycontrol &= ~self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
   
   
    def cursor(self):
        """ Cursor On """
       
        self.displaycontrol |= self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
   
   
    def noBlink(self):
        """ Turn on and off the blinking cursor """
       
        self.displaycontrol &= ~self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
   
   
    def noBlink(self):
        """ Turn on and off the blinking cursor """
       
        self.displaycontrol &= ~self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
   
   
    def DisplayLeft(self):
        """ These commands scroll the display without changing the RAM """
       
        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT)
   
   
    def scrollDisplayRight(self):
        """ These commands scroll the display without changing the RAM """
       
        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT);
   
   
    def leftToRight(self):
        """ This is for text that flows Left to Right """
       
        self.displaymode |= self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode);
   
   
    def rightToLeft(self):
        """ This is for text that flows Right to Left """
        self.displaymode &= ~self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
   
   
    def autoscroll(self):
        """ This will 'right justify' text from the cursor """
       
        self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
   
   
    def noAutoscroll(self):
        """ This will 'left justify' text from the cursor """
       
        self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
   
   
    def write4bits(self, bits, char_mode=False):
        """ Send command to LCD """
       
        self.delayMicroseconds(1000) # 1000 microsecond sleep
       
        bits=bin(bits)[2:].zfill(8)
       
        GPIO.output(self.pin_rs, char_mode)
       
        for pin in self.pins_db:
            GPIO.output(pin, False)
       
        for i in range(4):
            if bits[i] == "1":
                GPIO.output(self.pins_db[::-1][i], True)
       
        self.pulseEnable()
       
        for pin in self.pins_db:
            GPIO.output(pin, False)
       
        for i in range(4,8):
            if bits[i] == "1":
                GPIO.output(self.pins_db[::-1][i-4], True)
       
        self.pulseEnable()
        self.waitForReady()
   
   
    def delayMicroseconds(self, microseconds):
        seconds = microseconds / 1000000   # divide microseconds by 1 million for seconds
        sleep(seconds)
   
   
    def pulseEnable(self):
        GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)      # 1 microsecond pause - enable pulse must be > 450ns
        GPIO.output(self.pin_e, True)
        self.delayMicroseconds(1)      # 1 microsecond pause - enable pulse must be > 450ns
        GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)      # commands need > 37us to settle
   
   
    def message(self, text):
        """ Send string to LCD. Newline wraps to second line"""
       
        for char in text:
            if char == '\n':
                self.write4bits(0xC0) # next line
            else:
                self.write4bits(ord(char),True)


if __name__ == '__main__':
   
    lcd = Adafruit_CharOLED()
   
    lcd.clear()
    lcd.message("  Adafruit 16x2\n  Standard LCD")
uhclem
 
Posts: 46
Joined: Sun Jul 08, 2007 5:03 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by lardconcepts on Thu Feb 14, 2013 7:36 pm

uhclem wrote:On a cold power-up it does not work right but after that it does. I still have to figure out why there is no space between the characters.
Here's my code (don't forget this is python meant for python GPIO library on the Raspberry Pi):


MASSIVE respect and thanks! I'd been struggling for DAYS with this. Winstar datasheets are horribly broken, sections missing, fonts not properly embedded, incorrect initialisation information etc.

Fortunately, with a combination of your code and a couple of other helpful sites, I think I've figured out the character part of things. I've certainly got it to come on reliably, first time, every time, from cold. But,like yours, there's no spacing between the letters.

See this video for demo http://www.youtube.com/watch?v=jvXbHtohVCM

Still can't get proper initialisation AND the second line to display. Seems to be one or the other. Lines wrap 1,3 and 2,4 but I've yet to get lines 2 and 4 working at all. Line 1 used to wrap to line 3 with the "old" initialisation code, but when the display was cold booted, it showed part of line 3 on line one, then the next display refresh would sort it out.

The greatest extra help came from http://web.alfredstate.edu/weimandn/lcd ... index.html who deciphered the Winstar datasheets. I also found this helpful http://www.8051projects.net/lcd-interfa ... mmands.php

I'm having a MASSIVE headache trying to work out graphics mode, I mean, dot addressable graphics of the whole display, not just the custom 5x8 characters. I'd really appreciate some help.
Even if someone could just explain, in simpletons language that I can understand, how to place a dot at 0,1 then 0,2 then 1,1 and so on. Then at least I could have some hope of building my extra large characters. Unless, of course, someone's already done it. Not finding much from Google on the Raspberry Pi front.

I've posted my working character code at https://gist.github.com/lardconcepts/4947360 where it'll be updated.

Some of it's a bit redundant now, but I've kept it in for future reference.
lardconcepts
 
Posts: 1
Joined: Thu Feb 07, 2013 2:09 pm

Re: Blue OLED 16x2 Display not acting like LCD Versions

by uhclem on Wed Apr 17, 2013 8:30 pm

I am glad this was helpful. I don't recall having problems with the second line.

Someone has definitely figured this display out, since I have used it with a serial backpack which somehow spaces the characters properly and knows how to get big characters as well. Just a question of if they will share how they did it.
uhclem
 
Posts: 46
Joined: Sun Jul 08, 2007 5:03 pm