เริ่มจากจุดนี้: จับคู่อาการ
อาการ | สาเหตุที่เป็นไปได้มากที่สุด | ไปที่ |
|---|---|---|
ไม่พบอะไรเลยที่ 0x5D หรือ 0x14 จากการสแกน I2C | คอนโทรลเลอร์ไม่มีไฟเลี้ยง ขาด pull-up หรือชิปถูกค้างอยู่ในสถานะรีเซ็ต | ขั้นตอนที่ 1 |
พบที่ 0x14 แต่ไดรเวอร์คาดหวัง 0x5D (หรือกลับกัน) หรือที่อยู่เปลี่ยนไปในแต่ละครั้งที่บูต | ระดับลอจิกขา INT ระหว่างรีเซ็ต | ขั้นตอนที่ 2 |
ตรวจพบอุปกรณ์ อ่าน product ID ได้ถูกต้อง แต่ไม่มีสัญญาณทัชเข้ามา | รีจิสเตอร์สถานะไม่ถูกเคลียร์ ขอบของอินเทอร์รัพท์ตั้งผิด หรือ INT ไม่ได้เดินสาย | ขั้นตอนที่ 3 |
มีสัญญาณทัชเข้ามาแต่ตำแหน่งผิด กลับด้าน หรือหมุน 90 องศา | ความละเอียดในคอนฟิกของ GT911 ไม่ตรงกับพาเนล หรือต้องสลับแกน | ขั้นตอนที่ 4 |
กำลังจะเขียนคอนฟิกบล็อกใหม่ | อ่านส่วนนี้ก่อน | ขั้นตอนที่ 5 |
ทำตามขั้นตอนตามลำดับ ที่อยู่รีจิสเตอร์และจังหวะเวลาด้านล่างอ้างอิงจากไดรเวอร์ goodix ของ Linux, คอมโพเนนต์ esp_lcd_touch_gt911 ของ Espressif และเอกสารของ ESPHome; ลิงก์อยู่ในหมวด Sources
1. ตรวจสอบว่า GT911 มีไฟเลี้ยงและตอบสนองบน I2C
กำลังไฟและ pull-up
device-tree binding ของ Linux สำหรับคอนโทรลเลอร์ Goodix ระบุแหล่งจ่ายไฟ 2 สาย: AVDD28 (อนาล็อก) และ VDDIO (รางไฟของลอจิก I/O) บนโมดูลหรือ FPC ทั้งสองสายมักจ่ายจากคอนเนกเตอร์ของโฮสต์ ดังนั้นให้วัดไฟที่คอนเนกเตอร์ก่อนสงสัยที่เฟิร์มแวร์ นอกจากนี้ SDA และ SCL ยังต้องมีตัวต้านทาน pull-up อยู่ที่ใดที่หนึ่งบนบัส โดยโมดูลจอจำนวนมากไม่ได้มีมาให้
สแกนบัส
รันสเก็ตช์สแกน I2C หรือ i2cdetect GT911 จะตอบสนองที่ที่อยู่แบบ 7-bit ใดที่หนึ่งจากสองค่านี้:
ที่อยู่แบบ 7-bit | ไบต์ write / read แบบ 8-bit (ตามที่บางดาต้าชีตระบุ) |
|---|---|
| |
| |
คู่ค่าแบบ 8-bit มาจากคอมเมนต์ในโค้ดรีเซ็ตของไดรเวอร์ Linux หากเอกสารของผู้ขายระบุ "address 0xBA" นั่นคืออุปกรณ์ตัวเดียวกับ 0x5D แบบ 7-bit; ให้ใส่ 0x5D ใน Arduino, ESP-IDF และ Linux
อ่าน product ID
รีจิสเตอร์บน GT911 ใช้ที่อยู่แบบ 16-bit ไดรเวอร์ Linux อ่าน 6 ไบต์จาก 0x8140: 4 ไบต์แรกคือ product ID เป็นข้อความ ASCII และ 2 ไบต์สุดท้ายคือเวอร์ชันเฟิร์มแวร์ (little-endian) GT911 จะรายงานสตริง 911 หากได้ 911 แปลว่าบัส ไฟเลี้ยง และที่อยู่ทำงานถูกต้องทั้งหมด และปัญหาอยู่ในขั้นตอนถัดไปของลิสต์นี้
หากไม่มีอะไรตอบสนองที่ทั้งสองที่อยู่ ให้ตรวจสอบว่าขา reset ไม่ได้ถูกค้างอยู่ที่ระดับ low บนโมดูลจำนวนมาก RST เป็นอินพุตของ GT911 และต้องถูกขับเป็น high โดยโฮสต์ (หรือ pull-up บนบอร์ด) ก่อนคอนโทรลเลอร์จะเริ่มทำงาน
2. จัดลำดับรีเซ็ตและการเลือกที่อยู่ให้ถูกต้อง
GT911 เลือกที่อยู่ I2C จากระดับลอจิกบนขา INT ในช่วงเวลาที่รีเซ็ตถูกปล่อย ตามคำของ device-tree binding ของ Linux ขา INT "is sampled by the device on reset deassertion to select the I2C client address"
ระดับลอจิกขา INT เมื่อ RST เป็น high | ที่อยู่ I2C |
|---|---|
ต่ำ | |
สูง | |
ลำดับขั้นตอนที่ไดรเวอร์ Linux ใช้
- จ่ายสัญญาณ RST เป็นระดับต่ำ แล้วรอมากกว่า 10 ms (ไดรเวอร์รอ 20 ms)
- จ่ายสัญญาณ INT ไปที่ระดับของที่อยู่ที่ต้องการ: สูงสำหรับ
0x14, ต่ำสำหรับ0x5D - รอมากกว่า 100 µs
- จ่ายสัญญาณ RST เป็นระดับสูง แล้วรอมากกว่า 5 ms (ไดรเวอร์รอ 6–10 ms)
- จ่ายสัญญาณ INT เป็นระดับต่ำนาน 50 ms จากนั้นสลับ INT เป็นโหมดอินพุต
หาก INT ลอย (floating) ระหว่างขั้นตอนที่ 4 ที่อยู่อาจต่างกันไปในแต่ละครั้งที่จ่ายไฟ นั่นคือสาเหตุคลาสสิกของรายงานปัญหา "แฟลชแล้วใช้งานได้ แต่ cold boot แล้วใช้งานไม่ได้"
ESP-IDF: esp_lcd_touch_gt911
คอมโพเนนต์ของ Espressif กำหนด ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS เป็น 0x5D และ ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP เป็น 0x14 โดยจะรันลำดับขั้นตอนเลือกที่อยู่ก็ต่อเมื่อครบทั้งสามเงื่อนไขนี้:
rst_gpio_numเป็น GPIO จริง (ไม่ใช่GPIO_NUM_NC),int_gpio_numเป็น GPIO จริง,driver_dataชี้ไปที่esp_lcd_touch_io_gt911_config_tที่มีdev_addrเป็นที่อยู่ที่คุณต้องการ
มิฉะนั้นจะบันทึกล็อกว่า I2C address initialization procedure skipped - using default GT9xx setup แล้วทำรีเซ็ตแบบปกติ ในกรณีนี้ ที่อยู่จะเป็นไปตามที่การเดินสายของบอร์ดกำหนด และที่อยู่ I2C ของ panel-IO ที่คุณระบุต้องตรงกับผลการสแกน ค่าเริ่มต้น I2C clock ของคอมโพเนนต์ใน ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG() คือ 100 kHz
บอร์ดที่โฮสต์ไม่ได้ควบคุมขา INT
หาก INT ไม่ได้ต่อกับโฮสต์ โฮสต์จะเลือกที่อยู่ไม่ได้ จึงต้องสแกนทั้งสองที่อยู่แล้วใช้ที่อยู่ที่ตอบสนอง ยกตัวอย่างเช่น Sunton ESP32-8048S043C ขาอินเทอร์รัปต์ของ GT911 ไม่ได้เดินสายต่อกับ GPIO โดยค่าเริ่มต้น (ดูหน้าบอร์ดของเรา) หน้า GT911 ของ ESPHome ระบุว่าเมื่อ INT ต่อผ่าน IO expander ขานี้ยังคงถูกใช้ตั้งค่าที่อยู่ตอนบูต แต่การสัมผัสจะถูกอ่านแบบ polling แทนที่จะเป็นแบบ interrupt-driven
3. ตรวจพบชิปแต่ไม่มีอีเวนต์การสัมผัส
อ่านและเคลียร์สถานะเรจิสเตอร์
ข้อมูลการสัมผัสเริ่มต้นที่ 0x814E ไบต์แรกเป็นสถานะไบต์:
- บิต 7 (
0x80): บัฟเฟอร์พร้อม ข้อมูลใหม่จะใช้ได้ก็ต่อเมื่อบิตนี้ถูกเซ็ตเท่านั้น - บิต 0–3: จำนวนจุดสัมผัส ไดรเวอร์ Linux จะปฏิเสธค่าที่มากกว่าค่าสูงสุดที่ตั้งค่าไว้
- บิต 4: มีการกดคีย์ (ปุ่ม)
จุดสัมผัสแต่ละจุดถัดจากนั้นมีขนาด 8 ไบต์: track ID ตามด้วย X, Y และ size เป็นค่า 16 บิตแบบ little-endian
หลังจากอ่านแล้ว ทั้งไดรเวอร์ Linux และ esp_lcd_touch_gt911 จะเขียนค่า 0 ลงที่ 0x814E หากคุณเขียนไดรเวอร์เอง ควรทำเช่นเดียวกัน การละเว้นการเขียนนี้เป็นสาเหตุที่พบบ่อยที่ทำให้ไดรเวอร์ที่เขียนเองเห็นเฉพาะการสัมผัสแรก
จับคู่ขอบสัญญาณอินเทอร์รัปต์ให้ตรงกัน
ประเภททริกเกอร์อยู่ในคอนฟิกูเรชันของ GT911 เอง: บิต 0–1 ของไบต์คอนฟิกที่ 0x804D (ออฟเซ็ต 6 จากจุดเริ่มต้นคอนฟิกที่ 0x8047) ไดรเวอร์ Linux แมปค่านี้ดังนี้:
ค่า | ประเภทอินเทอร์รัปต์ |
|---|---|
0 | ขอบขึ้น (Rising edge) |
1 | ขอบลง (Falling edge) |
2 | ระดับต่ำ |
3 | ระดับสูง |
ตั้งค่า GPIO interrupt ให้ตรงกัน ใน esp_lcd_touch_gt911 การกำหนด levels.interrupt = 1 จะเลือกขอบขาขึ้น (rising-edge) และ 0 จะเป็นขอบขาลง (falling edge)
ไม่มีขา INT? ใช้การ Poll แทน
การ Poll ใช้งานได้ดีสำหรับงาน HMI ESPHome จะ Poll ทุก 50 ms ตามค่าเริ่มต้น (update_interval) เมื่อไม่ได้ตั้งค่า interrupt_pin ส่วนไดรเวอร์ Linux เมื่อมี interrupt จะรอบิต ready นานสูงสุด 20 ms ก่อนยอมแพ้ต่อหนึ่งเฟรม
4. จุดสัมผัสอยู่ผิดตำแหน่ง
ตรวจสอบค่าความละเอียดที่เก็บไว้ใน GT911
GT911 รายงานค่าพิกัดตามความละเอียดที่เขียนไว้ในคอนฟิกูเรชันของมันเอง ไม่ใช่ตามความละเอียดของจอแสดงผลของคุณ ตามไดรเวอร์ Linux ค่า X maximum คือค่า 16 บิตแบบ little-endian ที่ 0x8048 และ Y maximum อยู่ที่ 0x804A ให้อ่านค่าทั้งสองออกมา ถ้าคอนโทรลเลอร์ถูกตั้งค่าไว้ที่ 1024×600 แต่พาเนลของคุณเป็น 800×480 จุดสัมผัสจะไปอยู่ทางขวาและด้านล่างของนิ้ว และตำแหน่งขอบสุดจะหลุดออกนอกจอ วิธีแก้คือทำการสเกลค่า (หรือตั้งลิมิตของไดรเวอร์ให้ตรงกับค่าของคอนโทรลเลอร์)
แต่ละสแตกได้ค่าลิมิตมาจากที่ใด:
สแตก | แหล่งที่มาของความละเอียด | สลับและกลับด้าน (swap และ mirror) |
|---|---|---|
Linux | อ่านจากคอนฟิกของ GT911 หากคอนฟิกไม่มีค่าจะ fallback ไปที่ 4095 × 4095 | Device-tree |
ESP-IDF | ค่า | |
ESPHome | Touchscreen | |
คาลิเบรตจากค่า raw
หน้าเอกสาร touchscreen ของ ESPHome แนะนำให้ log ค่า touch.x_raw และ touch.y_raw ใน lambda ของ on_touch แล้วแตะมุมทั้งสี่ที่ริมพิกเซลสุดหลาย ๆ ครั้ง จากนั้นนำค่า raw ต่ำสุดและสูงสุดที่ได้มาใส่เป็นค่า calibration วิธีเดียวกันนี้ใช้ได้กับทุกแพลตฟอร์ม: พิมพ์ค่า raw X และ Y ออกมา แตะมุมทั้งสี่ แล้ว map ช่วงค่าเข้ากับหน้าจอ
แก้การวางแนวตามลำดับนี้: ก่อนอื่นให้แกน X และ Y อยู่ถูกด้าน (swap_xy) จากนั้นค่อยกลับแกนที่วิ่งสวนทาง (mirror_x / mirror_y) จุด (0, 0) เชิงตรรกะของจอต้องอยู่ที่มุมซ้ายบน
5. การเขียนคอนฟิก GT911 ใหม่: ทางเลือกสุดท้าย
บล็อกคอนฟิกูเรชันเริ่มต้นที่ 0x8047 สำหรับ GT911 ไดรเวอร์ Linux ถือว่าบล็อกนี้มีขนาด 186 ไบต์:
- ไบต์ 0 (
0x8047): เวอร์ชันของคอนฟิก - ไบต์ 1–4: ความละเอียด X และ Y (ดูขั้นตอนที่ 4)
- ไบต์ 5 (
0x804C): จำนวนจุดสัมผัสสูงสุด, 4 บิตล่าง - ไบต์ 6 (
0x804D): ชนิดการทริกเกอร์ interrupt, 2 บิตล่าง - ไบต์ 184 (
0x80FF): checksum, ค่า two's complement 8 บิตของผลรวมไบต์ 0–183 - ไบต์ 185 (
0x8100):config_freshซึ่งต้องเป็น1
ตัวไดรเวอร์ Linux เองจะเขียนคอนฟิกก็ต่อเมื่อมี GPIO ทั้ง INT และ RST และพบไฟล์เฟิร์มแวร์ (ชื่อค่าเริ่มต้น goodix_911_cfg.bin หรือชื่อที่ระบุในพรอเพอร์ตี goodix,config-name) ถ้าไม่มีไฟล์นั้น มันจะใช้คอนฟิกที่เก็บไว้แล้วในชิป
ก่อนเขียนอะไรลงไป ให้อ่านค่าทั้ง 186 ไบต์ออกมาและเก็บสำรองไว้ แก้ความละเอียดและการวางแนวในซอฟต์แวร์ให้มากที่สุดเท่าที่จะทำได้ บล็อกคอนฟิกที่ทำมาสำหรับพาเนลสัมผัสรุ่นอื่นอาจทำให้การสัมผัสบนพาเนลของคุณใช้งานไม่ได้ ดังนั้นถ้าจำเป็นต้องเปลี่ยนจริง ๆ ให้ขอไฟล์มาจากผู้ขายพาเนล
การเลือกโมดูลแบบ capacitive-touch
ถ้าคุณกำลังเลือกจอ CTP สำหรับงานออกแบบใหม่ ให้ถามผู้ขายสามข้อก่อนสั่งซื้อ samples: ใช้ตัวคอนโทรลเลอร์สัมผัสรุ่นใด, ส่งมอบพร้อม I2C address ใด และขา INT กับ RST เดินมาถึงคอนเนกเตอร์หรือไม่ ส่งขนาด, อินเทอร์เฟซ และโปรเซสเซอร์ของตัว host มาทาง Ask an Engineer แล้วเราจะแนบคำตอบทั้งสามข้อนี้มาพร้อมโมดูลที่เราแนะนำให้
คำถามที่พบบ่อย
I2C address ของ GT911 คืออะไร?
ใช้ได้ทั้ง 0x5D หรือ 0x14 (แบบ 7-bit) เมื่อสิ้นสุดสถานะ reset ตัวควบคุมจะอ่านระดับลอจิกที่ขา INT ทันที: ถ้า INT เป็น Low จะเลือก 0x5D ถ้า INT เป็น High จะเลือก 0x14 ส่วนดาต้าชีตที่ระบุ 0xBA/0xBB หรือ 0x28/0x29 นั้นคือที่อยู่เดียวกันในรูปแบบไบต์ write/read แบบ 8-bit
ทำไม GT911 ของฉันถึงเปลี่ยน address หลังจากรีบูต?
ขา INT ลอยอยู่หรือถูกขับโดยอย่างอื่นขณะสิ้นสุดสถานะ reset ทำให้ตัวควบคุมอ่านค่าระดับที่ต่างกันในแต่ละครั้ง วิธีแก้คือจูงขา INT ให้เป็น Low (สำหรับ 0x5D) หรือ High (สำหรับ 0x14) ก่อนปล่อย RST รอมากกว่า 5 ms คงสถานะ INT เป็น Low ไว้ 50 ms แล้วจึงตั้งเป็นอินพุต ถ้าฝั่ง host ควบคุมขา INT ไม่ได้ ให้สแกนหาทั้งสองที่อยู่
ทำไม GT911 ของฉันได้แค่การสัมผัสเดียว?
หลังอ่านข้อมูลทัชที่ 0x814E แล้วต้องเขียนค่า 0 กลับไปที่ 0x814E ดรายเวอร์ goodix ของ Linux และ esp_lcd_touch_gt911 ของ Espressif ต่างทำแบบนี้หลังทุกครั้งที่อ่าน ถ้าดรายเวอร์ข้ามขั้นตอนนี้ไป มักจะไม่เห็นการแตะใหม่อีกเลย
ทำไมพิกัดสัมผัสของ GT911 ถึงถูกสเกลหรือเลื่อนตำแหน่ง?
GT911 รายงานพิกัดตามความละเอียดที่เก็บไว้ในคอนฟิกของตัวเอง (X ที่ 0x8048, Y ที่ 0x804A) ถ้าค่านี้ต่างจากพาเนลของคุณ ให้สเกลค่าที่ได้ หรือตั้ง x_max/y_max ของดรายเวอร์ให้ตรงกับความละเอียดของตัวควบคุม จากนั้นใช้ swap_xy และ mirror_x/mirror_y ปรับทิศทาง
GT911 ใช้งานได้หรือไม่หากไม่มีขา INT?
ได้ครับ ให้เปลี่ยนจากการใช้ขา interrupt มาเป็นการอ่านสถานะจากรีจิสเตอร์ 0x814E แทน เมื่อไม่ได้ตั้งค่า interrupt_pin ESPHome จะทำการ polling ทุก 50 ms เป็นค่าเริ่มต้น และเนื่องจากไม่มีขา INT โฮสต์จึงไม่สามารถเลือกที่อยู่ของอุปกรณ์ได้ ให้ใช้ที่อยู่ใดก็ได้จาก 0x5D หรือ 0x14 ที่ตอบสนอง
ควรเขียนคอนฟิกูเรชันของ GT911 ใหม่หรือไม่?
ทำเฉพาะเมื่อทางเลือกอื่นหมดแล้วเท่านั้น ให้อ่านและสำรองบล็อกข้อมูล 186 ไบต์เดิมจาก 0x8047 ไว้ก่อน และถ้าจำเป็นต้องเขียนคอนฟิกจริง ๆ ให้ใช้ไฟล์คอนฟิกจากผู้ขายทัชแพเนล โดยเลือกแก้ความละเอียดและทิศทางในซอฟต์แวร์ก่อนเสมอ บล็อกนี้ปิดท้ายด้วย checksum แบบ 8-bit ที่ 0x80FF และไบต์ config_fresh ที่ 0x8100 ซึ่งต้องมีค่าเป็น 1
แหล่งที่มา
- Linux kernel: drivers/input/touchscreen/goodix.c
- Linux kernel: drivers/input/touchscreen/goodix.h (ที่อยู่รีจิสเตอร์)
- Linux kernel: Goodix touchscreen device-tree binding (goodix.yaml)
- Espressif ESP-BSP: ซอร์สโค้ดดรายเวอร์ esp_lcd_touch_gt911
- Espressif ESP-BSP: เฮดเดอร์ esp_lcd_touch_gt911 (ที่อยู่ I2C)
- ESPHome: GT911 touchscreen
- ESPHome: Touchscreen components (transform, calibration)