01076051Lecture 11

LCD & Touch Screen

บทที่ 11: จอแสดงผล LCD และหน้าจอสัมผัส (Touch Screen)

บทนี้พาไปรู้จักว่าภาพดิจิทัลเก็บเป็นข้อมูลได้อย่างไร จอ LCD ควบคุมแสงทีละพิกเซลด้วยอะไร และหน้าจอสัมผัสแต่ละแบบ (resistive / capacitive / infrared) ทำงานต่างกันตรงไหน. จากนั้นลงมือต่อจอ TFT ที่มีชิป ILI9341 เข้ากับบอร์ด NUCLEO-F767ZI ผ่าน SPI แล้วอ่านตำแหน่งที่นิ้วแตะ.

ผลการเรียนรู้ (Learning Outcomes)

  • อธิบายความต่างของภาพแบบ raster (พิกเซล) กับภาพแบบ vector และโครงสร้างของพิกเซลที่ประกอบด้วย sub-pixel แดง-เขียว-น้ำเงิน
  • อธิบายหลักการจอ LCD: แสง backlight ส่องผ่าน polarizer และ liquid crystal ที่ถูกควบคุมด้วยสนามไฟฟ้าเพื่อปรับความเข้มแสงแต่ละพิกเซล
  • เปรียบเทียบหน้าจอสัมผัสแบบ resistive, capacitive (surface / projected), และ infrared ทั้งหลักการ ข้อดี และข้อจำกัด
  • เข้ารหัสสีแบบ RGB565 (16 บิต) และอธิบายว่าทำไมจึงใช้แดง 5 บิต เขียว 6 บิต น้ำเงิน 5 บิต
  • ต่อจอ TFT ILI9341 เข้ากับ NUCLEO-F767ZI ผ่าน SPI พร้อมขา D/C, reset, chip select และ backlight (PWM)
  • อธิบายเทคนิค bit-banging และเขียนโปรแกรมอ่านตำแหน่งสัมผัสเพื่อวาดจุดบนจอ

§11.1 ภาพดิจิทัลและโครงสร้างพิกเซล

ภาพดิจิทัลเก็บได้ 2 แนวทางหลัก. แบบแรกคือภาพ raster (บางทีเรียก bitmap): เก็บข้อมูลเป็นจุดต่อจุด แต่ละจุดเรียก พิกเซล (pixel) ซึ่งเก็บความเข้มแสงของแม่สีที่ตำแหน่งนั้น. เมื่อนำพิกเซลหลายจุดมาเรียงเป็นตาราง 2 มิติก็ประกอบเป็นภาพขึ้นมา.

ถ้าเราซูมภาพ raster เข้าไปมากพอจะเห็นเป็นช่องสี่เหลี่ยม นั่นคือพิกเซลที่แบ่งย่อยไปกว่านี้ไม่ได้แล้ว. เพราะจำนวนพิกเซลมีจำกัด ภาพ raster จึงแตกเป็นรอยหยักเมื่อขยายใหญ่เกินไป. ไฟล์ตระกูลนี้เช่น BMP (เก็บดิบจุดต่อจุด ไม่บีบอัด) หรือ JPEG (บีบอัดโดยตัดข้อมูลบางส่วนทิ้งให้ไฟล์เล็กลง).

แบบที่สองคือภาพ vector: เก็บเป็นสมการคณิตศาสตร์ รูปที่เห็นเกิดจากการตัดกันของเส้นและเส้นโค้งตามสมการ. ข้อดีคือซูมได้เรื่อย ๆ โดยภาพไม่แตก จึงเหมาะกับโลโก้และฟอนต์ที่รายละเอียดไม่เยอะ (เช่นไฟล์จาก Adobe Illustrator).

หนึ่งพิกเซลบนจอสีไม่ได้มีจุดเดียว แต่ประกอบด้วย sub-pixel 3 จุด คือแดง (R) เขียว (G) น้ำเงิน (B). เมื่อควบคุมความเข้มของ sub-pixel ทั้งสามแยกกันก็ผสมได้ทุกสี. ดังนั้นจอที่บอก resolution 1920×1080 จะมี sub-pixel รวมเป็น 3 เท่าของจำนวนพิกเซล.

