Jump to content

Using 16x2 ('1602') LCD with I2C connector with Orange Pi PC


Recommended Posts

Hi All,

 

I recently bought a cheap 16 character, 2 row LCD display from aliexpress.com for use with my Orange Pi PC. I got it to work without too much pain, but I thought I would document it here for the benefit of others. Some good instructions are already available on the internet, but there are some tweaks required for the Orange PI.

 

Armbian I believe already has the I2C module compiled into the kernel directly. So no Linux Kernal insmod work required, unlike what many Raspberry PI guides seem to imply.

 

Step 1) Buy the things you will need.

 

1. You obviously need a 1602 LCD module which also comes with the the I2C converter. You can buy a 1602 LCD and wire it directly to the 16 GPIO pins required if you want, but that isn't the point of this guide.

2. You will need a level shifter. The LCD display works on +5volts. The OrangePI/H3 GPIO pins are 3.3 volts. I have seen guides stating that you don't need a level shifter, but I'm sure you're slowly frying some transistors in your OrangePI over time.

3. You will need a bunch of jumper cables etc. Like these, female to female only required really.

 

Step 2) Wire things up accordingly.

Thanks to this fantastic guide, the instructions on wiring the Orange PI to the Level Shifter LV ('low voltage') pins, and then the Level Shifter HV ('high voltage') pins to the 1602 I2C module is pretty clear: http://www.raspberrypi-spy.co.uk/2015/05/using-an-i2c-enabled-lcd-screen-with-the-raspberry-pi/

 

 

Level Shifter OrangePI 1602 I2C Backpack
LV 3.3V (pin 1)
LV1 SDA (pin 3)
LV2 SCL (pin 5)
GND GND (pin 6) GND
HV 5V (pin 2) VCC
HV1   SDA
HV2   SCL

 

Note, you connect the 1602 I2C module/backpack directly to the 5Volt Pin on the PI (Pin 2 or 4) and Ground (Pin 6) respectively.

 

Note: For some strange reason the level shifter works if you don't connect the ground pins to either side of it (i.e. Use the LV, LV1, LV2, HV, HV1 and HV2 pins only). No idea why - electrical engineering degree required I think.

 

If all works well, you should see the LCD module light-up with the top row being a bunch of white bars (you might need to check the contrast setting of the module as well). White bars = uninitialised LCD screen.

 

592b114c59a62_IMG_20170528_1904172951.thumb.jpg.a97e7deb7680b5a90fc686321151f8c5.jpg

 

Step 3) Install the required packages int Armbian

Reference:  https://www.abelectronics.co.uk/kb/article/1061/i2c--smbus-and-armbian-linux

sudo apt-get install -y python-smbus i2c-tools

Step 4) Check to see what the address of the LCD Screen is:

 

Reference: http://www.raspberrypi-spy.co.uk/2014/11/enabling-the-i2c-interface-on-the-raspberry-pi/

user@orangepipc:~/Downloads/i2c$  sudo i2cdetect -y 0
[sudo] password for userpi:
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3f
40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

user@orangepipc:~/Downloads/i2c$  sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Looks like it's 0x3f as the address on I2C bus 0 (which is apparently right according to the aliexpress buyer feedback comments)

 

Step 5) Download Example Script

 

Reference: http://www.raspberrypi-spy.co.uk/2015/05/using-an-i2c-enabled-lcd-screen-with-the-raspberry-pi/

 

The example script will allow you to send text to the screen via I2C. It is very similar to my scripts for the normal 16×2 screen. To download the script directly to your Pi you can use :

 

wget https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/lcd_i2c.py

 

Step 6) Adjust the Sample Script

 

I need to adjust the script to reference a 1602 LCD device with address 0x3f, on Orange Pi PC I2C Bus, 0. The script as it is references a device of 0x27 on Bus 1 - it won't work. You might have a LCD device of address 0x27 (you'll know from the previous step), but it seems many of the cheap LCD modules from aliexpress are 0x3f for some reason.

 

Adjusted script below:

 

