[TH] ใช้งาน DAC12 บิตกับ MicroPython

บทความนี้กล่าวถึงหลักการทำงานของโมดูลแปลงสัญญาณดิจิทัลเป็นแอนาล็อกแบบ 12 บิตจำนวน 2 ช่องสัญญาณที่ทำงานด้วยไอซี MCP4922 ด้วย MicroPython ของบอร์ด ml4m ผ่านทางบัส SPI เพื่อนำอออกสัญญาณแอนาล็อกเป็นรูปคลื่นสามเหลี่ยมและสี่เหลี่ยมดังภาพที่ 6 และ 7 ของตัวอย่างในบทความนี้

ภาพที่ 1 บอร์ด et-mini MCP4922

อุปกรณ์

อุปกรณ์สำหรับการทดลองในบทความนี้ประกอบด้วย

  1. ET-mini MCP4922 หรือไอซี MCP4922 ที่ต่อตามภาพที่ 2
  2. บอร์ดไมโครคอนโทรลเลอร์ esp32

MCP4922

คุณสมบัติ

  1. มีความละเอียดในการทำงานแปลงค่าดิจิทัลเป็นสัญญาณแอนาล็อกขนาด 12 บิต
  2. มีช่องนำออกสัญญาณแอนาล็อก 2 ช่องสัญญาณผ่านทาง OUT_A และ OUT_B
  3. ความเร็วสูงสุดในการสื่อสารผ่านบัส SPI อยู่ที่ 20MHz
  4. ใช้เวลาในการแปลงระดับแรงดันหรือสัญญาณแอนาล็อกประมาณ 45nsec
  5. ทำงานกับแรงดันกระแสงตรงที่ระดับแรงดัน 2V7 ถึง 5V5
  6. กำหนดการขยายสัญญาณได้ระหว่าง x1 และ x2

ผังการเชื่อมต่อ

การเชื่อมต่อระหว่าง MCP4922 กับ esp32 เป็นดังภาพที่ 2 คือ

  • ขา SCK ของ MCP4922 ต่อเข้ากับขา IO18 ของ esp32
  • ขา SDI ของ MCP4922 ต่อเข้ากับขา IO23 ของ esp32
  • ขา CS ของ MCP4922 ต่อเข้ากับขา IO27 ของ esp32
ภาพที่ 2 การเชื่อมต่อระหว่าง esp32 WROOM กับ MCP4922

การวางขา

ไอซี MCP4922 ที่ทางเราใช้เป็นไอซี 14 ขาที่มีการจัดวางขาเป็นดังภาพที่ 3

ภาพที่ 3 การจัดวางขาของ MCP49x2
ที่มา

จากภาพที่ 3

  • ขา SDI ใช้รับข้อมูลจากไมโครคอนโทรลเลอร์
  • ขา CS สำหรับรับสัญญาณ CS
  • ขา VOUTA สำหรับนำออกแรงดันจากช่องสัญญาณ A
  • ขา VOUTB สำหรับนำออกแรงดันจากช่องสัญญาณ B
  • ขา LDAC สำหรับส่งพัลส์เพื่อนำออกข้อมูลจากบัฟเฟอร์ไปยัง VOUTA หรือ VOUTB
  • ขา SHDN สำหรับเปิดหรือปิดการทำงานของไอซี
  • ขา VREFA และ VREFB สำหรับแรงดันอ้างอิงของช่องสัญญาณ A และ B

ผังการทำงาน

ผังการทำงานเป็นดังภาพที่ 4 โดยขาสำหรับควบคุมการทำงานจะเป็นขา SHDN ซึ่งเมื่อกำหนดให้ 0 จะส่งผลให้โมดูล MCP4922 หยุดทำงาน และถ้าเป็น 1 เป็นการสั่งให้ทำงาน หรือสั่งงานการเปิดหรือปิดการทำงานนี้ได้จากการกำหนดในชุดคำสั่งที่กล่าวถึงต่อไป นอกจากนี้การทำงานของ MCP4922 รองรับการเพิ่มระดับแรงดันแบบ 1 เท่า (x1) และ 2 เท่า (x2) โดยกำหนดจาก Gain Logic ซึ่งกำหนดค่าจากบิตคำสั่งเช่นเดียวกัน

การกำหนดระดับแรงดันนำออกของ VOUTA และ VOUTB ทำได้จากการกำหนดระดับแรงดันจากขา VREFA และ VREFB

ภาพที่ 4 ผังการทำงานภายในของ MCP49x2
ที่มา

ผังไม์ทมิง

ผังไทม์มิง (Timing Diagram) ของไอซี MCP4922 เป็นดังภาพที่ 5 ซึ่งการสั่งงานจะใช้การกำหนดคำสั่งผนวกเข้าไปใน 4 บิตแรกของข้อมูลที่ส่งไปยังขา MOSI ซึ่งจะกล่าวถึงในหัวข้อถัดไป

ภาพที่ 5 ผังไทม์มิ่ง SPI ของ MCP49x2
ที่มา

จากภาพที่ 5 จะได้ความสัมพันธ์ในการสั่งงาน คือ ก่อนเริ่มขา CS และ LDAC จะมีสถานะเป็น 1 และเมื่อให้โมดูลทำงานต้องเปลี่ยนสถานะของ CS เป็น 0 หลังจากนั้นทำการส่งข้อมูลผ่านทาง SI หรือขา MOSI ของไมโครคอนโทรลเลอร์ไล่เรียงจากไบต์บนสุดไปจนถึงบิตสุดท้ายของไบต์ต่ำสุดหลังจากนั้นยกระดับของขา CS กลับไปเป็น 1 ซึ่งตอนนี้ผู้เขียนโปรแกรมสามารถสั่งให้นำออกข้อมูลจากบัฟเฟอร์ไปที่ OUT_A หรือ OUT_B ด้วยการส่งพัลซ์ 1->0->1 จากขา LDAC หรือกำหนดให้ขา LDAC เป็นสถานะ 0 ตลอดเพื่อให้นำออกอัตโนมัติได้เช่นกัน