VIZ-57ซูมพิกเซล / ซับพิกเซล
ระดับซูม

ซูมเข้าไปเรื่อย ๆ ภาพจะแตกเป็นตารางพิกเซล

เลื่อนระดับการซูมเพื่อดูภาพแตกเป็นพิกเซล แล้วแตกเป็นซับพิกเซล R/G/B. โหมด raster จะแตกเป็นบล็อก, โหมด vector จะคมชัดเสมอ.

§11.2 เทคโนโลยีจอ LCD ทำงานอย่างไร

LCD ย่อจาก Liquid Crystal Display (จอผลึกเหลว). ประเด็นสำคัญคือ LCD ส่องสว่างด้วยตัวเองไม่ได้ ต้องมีไฟส่องสว่างอยู่ข้างหลังเรียก backlight แล้ว LCD ทำหน้าที่เป็นวาล์วคอยปิด-เปิดแสงของแต่ละพิกเซล. ต่างจากจอ CRT รุ่นเก่า (ยิงอิเล็กตรอนใส่สารเรืองแสง) หรือจอ OLED ยุคใหม่ที่แต่ละพิกเซลเปล่งแสงเองได้.

หัวใจอยู่ที่ polarizer (ตัวกรองแสงเชิงขั้ว). แสงจาก backlight สั่นได้ทุกทิศทาง เมื่อผ่าน polarizer จะเหลือเฉพาะระนาบเดียว. ถ้าวาง polarizer สองแผ่นตั้งฉากกัน แสงจะผ่านไม่ได้เลย (มืดสนิท).

ระหว่าง polarizer สองแผ่นคือชั้น liquid crystal. เมื่อ ไม่ จ่ายไฟ โมเลกุลคริสตัลเรียงตัวบิดระนาบของแสงให้ผ่าน polarizer แผ่นที่สองได้ (สว่าง). เมื่อ จ่ายไฟ เกิดสนามไฟฟ้า คริสตัลเรียงตัวใหม่ไม่บิดแสง แสงจึงถูก polarizer แผ่นที่สองกั้น (มืด). การปรับแรงดันจึงปรับความเข้มแสงของพิกเซลได้ต่อเนื่อง — นี่คือหลักของจอแบบ TN (Twisted Nematic). จอสมัยใหม่ส่วนใหญ่ใช้ IPS ซึ่งคุมคริสตัลคนละแบบแต่หลักการพื้นฐานคล้ายกัน.

backlight สมัยนี้ใช้ LED (เดิมใช้หลอด fluorescent ที่ร้อนและใหญ่). แสงจาก LED จะผ่าน diffuser ให้กระจายทั่วหน้าจอ ผ่าน prism บังคับทิศให้พุ่งไปข้างหน้า แล้วจึงเข้าชั้น LCD panel.

เนื่องจาก backlight เป็นแสงขาว เราจึงฉาบ ฟิล์มสี (color filter) ลงบน sub-pixel แต่ละจุดให้เป็นแดง เขียว น้ำเงิน. คริสตัลด้านในของทั้งสาม sub-pixel เหมือนกันหมด ต่างกันแค่สีฟิล์มที่ฉาบทับ. เพราะต้องควบคุมทุก sub-pixel แยกกัน จอรุ่นแรก ๆ จึงมีปัญหา dead pixel (จุดเสียดับ) และ stuck pixel (จุดค้าง) ได้ง่าย.

ลำดับชั้นหน้าที่
1Backlight (LED)แหล่งกำเนิดแสงขาว
2Diffuserกระจายแสงให้สม่ำเสมอทั้งจอ
3Prismบังคับทิศแสงให้พุ่งไปข้างหน้า
4Polarizer แผ่นแรกกรองแสงเหลือระนาบเดียว
5Liquid crystal + electrodeปรับการบิดระนาบแสงด้วยสนามไฟฟ้า
6Color filter (R/G/B)ให้ sub-pixel ได้แม่สี
7Polarizer แผ่นที่สองตัดสินว่าแสงผ่านออกมา (สว่าง) หรือถูกกั้น (มืด)
ลำดับชั้นของแสงในจอ LCD (จากหลังจอมาหน้าจอ)
VIZ-58หน้าตัดชั้นแสงของจอ LCD
pixel สว่าง
BacklightDiffuserPrismPolarizer 1Liquid CrystalColor FilterPolarizer 2บิด 90°ตา