#!/usr/bin/python
#--------------------------------------
#    ___  ___  _ ____
#   / _ \/ _ \(_) __/__  __ __
#  / , _/ ___/ /\ \/ _ \/ // /
# /_/|_/_/  /_/___/ .__/\_, /
#                /_/   /___/
#
#  lcd_i2c.py
#  LCD test script using I2C backpack.
#  Supports 16x2 and 20x4 screens.
#
# Author : Matt Hawkins
# Date   : 20/09/2015
#
# http://www.raspberrypi-spy.co.uk/
#
# Copyright 2015 Matt Hawkins
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#--------------------------------------
import smbus
import time

# Define some device parameters
I2C_ADDR  = 0x3f # I2C device address
LCD_WIDTH = 16   # Maximum characters per line

# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line

LCD_BACKLIGHT  = 0x08  # On
#LCD_BACKLIGHT = 0x00  # Off

ENABLE = 0b00000100 # Enable bit

# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005

#Open I2C interface
bus = smbus.SMBus(0)  # Rev 1 Pi uses 0 (and Orange PI PC, for pins 3 and 5)
#bus = smbus.SMBus(1) # Rev 2 Pi uses 1

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD) # 110011 Initialise
  lcd_byte(0x32,LCD_CMD) # 110010 Initialise
  lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
  lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off 
  lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
  lcd_byte(0x01,LCD_CMD) # 000001 Clear display
  time.sleep(E_DELAY)

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = the data
  # mode = 1 for data
  #        0 for command

  bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
  bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT

  # High bits
  bus.write_byte(I2C_ADDR, bits_high)
  lcd_toggle_enable(bits_high)

  # Low bits
  bus.write_byte(I2C_ADDR, bits_low)
  lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
  # Toggle enable
  time.sleep(E_DELAY)
  bus.write_byte(I2C_ADDR, (bits | ENABLE))
  time.sleep(E_PULSE)
  bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
  time.sleep(E_DELAY)

def lcd_string(message,line):
  # Send string to display

  message = message.ljust(LCD_WIDTH," ")

  lcd_byte(line, LCD_CMD)

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def main():
  # Main program block

  # Initialise display
  lcd_init()

  while True:

    # Send some test
    lcd_string("RPiSpy         <",LCD_LINE_1)
    lcd_string("I2C LCD        <",LCD_LINE_2)

    time.sleep(3)
  
    # Send some more text
    lcd_string(">         RPiSpy",LCD_LINE_1)
    lcd_string(">        I2C LCD",LCD_LINE_2)

    time.sleep(3)

if __name__ == '__main__':

  try:
    main()
  except KeyboardInterrupt:
    pass
  finally:
    lcd_byte(0x01, LCD_CMD)

 

Step 7) ADD YOUR USER ACCOUNT TO 'i2c' GROUP

 

This is a really useful thing to do, otherwise you'll need to run the python script as ROOT (via. sudo etc.) every  time. No good if you want to write a python script that runs using your normal user account and sends messages over I2C to the LCD.

 

Reference: https://www.abelectronics.co.uk/kb/article/1061/i2c--smbus-and-armbian-linux

sudo adduser <YOUR_USER_ID> i2c

eg: sudo adduser johnsmith i2c

 

Step 8) Run your script!

 

python lcd_i2c.py

Amazing!

 

IMG_20170528_182639086.thumb.jpg.f80f01699476e683feecc840e209df35.jpg

 

Please note: You can probably use a more advanced library to output data to the LCD, but for now, it probably isn't required:

https://gist.github.com/DenisFromHR (you will need to adjust the code in 'RPi_I2C_driver.py' to refer to port=0, not port=1 to get this to work. Also change the address of the LCD device if required)

http://www.circuitbasics.com/raspberry-pi-i2c-lcd-set-up-and-programming/ 

 

What a level shifter looks like:

 

LevelShifter.jpg

Link to comment
Share on other sites

13 hours ago, gungsukma said:

But if I power the LCD and I2C module with 3.3V, it shouldn't output 5V, right?

 

If  run the LCD screen + IC2 module off the 3.3volt rail directly, you won't need a level converter. When I tried using the 3.3volts to power the LCD the screen was really dim/dull. I didn't check to see if it worked though. If it did, then you've saved yourself a bit of hassle :-) 

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines