วันอังคาร, ธันวาคม 17

MicroPython: การใช้งานเซ็นเซอร์วัดอุณหภูมิ DS18B20 ด้วย ESP32



บทความนี้แสดงวิธีใช้เซ็นเซอร์อุณหภูมิ DS18B20 กับ ESP32 โดยใช้เฟิร์มแวร์ MicroPython คุณจะได้เรียนรู้วิธีการอ่านอุณหภูมิจากเซ็นเซอร์ DS18B20 และจะสร้างเว็บเซิร์ฟเวอร์เพื่อแสดงการอ่านค่าจากเซ็นเซอร์ DS18B20


### อุปกรณ์ที่ใช้ ###


1. PICO KIT V4 ESP32 Development Board WiFi + Bluetooth

2. Micro USB Cable Wire 1m for NodeMCU

3. Breadboard 830 Point MB-102

4. Jumper (M2M) 20cm Male to Male

5. DS18B20 TO92 Temperature Sensor

6. รีซิสเตอร์ 4.7K Ohm 1/4W 5%


เซนเซอร์วัดอุณหภูมิ DS18B20

เซ็นเซอร์อุณหภูมิ DS18B20 เป็นเซ็นเซอร์อุณหภูมิแบบดิจิตอลหนึ่งสาย ซึ่งหมายความว่ามันต้องการเพียงหนึ่งสายข้อมูล (และ GND) เพื่อสื่อสารกับ ESP32 ของคุณ

สามารถทำงานโดยแหล่งจ่ายไฟภายนอกหรือสามารถรับพลังงานจากสายข้อมูล (เรียกว่า "parasite mode") ซึ่งไม่จำเป็นต้องใช้แหล่งจ่ายไฟภายนอก




เซ็นเซอร์อุณหภูมิ DS18B20 แต่ละตัวมีรหัสซีเรียล (address) 64 บิตที่ไม่ซ้ำกัน วิธีนี้ช่วยให้คุณสามารถใช้เซ็นเซอร์หลายๆตัวเข้ากับสายข้อมูลเดียวกันได้ ดังนั้นคุณสามารถรับอุณหภูมิจากเซ็นเซอร์หลายๆตัวโดยใช้ GPIO เพียงพินเดียว


โดยขั้นตอนการทำงานมีดังนี้


1. เริ่มต้นใช้งาน MicroPython กับ ESP32 ด้วย uPyCraft IDE



2. 
การใช้งานเซ็นเซอร์วัดอุณหภูมิ DS18B20 ด้วย ESP32


เชื่อมต่อ ESP32 กับ เซ็นเซอร์วัดอุณหภูมิ DS18B20




3. อัพโหลดโค้ด


3.1 อัพโหลดโค้ด ไฟล์ main.py


3.2.1  แก้ไขไฟล์ main.py ที่เคยสร้างไว้แล้ว (อยู่ที่คอมพิวเตอร์เรา workSpace) ตามโค้ดด้านล่าง 
โค้ดนี้จะรับอุณหภูมิจากเซ็นเซอร์อุณหภูมิ DS18B20 และแสดงการอ่านที่ บน Python shell





import machine, onewire, ds18x20, time

ds_pin = machine.Pin(32)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

roms = ds_sensor.scan()
print('Found DS devices: ', roms)

while True:
  ds_sensor.convert_temp()
  time.sleep_ms(750)
  for rom in roms:
    print(rom)
    print(ds_sensor.read_temp(rom))
  time.sleep(5)


โค้ดทำงานอย่างไร