แสงวิ่งผ่านชั้นต่าง ๆ ซ้ายไปขวา. ผลึกเหลวเป็นวาล์วแสง: ไม่จ่ายไฟ=บิดให้แสงผ่าน (สว่าง), จ่ายไฟ=เรียงตรงบล็อกแสงที่ polarizer 2 (มืด). มีเพียง polarizer 2 ที่ตัดสินสว่าง/มืด.

§11.3 เทคโนโลยีหน้าจอสัมผัส (Touch Screen)

หน้าจอสัมผัสเป็นคนละอุปกรณ์กับ LCD มันเป็นแผ่นใสที่วางทับบนจอ LCD อีกที จึงต้องโปร่งแสงมากที่สุดเพื่อไม่บังภาพ. มีหลายเทคโนโลยี แต่ละแบบตรวจตำแหน่ง XY ที่นิ้วแตะด้วยหลักฟิสิกส์ต่างกัน.

แบบ Resistive (ความต้านทาน): มีฟิล์มนำไฟฟ้า ITO (Indium Tin Oxide) สองชั้นประกบกัน โดยมีช่องว่างกั้น. เมื่อกดลงไป ฟิล์มสองชั้นแตะกันเกิดจุดที่กระแสไหลผ่าน. เรียกโครงสร้างนี้ว่า 4-wire เพราะมีขั้ว X+, X−, Y+, Y−. การหาพิกัด Y ทำโดยจ่ายไฟคร่อม Y+ กับ Y− แล้วอ่านแรงดันที่ X+; พิกัด Y = (แรงดันที่อ่านได้ ÷ แรงดันที่จ่าย) × ความสูงจอ. การหาพิกัด X ทำกลับด้าน คือจ่ายไฟคร่อมแกน X แล้วอ่านแรงดันที่ Y+.

ข้อดีของ resistive คือราคาถูก และกดด้วยอะไรก็ได้ที่มีแรง (นิ้ว ปากกา ถุงมือ) เพราะอาศัยแรงกดไม่ได้อาศัยประจุ. ข้อจำกัดคือได้ทีละ 1 จุดเท่านั้น (ถ้าแตะ 2 นิ้วจะได้ค่าเฉลี่ยตรงกลาง) ความโปร่งแสงเพียง 75–85% และของมีคมทำให้ผิวด้านบนเสียหายได้.

แบบ Capacitive (ความจุประจุ): มาตรฐานที่ใช้กันทุกวันนี้. จอปล่อยประจุไฟฟ้าไว้ นิ้วคนซึ่งนำประจุได้จะไปรบกวนสภาพประจุของจุดนั้น ตัว controller จึงรู้ว่ามีการสัมผัสที่ใด. แบ่งย่อยเป็น surface (ใส่ขั้วที่มุมจอ วัดกระแสจากแต่ละมุมแล้วคำนวณระยะ ได้ความละเอียดต่ำ) กับ projected (วางกริดสายส่ง-สายรับถี่ ๆ ทั่วจอ เมื่อแตะใกล้จุดใดประจุรั่วเข้านิ้วทำให้ตัวรับได้ประจุน้อยลง ได้ความละเอียดสูงและรองรับ multi-touch 10 จุด).

ข้อดีของ capacitive คือทนทาน (ไม่มีชั้นที่ต้องกดยืดหยุ่น) แม่นยำ และโปร่งแสงดี. ข้อจำกัดคือต้องแตะด้วยวัตถุที่นำประจุ นิ้วมือใช้ได้แต่ถุงมือธรรมดาใช้ไม่ได้ ต้องใช้ stylus แบบ active (ใส่ถ่าน) หรือถุงมือชนิดพิเศษที่ปลายนิ้วนำประจุ.

