Raspberry Pi - LCD display 1602


01.11.2014

WH1602D Одні з найпопулярніших дисплеїв - це символьні LCD дисплеї. Вони можуть бути різних розмірів та відрізнятися кількістю рядків і символів. Найпопулярніший з них 1602 - тобто по 16 символів у двох рядках. Раніше я писав про символьні дисплеї у статті Использование cимвольных жидкокристаллических LCD дисплеев. Пример на GCC (WinAVR) для Atmega 8. Вони дуже добре себе зарекомендували. Приєднаємо дисплей WH1602 до Raspberry Pi за наступною схемою:

WH1602

1 : GND 2 : 5V 3 : Contrast (0-5V) 4 : RS (Register Select) -> GPIO25 5 : R/W (Read Write) -> GND 6 : Enable or Strobe -> GPIO24 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 -> GPIO23 12: Data Bit 5 -> GPIO17 13: Data Bit 6 -> GPIO27 14: Data Bit 7 -> GPIO22

Для роботи з рядковим дисплеєм WH1602 існує бібліотека у проекті Adafruit-Raspberry-Pi-Python-Code. Клонуємо його:


git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git

Після цього треба у файлі Adafruit_CharLCD.py перевірити які ноги використовуються. Справа в тому, що у Raspberry Pi B rev2.0 замінили GPIO21  на GPIO27. Тому треба скоригувати номер ноги у відповідності з версією вашого Raspberry Pi.


cd ./Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCD
nano Adafruit_CharLCD.py:

Заміняємо (21 на 27) (у нас rev2.0): було:


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

стало:


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

Запускаємо приклад:


python Adafruit_CharLCD_IPclock_example.py

Насолоджуємося. Якщо бажаєте щось простіше, можна використати цей скрипт:


#!/usr/bin/python
import RPi.GPIO as GPIO
import time

# Define GPIO to LCD mapping
LCD_RS = 25
LCD_E  = 24
LCD_D4 = 23
LCD_D5 = 17
LCD_D6 = 27
LCD_D7 = 22

# Define some device constants
LCD_WIDTH = 16    # Maximum characters per line
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line

# Timing constants
E_PULSE = 0.00005
E_DELAY = 0.00005

def main():
  # Main program block

  GPIO.setmode(GPIO.BCM)       # Use BCM GPIO numbers
  GPIO.setup(LCD_E, GPIO.OUT)  # E
  GPIO.setup(LCD_RS, GPIO.OUT) # RS
  GPIO.setup(LCD_D4, GPIO.OUT) # DB4
  GPIO.setup(LCD_D5, GPIO.OUT) # DB5
  GPIO.setup(LCD_D6, GPIO.OUT) # DB6
  GPIO.setup(LCD_D7, GPIO.OUT) # DB7

  # Initialise display
  lcd_init()

  # Send some test
  lcd_byte(LCD_LINE_1, LCD_CMD)
  lcd_string("Raspberry Pi")
  lcd_byte(LCD_LINE_2, LCD_CMD)
  lcd_string("Model B")

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD)
  lcd_byte(0x32,LCD_CMD)
  lcd_byte(0x28,LCD_CMD)
  lcd_byte(0x0C,LCD_CMD)
  lcd_byte(0x06,LCD_CMD)
  lcd_byte(0x01,LCD_CMD)

def lcd_string(message):
  # Send string to display

  message = message.ljust(LCD_WIDTH," ")

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

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = data
  # mode = True  for character
  #        False for command

  GPIO.output(LCD_RS, mode) # RS

  # High bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x10==0x10:
    GPIO.output(LCD_D4, True)
  if bits&0x20==0x20:
    GPIO.output(LCD_D5, True)
  if bits&0x40==0x40:
    GPIO.output(LCD_D6, True)
  if bits&0x80==0x80:
    GPIO.output(LCD_D7, True)

  # Toggle `Enable` pin
  time.sleep(E_DELAY)
  GPIO.output(LCD_E, True)
  time.sleep(E_PULSE)
  GPIO.output(LCD_E, False)
  time.sleep(E_DELAY)

  # Low bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x01==0x01:
    GPIO.output(LCD_D4, True)
  if bits&0x02==0x02:
    GPIO.output(LCD_D5, True)
  if bits&0x04==0x04:
    GPIO.output(LCD_D6, True)
  if bits&0x08==0x08:
    GPIO.output(LCD_D7, True)

  # Toggle `Enable` pin
  time.sleep(E_DELAY)
  GPIO.output(LCD_E, True)
  time.sleep(E_PULSE)
  GPIO.output(LCD_E, False)
  time.sleep(E_DELAY)

if __name__ == `__main__`:
  main()

RaspberryPi WH1602 RaspberryPi WH1602

Як бачите, нічого складного. Тепер розберемося з підсвічуванням дисплея. Дисплеї можуть мати підсвічування різного кольору на різні смаки, в деяких моделях його немає взагалі. Типи підсвічування теж можуть бути різними. Зараз нас цікавить струм, який споживають елементи підсвічування. Деякі можуть споживати майже 500мА. Так! пів ампера! Тому, перед тим як вмикати підсвічування дисплея, поцікавтеся - чи потягне Ваш блок живлення такий струм?