นำเข้าโมดูล machine เพื่อติดต่อกับ GPIO, โมดูล onewire และ ds18x20 เพื่อติดต่อกับเซ็นเซอร์อุณหภูมิ DS18B20 และโมดูล time เพื่อ หน่วงเวลา
import machine, onewire, ds18x20, time
สร้างตัวแปรที่ชื่อว่า ds_pin ที่อ้างถึง GPIO 32 ซึ่งเป็นพินที่เชื่อมต่ออยู่กับสายข้อมูลของเซ็นเซอร์อุณหภูมิ DS18B20 
ds_pin = machine.Pin(32)
จากนั้นสร้างวัตถุ ds18x20 ชื่อ ds_sensor บน ds_pin ที่กำหนดไว้ก่อนหน้า หากคุณต้องการอ่านเซ็นเซอร์โดยใช้พินอื่นคุณต้องแก้ไขโค้ดบรรทัดก่อนหน้า
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
DS18B20 สื่อสารผ่านโปรโตคอลการสื่อสารแบบหนึ่งสายและเซ็นเซอร์แต่ละตัวมีรหัสซีเรียล (address) 64 บิตที่ไม่ซ้ำกัน ซึ่งหมายความว่าคุณสามารถอ่านเซ็นเซอร์อุณหภูมิหลายสายบน GPIO เดียวกันได้

บรรทัดต่อไปนี้ใช้ฟังก์ชัน scan () เพื่อสแกนหาเซ็นเซอร์ DS18B20 โดย address ที่พบจะถูกบันทึกไว้ในตัวแปร roms (ตัวแปร roms เป็น type list)

roms = ds_sensor.scan()
แสดงที่อยู่ (address) ของเซ็นเซอร์แต่ละตัวไปที่ Python shell:
print('Found DS devices: ', roms)
จากนั้นจึงมีการวนลูปเพื่อรับค่าอุณหภูมิจากเซ็นเซอร์ DS18B20 ทุก 5 วินาที
คุณต้องเรียกใช้ฟังก์ชัน convert_temp () บนวัตถุ ds_sensor ทุกครั้งที่คุณต้องการเก็บค่าอุณหภูมิ 
ds_sensor.convert_temp()
เพิ่มการหน่วงเวลา 750 ms เพื่อให้มีเวลาเพียงพอในการแปลงหน่วยอุณหภูมิ:
time.sleep_ms(750)
หลังจากนั้นเราสามารถอ่านอุณหภูมิของที่อยู่ที่พบก่อนหน้านี้โดยใช้วิธี read_temp () และส่ง address เป็นอาร์กิวเมนต์
print(ds_sensor.read_temp(rom))
เนื่องจากคุณสามารถเพิ่มเซ็นเซอร์หลายตัวในสายข้อมูลเดียวกัน
เราจึงมีการวนลูป 
address ทั้งหมดและแสดงอุณหภูมิสำหรับแต่ละเซ็นเซอร์:
for rom in roms:
  print(rom)
  print(ds_sensor.read_temp(rom))

4. ทดสอบการทำงานเซ็นเซอร์ DS18B20


4.1 อัพโหลดโค้ด main.py ไปยัง บอร์ด ESP32




4.2 ที่ Python shell แสดง อุณหภูมิที่วัดได้จากเซ็นเซอร์ DS18B20 (แสดงว่าประสบความสำเร็จแล้ว)




5. แสดงอุณหภูมิ DS18B20 บนเว็บเซิร์ฟเวอร์ 


5.1 อัพโหลดโค้ด 
ไฟล์ boot.py



สร้างไฟล์ boot.py โดยจะสร้างไว้ที่ workSpace ซึ่งส่วนนี้จะเก็บอยู่ที่ คอมพิวเตอร์ของเรา

(
ไฟล์ boot.py ถ้าอยู่ที่บอร์ด ESP32 จะทำงานโดยอัตโนมัติเมื่อมีการรีเซตบอร์ด และหลังจากนั้น ถ้ามีไฟล์ชื่อ main.py ก็จะทำงานเป็นลำดับถัดไป)


5.1.2 คลิกที่ New file





5.1.3 เขียนโค้ดดังนี้

คัดลอกโค้ดต่อไปนี้ไปยังไฟล์ boot.py และอัปโหลดไปยังบอร์ด ESP32 ของคุณ 


