Blue OLED 16x2 Display not acting like LCD Versions

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
erikroby
 
Posts: 5
Joined: Mon Jun 04, 2012 3:17 pm

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

Post by erikroby »

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

User avatar
techman
 
Posts: 11
Joined: Sun Jun 10, 2012 8:10 pm

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

Post by techman »

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

User avatar
rustybikes
 
Posts: 15
Joined: Sun Jul 15, 2012 2:25 pm

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

Post by rustybikes »

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.

User avatar
techman
 
Posts: 11
Joined: Sun Jun 10, 2012 8:10 pm

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

Post by techman »

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

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

User avatar
rustybikes
 
Posts: 15
Joined: Sun Jul 15, 2012 2:25 pm

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

Post by rustybikes »

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

/*
 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.. :)

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

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

Post by adafruit_support_bill »

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
rustybikes
 
Posts: 15
Joined: Sun Jul 15, 2012 2:25 pm

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

Post by rustybikes »

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... :)

User avatar
uhclem
 
Posts: 107
Joined: Sun Jul 08, 2007 6:03 pm

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

Post by uhclem »

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

#!/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")


User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

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

Post by adafruit_support_bill »

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
uhclem
 
Posts: 107
Joined: Sun Jul 08, 2007 6:03 pm

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

Post by uhclem »

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!

User avatar
uhclem
 
Posts: 107
Joined: Sun Jul 08, 2007 6:03 pm

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

Post by uhclem »

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 4231 times

JD3
 
Posts: 101
Joined: Sat Jul 28, 2012 8:01 am

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

Post by JD3 »

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


#include <Wire.h>
#include <LiquidCrystal.h>

User avatar
uhclem
 
Posts: 107
Joined: Sun Jul 08, 2007 6:03 pm

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

Post by uhclem »

Getting pretty close:
0914122201.png
0914122201.png (367.71 KiB) Viewed 4211 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

#!/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 BANNED 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")

User avatar
uhclem
 
Posts: 107
Joined: Sun Jul 08, 2007 6:03 pm

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

Post by uhclem »

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.

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”