แบบ Infrared (อินฟราเรด): เหมาะกับจอขนาดใหญ่มาก (video wall) ที่ resistive/capacitive เริ่มคำนวณยากเพราะความต้านทานและการสูญเสียประจุ. วาง LED อินฟราเรดยิงลำแสงขวางหน้าจอ อีกด้านมีตัวรับ. เมื่อนิ้วหรือ stylus ไปขวางลำแสง ตัวรับฝั่งนั้นจะรับไม่ได้ ระบบจึงคำนวณตำแหน่งที่ถูกบังได้.

หัวข้อResistiveCapacitiveInfrared
หลักการแรงกดให้ฟิล์มแตะกันนิ้วรบกวนประจุนิ้วบังลำแสง
สัมผัสด้วยอะไรก็ได้ที่มีแรงวัตถุนำประจุเท่านั้นวัตถุทึบแสงอะไรก็ได้
Multi-touchไม่ได้ (1 จุด)ได้ (ถึง 10 จุด)ได้
ความโปร่งแสง75–85%ดีไม่บังจอ
ราคา/ความทนถูก/ผิวเสียง่ายแพงกว่า/ทนทานเหมาะจอใหญ่
เปรียบเทียบเทคโนโลยีหน้าจอสัมผัส
VIZ-59เปรียบเทียบเทคโนโลยีหน้าจอสัมผัส
ITO layer A (Y drive)ITO layer B (X read)คลิกเพื่อแตะ

สองชั้น ITO ถูกกดให้แตะกันที่จุดสัมผัส เกิดวงจรแบ่งแรงดัน

การหาพิกัด XY

จ่ายแรงดันแกน Y แล้ววัดแรงดันที่ X+ → คำนวณพิกัดจากอัตราส่วนแรงดัน

ข้อจำกัด

รองรับสัมผัสเดียว (single-touch) — สองจุดจะได้ค่าเฉลี่ย

เลือกเทคโนโลยีแล้วคลิกในแผงเพื่อ 'แตะ'. แต่ละแบบหาพิกัด XY ต่างกัน และมีข้อจำกัดต่างกัน — resistive สัมผัสเดียว, capacitive/IR รองรับหลายจุด.

§11.4 การเข้ารหัสสี RGB565

จอ TFT ในแล็บแสดงสีได้ 65,536 สี (= 2 ยกกำลัง 16) ที่ resolution 320×240 ใช้ชิป controller เบอร์ ILI9341. การแทนสี 16 บิตนี้เรียก RGB565.

RGB565 แบ่ง 16 บิตเป็น แดง 5 บิต (บิต 15–11), เขียว 6 บิต (บิต 10–5), น้ำเงิน 5 บิต (บิต 4–0). ที่เขียวได้ 6 บิต (มากกว่าอีกสองสี) เพราะตาคนไวต่อสีเขียวมากที่สุด การเพิ่มระดับสีเขียวจึงช่วยให้ไล่เฉดดูเนียนขึ้น.

ตัวอย่างการคิดค่าสี: สีแดงเต็ม = บิตแดงเป็น 1 ทั้งหมด บิตเขียวและน้ำเงินเป็น 0 ได้ 0xF800. สีเขียวเต็ม = 0x07E0. สีน้ำเงินเต็ม = 0x001F. สีเหลือง = แดง+เขียว (น้ำเงินเป็น 0) = 0xFFE0. ในโปรแกรมจริงนิยมตั้งชื่อ constant ให้สี (เช่น RED, GREEN) แทนการจำเลขฐานสิบหกเพื่อให้โค้ดอ่านง่าย.

สีR (5 บิต)G (6 บิต)B (5 บิต)ค่า hex
แดง11111000000000000xF800
เขียว00000111111000000x07E0
น้ำเงิน00000000000111110x001F
เหลือง11111111111000000xFFE0
ขาว11111111111111110xFFFF
ตัวอย่างค่า RGB565 (16 บิต)
VIZ-60ตัวประกอบสี RGB565
R (5 บิต)
G (6 บิต +1)
B (5 บิต)
0xFFFF
R=31 · G=63 · B=31
rgb(255, 255, 255)