try:
  import usocket as socket
except:
  import socket
  
from time import sleep
from machine import Pin
import onewire, ds18x20

import network

import esp
esp.osdebug(None)

import gc
gc.collect()

ds_pin = Pin(32)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

station = network.WLAN(network.STA_IF)

station.active(True)
station.connect(ssid, password)

while station.isconnected() == False:
  pass

print('Connection successful')
print(station.ifconfig())


ก่อนการอัพโหลดต้องแก้ไขโค้ด ตรงตัวอักษรสีแดงให้ถูกต้อง ตามเครือข่าย WiFi ที่เลือกใช้งาน โดย

ssid = 'REPLACE_WITH_YOUR_SSID' # เครือข่าย Wi-Fi ที่ต้องการเชื่อมต่อ

password = 'REPLACE_WITH_YOUR_PASSWORD' # รหัสผ่านเครือข่าย




โค้ดทำงานอย่างไร

ไฟล์นี้นำเข้าไลบรารีที่จำเป็นในการอ่านค่าจากเซ็นเซอร์ DS18B20 และเชื่อมต่อกับเครือข่ายของคุณ

ที่นี่เรากำลังตั้งค่าพินข้อมูลของ DS18B20 เป็น GPIO 32 แต่คุณสามารถใช้หมุดอื่นที่เหมาะสม:
ds_pin = Pin(32)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
คุณต้องใส่ข้อมูลในการเข้าใช้งานเครือข่ายของคุณในตัวแปรต่อไปนี้เพื่อให้ ESP32 สามารถเชื่อมต่อกับเครือข่ายของคุณได้
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

5.1.4 คลิกที่ Save file





5.1.5 ตั้งชื่อไฟล์ เป็น boot.py -> ok






5.1.6 อัพโหลดโค้ด ไปที่ ESP32 หากสามารถอัพโหลดโปรแกรมลงบอร์ดได้สำเร็จ จะแสดงคำว่า download ok ที่ Python shell แถบด้านล่าง และ แสดง IP ของ ESP32 ในตัวอย่างนี้คือ 192.168.1.39






5.2 อัพโหลดโค้ด ไฟล์ main.py


ในไฟล์ main.py เป็นที่ที่เราจะสร้างเว็บเซิร์ฟเวอร์และจัดการกับคำขอ โดยคัดลอกโค้ดต่อไปนี้ไปยังไฟล์ main.py ของคุณ ที่เคยสร้างไว้แล้ว (อยู่ที่คอมพิวเตอร์เรา workSpace) ตามโค้ดด้านล่าง





def read_ds_sensor():
  roms = ds_sensor.scan()
  print('Found DS devices: ', roms)
  print('Temperatures: ')
  ds_sensor.convert_temp()
  for rom in roms:
    temp = ds_sensor.read_temp(rom)
    if isinstance(temp, float):
      msg = round(temp, 2)
      print(temp, end=' ')
      print('Valid temperature')
      return msg
  return b'0.0'
  
def web_page():
  temp = read_ds_sensor()
  html = """<!DOCTYPE HTML><html><head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <style> html { font-family: Arial; display: inline-block; margin: 0px auto; text-align: center; }
    h2 { font-size: 3.0rem; } p { font-size: 3.0rem; } .units { font-size: 1.2rem; } 
    .ds-labels{ font-size: 1.5rem; vertical-align:middle; padding-bottom: 15px; }
  </style></head><body><h2>ESP with DS18B20</h2>
  <p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature</span>
    <span id="temperature">""" + str(temp) + """</span>
    <sup class="units">&deg;C</sup>
  </p>
    <p><i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature</span>
    <span id="temperature">""" + str(round(temp * (9/5) + 32.0, 2)) + """</span>
    <sup class="units">&deg;F</sup>
  </p></body></html>"""
  return html

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)

