วันพฤหัสบดีที่ 16 กุมภาพันธ์ พ.ศ. 2560

การใช้งาน LCD กับ Arduino

สัปดาห์นี้เรามาพูกถึงการใช้งานจอ LCD กันครับ
  ที่พวกเราเรียกว่า LCD นั้น มาจากคำว่า Liquid Crystal Display ครับ หลักการทำงานของมันอาศัย-ของเหลวพิเศษที่มีคุณสมบัติการบิดแกนโพราไรซ์ของแสงครับ  ถ้าจ่ายแรงดันไฟฟ้าเข้าไประหว่างสารเหลวนี้  โมเลกุลของมันจะบิดตัวและทำให้แสงไม่สามารถผ่านกระจกออกมาได้  ถ้าไม่มีการจ่ายแรงดันไฟฟ้าแสงจะทะลุผ่านออกมาได้
  รูปด้านล่างอธิบายความได้เป็นอย่างดีครับ  การทำงานของมันเกิดจากกระจกโพลาไรซ์ 2 แผ่น ที่มีแกนตั้งฉากกัน   ดังนั้นถ้าไม่ทำอะไรเลยแสงจะไม่สามารถลอดผ่านออกมาได้  เหมือนเอาแว่นตาโพลาไรซ์สองอันมาบิดทำมุมตั้งฉากกัน แสงจะไม่ลอดผ่าน  ทีนี้มีคนไปพบว่ามีของเหลวชนิดนึงที่ปกติแล้วจะสามารถ "บิดแกนโพลาไรซ์ของแสง" ได้ ก็เลยเกิดความคิดเอามาทำจอ LCD
ถ้าไม่มีการจ่ายแรงดันเข้าไป  สารเหลวที่ว่านี้จะบิดแกนโพลาไรซ์ของแสงไป 90 องศา ทำให้แสงสามารถลอดออกมาได้จากกระจกโพลาไรซ์คู่นี้ได้   ในทางกลับกัน ถ้ามีแรงดันจ่ายไประหว่างสารเหลวนี้  จะไม่เกิดการปิดตัวของแสง ทำให้แสง "ไม่สามารถ" ลอดออกมาได้ครับ
  คลิปวีดีโอด้านล่างอาจจะทำให้เข้าใช้ได้ง่ายขึ้นครับ

  ทีนี้ก็มีการนำหลักการนี้มาใช้หลายแบบครับ แบบแรกง่ายๆ ก็คือการเอาอิเล็กโทรดที่บังคับการทำงานของของเหลวได้นี้มาทำเป็นรูปตัวเลข ก็จะเห็นแบบที่ใช้ในเครื่องคิดเลข   หรือ โดยประกอบเซลล์เล็กๆ ขึ้นมาเป็นเมตริกซ์ ทำให้สามารถควบคุมให้เป็นตัวอักษร หรือ รูปภาพได้   
  แรกๆที่ทำออกมาก็ไม่ซับซ้อนครับ ใช้ทำเครื่องคิดเลขบ้าง นาฬิกาบ้าง  ต่อมาก็เอามาทำจอ LCD Matrix  จากนั้นเริ่มมีการผสมสี RGB และทำให้จอมีความละเอียดมากขึ้น  (Pixel ต่อ พื้นที่่)  ก็เลยกลายเป็นทีวีจอ  LCD  สีที่เราเห็นครับ
   ในบทความนี้ผมจะพูดถึงเฉพาะ LCD ชนิดที่เป็น matrix ซึ่งใช้แสดงตัวอักษรมาตรฐานนะครับ  จึงอยู่ว่าจอ LCD matrix สามารถแสงเป็นภาพ หรือ ตัวอักษรตามแต่ผู้ใช้จะควบคุม  แต่บทความนี้เอาแบบสั้นๆ คนทั่วไปใช้ละกันครับ  เลยเขียนเฉพาะการควบคุมให้แสดงตัวอักษรมาตรฐาน
  หลักการทำงานก็จบไป  มาถึงรายละเอียดของตัว LCD กันบ้างว่ามีอะไรกันบ้าง มีกี่ Pin   ตารางด้านล่างนี้เป็นรายละเอียดของ PIN ของ LCD แบบที่นิยมใช้กันมากๆ คือ 16 x 2 (หมายถึง 16 ตัวอักษร 2 บรรทัดนะครับ)  ถ้าดูที่แต่ละตัวอักษรจะเห็นว่ามันเป็น matrix  5x8 ซึ่งแสดงถึงความละเอียดของตัวอักษรนะครับ
  ทีนี้ Pin ของ LCD ก็จะมี 16 Pin ตามรายละเอียดในตารางครับ
Pin Description: 
 Pin No
 Function
 Name
1
Ground (0V)
Ground
2
Supply voltage; 5V (4.7V – 5.3V)
 Vcc
3
Contrast adjustment; through a variable resistor
 VEE