คลิกบิตหรือเลื่อนสไลเดอร์ แล้วดูค่า hex และสีจริงอัปเดตทันที. แบ่งเป็น 5-6-5 บิต — เขียวได้ 6 บิตเพราะตาคนไวต่อสีเขียวมากที่สุด.

§11.5 ต่อจอ TFT เข้ากับ NUCLEO ผ่าน SPI

จอที่ใช้ในแล็บขนาด 2.8 นิ้ว 320×240 controller ILI9341 ใช้ไฟ 3.3–5V. ข้อควรจำเวลาซื้อจอคือ ให้ดูเบอร์ controller ก่อน (เช่น ILI9341, ILI9325) เพราะต้องมี library ที่คุม controller เบอร์นั้นได้.

จอนี้มี SPI (Serial Peripheral Interface) ถึง 3 ชุด: ชุดแรกสำหรับส่งข้อมูลภาพ RGB ไป LCD, ชุดที่สองสำหรับ touch sensor, ชุดที่สามสำหรับ SD card (ถ้าบอร์ดมี). SPI เป็นบัสแบบ master-out/slave-in ที่เราเคยเรียน MCU เป็น master ส่วนจอเป็น slave.

นอกจากสาย SPI (SCK, MOSI, MISO) ยังมีขาคุมอีกหลายเส้นที่ต่อเป็น GPIO ธรรมดา: D/C (Data/Command — บอกว่าไบต์ที่ส่งเป็นข้อมูลภาพหรือเป็นคำสั่ง), RESET, CS (Chip Select) และ LED (คุม backlight). ถ้าอยากให้ backlight ติด 100% ต่อขา LED เข้าไฟตรง ๆ ได้ แต่ถ้าอยากหรี่-เพิ่มความสว่างให้ต่อ PWM (ควรผ่านทรานซิสเตอร์เพราะกระแสจากขา MCU เส้นเดียวอาจไม่พอ).

เรื่องน่าสังเกต: ขา touch sensor ดูชื่อเป็น SPI แต่ตัวอย่างในแล็บกำหนดให้เป็น GPIO ธรรมดา. เหตุผลคือใช้เทคนิค bit-banging — ใช้ ซอฟต์แวร์ จำลองการทำงานของโพรโทคอล SPI ด้วยการสั่งขา GPIO ขึ้น-ลงเองตามจังหวะ แทนการใช้ฮาร์ดแวร์ SPI (เหมือน SoftwareSerial ใน Arduino ที่จำลอง UART). ทำเช่นนี้เมื่อโมดูลฮาร์ดแวร์ SPI มีไม่พอหรือต้องการวางขาที่สะดวกกว่า.

ในตัวอย่าง LCD Demo ยังต้องตั้งค่าเพิ่ม 3 อย่างใน CubeMX. หนึ่ง ตั้ง timer (ตัวอย่างใช้ TIM1) สำหรับ PWM backlight. สอง จำกัด system clock ที่ 200 MHz (ไม่ใช่ 216 MHz เต็ม) เพราะมีข้อจำกัดบางอย่างใน path ของ LCD. สาม เปิดใช้ (enable) Cache ของ Cortex-M7 เพราะการวาดจอทำงานกับพิกเซลที่อยู่ติดกัน (มี locality สูง) การมี Cache จึงช่วยให้วาดเร็วขึ้น เหมาะกับงานทำเกมบนจอ.

เคล็ดลับการตั้งชื่อขา: ใน CubeMX ช่อง User Label เราตั้งชื่อขาเองได้ เช่นตั้ง PB0 เป็น LD1, PB7 เป็น LD2, PB14 เป็น LD3. เวลาเขียนโปรแกรมจะเรียกด้วยชื่อนี้ ทำให้ย้ายบอร์ด/เปลี่ยนขาแล้วแก้แค่ที่ตั้งชื่อ โค้ดส่วนอื่นยังทำงานได้เหมือนเดิม.