while True:
  try:
    if gc.mem_free() < 102000:
      gc.collect()
    conn, addr = s.accept()
    conn.settimeout(3.0)
    print('Got a connection from %s' % str(addr))
    request = conn.recv(1024)
    conn.settimeout(None)
    request = str(request)
    print('Content = %s' % request)
    response = web_page()
    conn.send('HTTP/1.1 200 OK\n')
    conn.send('Content-Type: text/html\n')
    conn.send('Connection: close\n\n')
    conn.sendall(response)
    conn.close()
  except OSError as e:
    conn.close()
    print('Connection closed')

อัพโหลดโค้ด ไปที่ ESP32 หากสามารถอัพโหลดโปรแกรมลงบอร์ดได้สำเร็จ จะแสดงคำว่า download ok ที่ Python shell แถบด้านล่าง 



โค้ดทำงานอย่างไร



โค้ดเริ่มต้นด้วยการสร้างฟังก์ชั่นที่ชื่อว่า read_ds_sensor () ที่รับอุณหภูมิจากเซ็นเซอร์อุณหภูมิ DS18B20 หากคุณติดตามหัวข้อก่อนหน้านี้คุณควรคุ้นเคยกับวิธีการที่ใช้ในที่นี้
def read_ds_sensor():
  roms = ds_sensor.scan()
  print('Found DS devices: ', roms)
  ds_sensor.convert_temp()
  for rom in roms:
    temp = ds_sensor.read_temp(rom)
    if isinstance(temp, float):
      temp = round(temp, 2)
      print('Valid temperature')
      return temp
  return '0'

ฟังก์ชั่น web_page () จะส่งคืนหน้า HTML ด้วยการอ่านอุณหภูมิล่าสุด หลังจากนั้นทำตามขั้นตอนปกติเพื่อสร้างซ็อกเก็ตเซิร์ฟเวอร์
while True:
  try:
    if gc.mem_free() < 102000:
      gc.collect()
    conn, addr = s.accept()
    conn.settimeout(3.0)
    print('Got a connection from %s' % str(addr))
    request = conn.recv(1024)
    conn.settimeout(None)
    request = str(request)
    print('Content = %s' % request)
    response = web_page()
    conn.send('HTTP/1.1 200 OK\n')
    conn.send('Content-Type: text/html\n')
    conn.send('Connection: close\n\n')
    conn.sendall(response)
    conn.close()
  except OSError as e:
    conn.close()
    print('Connection closed')
โดยทั่วไปเมื่อ ESP32 ได้รับคำขอเราจะส่งเว็บเพจที่มีการอ่านล่าสุดเป็นการตอบกลับ:
response = web_page()
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(response)


หลังจากอัปโหลดไฟล์ boot.py และ main.py ไปยังบอร์ดของคุณ คลิกปุ่ม EN เพื่อเรียกใช้งานโค้ด



5.3 กดที่ปุ่ม EN 1 ครั้ง เพื่อเริ่มการทำงาน ของ ESP32






5.4 รอจนกระทั่งที่ Python shelll แสดง IP ของ ESP32 ในตัวอย่างนี้คือ 192.168.1.39





5.5 ทดสอบการทำงานโดย ใช้ คอมพิวเตอร์ หรือ สมาร์ทโฟน ที่เชื่อมต่อเครือข่าย WiFi เดียวกันกับ ESP32 แล้วเปิดเว็บบราวเซอร์ ที่ URL ป้อนไอพี  ที่ได้มาจากข้อ 5.4  ในตัวอย่างนี้คือ 192.168.1.39


เว็บเพจจะแสดงอุณหภูมิที่วัดได้จาก DS18B20 เป็นองศาเซลเซียสและฟาเรนไฮต์  (แสดงว่าประสบความสำเร็จแล้ว)





credit : https://randomnerdtutorials.com/micropython-ds18b20-esp32-esp8266/

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

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