[TH] แถบแสดงค่าอุณหภูมิและความชื้น

บทความนี้เป็นตัวอย่างโปรแกรมสำหรับกรณีที่ต้องการแสดงแถบแสดงค่าอุณหภูมิและความชื้นดังภาพที่ 1 ด้วย MicroPython กับบอร์ด esp32 ที่ติดตั้ง OLED จะเขียนอย่างไร โดยอุปกรณ์ในการทดลองครั้งนี้ใช้ DHT22 เป็นอุปกรณ์วัดความชื้นและอุณหภูมิ โดยบอร์ดเชื่อมต่อกับบัส I2C เพื่อสื่อสารกับ OLED ผ่านทางขา GPIO4 และ GPIO5 สำหรับทำหน้าที่ SCL และ SDA ตามลำดับ พร้อมกันนี้ได้ต่อขาสัญญาณของ DHT22 เข้ากับขา GPIO15 เพื่อใช้สื่อสารกันระหว่างเซ็นเซอร์กับไมโครคอนโทรเลอร์

ภาพที่ 1 ตัวอย่างผลัพธ์ของการแสดงแถบแสดงค่าอุณหภูมิและความชื้น

ขั้นตอนการทำงานของโปรแกรม

ขั้นตอนการทำงานของโปรแกรมตัวอย่างเป็นดังนี้

  1. กำหนดค่าการทำงานเบื้องต้น
  2. เริ่มต้นการทำงานของ OLED
  3. เริ่มต้นการทำงานของเซ็นเซอร์
  4. วงรอบโปรแกรมหลัก
    1. อ่านค่าจากเซ็นเซอร์
    2. แสดงค่าอุณหภูมิ
      1. แสดงข้อความค่าอุณหภูมิ
      2. แสดงค่าเริ่มต้น (0)
      3. แสดงค่าอุณหภูมิสูงสุด
      4. วาดเส้นกราฟแนวนอน
      5. คำนวณตำแหน่งของตัวชี้ค่าอุณหภูมิ (x1)
      6. วาดตัวชี้ตำแหน่งค่าอุณหภูมิ
    3. แสดงค่าความชื้น
      1. แสดงข้อความค่าความชื้น
      2. แสดงค่าเริ่มต้นของค่าความชื้น (0)
      3. แสดงค่าสูงสุดของค่าความชื้น
      4. วาดเส้นกราฟแนวนอน
      5. คำนวณตำแหน่งของตัวชี้ค่าความชื้น (x2)
      6. วาดตัวขี้ตำแหน่งของค่าความชื้น

โค้ดโปรแกรม

จากขั้นตอนของการทำงานนำมาเขียนโปรแกรมได้ดังนี้

# dhtBar.py
from machine import Pin,I2C
import dht
import machine
import gc
import ssd1306
import time

# system
gc.enable()
gc.collect()
machine.freq(240000000)

# OLED
sclPin = Pin(4)
sdaPin = Pin(5)
i2c = I2C(0,scl=sclPin,sda=sdaPin)
oled = ssd1306.SSD1306_I2C(128,32,i2c)
oled.poweron()
oled.contrast(255)
oled.init_display()
oled.fill(0)
oled.text("JarutEx", 40, 24)
for i in range(32):
    oled.show()
    oled.scroll(0,-1)
    time.sleep_ms(30)

# Sensor
dht22 = dht.DHT22(Pin(15))

# main program
barWidth = 88
barHeight = 6
maxTem = 40.0
maxHum = 100.0

while True:
    dht22.measure()
    tem = dht22.temperature()
    hum = dht22.humidity()
    oled.fill(0)
    oled.text("T={}C".format(tem), 10, 0)
    oled.text("0",0,8)
    oled.text("{}".format(int(maxTem)),100,8)
    for x in range(barWidth):
        oled.pixel(10+x,10,1)
    x1 = int(barWidth*tem/maxTem)
    for y in range(barHeight):
        oled.pixel(x1-1,8+y,1)
        oled.pixel(x1,8+y,1)
        oled.pixel(x1+1,8+y,1)

    oled.text("H={}%".format(hum), 10, 16)
    oled.text("0",0,24)
    oled.text("{}".format(int(maxHum)),100,24)
    for x in range(barWidth):
        oled.pixel(10+x,26,1)
    x2 = int(barWidth*hum/maxHum)
    for y in range(barHeight):
        oled.pixel(x2-1,24+y,1)
        oled.pixel(x2,24+y,1)
        oled.pixel(x2+1,24+y,1)
    oled.show()
    time.sleep_ms(10000)


และเพื่อให้ดูแปลกตาในครั้งแรกที่ระบบทำงานเราจะให้ตัวชี้ค่าของอุณหภูมิและความชื้นวิ่งจาก 0 ไปหาค่าปัจจุบัน ทำให้โปรแกรมออกมาเป็นดังนี้

# dhtBar.py
from machine import Pin,I2C
import dht
import machine
import gc
import ssd1306
import time

# system
gc.enable()
gc.collect()
machine.freq(240000000)

# OLED
sclPin = Pin(4)
sdaPin = Pin(5)
i2c = I2C(0,scl=sclPin,sda=sdaPin)
oled = ssd1306.SSD1306_I2C(128,32,i2c)
oled.poweron()
oled.contrast(255)
oled.init_display()
oled.fill(0)
oled.text("JarutEx", 40, 24)
for i in range(32):
    oled.show()
    oled.scroll(0,-1)
    time.sleep_ms(30)