ชุดคำสั่ง

การสั่งงานโมดูล MCP4922 จะต้องใช้คำสั่งขนาด 4 บิตไบต์บนหรือบิตที่ 8 ถึง 15 เพื่อกำหนดการทำงานดังนี้

บิต15141312111098
ความหมายช่องสัญญาณการบัฟเฟอร์ค่า
Gain หรือระดับแรงดันเปิด/ปิดการทำงานของไอซีข้อมูลบิตที่11ข้อมูลบิตที่10ข้อมูลบิตที่9ข้อมูลบิตที่8
ค่า0 ช่อง A
1 ช่อง B
0 ไม่ทำบัฟเฟอร์
1 ให้ทำบัฟเฟอร์ไว้
0 ใช้ระดับแรงดัน x2
1 ใช้ระดับแรงดัน x1
0 ปิดการทำงาน
1 เปิดการทำงาน

และสำหรับไบต์ล่างหรือบิตที่ 0 ถึง 7 เป็นดังนี้

บิต76543210
ความหมายข้อมูลบิตที่7ข้อมูลบิตที่6ข้อมูลบิตที่5ข้อมูลบิตที่4ข้อมูลบิตที่3ข้อมูลบิตที่2ข้อมูลบิตที่1ข้อมูลบิตที่0

ตัวอย่างโปรแกรม

ตัวอย่างโปรแกรมการส่งเวฟสามเหลี่ยม หรือเริ่มจาก 0 ไปหา 4095 และลดลงจาก 4094 มาที่ 0 เขียนโค้ดได้ดังนี้

######################################################################
#
# MCP4922 12-bit ADC with SPI Interface
# 
# (C) 2021, JarutEx
#     https://www.jarutex.com
######################################################################
from machine import SPI, Pin, ADC
import time

pinCS = Pin(27, Pin.OUT)
pinCS.on()

spi = SPI(1,baudrate=20000000,sck=Pin(18,Pin.OUT),mosi=Pin(23,Pin.OUT),miso=Pin(19,Pin.IN))

try:
    dacData = 0
    dacDir = 0
    while True:
        x2 = 0b0111000000000000
        x2 |= (dacData & 0b0000111111111111) 
        buffer = x2.to_bytes(2,'big')
        pinCS.off()
        spi.write(buffer)
        pinCS.on()
        if (dacDir):
            dacData -= 1
            if (dacData < 0):
                dacData = 1
                dacDir = 0
        else:
            dacData += 1
            if (dacData > 4095):
                dacData = 4094
                dacDir = 1
        time.sleep_us(10)
except KeyboardInterrupt:
    pass
tmr0.deinit()
spi.deinit()


ตัวอย่างผลลัพธ์เป็นดังภาพที่ 6

ภาพที่ 6 ตัวอย่างผลลัพธ์จากโปรแกรมที่ 1

ตัวอย่างถัดมาเป็นการสร้างคลื่นสี่เหลี่ยมดังตัวอย่างผลลัพธ์ภาพที่ 7

######################################################################
#
# MCP4922 12-bit ADC with SPI Interface
# 
# (C) 2021, JarutEx
#     https://www.jarutex.com
######################################################################
from machine import SPI, Pin, ADC
import time

spi = SPI(1,baudrate=20000000,sck=Pin(18,Pin.OUT),mosi=Pin(23,Pin.OUT),miso=Pin(19,Pin.IN))
pinCS = Pin(27, Pin.OUT)
pinCS.on()

try:
    dacData = 0
    dacDir = 0
    while True:
        dacData = 4000
        x2 = ((dacData & 0b0000111111111111) | 0b0111000000000000)
        buffer = x2.to_bytes(2,'big')
        pinCS.off()
        spi.write(buffer)
        pinCS.on()
        time.sleep_ms(500)
        dacData = 100
        x2 = ((dacData & 0b0000111111111111) | 0b0111000000000000)
        buffer = x2.to_bytes(2,'big')
        pinCS.off()
        spi.write(buffer)
        pinCS.on()
        time.sleep_ms(500)
except KeyboardInterrupt:
    pass
tmr0.deinit()
spi.deinit()



ภาพที่ 7 ตัวอย่างผลลัพธ์จากโปรแกรมที่ 2

สรุป

จากบทความนี้ทางทีมงานของเราหวังว่าผู้อ่านจะสามารถนำการใช้โมดูล DAC ไปใช้กับบอร์ดไมโครคอนโทรลเลอร์ต่อไปในอนาคน ซึ่งจะพบว่าการสั่งงานนั้นง่ายเนื่องจาก MCP4922 มีวิธีการสั่งงานที่ไม่ซับซ้อนด้วยการกำหนดค่า 4 บิตแรกของข้อมูลที่ส่งไปในบัส SPI เพื่อเลือกช่องสัญญาณ การทำบัฟเฟอร์ การเกน และการสั่งเปิดหรือปิดการทำงานของช่องสัญญาณนั้น และขอให้สนุกกับการเขียนโปรแกรมครับ

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

แหล่งอ้างอิง

  1. Microchip MCP4922
  2. Data sheet MCP4922
  3. ET-mini MCP4922
  4. คู่มือ ET-mini MCP4922

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

ปรับปรุงเมื่อ 2021-09-12, 2021-11-29