บทความนี้จะสาธิตการใช้งานจอ LCD หรือจอ LiquidCrystal ที่ใช้โมดูล I2C ในการสื่อสารกับ Arduino ให้สามารถต่อได้หลายๆตัวพร้อมกัน และแสดงผลต่างกันได้ด้วย มาดูอุปกรณ์ที่ถูกใช้ในบทความนี้กันครับอุปกรณ์ที่ใช้ในบทความ1. Screw Shield V2 expansion board is compatible with UNO R3 and arduino-compatible board2. UNO R3 development board improved version enhanced version ATmega328P microcontroller Micro USB port พร้อมสาย (Arduino-Compatible Board)3. จอ LCD2004 สีฟ้า แบบ I2C ใช้สายข้อมูลเพียง 2 เส้น4. สายไฟ jumper ผู้-เมีย ยาว 20cm. จำนวน 40 เส้น
โดยปกติเราสามารถใช้ Arduino uno r3 กับตัวจอได้โดยตรงเลย แต่ที่ผมเลือกใช้ Screw shield (ตัวสีดำ) เพราะ shield นี้ช่วยในการป้องกันสายหลวมหรือสายหลุดได้ดี เพราะใช้วิธีขันน๊อตลงสายไฟ และยังช่วยกระจายขาไฟเลี้ยงให้กับเซนเซอร์ต่างๆ เรียกว่าเหมาะกับงานที่ใช้เซนเซอร์จำนวนมากๆ เป็นอย่างยิ่งเริ่มต้นโดยการสวม Screw shield เข้า Arduino UNO r3 ก่อน
จบละ ขาไม่ตรงช่อง Uno r3 ... ล้อเล่นครับ ให้หักตัว shield แยกเป็นสองชิ้นและสวมด้านละฝั่งของ Uno r3 ดังรูป
เป็น Shield ที่ดูดีเลยใช่ไหมครับ ต่อไปก็มาดูส่วนของ LCD โดยตัว LCD ที่มาพร้อมตัวแปลง I2C จะใช้โมดูล PCF8574T ซึ่งเป็นโมดูลแปลงสัญญาณ digital หลายๆสาย ให้เป็น i2c ที่ใช้แค่ 2 สาย โดย I2C เป็นสัญญาณที่เราสามารถใส่อุปกรณ์ต่อขนานกับสัญญาณนี้ได้หลายตัว ตราบใดที่มี Address คนละค่ากัน โดยปกติ Adress ที่มากับตัว PCF8574T ที่มากับ LCD จะเป็นค่าโรงงานค่าเดียวกัน การเปลี่ยน Address เพื่อให้ LCD ทำงานผ่านบัส I2C ด้วยกันหลายตัวจึงเป็นสิ่งที่ต้องทำ เราจะเห็นว่าตรงที่ผมชี้จะมี A0 A1 A2 และมีขั้วสี่เหลี่ยมอยู่ เราต้องบัดกรีตรงนี้เพื่อให้เลข address ต่างกัน
ผมเลือกบัดกรี A0 ตัวนึงของ LCD อันนึง อีกอันปล่อยค่าโรงงานไว้ ผมใช้เศษตัวต้านทานนิดหน่อยเพื่อให้ง่ายต่อการบัดกรี
หน้าตาจะได้ดังรูป
จากนั้นต่อ LCD กับตัว Screw shield บน Uno r3 โดยต่อดังนี้Arduino UNO r3 ---> LCD 1GND ---> GND5v ---> VCCA4 ---> SDAA5 ---> SCLArduino UNO r3 ---> LCD 2GND ---> GND5v ---> VCCA4 ---> SDAA5 ---> SCLจากนั้นให้ดาวน์โหลด Library LiquidCrystal_I2C ผ่านทาง Library manager หากใครเคยดาวน์โหลดแล้ว แนะนำให้ลองลบและติดตั้งของคุณ enjoyneering ดูนะครับ ไม่ต้องปวดหัวกับการหาเลข Address เองเลย เพราะมีตัวแปรที่อ้างอิงกับตำแหน่งที่เราบัดกรีให้อยู่แล้ว ส่วนตัวแปรที่ว่า ผมอธิบายไว้เป็นภาษาไทยในโค้ดเรียบร้อยครับจากนั้นนำโค้ดนี้ไปใช้ได้เลย
/**
* www.modulemore.com
* บทความ : ต่อ Arduino กับ LCD หลายจอ ง่ายนิดเดียว
*/
#include <Wire.h> //สำหรับ ESP8266 ให้ใช้ไลบรารี่สำหรับ I2C ตัวนี้ -> https://github.com/enjoyneering/ESP8266-I2C-Driver
#include <LiquidCrystal_I2C.h> //ไลบรารี่สำหรับจอ LCD ทุกขนาด
/* -------------------------------------------------------------------------- */
/* กำหนดขนาดของจอ */
/* -------------------------------------------------------------------------- */
#define COLUMS 20
#define ROWS 4
/* -------------------------------------------------------------------------- */
/* สร้างตัวแปรสำหรับแทนจอแต่ละจอ */
/* -------------------------------------------------------------------------- */
/**
* โดยตัวแปร PCF8574_ADDR_A2X_A1X_A0X หมายถึงขั้วของ A0, A1, A2 หลังตัวโมดูล PCF8574
* โดย X คือตัวเลข 0-1 ซึ่ง 1 หมายถึงไม่บัดกรี 0 หมายถึงบัดกรี
*
*
PCF8574_ADDR_A21_A11_A01 = 0x27, //i2c address A2 = 1, A1 = 1, A0 = 1 (by default)
PCF8574_ADDR_A21_A11_A00 = 0x26, //i2c address A2 = 1, A1 = 1, A0 = 0
PCF8574_ADDR_A21_A10_A01 = 0x25, //i2c address A2 = 1, A1 = 0, A0 = 1
PCF8574_ADDR_A21_A10_A00 = 0x24, //i2c address A2 = 1, A1 = 0, A0 = 0
PCF8574_ADDR_A20_A11_A01 = 0x23, //i2c address A2 = 0, A1 = 1, A0 = 1
PCF8574_ADDR_A20_A11_A00 = 0x22, //i2c address A2 = 0, A1 = 1, A0 = 0
PCF8574_ADDR_A20_A10_A01 = 0x21, //i2c address A2 = 0, A1 = 0, A0 = 1
PCF8574_ADDR_A20_A10_A00 = 0x20, //i2c address A2 = 0, A1 = 0, A0 = 0
PCF8574A_ADDR_A21_A11_A01 = 0x3F, //i2c address A2 = 1, A1 = 1, A0 = 1
PCF8574A_ADDR_A21_A11_A00 = 0x3E, //i2c address A2 = 1, A1 = 1, A0 = 0
PCF8574A_ADDR_A21_A10_A01 = 0x3D, //i2c address A2 = 1, A1 = 0, A0 = 1
PCF8574A_ADDR_A21_A10_A00 = 0x3C, //i2c address A2 = 1, A1 = 0, A0 = 0
PCF8574A_ADDR_A20_A11_A01 = 0x3B, //i2c address A2 = 0, A1 = 1, A0 = 1
PCF8574A_ADDR_A20_A11_A00 = 0x3A, //i2c address A2 = 0, A1 = 1, A0 = 0
PCF8574A_ADDR_A20_A10_A01 = 0x39, //i2c address A2 = 0, A1 = 0, A0 = 1
PCF8574A_ADDR_A20_A10_A00 = 0x38 //i2c address A2 = 0, A1 = 0, A0 = 0
*/
LiquidCrystal_I2C lcd1(PCF8574_ADDR_A21_A11_A01, 4, 5, 6, 16, 11, 12, 13, 14, POSITIVE);
LiquidCrystal_I2C lcd2(PCF8574_ADDR_A21_A11_A00, 4, 5, 6, 16, 11, 12, 13, 14, POSITIVE);
void setup()
{
Serial.begin(115200);
/* ------- ตรวจสอบจอ ระบบจะทำงานไม่ได้หากจอตั้งค่าผิดหรือสื่อสารไม่ได้ ------ */
while (lcd1.begin(COLUMS, ROWS) != 1) //colums - 20, rows - 4
{
Serial.println(F("PCF8574 is not connected or lcd1 pins declaration is wrong. Only pins numbers: 4,5,6,16,11,12,13,14 are legal."));
delay(5000);
}
/* ------- ตรวจสอบจอ ระบบจะทำงานไม่ได้หากจอตั้งค่าผิดหรือสื่อสารไม่ได้ ------ */
while (lcd2.begin(COLUMS, ROWS) != 1) //colums - 20, rows - 4
{
Serial.println(F("PCF8574 is not connected or lcd1 pins declaration is wrong. Only pins numbers: 4,5,6,16,11,12,13,14 are legal."));
delay(5000);
}
/* ------------------- โชว์ข้อความเพื่อแสดงว่าจอทำงานแล้ว ------------------- */
lcd1.print(F("PCF8574 is OK...")); //(F()) saves string to flash & keeps dynamic memory free
lcd2.print(F("PCF8574 is OK...")); //(F()) saves string to flash & keeps dynamic memory free
delay(2000);
/* -------------------------- เคลียร์หน้าจอทั้งสอง -------------------------- */
lcd1.clear();
lcd2.clear();
/* - เซ็ตให้เริ่มเขียนที่ตำแหน่ง col 0 (อักษรแรก) row 1 (บรรทัดที่ 2) - */
lcd1.setCursor(0, 1); //set 1-st colum & 2-nd row, 1-st colum & row started at zero
lcd1.print(F("ArduinoNa.com->"));
/* - เซ็ตให้เริ่มเขียนที่ตำแหน่ง col 0 (อักษรแรก) row 2 (บรรทัดที่ 3) - */
lcd1.setCursor(0, 2);
lcd1.print(F("Time: "));
/* - เซ็ตให้เริ่มเขียนที่ตำแหน่ง col 0 (อักษรแรก) row 1 (บรรทัดที่ 2) - */
lcd2.setCursor(0, 1); //set 1-st colum & 2-nd row, 1-st colum & row started at zero
lcd2.print(F("ModuleMore.com"));
/* - เซ็ตให้เริ่มเขียนที่ตำแหน่ง col 0 (อักษรแรก) row 2 (บรรทัดที่ 3) - */
lcd2.setCursor(0, 2);
lcd2.print(F("Time: "));
}
void loop()
{
/* -------------- ปริ้นค่าที่มีการเปลี่ยนแปลงตลอดเวลาไว้ใน loop ------------- */
lcd1.setCursor(5, 2);
lcd1.print(millis());
lcd2.setCursor(5, 2);
lcd2.print(millis());
delay(50);
}
จะได้จอที่พร้อมใช้งานพร้อมกันสองจอแล้วล่ะครับ สำหรับการเพิ่มจอ 3,4 ไปเรื่อยๆ ก็แค่เพิ่มตัวแปร lcd3, lcd4 และกำหนด Address ในโค้ดให้ตรงกับที่เราบัดกรีก็ไม่มีปัญหาแล้วครับ

ธนบดี บุหลันศรีชาติ
ผู้เขียน