4
Selects command register when low; and data register when high
Register Select
5
Low to write to the register; High to read from the register
Read/write
6
Sends data to data pins when a high to low pulse is given
Enable
7
8-bit data pins
DB0
8
DB1
9
DB2
10
DB3
11
DB4
12
DB5
13
DB6
14
DB7
15
Backlight VCC (5V)
Led+
16
Backlight Ground (0V)
Led-
 16 PIN ที่ว่าก็จะมีตั้งแต่ไฟเลี้ยง กราวด์ Data การควบคุมแสง การควบคุมการแสดงครับ  
สำหรับการให้ข้อมูลการแสดงบนหน้าจอ หรือ การติดต่อควบคุมการทำงานของ LCD ก็จะทำโดยผ่าน IC ของบริษัท Hitachi เบอร์ HD44780   เจ้านี้เขาทำเจ้าแรกๆ จนกลายเป็นมาตรฐานของโลกไปแล้วครับ
    HD44780 สามารถคุยด้วยได้ 2 แบบหลักคือ แบบ 4 Bit  (DB4 - DB7) และ แบบ 8 Bit (DB0 - DB7)  ทั้งสองแบบนี้ก็ต่างกันตรงที่ใช้จำนวน pin จาก Arduino 4 pin กับ 8 pin ครับ    ก็แน่นอนครับ เราคงไม่อยากใช้ Port เปลือง ดังนั้นส่วนมากคนก็จะนิยมใช้แบบ 4 Pin กันครับ  แต่ก็มีความเร็วในการส่งข้อมูลช้ากว่าแบบ 8 pin ครับ   แต่ความเร็วที่ว่าก็ไม่ได้เป็นอุปสรรคเลยครับ 4 bit ก็เร็วมากจนสายตาของเราแยกไม่ออกแล้วครับ    สรุปก็คือว่าผมแนะนำการต่อแบบ 4 bit ละกันนะครับ ตามภาพด้านบนก็ได้ครับ  แล้วแบบ 8 bit มีไว้ทำไมละ  คำตอบก็คือ ในยุคแรกๆ ไมโครคอนโทรลเลอร์เขาออกมาเป็นแบบ 8 bit แล้วเพื่อให้เขียนโปรแกรมไม่ซับซ้อนมากนัก ก็เลยใช้ 8 bit ให้เหมือนกัน register ในไมโครคอนโทรลเลอร์ซะครับ
   สำหรับ Arduino แล้ว เราจะใช้ LCD แบบบ้านๆ ที่มีขายตามบ้านหม้อ (ถ้าดูภาพแรกก็คือ LCD อันล่าง) หรือจะใช้เป็นแบบ LCD Shield  ก็มีหลักการทำงานเดียวกัน  ใช้ library เดียวกันครับ  ถ้าใช้แบบ LCD เดี่ยวๆ ก็ต้องมาต่อขากันเองนิดหน่อย แต่ถ้าใช้ LCD Shield ก็จับยัดได้เลยครับ แถมมีปุ่มกดมาให้ด้วยครับ  ก็แล้วแต่งานที่ต้องเอาไปประยุกต์ใช้ครับ
  และก็ตามสไตล์ของ Arduino ครับคือการมี library ที่่ทำให้ใช้งานได้สะดวกมากๆ  ใครที่เคยใช้ ไมโครคอนโทรลเลอร์ตัวอื่นมาก่อนจะรู้สึกถึงความแตกต่างชัดเจนครับ   Library ของ LCD ก็คือ    มีคำสั่งที่สำคัญดังนี้ครับ

  • LiquidCrystal()  ก็ใช้ในการประกาศ Pin ที่เราจะส่งข้อมูลไปที่จอ LCD ครับ เช่น LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  ก็หมายถึง RS ที่ Pin 8   Enable ที่ Pin 9 และ DB4 - DB 7 ที่ขา 4, 5, 6, 7  ตามลำดับครับ   ถ้าดูรายละเอียดในคำสั่งนี้ เราจะสามารถใช้การส่งข้อมูลแบบ 8 บิตได้ด้วยครับ
  • begin() ใช้ในการกำหนดลักษณะการแสดงของจอ เช่น  lcd.begin(16, 2);  คือการแสดงภาพ 16 ตัวอักษร 2 แถวครับ
  • print() ใช้ในการเขียนข้อความ เช่น  lcd.print("Hello !!!");
  • setCursor() ใช้ในการกำหนดตำแหน่งของ Cursor เช่น  lcd.setCursor(13, 1); คือให้เคอร์เซอร์ไปที่ ตัวอักษรที่ 13 และแถวที่ 1  (อย่าลืมนะครับ มันจะเริ่มนับจาก 0 ตามสไตล์ภาษา C)
  •  cursor() ก็คือการแสดงตัว Cursor บนหน้าจอครับ เช่น lcd.cursor();
  •  noCursor() ก็คือการซ่อน Cursor 
 ที่เหลือ รบกวนไปที่ Arduino.cc นะครับ
    สำคัญคือการต่อนะครับ ต้องต่อตามที่เขียนไว้ในคำสั่ง LiquidCrystal()   นะครับ Arduino จะได้สั่งงานไปถูกขา
 ทีนี้เอาแบบง่ายๆ คือ Hello Arduitronics ครับ  ผมสาธิตโดยการใช้  LCD Shield  นะครับ ทีนี้ตัว  LCD Shield นี้มันก็มีการต่อขาไว้ที่ตัว LCD แบบตายตัวแล้ว เปลี่ยนไม่ได้ซะด้วย ก็ใช้ตามนี้เลยนะครับ
