Last active
August 29, 2015 14:16
-
-
Save mattbrailsford/c262d0074683a2442d0d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# | |
# OLED Library for Raspberry Pi | |
# | |
# Author : Matt Brailsford/Robert Coward/Paul Carpenter (based on driver by Matt Hawkins/) | |
# Site : http://www.raspberrypi-spy.co.uk | |
# http://www.pcserviceslectronics.co.uk | |
# http://www.circuitbeard.co.uk | |
# | |
# Date : 06/03/2015 | |
# | |
# The wiring for the OLED is as follows: | |
# 1 : GND | |
# 2 : 5V | |
# 3 : Contrast (0-5V)* - NOT USED | |
# 4 : RS (Register Select) | |
# 5 : R/W (Read Write) - GROUND THIS PIN | |
# 6 : Enable or Strobe | |
# 7 : Data Bit 0 - NOT USED | |
# 8 : Data Bit 1 - NOT USED | |
# 9 : Data Bit 2 - NOT USED | |
# 10: Data Bit 3 - NOT USED | |
# 11: Data Bit 4 | |
# 12: Data Bit 5 | |
# 13: Data Bit 6 | |
# 14: Data Bit 7 | |
# 15: LCD Backlight +5V** - NOT USED | |
# 16: LCD Backlight GND - NOT UDES | |
import RPi.GPIO as GPIO | |
import time | |
class OLED: | |
# Timing constants for low level write operations | |
# NOTE: Enable cycle time must be at least 1 microsecond | |
# NOTE2: Actually, these can be zero and the LCD will typically still work OK | |
EDEL_TAS = 0.00001 # Address setup time (TAS) | |
EDEL_PWEH = 0.00001 # Pulse width of enable (PWEH) | |
EDEL_TAH = 0.00001 # Address hold time (TAH) | |
# Timing constraints for initialisation steps - IMPORTANT! | |
# Note that post clear display must be at least 6.2ms for OLEDs, as opposed | |
# to only 1.4ms for HD44780 LCDs. This has caused confusion in the past. | |
DEL_INITMID = 0.01 # middle of initial write (min 4.1ms) | |
DEL_INITNEXT = 0.0002 # post second initial write (min 100ns) | |
DEL_POSTCLEAR = 0.01 # post clear display step (busy, min 6.2ms) | |
ROW_OFFSETS = [ 0x00, 0x40, 0x14, 0x54 ] | |
LCD_CLEAR = 0x01 | |
LCD_HOME = 0x02 | |
LCD_CGRAM = 0x40 | |
LCD_DGRAM = 0x80 | |
LCD_CHR = True | |
LCD_CMD = False | |
def __init__(self, pinmap, columns = 16, rows = 2): | |
# Store values | |
self.pinmap = pinmap | |
self.lcdPins = [ self.pinmap['D7'], self.pinmap['D6'], self.pinmap['D5'], self.pinmap['D4'] ] | |
self.columns = columns | |
self.rows = rows | |
# Configure the GPIO to drive the LCD display correctly | |
GPIO.setmode(GPIO.BCM) # Use BCM GPIO numbers | |
GPIO.setwarnings(False) | |
# setup all output pins for driving LCD display | |
GPIO.setup(self.pinmap['E'], GPIO.OUT) # E | |
# PC - better safe starting state | |
GPIO.output(self.pinmap['E'], 0) # set low as idle state | |
GPIO.setup(self.pinmap['RS'], GPIO.OUT) # RS | |
# PC - more maintainable initialisation | |
for val in self.lcdPins: # enable DB7 to DB4 | |
GPIO.setup(val, GPIO.OUT) | |
GPIO.output(val, 0) # set low | |
# Initialise display into 4 bit mode, using recommended delays | |
self.write_byte(0x33, self.LCD_CMD, self.DEL_INITNEXT, self.DEL_INITMID) | |
self.write_byte(0x32, self.LCD_CMD, self.DEL_INITNEXT) | |
# Now perform remainder of display init in 4 bit mode - IMPORTANT! | |
# These steps MUST be exactly as follows, as OLEDs in particular are rather fussy | |
self.write_byte(0x28, self.LCD_CMD, self.DEL_INITNEXT) # two lines and correct font | |
self.write_byte(0x08, self.LCD_CMD, self.DEL_INITNEXT) # display OFF, cursor/blink off | |
self.write_byte(0x01, self.LCD_CMD, self.DEL_POSTCLEAR) # clear display, waiting for longer delay | |
self.write_byte(0x06, self.LCD_CMD, self.DEL_INITNEXT) # entry mode set | |
# extra steps required for OLED initialisation (no effect on LCD) | |
self.write_byte(0x17, self.LCD_CMD, self.DEL_INITNEXT) # character mode, power on | |
# now turn on the display, ready for use - IMPORTANT! | |
self.write_byte(0x0C, self.LCD_CMD, self.DEL_INITNEXT) # display on, cursor/blink off | |
# ============================================================================== | |
# Defines a new custom character in the CGRAM | |
# The index specifies the CGRAM character index you wish to define | |
# The data specifies the character patern | |
def define_char(self, index, data): | |
self.write_byte(self.LCD_CGRAM | ((index & 7) << 3), self.LCD_CMD, 0.002) | |
for i in range(0, 8): | |
self.write_byte(data[i], self.LCD_CHR) | |
# ============================================================================== | |
# Puts the cursor back in the home position | |
def home(self): | |
self.write_byte(self.LCD_HOME, self.LCD_CMD, 0.005) | |
# ============================================================================== | |
# Clears the LCD screen | |
def clear(self): | |
self.write_byte(self.LCD_HOME, self.LCD_CMD) | |
self.write_byte(self.LCD_CLEAR, self.LCD_CMD, 0.005) | |
# ============================================================================== | |
# Sets the cursor to a specific position | |
def set_position(self, x, y): | |
if ((x > self.columns) or (x < 0)): | |
return | |
if ((y > self.rows) or (y < 0)): | |
return | |
self.write_byte(x + (self.LCD_DGRAM | self.ROW_OFFSETS[y]), self.LCD_CMD) | |
# ============================================================================== | |
# Outputs string of characters to the LCD display line | |
# NOTE: Incoming string MUST be a string of simple characters with no complex | |
# unicode types present, as otherwise incorrect encoding will occur. | |
def write_string(self, message): | |
for i in range(len(message)): | |
self.write_char(ord(message[i])R) | |
# ============================================================================== | |
# Outputs char to the LCD display line | |
# NOTE: Incoming char MUST be a simple character and not a complex | |
# unicode type, as otherwise incorrect encoding will occur. | |
def write_char(self, char): | |
self.write_byte(char, self.LCD_CHR) | |
# ============================================================================== | |
# Low level routine to output a byte of data to the LCD display | |
# over the 4 bit interface. Two nybbles are sent, one after the other. | |
# The post_delay specifies optional delay to cover busy periods | |
# The mid_delay specifies optional delay between the 4 bit nibbles (special case) | |
def write_byte(self, byteVal, mode, post_delay = 0, mid_delay = 0): | |
# convert incoming value into 8 bit array, padding as required | |
bits = bin(byteVal)[2:].zfill(8) | |
# set mode = True for character, False for command | |
GPIO.output(self.pinmap['RS'], mode) # RS | |
# Output the four High bits | |
for i in range(4): | |
GPIO.output(self.lcdPins[i], int(bits[i])) | |
# Toggle 'Enable' pin, wrapping with minimum delays | |
time.sleep(self.EDEL_TAS) | |
GPIO.output(self.pinmap['E'], True) | |
time.sleep(self.EDEL_PWEH) | |
GPIO.output(self.pinmap['E'], False) | |
time.sleep(self.EDEL_TAH) | |
# Wait for extra mid delay if specified (special case) | |
if mid_delay > 0: | |
time.sleep(mid_delay) | |
# Output the four Low bits | |
for i in range(4,8): | |
GPIO.output(self.lcdPins[i-4], int(bits[i])) | |
# Toggle 'Enable' pin, wrapping with minimum delays | |
time.sleep(self.EDEL_TAS) | |
GPIO.output(self.pinmap['E'], True) | |
time.sleep(self.EDEL_PWEH) | |
GPIO.output(self.pinmap['E'], False) | |
time.sleep(self.EDEL_TAH) | |
# Wait for extra post delay if specified (covers busy period) | |
if post_delay > 0: | |
time.sleep(post_delay) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
import time | |
import RPi.GPIO as GPIO | |
from oled import OLED | |
# Define GPIO to LCD mapping (USES BCM MODE NUMBERING scheme) | |
oled_pinmap = { | |
'RS': 22, | |
'E': 17, | |
'D4': 25, | |
'D5': 18, | |
'D6': 24, | |
'D7': 23 | |
} | |
oled = OLED(oled_pinmap, 20, 2) | |
oled.set_position(0, 0) | |
oled.write_string("Hello world!") | |
time.sleep(3) | |
oled.set_position(0, 0) | |
oled.write_string("circuitbeard.co.uk") | |
oled.set_position(0, 1) | |
oled.write_string("@circuitbeard") | |
time.sleep(3) | |
oled.set_position(0, 0) | |
oled.write_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ") | |
oled.set_position(0, 1) | |
oled.write_string("1234567890!$%^&*()") | |
time.sleep(3) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment