[TH] Arduino: The LGT8F328P’s ADC/DAC.

บทความนี้เป็นบทความที่ต่อเนื่องจากบทความแนะนำบอร์ด LGT8F328P และการใช้ ADC และ DAC ในก่อนหน้านี้ โดยเน้นที่การใช้งานสำหรับชิพ LGT8F328P เป็นหลัก โดยการใช้งานนั้นจะแตกต่างจาก SAM-D21 ตรงที่ ใช้ขา D4 เป็นขาที่ทำหน้าที่ DAC0 และวงจร DAC มีความละเอียดในการทำงานระดับ 8 บิต หรือส่งออกค่าได้ตั้งแต่ 0 ถึง 255 ส่วนภาค ADC นั้นใช้ขา A0, A1, … ได้ตามปกติ และมีความละเอียดในการทำงาน 12 บิต ดังนั้น ในบทความนี้จึงใช้การเชื่อมต่อขาจาก A0 เข้ากับ D4 ในการทดลองดังภาพที่ 1

ภาพที่ 1 บอร์ด LGT8F328P เชื่อมต่อขา A0 เข้ากับ D4

คำสั่ง

คำสั่งสำหรับการใช้งาน ADC และ DAC มีดังต่อไปนี้

การกำหนดขา DAC

คำสั่งสำหรับกำหนดให้ขา DAC0 ทำงานเป็นแบบแอนาล็อกสามารถใช้คำสั่งดังนี้

pinMode(DAC0, ANALOG);

การปรับความละเอียดของ ADC

คำสั่งสำหรับปรับความละเอียดของ ADC ของไมโครคอนโทรลเลอร์ LGT8F328P มีรูปแบบการใช้งานดังนี้ โดย x คือตัวเลขจำนวนบิตในการทำงาน

analogReadResolution( x )

คำสั่งสำหรับอ่านค่า ADC

รูปแบบคำสั่งสำหรับอ่านค่า ADC ของชิพ LGT8F328P ใช้คำสั่ง analogRead( ) พร้อมระบุหมายเลขขาสำหรับอ่านค่า โดยขาที่อ่านได้คือ A0, A1, A2, A3, 4, A5, A6 และ A7

ค่าที่อ่านได้ = analogRead( หมายเลขขา )

คำสั่งส่งข้อมูลออก DAC

สำหรับคำสั่งนำออกข้อมูลขนาด 8 บิตของ LGT8F328P นั้นสามารถใช้คำสั่งตามรูปแบบต่อไปนี้โดยกำหนดขาเป็น D4 หรือ DAC0

analogWrite( ขา, ค่านำออก )

คำสั่งกำหนดขาแรงดันอ้างอิง

สำหรับกรณีที่ต้องการแหล่งแรงดันอ้างอิงสำหรับการทำงานของภาคแอนาล็อกสามารถระบุแหล่งอ้างอิงได้จากคำสั่ง analogReference() โดยกำหนดแหล่งอ้างอิง x ดังรูปแบบต่อไปนี้

analogReference( x )

จากคำสั่ง ค่า x เป็นดังนี้

  • DEFAULT ใช้แรงดันอ้างอิง 5V
  • EXTERNAL ใช้ขา REF เป็นขานำเข้าแหล่งแรงดันอ้างอิง
  • INTERNAL4V096 ใช้แรงดันอ้างอิง 4.096v จากภายในบอร์ด
  • INTERNAL2V048 ใช้แรงดันอ้างอิง 2.048v จากภายในบอร์ด
  • INTERNAL1V048 ใช้แรงดันอ้างอิง 1.048v จากภายในบอร์ด

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

ตัวอย่างโปรแกรมวาดกราฟ 3 แบบ คือ กราฟฟันปลา กราฟสามเหลี่ยม และกราฟคลื่นไซน์ มีโค้ดการทำงานดังนี้

กราฟฟันปลา

การสร้างกราฟฟันปลาเป็นการส่งค่า 0 ถึงค่าสูงสุดที่เป็นไปได้ของภาค DAC หลังจากนั้นวนรอบส่งใหม่อีกครั้ง โดยโค้ดสำหรับ LGT8F328P เป็นดังนี้ และได้ผลลัพธ์ดังตัวอย่างภาพที่ 2 และทางเราพบว่าในบางบอร์ดกลับให้ผลลัพธ์ที่ผิดพลาดดังภาพที่ 3 ดังนั้น ก่อนใช้งานจริง ผู้อ่านควรตรวจสอบการทำงานของชิพก่อน

#include <Arduino.h>

#define pinSpk DAC0 // D4
#define pinMic A0
#define MAX_VALUE 255
#define ADC_BITS 12

int adcValue;

void setup() {
  Serial.begin(9600);
  analogReadResolution(ADC_BITS);
  analogReference(DEFAULT);  // 5v
  pinMode(DAC0, ANALOG);
}

void loop() {
  for (int i = 0; i < MAX_VALUE+1; i ++) {
    analogWrite( pinSpk, i);
    adcValue = analogRead(pinMic);
    Serial.println(adcValue);
  }
}
ภาพที่ 2 ตัวอย่างกราฟฟันปลา
ภาพที่ 3 ตัวอย่างกราฟฟันปลาจากบอร์ดที่ชิพภายในมีปัญหา

กราฟสามเหลี่ยม

กราฟสามเหลี่ยมมีหลักการคล้ายกับฟันปลาด้วยการเพิ่มการวนรอบเพื่อส่งค่ามากสุดกลับมาเป็น 0 ดังโค้ดของ LGT8F328P ดังต่อไปนี้ และตัวอย่างผลลัพธ์เป็นดังภาพที่ 4

#include <Arduino.h>

#define pinSpk DAC0 // D4
#define pinMic A0
#define MAX_VALUE 255
#define ADC_BITS 12

int adcValue;

void setup() {
  Serial.begin(9600);
  analogReadResolution(ADC_BITS);
  analogReference(DEFAULT);  // 5v
  pinMode(DAC0, ANALOG);
}

void loop() {
  int i;
  for (i = 0; i < MAX_VALUE+1; i ++) {
    analogWrite( pinSpk, i);
    adcValue = analogRead(pinMic);
    Serial.println(adcValue);
  }
  for (i = MAX_VALUE-1; i >= 0; i--) {
    analogWrite( pinSpk, i);
    adcValue = analogRead(pinMic);
    Serial.println(adcValue);
  }
}
ภาพที่ 4 ตัวอย่างกราฟสามเหลี่ยม

กราฟคลื่นไซน์

การสร้างกราฟคลื่นรูปไซน์ใช้การกำหนดให้มีการวนรอบเพื่อเพิ่มค่ามุมองศาจาก 0 ไปถึง 359 โดยในแต่ละรอบทำสิ่งต่อไปนี้

  1. แปลงค่าองศาเป็นเรเดียน
  2. คำนวณหาไซน์จากมุมเรเดียน
  3. แปลงค่าทศนิยมให้เป็นจำนวนเต็มในช่วงค่าที่ DAC รองรับ
  4. อ่านค่าจาก ADC
  5. ส่งข้อมูลออกทางพอร์ตอนุกรมให้โปรแกรม Serial Plotter

โค้ดสำหรับ LGT8F328P เป็นดังนี้ และตัวอย่างผลลัพธ์ดังภาพที่ 5

#include <Arduino.h>

#define pinSpk DAC0 // D4
#define pinMic A0
#define MAX_VALUE 255
#define ADC_BITS 12

int adcValue;

void setup() {
  Serial.begin(9600);
  analogReadResolution(ADC_BITS);
  analogReference(DEFAULT);  // 5v
  pinMode(DAC0, ANALOG);
}

void loop() {
  int degree = 0;
  float radian = 0.0;
  float sineValue = 0.0;
  int dValue = 0;

  for (degree = 0; degree < 360; degree++) {
    radian = (float)degree * (2.0 * 3.1415926) / 360.0;
    sineValue = sin(radian);
    dValue = (int)((1.0 + sineValue) * 125.0);
    analogWrite( pinSpk, dValue );
    adcValue = analogRead(pinMic);
    Serial.println(adcValue);
  }  
}
ภาพที่ 5 ตัวอย่างผลลัพธ์กราฟรูปไซน์

สรุป

จากบทความนี้จะพบว่า ADC ของ LGT8F328P นั้นมีความเป็นเส้นตรงพอสมควร แต่ทางทีมงานเราพบว่ามีหลายบอร์ดที่เราสั่งมามีอาการสัญญาณรบกวนเยอะกว่าปกติ และบางบอร์ดไม่ทำงานในกรณีของกราฟคลื่นไซน์ ส่วนภาค DAC นั้นมีความละเอียด 8 บิต ซึ่งมีความละเอียดเท่ากับ esp32 แต่ด้วยราคาที่ถูกกว่าทั้ง SAM-D21 และ ESP32 ทำให้ชิพ LGT8F328P ดูมีความน่าสนใจสำหรับการนำมาใช้งาน เพราะอย่างน้อยก็มีขา ADC ที่มากกว่า SAM-D21 สุดท้าย ขอให้สนุกกับการเขียนโปรแกรมครับ

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