บทความนี้เป็นการเขียนไลบรารีเพื่อสั่งงานโมดูลแอลซีดีตัวอักษรโดยใช้การสั่งงานผ่านบัส I2C ซึ่งเลือกใช้โมดูล PCF8574 ที่ออกแบบมาเพื่อเชื่อมต่อกับแอลซีดี ทำให้สามารถใช้ขาสั่งงาน 2 ขาจาก ESP8266 ต่อสั่งงานโมดูลแอลซีดีได้ 8 ขา คือ RS, R/W, EN, A, D0, D1, D2 และ D3 พร้อมทั้งสามารถเปิด/ปิดการใช้แสงส่องหลังโมดูลแอลซีดีและปรับความชัดของตัวอักษรของโมดูลแอลซีดีได้จากตัวต้านทานปรับค่าได้ที่อยู่บนโมดูล PCF8574
อุปกรณ์
อุปกรณ์สำหรับการทดลองเป็นดังนี้
- ESP8266
- โมดูลแสดงผลแอลซีดีขนาด 16 คอลัมน์ 2 แถว หรือขนาดอื่น ๆ ได้ แต่ต้องปรับแต่งเมธอด goto() ของไลบรารี kjlcd
- 1602 2004 LCD Adapter Plate IIC I2C Interface ทางเราขอเรียกว่า โมดูล PCF8574 สำหรับเชื่อมต่อระหว่างโมดูลแอลซีดีและ ESP8266
LCD-I2C
โมดูล PCF8574 เป็นวงจรขับแอลซีดีตัวอักษรแบบขนาน (Parallel) แบบ 4 บิต และสื่อสารกับ ESP8266 ผ่านทางบัส I2C ด้วยการใช้ไอซี PCF8574 เป็นตัวรับ/ส่งข้อมูลขนาด 8 บิต จากบัส I2C และส่งข้อมูลที่รับเข้ามาไปยังโมดูลแอลซีดี ทำให้ใช้ขาของ ESP8266 เพียง 2 ขาเพื่อเชื่อมต่อสั่งงานโมดูลแอลซีดีแบบ 4 บิต (D0, D1, D2, D3) พร้อม RS, R/W, EN และ A (การเปิด/ปิดไฟหลังโมดูลแอลซีดี)
จากภาพที่ 2 จะพบว่า การใช้งานจะอาศัยโมดูล PCF8574 เป็นตัวเชื่อมต่อกับโมดูลแอลซีดี ซึ่งเป็นการเชื่อมต่อแบบขนาน และที่โมดูล PCF8574 มีจัมเปอร์ (Jumper) สำหรับเปิด/ปิดการใช้แสงหลังของแอลซีดี (backlight)
นอกจากนี้ โมดูล PCF8574 มีตัวต้านทานปรับค่าได้สำหรับปรับค่า contrast หรือค่าความสว่าง (ความเปรียบต่าง/ความชัด) ของตัวอักษรที่ปรากฎบนโมดูลแอลซีดี
การใช้งานโมดูล PCF8574 ต้องต่อสายเข้ากับขั้วต่อ 4 ขา คือ
- VCC สำหรับจ่ายไฟฟ้ากระแสตรง แรงดัน 5V (เพราะผู้เขียนใช้โมดูลแอลซีดีแบบแรงดัน 5V)
- GND สำหรับต่อกับกราวด์
- SCL สำหรับต่อเข้ากับขาให้สัญญาณนาฬิกาของบัส I2C
- SDA สำหรับต่อเข้ากับขารับ/ส่งข้อมูลของบัส I2C
การเชื่อมต่อ
การเชื่อมต่อระหว่าง ESp8266 กับโมดูล PCF8574 เป็นดังนี้ (ดูภาพที่ 3, 4 และ 5 ประกอบ)
ESP8266 | โมดูล PCF8574 |
---|---|
5V | Vcc |
GND | GND |
GPIO5 (D1) | SCL |
GPIO4 (D2) | SDA |
ไลบรารี
ไลบรารี kjlcd.py ต่อไปนี้เป็นตัวอย่างการเขียนโปรแกรมภาษาไพธอนเพื่อส่งคำสั่งและข้อมูลผ่านโมดูล PCF8574 เพื่อส่งต่อไปยังแอลซีดีตัวอักษร โดยการเชื่อมต่อระหว่างโมดูล PCF8574 และโมดูลแอลซีดีเป็นตามภาพที่ 2
การใช้งานไลบรารีต้องทำการโอนไฟล์ kjlcd.py ไปเก็บใน ESP8266 ด้วยการโยนไฟล์ผ่าน Thonny หรือใช้ ampy
การเริ่มต้นทำงานต้องกำหนดค่าตำแหน่ง lcd_addr ที่ถูกต้อง ซึ่งทางทีมผู้เขียนกำหนดค่าเริ่มต้นเอาไว้ที่ตำแหน่ง 0x38
เมธอดที่เรียกใช้งานได้ มีดังนี้
- reset( ) สำหรับให้โมดูลแอลซีดีเริ่มต้นทำงานใหม่
- write( ) สำหรับสเขียนข้อมูลหรือคำสั่งไปให้โมดูล PCF8574 ทางบัส I2C
- cmd() สำหรับส่งคำสั่งไปให้โมดูลแอลซีดีผ่านทางโมดูล PCF8574 ทางบัส I2C
- data() สำหรับส่งข้อมูลไปให้โมดูลแอลซีดีผ่านทางโมดูล PCF8574 ทางบัส I2C
- backlight() สำหรับสั่งเปิด/ปิดไฟลแอลอีดีฉากหลัง
- goto( ) สำหรับย้ายตำแหน่งเคอร์เซอร์แสดงผลของโมดูลแอลซีดี
- putc() สำหรับสั่งแสดงตัวอักษร ณ ตำแหน่งเคอร์เซอร์
- puts( ) สำหรับแสดงข้อความ ณ ตำแหน่งเคอเซอร์
# JarutEx I2C Character LCD Library
import time
class LCD():
MASK_RS = const(0x01)
MASK_RW = const(0x02)
MASK_E = const(0x04)
SHIFT_BACKLIGHT = const(3)
SHIFT_DATA = const(4)
def __init__(self, i2c, lcd_addr=0x38):
self.lcd_bl = True
self.lcd_addr = lcd_addr
self.i2c = i2c
self.reset()
def reset(self):
time.sleep_ms(250)
self.cmd(0x33)
self.cmd(0x32)
self.cmd(0x06)
self.cmd(0x0C)
self.cmd(0x28)
self.cmd(0x01)
time.sleep_ms(500)
self.backlight()
def write(self, value):
buffer = bytearray(1)
buffer[0] = value & 0xff
self.i2c.writeto(self.lcd_addr, buffer)
def cmd(self,byte):
high_nib = (byte & 0xF0)|(self.lcd_bl << SHIFT_BACKLIGHT)
low_nib = ((byte<<4) & 0xF0)|(self.lcd_bl << SHIFT_BACKLIGHT)
self.write(high_nib|MASK_E)
self.write(high_nib)
self.write(low_nib|MASK_E)
self.write(low_nib)
def data(self,byte):
high_nib = (byte & 0xF0)|MASK_RS|(self.lcd_bl << SHIFT_BACKLIGHT)
low_nib = ((byte<<4) & 0xF0)|MASK_RS|(self.lcd_bl << SHIFT_BACKLIGHT)
self.write(high_nib|MASK_E)
self.write(high_nib)
self.write(low_nib|MASK_E)
self.write(low_nib)
def backlight(self,status=True):
if status:
self.write(1<<SHIFT_BACKLIGHT)
self.lcd_bl = True
else:
self.write(0)
self.lcd_bl = False
def goto(self,x,y):
if y==1:
pos = 0xC0
else:
pos = 0x80
self.cmd(pos|x)
def putc(self,ch):
self.data(ord(ch))
def puts(self,s):
for idx in range(len(s)):
self.putc(s[idx])
ตัวอย่างโปรแกรม
ตัวอย่างโปรแกรม code13-1 เป็นการใช้ไลบรารี kjlcd เพื่อแสดงผลข้อความในบรรทัดแรกเป็น sys.platform ตามด้วยขนาดของแฟลชรอม (esp.flash_size()) และในบรรทัดที่ 2 แสดงข้อความ (C)2020,JarutEx ดังภาพที่ 6
กรณีที่โมดูลแอลซีดีไม่แสดงผลให้ทำการตรวจสอบความสว่างของการแสดงผลด้วยการปรับที่กระปุกตัวต้านทานปรับค่าได้สีน้ำเงิน และกรณีที่เกิดข้อผิดพลาดในการทำงานของไลบรารีแอลซีดีเนื่องจากไม่สามารถส่งข้อมูลไปยังโมดูล PCF8574 ได้นั้นอาจเป็นเหตุจากการต่อสาย SDA/SCL กลับกัน หรือกำหนดค่าตำแหน่งโมดูล PCF8574 ผิดพลาด (ในตัวอย่างนี้ตัวโมดูลอยู่ที่ตำแหน่ง 0x27) ให้ทำการแก้ไขค่าตำแหน่งให้ถูกต้องด้วยการกำหนดค่าตำแหน่งให้แก่ตัวแปร lcd_addr = const( ค่าตำแหน่งที่ถูกต้อง )
# code13-1
import sys
import gc
import os
import esp
import time
import math
import machine as mc
from kjlcd import LCD
scl_pin = mc.Pin(5)
sda_pin = mc.Pin(4)
i2c = mc.I2C(scl=scl_pin,sda=sda_pin)
lcd_addr= const(0x27)
lcd = LCD(i2c,lcd_addr)
lcd.goto(0,0)
lcd.puts("{}[{}]".format(sys.platform,esp.flash_size()))
lcd.goto(0,1)
lcd.puts("(C)2020,JarutEx")
สรุป
จากบทความนี้ ผู้อ่านสามารถเขียนโปรแกรมภาษาไพธอนเพื่อสั่งใช้งานโมดูลแอลซีดีที่เชื่อมต่อผ่านทางบัส I2C ซึ่งจะพบว่า การสั่งงานนั้นขึ้นอยู่กับการส่งคำสั่งและข้อมูลไปยังโมดูลแอลซีดี ซึ่งคำสั่งและวิธีการเหล่านี้จะต้องอ่านจากเอกสารประกอบอุปกรณ์แสดงผล และเปลี่ยนมาเป็นชุดคำสั่งเพื่อส่งไปให้โมดูล PCF8574 อ่านทางบัส I2C
พวกเราคิดว่าบทความนี้คงเป็นประโยชน์แก่ผู้สนใจเขียนโปรแกรมสั่งงานโมดูลแอลซีดีตัวอักษรผ่านทางบัส I2C บ้างไม่มากก็น้อย และสามารถนำไปปรับปรุงฟังก์ชันการทำงานให้มากขึ้น เนื่องจากในโมดูลแอลซีดีตัวอักษรยังมีชุดคำสั่งอีกมากมาย เช่น คำสั่งสำหรับการเปิด/ปิดเคอร์เซ้ร์ การสกรอลล์ และการเปิด/ปิดหน้าจอ เป็นต้น
สุดท้ายนี้ขอให้สนุกกับการเขียนโปรแกรมครับ
(C) 2020, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2020-10-27
ปรับปรุงเมื่อ 2021-05-15