ตัวอย่าง: วาดจุดตรงตำแหน่งที่สัมผัส (loop หลัก)c
uint16_t pos[2];
while (1) {
  // อ่านสถานะสัมผัส: คืน 1 ถ้ามีการแตะ, 0 ถ้าไม่มี
  if (TS_IsTouched()) {
    HAL_GPIO_WritePin(GPIOB, LD3_Pin, GPIO_PIN_RESET); // สัมผัส → LD3 ดับ
    TS_GetCoordinate(pos);        // คืนพิกัดเป็น array 2 ตัว: pos[0]=X, pos[1]=Y
    uint16_t x = pos[0];
    uint16_t y = pos[1];
    LCD_DrawCircle(x, y, 2, BLACK); // วาดวงกลมรัศมี 2 พิกเซลสีดำตรงจุดที่แตะ
    LCD_DrawText(x, y, "touch");     // พิมพ์ข้อความตรงจุดนั้น
  } else {
    HAL_GPIO_WritePin(GPIOB, LD3_Pin, GPIO_PIN_SET); // ไม่สัมผัส → LD3 ติด
  }
}
VIZ-61การต่อสาย ILI9341 ผ่าน SPI + จังหวะ D/C
HW SPIGPIO ควบคุมbit-banged / backlight
NUCLEO-F767ZIILI9341 TFTSCKMOSIMISOCSD/CRESETLED (backlight)
จังหวะ D/C + ไบต์บน SPI
D/C0SCKMOSI00101010

0x2A D/C=0 → คำสั่ง (command). คำสั่ง: ตั้งช่วงคอลัมน์ (CASET)

ต่อ NUCLEO-F767ZI เข้ากับจอ TFT: สาย SPI (ฟ้า), สายควบคุม GPIO, และไฟส่องหลัง. วางเมาส์บนสายเพื่อดูหน้าที่. เส้น D/C บอกว่าแต่ละไบต์เป็นคำสั่งหรือข้อมูล.

แบบฝึกหัด

12 ข้อ — แต่ละข้อมีชนิดและระดับความยากกำกับ กดปุ่ม "ดูเฉลย" เพื่อดูคำตอบและคำอธิบาย

  1. 1.ปรนัยง่าย

    ภาพแบบ vector ต่างจากภาพแบบ raster ตรงไหน

  2. 2.ปรนัยง่าย

    หนึ่งพิกเซลสีประกอบด้วย sub-pixel กี่สีอะไรบ้าง

  3. 3.ถูก/ผิดง่าย

    จอ LCD เปล่งแสงด้วยตัวเองได้โดยไม่ต้องมี backlight

  4. 4.ปรนัยกลาง

    เมื่อ จ่ายไฟ ให้พิกเซลของจอ LCD แบบ TN จะเกิดอะไร

  5. 5.ปรนัยกลาง

    ทำไม backlight สีขาวจึงกลายเป็นภาพสีได้

  6. 6.ปรนัยกลาง

    ข้อจำกัดสำคัญของหน้าจอสัมผัสแบบ resistive คือข้อใด

  7. 7.ปรนัยกลาง

    หน้าจอ capacitive ต้องสัมผัสด้วยอะไรจึงจะตรวจเจอ

  8. 8.เติมคำกลาง

    ในการเข้ารหัส RGB565 สีเขียวได้จำนวนบิตเท่าใด และมากกว่าแดง/น้ำเงินเพราะเหตุใด

  9. 9.ปรนัยยาก

    ใน RGB565 ค่า hex ของสีเหลืองเต็ม (แดง+เขียว) คือข้อใด

  10. 10.ปรนัยยาก

    เทคนิค bit-banging หมายถึงอะไร

  11. 11.วิเคราะห์ยาก

    ในแล็บต้อง enable Cache ของ Cortex-M7 สำหรับงานวาดจอ เพราะเหตุใดจึงช่วยให้เร็วขึ้น

  12. 12.วิเคราะห์ยาก

    โปรแกรมต้องคอยเรียก TS_IsTouched() ใน loop เพื่อเช็กการสัมผัส วิธี polling แบบนี้มีข้อเสียอย่างไร และแก้ได้อย่างไร