liquidCrystal lcd(8, 9, 4, 5, 6, 7); 
ถ้าต่อเองก็เลือกเอาตามอัธยาสัยได้เลยครับ 

/*
  LiquidCrystal Library - "Hello !!!!  Arduitronics"
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 This sketch prints "Hello !!!!  Arduitronics" to the LCD
 and shows the time.
  The circuit:
 * LCD RS pin to digital pin 8
 * LCD Enable pin to digital pin 9
 * LCD D4 pin to digital pin 4
 * LCD D5 pin to digital pin 5
 * LCD D6 pin to digital pin 6
 * LCD D7 pin to digital pin 7
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe
 Modified by Arduitronics
 This example code is in the public domain.
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */
// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Hello !!!");
  lcd.setCursor(0, 1);
  lcd.print("Arduitronics");
}
void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(13, 1);
  // print the number of seconds since reset:
  lcd.print(millis()/1000);
}
ถ้าต่อถูกต้องก็ตามภาพด้านล่างนี้เลยครับ 

อีกตัวอย่างครับ ทีนี้เราจะเริ่มมีการใช้ปุ่มกดกันบ้าง  อันนี้ผมได้ตัวอย่างมาจากผู้ผลิตนะครับ DFROBOT 
//Sample using LiquidCrystal library
#include
/*******************************************************
This program will test the LCD panel and the buttons
Mark Bramwell, July 2010
********************************************************/
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
// read the buttons
int read_LCD_buttons()
{
 adc_key_in = analogRead(0);    // read the value from the sensor 
 // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
 // we add approx 50 to those values and check to see if we are close
 if (adc_key_in > 1000) return btnNONE;
 // the 1st option for speed reasons since it will be the most likely result
 // For V1.1 us this threshold
 if (adc_key_in < 50)   return btnRIGHT;  
 if (adc_key_in < 250)  return btnUP; 
 if (adc_key_in < 450)  return btnDOWN; 
 if (adc_key_in < 650)  return btnLEFT; 
 if (adc_key_in < 850)  return btnSELECT;  
 // For V1.0 comment the other threshold and use the one below:
/*
 if (adc_key_in < 50)   return btnRIGHT;  
 if (adc_key_in < 195)  return btnUP; 
 if (adc_key_in < 380)  return btnDOWN; 
 if (adc_key_in < 555)  return btnLEFT; 
 if (adc_key_in < 790)  return btnSELECT;   
*/
 return btnNONE;  // when all others fail, return this...
}
void setup()
{
 lcd.begin(16, 2);              // start the library
 lcd.setCursor(0,0);
 lcd.print("Push the buttons"); // print a simple message
}
void loop()
{
 lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over
 lcd.print(millis()/1000);      // display seconds elapsed since power-up
 lcd.setCursor(0,1);            // move to the begining of the second line
 lcd_key = read_LCD_buttons();  // read the buttons
 switch (lcd_key)    // depending on which button was pushed, we perform an action
 {
   case btnRIGHT:
     {
     lcd.print("RIGHT ");
     break;
     }
   case btnLEFT:
     {
     lcd.print("LEFT   ");
     break;
     }
   case btnUP:
     {
     lcd.print("UP    ");
     break;
     }
   case btnDOWN:
     {
     lcd.print("DOWN  ");
     break;
     }
   case btnSELECT:
     {
     lcd.print("SELECT");
     break;
     }
     case btnNONE:
     {
     lcd.print("NONE  ");
     break;
     }
 }
}
 เช่นกันครับ ถ้าต่อถูกก็ตามนี้ครับ
สำหรับ Data Sheet ของ LCD ก็ตามนี้ครับ 
ถ้าเป็น  LCD Shield  ก็ตามนี้ครับ  ข้อดีอีกอันของการใช้ Shield ก็คือ มี R ปรับค่าได้ไว้ปรับความสว่างของหน้าจอมาให้ด้วยนะครับ  
แถมอีกนิดครับ  เนื่องจากที่ผมเขียนมาทั้งหมด ก็ยังมีคนรู้สึกว่ามันยังต้องใช้ Pin เยอะอยู่ดี  ดังนั้นเลยต้องการลดการใช้ PIN ลงอีก  จึงประยุกต์ใช้การสื่อสารแบบอนุกรม แบบ I2C (Inter - IC communication) ซะเลย  จึงลดขา DB ต่างๆ ลงมาอีก ให้เหลือแค่ 2 PIN 
I2C/SPI LCD

นาย สุธรรม แสงทรง

อ้างอิง
https://www.arduitronics.com/article/28/การใช้งาน-lcd-กับ-arduino

ไม่มีความคิดเห็น:

แสดงความคิดเห็น