# Sensor
dht22 = dht.DHT22(Pin(15))

# main program
barWidth = 88
barHeight = 6
maxTem = 40.0
maxHum = 100.0
bT0 = True

while True:
    dht22.measure()
    tem = dht22.temperature()
    hum = dht22.humidity()
    if (bT0): # 1st time ให้เอนิเมทกราฟ
        bT0 = False
        x1 = int(barWidth*tem/maxTem)
        x2 = 0
        xAnim = 0
        while (xAnim <= x1):
            oled.fill(0)
            oled.text("T={}C".format(tem), 10, 0)
            oled.text("0",0,8)
            oled.text("{}".format(int(maxTem)),100,8)
            oled.text("H={}%".format(hum), 10, 16)
            oled.text("0",0,24)
            oled.text("{}".format(int(maxHum)),100,24)
            for x in range(barWidth):
                oled.pixel(10+x,10,1)
                oled.pixel(10+x,26,1)
            for y in range(barHeight):
                oled.pixel(xAnim-1,8+y,1)
                oled.pixel(x2-1,24+y,1)
                oled.pixel(xAnim,8+y,1)
                oled.pixel(x2,24+y,1)
                oled.pixel(xAnim+1,8+y,1)
                oled.pixel(x2+1,24+y,1)
            oled.show()
            xAnim += 1
        x2 = int(barWidth*hum/maxHum)
        xAnim = 0
        while (xAnim <= x2):
            oled.fill(0)
            oled.text("T={}C".format(tem), 10, 0)
            oled.text("0",0,8)
            oled.text("{}".format(int(maxTem)),100,8)
            oled.text("H={}%".format(hum), 10, 16)
            oled.text("0",0,24)
            oled.text("{}".format(int(maxHum)),100,24)
            for x in range(barWidth):
                oled.pixel(10+x,10,1)
                oled.pixel(10+x,26,1)
            for y in range(barHeight):
                oled.pixel(x1-1,8+y,1)
                oled.pixel(xAnim-1,24+y,1)
                oled.pixel(x1,8+y,1)
                oled.pixel(xAnim,24+y,1)
                oled.pixel(x1+1,8+y,1)
                oled.pixel(xAnim+1,24+y,1)
            oled.show()
            xAnim += 1
    else:
        oled.fill(0)
        oled.text("T={}C".format(tem), 10, 0)
        oled.text("0",0,8)
        oled.text("{}".format(int(maxTem)),100,8)
        oled.text("H={}%".format(hum), 10, 16)
        oled.text("0",0,24)
        oled.text("{}".format(int(maxHum)),100,24)
        for x in range(barWidth):
            oled.pixel(10+x,10,1)
            oled.pixel(10+x,26,1)
        x1 = int(barWidth*tem/maxTem)
        x2 = int(barWidth*hum/maxHum)
        for y in range(barHeight):
            oled.pixel(x1-1,8+y,1)
            oled.pixel(x2-1,24+y,1)
            oled.pixel(x1,8+y,1)
            oled.pixel(x2,24+y,1)
            oled.pixel(x1+1,8+y,1)
            oled.pixel(x2+1,24+y,1)
        oled.show()
        time.sleep_ms(10000)


ส่วนตัวอย่างด้านล่างนี้เพิ่มเรื่องของการเอนิเมชันและให้แสดงค่าในช่วง min..max เพื่อให้ดูง่ายขึ้น

สรุป

จากบทความนี้จะพบว่าการแสดงกราฟแบบต่าง ๆ ต้องอาศัยการคำนวณเพื่อปรับค่าหรือแปลงค่าให้เหมาะสมกับการแสดงผล โดยหลักการคำนวณดังกล่าวนี้ยังคงเหมือนเดิมแม้เปลี่ยนอุปกรณ์แสดงผล แต่ค่าพารามิเตอร์ของความกว้าง ความสูง หรือตำแหน่งของการแสดงผลจะแตกต่างตามขนาดของอุปกรณ์ และผู้อ่านจะพบว่า ภาษาไพธอนของ Micropython เพียงพอสำหรับการแสดงผลเช่นกัน ถึงแม้การทำงานจริงนั้นช้ากว่าภาษา C/C++  ค่อนข้างมาก แต่ด้วยลักษณะของการทำงาน คือ อ่านค่าจากเซ็นเซอร์ DHT22 หรือ DHT11  ซึ่งทำงานแปลงค่า 2 วินาที และ 1 วินาที ตามลำดับ ซึ่งเป็นระยะเวลาที่มากพอสำหรับให้ภาษาไพธอนคำนวณและแสดงผล แต่การเขียนโปรแกรมทำได้ง่าย แก้ไขงานได้ันทีโดยไม่ต้องคอมไพล์และเริ่มต้นอัพโหลดใหม่ซึ่งกินเวลาในขั้นตอนของการพัฒนามากกว่าภาษาไพธอน นั่นหมายความว่าในข้อเสียย่อมมีข้อดีอยู่บ้าง และในข้อดีก็มีข้อเสียอยู่เช่นกัน

สุดท้าย ขอให้สนุกกับการเขียนโปรแกรมครับ

ท่านใดต้องการพูดคุยสามารถคอมเมนท์ได้เลยครับ

(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ

ปรับปรุงเมื่อ 2021-08-26, 2021-11-25