Програмне керування підсвічуванням дисплея

Ми вже з`ясували, що струм підсвічування може сягати значно більшого, ніж може витримати нога Raspberry Pi. Щоб керувати підсвічуванням, включимо його, як вказано на схемі.

WH1602_LIGHT

Оптопара захищає ноги Raspberry Pi від потрапляння на них напруги, яка подається на підсвічування. Вона вища за ту напругу, яку може витримати Raspberry Pi. Але сама оптопара не може комутувати потрібний нам струм, тому встановлено більш потужний транзистор. Звісно, транзистор має витримувати струм, який споживає підсвічування, з деяким запасом. У моєму випадку підсвічування споживало 420мА при напрузі 6,4В, а транзистор витримує 1 А.

RaspberryPi WH1602 RaspberryPi WH1602

Тепер ми можемо підключити вхід оптопари до ноги GPIO18 та вмикати і вимикати світло. Взагалі, можна підключити до іншої ноги, але на GPIO18 виведений апаратній ШІМ (PWM). PWM будемо використовувати трохи пізніше. Докладніше про PWM у статті Raspberry Pi — PWM і Сервопривод

Налаштовуємо GPIO18:


echo 18 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio18/direction

Вмикаємо підсвічування:


echo 1 > /sys/class/gpio/gpio18/value

Вимикаємо підсвічування:


echo 0 > /sys/class/gpio/gpio18/value

Якщо потрібно привернути увагу до показань на дисплеєві, можна поморгати підсвічуванням. Наприклад, коли якісь значення досягають довгоочікуваного рівня. Або навпаки - є небезпечними.

Але, просто вмикати і вимикати - це сумно. Спробуємо регулювати яскравість підсвічування. Це дозволить налаштувати яскравість підсвічування за бажанням або змінювати автоматично, наприклад, в залежності від освітлення. Регулювати яскравість будемо за допомогою PWM. Для генерації PWM використаємо апаратні можливості Raspberry Pi. Це зменшить навантаження на процесор. Підключимо вхід оптопари до ноги GPIO18 та налаштуємо PWM. Ми будемо використовувати WiringPi. Встановіть WiringPi, якщо він у Вас ще не встановлений:


sudo apt-get install git-core
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
cd ..

Налаштовуємо PWM:


gpio mode 1 pwm

Змінюючи значення від 0 до 1023 коригуємо яскравість підсвічування. На практиці, найбільш помітні зміни яскравості - при значеннях pwm від 0 до 80.


gpio pwm 1 10

Я зняв невеличке демонстраційне відео, на якому відпрацьовує наступний скрипт плавного вмикання підсвічування lcd_light_smooth_on.bash:


#!/bin/bash

#PWM
gpio mode 1 pwm

for (( c=1; c<=50; c++ ))
do
  gpio pwm 1 $c
  sleep 0.01
done

Скрипт плавного вимикання підсвічування: lcd_light_smooth_off.bash:


#!/bin/bash

#PWM
gpio mode 1 pwm

for (( c=50; c>0; c-- ))
do
  gpio pwm 1 $c
  sleep 0.01
done

gpio pwm 1 0

Та загальний тестовий скрипт lcd_light.bash:


#!/bin/bash

echo 18 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio18/direction
#ON
echo 1 > /sys/class/gpio/gpio18/value
sleep 3
#OFF
echo 0 > /sys/class/gpio/gpio18/value
sleep 2

for (( c=1; c<=5; c++ ))
do
  #BLINK
  echo 1 > /sys/class/gpio/gpio18/value
  sleep 0.1
  #OFF
  echo 0 > /sys/class/gpio/gpio18/value
  sleep 0.1
done

echo 18 > /sys/class/gpio/unexport

#PWM
gpio mode 1 pwm

gpio pwm 1 1000
sleep 1
gpio pwm 1 100
sleep 1
gpio pwm 1 50
sleep 1
gpio pwm 1 10
sleep 1
gpio pwm 1 5

sleep 2

for (( i=1; i<=5; i++ ))
do
  for (( c=1; c<=50; c++ ))
  do
    gpio pwm 1 $c
    sleep 0.01
  done

  for (( c=50; c>0; c-- ))
  do
    gpio pwm 1 $c
    sleep 0.01
  done
done

gpio unexportall

Команди налаштування підсвічування дисплею можна розташувати в стартові скрипти, або прописати скрипт в crontab, щоб у вечері вмикати підсвічування, а вдень - вимикати, або коригувати яскравість по годиннику або в залежності від освітлення.

Успіхів.

P.S. Якщо ви використовуєте WH1602D. Я маю на увазі саме літеру D, і у Вас нічого не працює, не хвилюйтеся. Зазирніть у документацію. Саме у дисплеїв з літерою D живлення подається навпаки: PIN1-> 5V, PIN2-> GND.

Дивись також:

Raspberry Pi
Коментарі:
Додати коментар
Code
* - обов'язкові поля

Архіви