บทความนี้เป็นการเชื่อมต่อ ESP8266 เข้ากับโอแอลอีดี หรือ OLED ซึ่งเป็นแอลอีดีกราฟิกแบบ 2 สี คือ สี 0 แทนไม่แสดงจุดสี และ 1 แทนการแสดงจุดสี โดยเชื่อมต่อกับไมโครคอนโทรลเลอร์ผ่านบัส I2C โดยกล่าวถึงวิธีการใช้และฟังก์ชันสำหรับใช้งานเพื่อเป็นแนวทางและเนื้อหาอ้างอิงในการนำไปใช้ต่อไป
ตัวควบคุมการแสดงผล
โอแอลอีดีที่ผู้เขียนใช้งานพบว่ามีตัวควบคุมการแสดงผล 2 ประเภท คือ ใช้ไอซี sh1106 หรือ ssd1306 ซึ่งโมดูลแอลอีดีมักไม่ได้ระบุไว้ และผู้ใช้งานไม่สามารถมองเห็นได้เนื่องจากถูกโมดูลแอลอีดีบังไว้ โดย OLED (มีสีฟ้า และสีขาว หรือบางรุ่นมีการกำหนดให้บางแถวเป็นสีหนึ่งและบางแถวเป็นอีกสีหนึ่ง) ที่เลือกใช้ในบทความนี้เป็นแบบ I2C ดังภาพที่ 2 และเชื่อมต่อกับขาของ esp8266 ดังภาพที่ 3
ไลบรารีที่ต้องใช้
import sh1106
หรือ
import ssd1306
ในการเรียกใช้ต้องทดลองว่าผลลัพธ์เป็นอย่างไร ถ้าออกมาผิดพลาดให้กลับไปเลือกอีกตัวหนึ่ง
เตรียมการ i2c
from machine import I2C, Pin
i2c = I2C(sda=Pin(4), scl=Pin(5))
oled_addr = const(0x3c)
oled = sh1106.SH1106_I2C(128,64,i2c,None,oled_addr)
หลังจากเรียกใช้ไลบรารีสำหรับตัวควบคุมแอลอีดี ขั้นตอนต่อมาคือเปิดการใช้งาน บัส I2C และสร้างตัวแปรสำหรับชี้ไปยังโมดูลแอลอีดีแบบโอแอลอีดี
แสดงข้อความ
oled.text("ข้อความ", x, y, c=1)
โดย
c คือ สีของจุด ซึ่ง 1 แทนสีสว่าง และ 0 แทนสีดำ
x,y คือ พิกัดมุมซ้ายบนของข้อความที่เริ่มต้นแสดงผล
สั่งแสดงข้อมูลที่จอแสดงผล
oled.show()
การสั่ง show( ) เป็นสั่งให้ตัวควบคุมโมดูลแอลอีดีนำข้อมูลจากบัฟเฟอร์ทั้งหมดเขียนลงโมดูลแอลอีดี ทำให้มองเห็นผลลัพธ์คำสั่งที่สั่งให้กับตัวควบคุม
สั่งเติมสี
oled.fill( 1 ) # เติมสีสว่าง
oled.fill( 0 ) # เติมสีดำ
การเติมสี เป็นการกำหนดให้สีฉากหลังของโมดูลแอลอีดีทั้งหมดเป็นสี 0 หรือ 1 เปรียบเสมือนการล้างค่าหน้าจอด้วยสี 0 หรือ 1
สั่งลงพิกเซลที่ตำแหน่ง (x,y)
oled.pixel( x, y, c )
โดย
x,y คือ พิกัดของพิกเซลซึ่งค่า x อยู่ในช่วง [0, 127] และ y อยู่ในช่วง [0, 63]
c คือ ค่าสีของพิกเซล ซึ่งมีค่าเป็น 0 หรือ 1
สั่งให้กลับสี
oled.invert( True )
oled.invert( False )
การสั่งกลับสีทำให้จุดสีถูกเปลี่ยนเป็นสีตรงกันข้าม คือ เดิมที่เป็น 0 จะเปลี่ยนเป็น 1 และจาก 1 กลายเป็น 0 ดังนั้น เมื่อนำเทคนิคการกลับสีมาใช้กับการกะพริบหน้าจอ 5 ครั้ง ในเวลา 1 วินาที จะเขียนโค้ดได้ดังนี้
for counter in range(5):
oled.invert(True)
time.sleep_ms(100)
old.invert(False)
time.sleep_ms(100)
สั่งอ่านค่าสีที่ตำแหน่ง (x,y)
c = oled.pixel( x, y )
โดย c คือ ค่าสีที่อ่านได้จากพิกัด (x,y)
สั่งวาดเส้นตรงในแนวนอน
oled.hline( x, y, w, c=1 )
โดย
x,y คือ ตำแหน่งเริ่มต้น
w คือ ความยาวของเส้น
c คือ สี
สั่งวาดเส้นตรงในแนวตั้ง
oled.vline( x, y, h, c=1 )
โดย
x,y คือ ตำแหน่งเริ่มต้น
h คือ ความยาวของเส้น
c คือ สี
สั่งวาดเส้นตรง
oled.line( x1, y1, x2, y2, c=1 )
โดย
x1,y1 คือ พิกัดเริ่มต้นของเส้นตรง
x2,y2 คือ พิกัดสิ้นสุดของเส้นตรง
c คือ สี
สั่งวาดสี่เหลี่ยม
oled.rect( x, y, w, h, c )
โดย
x,y คือ พิกัดมุมซ้ายบนของสี่เหลี่ยม
w คือ ความกว้างของสี่เหลี่ยม
h คือ ความสูงของสี่เหลี่ยม
c คือ สี
สั่งวาดสี่เหลี่ยมทึบ
oled.fill_rect( x, y, w, h, c )
โดย
x,y คือ พิกัดมุมซ้ายบนของสี่เหลี่ยม
w คือ ความกว้างของสี่เหลี่ยม
h คือ ความสูงของสี่เหลี่ยม
c คือ สี
สั่งเลื่อนหน้าจอในแกน x และ y
oled.scroll( x, y )
โดย
x คือ ตำแหน่งการเลื่อนในแกน x
y คือ ตำแหน่งการเลื่อนในแกน y
เช่น ต้องการเลื่อนหน้าจอลง 4 จุด พร้อมทั้งเลื่อนไปทางซ้าย 8 จุด สามารถสั่งงานได้เป็น
oled.scroll( -8, -4 )
การวาดภาพที่สร้างเองด้วยการลงพิกเซล
การวาดโดยใช้ข้อมูล 1 ตัวต่อ 1 พิกเซล
ขั้นตอนที่ 1 สร้างตัวแปรเก็บค่ารูปภาพ เช่น ต้องการแสดง “ก”
korkai = [
[ 0, 0, 1, 1, 1, 1, 1, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 1 ],
[ 0, 0, 1, 0, 0, 0, 0, 1 ],
[ 0, 1, 0, 0, 0, 0, 0, 1 ],
[ 0, 1, 0, 0, 0, 0, 0, 1 ],
[ 0, 1, 0, 0, 0, 0, 0, 1 ],
[ 0, 1, 0, 0, 0, 0, 0, 1 ],
[ 0, 1, 0, 0, 0, 0, 0, 1 ]
]
ขั้นตอนที่ 2 สั่งลงพิกเซล เช่น
for ch_row in range(8):
for ch_col in range(8):
oled.pixel( ch_col, ch_row, korkai[ch_row][ch_col] )
ขั้นตอนที่ 3 สั่งแสดงผล
oled.show( )
การวาดโดยใช้ข้อมูล 1 บิตต่อ 1 พิกเซล
ขั้นตอนที่ 1 สร้างตัวแปรเก็บค่ารูปภาพ เช่น ต้องการแสดง “ก”
korkai = [
0b00111110,
0b01000001,
0b00100001,
0b01000001,
0b01000001,
0b01000001,
0b01000001,
0b01000001
]
ขั้นตอนที่ 2 สั่งลงพิกเซล เช่น
for ch_row in range(8):
bit = 0x80
for ch_col in range(8):
cl = korkai[ch_row]&bit
oled.pixel( ch_col, ch_row, cl)
bit >>= 1
ขั้นตอนที่ 3 สั่งแสดงผล
oled.show( )
การวาดแบบบิตและให้ตัวหนา
ให้ปรับแต่งขั้นตอนที่ 2 เพื่อสั่งวาดพิกเซล 2 จุดติดกันแทนการวาดเพียงจุดเดียว
for ch_row in range(8):
bit = 0x80
for ch_col in range(8):
cl = korkai[ch_row]&bit
oled.pixel( ch_col*2, ch_row, cl)
oled.pixel( ch_col*2+1, ch_row, cl)
bit >>= 1
การวาดแบบบิตและให้ตัวใหญ่ 2 เท่า
ให้ปรับแต่งขั้นตอนที่ 2 เพื่อสั่งวาดสี่เหลี่ยมแบบเติมสีขนาด 2×2 แทนการใช้พิกเซล
for ch_row in range(8):
bit = 0x80
for ch_col in range(8):
cl = korkai[ch_row]&bit
oled.fill_rect( ch_col*2, ch_row*2, 2, 2, cl)
bit >>= 1
การวาดแบบโปร่งใส
การวาดแบบโปร่งใสหรือโปร่งแสงเป็นการตรวจสอบข้อมูลสีในการวาด คือ ถ้าเป็น 1 จึงจะลงจุดสี แต่ถ้าเป็น 0 จะไม่ลงจุดสี ซึ่งการไม่ลงจุดสีนี้มีผลทำให้ข้อมูลสีที่ลงไว้ก่อนหน้าไม่ถูกทับด้วยสี 0 ตัวอย่าง การตรวจสอบและการวาดแบบโปร่งแสงเป็นดังนี้
for ch_row in range(8):
bit = 0x80
for ch_col in range(8):
cl = korkai[ch_row]&bit
if cl:
oled.pixel( ch_col, ch_row, 1)
bit >>= 1
จัดเก็บบิตแม็พแบบ bytearray
ขั้นตอนที่ 1 สร้างตัวแปรเก็บค่ารูปภาพ เช่น ต้องการแสดง “ก” ซึ่งวิธีการนี้เป็นการรับประกันขนาดของข้อมูลแต่ละชุกมีขนาด 1 ไบต์
korkai = bytearray(
[0b00111110,
0b01000001,
0b00100001,
0b01000001,
0b01000001,
0b01000001,
0b01000001,
0b01000001]
)
ขั้นตอนที่ 2 สั่งลงพิกเซล เช่น
for ch_row in range(8):
bit = 0x80
for ch_col in range(8):
cl = korkai[ch_row]&bit
oled.pixel( ch_col, ch_row, cl)
bit >>= 1
ขั้นตอนที่ 3 สั่งแสดงผล
oled.show( )
สั่งปรับความสว่าง
oled.contrast( cn )
โดย cn คือ ระดับความสว่างมีค่าอยู่ในช่วง 0 ถึง 255
การบลิต
การบลิต (blit) เป็นเทคนิคของการส่งบัฟเฟอร์ข้อมูลขนาด WxH ไปยังบัฟเฟอร์แสดงผล ทำให้ประสิทธิภาพในการส่งข้อมูลดีกว่าการสั่งแสดงพิกเซลจำนวน WxH พิกเซลด้วยการวนรอบ W*H ครั้ง
รูปแบบของข้อมูลที่นำไปใช้กับการบลิตต้องเป็นข้อมูลประเภท bytearray และรูปแบบของคำสั่งใช้งานเป็นดังนี้
oled.blit( buf, x, y )
โดย
buf คือ ข้อมูลประเภท FrameBuffer ที่เก็บข้อมูลภาพ
x,y คือ พิกัดมุมบนซ้ายของโมดูลแอลอีดีที่ใช้เริ่มต้นบลิตภาพ
การสร้างข้อมูลแบบ framebuffer มีขั้นตอนการทำดังนี้
import framebuf
data = bytearray([ข้อมูล])
buf = framebuf.FrameBuffer( data, width, height, framebuf.MONO_HLSB)
ตัวอย่างการวาดภาพ “ก” ด้วยการบลิต
ขั้นตอนที่ 1 สร้างตัวแปรเก็บค่ารูปภาพ เช่น ต้องการแสดง “ก”
korkai = bytearray(
[0b00111110,
0b01000001,
0b00100001,
0b01000001,
0b01000001,
0b01000001,
0b01000001,
0b01000001]
)
ขั้นตอนที่ 2 สร้าง FrameBuffer
buf = framebuf.FrameBuffer( korkai, 8, 8, framebuf.MONO_HLSB)
ขั้นตอนที่ 3 สั่งบลิตภาพที่ตำแหน่ง (x, y)
oled.blit(buf, x, y )
ขั้นตอนที่ 4 สั่งแสดงผล
oled.show( )
สรุป
จากบทความนี้จะพบว่า เราสามารถสั่งงานแสดงผลโมดูล OLED ผ่านบัส I2C โดยใช้สายสัญญาณเพียง 2 เส้น คือ sda และ scl พร้อมทั้งได้เรียนรู้คำสั่ง และตัวอย่างวิธีการใช้งาน สุดท้ายหวังว่าบทความนี้คงเป็นประโยชน์บ้างไม่มากก็น้อยและขอให้สนุกกับการเขียนโปรแกรมครับ
อ้างอิง
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-06-11, 2021-06-28, 2021-09-27