[TH] ESP8266 and I2C LCD 16×2

บทความนี้เป็นการเขียนไลบรารีเพื่อสั่งงานโมดูลแอลซีดีตัวอักษรโดยใช้การสั่งงานผ่านบัส I2C ซึ่งเลือกใช้โมดูล PCF8574 ที่ออกแบบมาเพื่อเชื่อมต่อกับแอลซีดี ทำให้สามารถใช้ขาสั่งงาน 2 ขาจาก ESP8266 ต่อสั่งงานโมดูลแอลซีดีได้ 8 ขา คือ RS, R/W, EN, A, D0, D1, D2 และ D3 พร้อมทั้งสามารถเปิด/ปิดการใช้แสงส่องหลังโมดูลแอลซีดีและปรับความชัดของตัวอักษรของโมดูลแอลซีดีได้จากตัวต้านทานปรับค่าได้ที่อยู่บนโมดูล PCF8574

ภาพที่ 1

อุปกรณ์

อุปกรณ์สำหรับการทดลองเป็นดังนี้

  1. ESP8266
  2. โมดูลแสดงผลแอลซีดีขนาด 16 คอลัมน์ 2 แถว หรือขนาดอื่น ๆ ได้ แต่ต้องปรับแต่งเมธอด goto() ของไลบรารี kjlcd
  3. 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 ขา คือ

  1. VCC สำหรับจ่ายไฟฟ้ากระแสตรง แรงดัน 5V (เพราะผู้เขียนใช้โมดูลแอลซีดีแบบแรงดัน 5V)
  2. GND สำหรับต่อกับกราวด์
  3. SCL สำหรับต่อเข้ากับขาให้สัญญาณนาฬิกาของบัส I2C
  4. SDA สำหรับต่อเข้ากับขารับ/ส่งข้อมูลของบัส I2C
ภาพที่ 2 การต่อโมดูล I2C PCF8574 เข้ากับโมดูลแอลซีดีตัวอักษร 16×2

การเชื่อมต่อ

การเชื่อมต่อระหว่าง ESp8266 กับโมดูล PCF8574 เป็นดังนี้ (ดูภาพที่ 3, 4 และ 5 ประกอบ)

ESP8266โมดูล PCF8574
5VVcc
GNDGND
GPIO5 (D1)SCL
GPIO4 (D2)SDA
ภาพที่ 3 การต่อสายฝั่ง ESP8266
ภาพที่ 4 การต่อสายของโมดูล PCF8574
ภาพที่ 5 การเชื่อมต่อระหว่างโมดูล PCF8574 เข้ากับ ESP8266

ไลบรารี

ไลบรารี kjlcd.py ต่อไปนี้เป็นตัวอย่างการเขียนโปรแกรมภาษาไพธอนเพื่อส่งคำสั่งและข้อมูลผ่านโมดูล PCF8574 เพื่อส่งต่อไปยังแอลซีดีตัวอักษร โดยการเชื่อมต่อระหว่างโมดูล PCF8574 และโมดูลแอลซีดีเป็นตามภาพที่ 2

การใช้งานไลบรารีต้องทำการโอนไฟล์ kjlcd.py ไปเก็บใน ESP8266 ด้วยการโยนไฟล์ผ่าน Thonny หรือใช้ ampy

การเริ่มต้นทำงานต้องกำหนดค่าตำแหน่ง lcd_addr ที่ถูกต้อง ซึ่งทางทีมผู้เขียนกำหนดค่าเริ่มต้นเอาไว้ที่ตำแหน่ง 0x38

เมธอดที่เรียกใช้งานได้ มีดังนี้

  1. reset( ) สำหรับให้โมดูลแอลซีดีเริ่มต้นทำงานใหม่
  2. write( ) สำหรับสเขียนข้อมูลหรือคำสั่งไปให้โมดูล PCF8574 ทางบัส I2C
  3. cmd() สำหรับส่งคำสั่งไปให้โมดูลแอลซีดีผ่านทางโมดูล PCF8574 ทางบัส I2C
  4. data() สำหรับส่งข้อมูลไปให้โมดูลแอลซีดีผ่านทางโมดูล PCF8574 ทางบัส I2C
  5. backlight() สำหรับสั่งเปิด/ปิดไฟลแอลอีดีฉากหลัง
  6. goto( ) สำหรับย้ายตำแหน่งเคอร์เซอร์แสดงผลของโมดูลแอลซีดี
  7. putc() สำหรับสั่งแสดงตัวอักษร ณ ตำแหน่งเคอร์เซอร์
  8. 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")

ภาพที่ 6 ผลลัพธ์จากตัวอย่างโปรแกรม code13-1

สรุป

จากบทความนี้ ผู้อ่านสามารถเขียนโปรแกรมภาษาไพธอนเพื่อสั่งใช้งานโมดูลแอลซีดีที่เชื่อมต่อผ่านทางบัส I2C ซึ่งจะพบว่า การสั่งงานนั้นขึ้นอยู่กับการส่งคำสั่งและข้อมูลไปยังโมดูลแอลซีดี ซึ่งคำสั่งและวิธีการเหล่านี้จะต้องอ่านจากเอกสารประกอบอุปกรณ์แสดงผล และเปลี่ยนมาเป็นชุดคำสั่งเพื่อส่งไปให้โมดูล PCF8574 อ่านทางบัส I2C

พวกเราคิดว่าบทความนี้คงเป็นประโยชน์แก่ผู้สนใจเขียนโปรแกรมสั่งงานโมดูลแอลซีดีตัวอักษรผ่านทางบัส I2C บ้างไม่มากก็น้อย และสามารถนำไปปรับปรุงฟังก์ชันการทำงานให้มากขึ้น เนื่องจากในโมดูลแอลซีดีตัวอักษรยังมีชุดคำสั่งอีกมากมาย เช่น คำสั่งสำหรับการเปิด/ปิดเคอร์เซ้ร์ การสกรอลล์ และการเปิด/ปิดหน้าจอ เป็นต้น

สุดท้ายนี้ขอให้สนุกกับการเขียนโปรแกรมครับ

(C) 2020, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2020-10-27
ปรับปรุงเมื่อ 2021-05-15