[TH] Arduino: STM32L432 Nucleo-32’s DAC&ADC.

จากที่ได้อ่านบทความ การใช้งาน STM32 Core Support for Arduino สำหรับบอร์ด Nucleo L432KC ของอาจารย์ เรวัต ศิริโภคาภิรมย์ ทางเราเลยได้จัดหาบอร์ดมาทดลองใช้งานและเชื่อมต่อขาสำหรับส่งข้อมูลออก DAC ไปยัง ADC ตามภาพที่ 1 เพื่อทดสอบการทำงานของภาค DAC และ ADC ของบอร์ดโดยใช้โค้ดการทำงานเหมือนกับบอร์ดไมโครคอนโทรลเลอร์ ESP32, SAM-D21 และ LGT8F328P ว่าเป็นอย่างไร มาติดตามกันครับ

ภาพที่ 1 บอร์ด Neucleo L432KC เชื่อมต่อขา A3 เข้ากับ D3

คุณสมบัติของ STM32L432

STM32L432 เป็นไมโครคอนโทรลเลอร์สถาปัตยกรรม ARM แบบ 32 บิต แบบ Cortex-M4 แบบประหยัดพลังงาน โดยคุณสมบัติของชิพตัวนี้จากเอกสาร Data Sheet และเว็บ armMBED กับ Zephyr เป็นดังนี้

  • รองรับการคำนวณทศนิยมโดยมี FPU (Floating Point Unit) มาในตัว
  • ความถี่สัญญาณนาฬิกา 80MHz
  • มี Timer จำนวน 11 ตัว
  • ฮาร์ดแวร์รองรับ RTC
  • มีขา I/O แบบความเร็วสูงที่รองรับการใช้งานกับ 5V จำนวน 26 ขา
  • มี 2 PLL สำหรับสัญญาณนาฬิกาของระบบ, USB, Audio และ ADC
  • มีหน่วยความจำแรม 64KB
  • มีหน่วยความจำรอม 256KB
  • มี ADC ความละเอียด 12 บิต จำนวน 1 ช่องสัญญาณ
  • มี DAC ความละเอียด 12 บิต จำนวน 2 ช่องสัญญาณ
  • รองรับการทำงาน USB OTG 2.0, SAI (serial audio interface), I2C, USART, SPI, CAN, SWPMI และ IRTIM (Infrared interface)
  • ทำ DMA ได้ 14 ช่องสัญญาณ
  • รองรับ True random number generator
  • มีหน่วยประมวลผลสำหรับคำนวณ CRC

ตัวบอร์ดเป็น Neucleo-32 ดังภาพที่ 2

ภาพที่ 2 การจัดวางขาของบอร์ด Neucleo L432KC
ที่มา https://docs.zephyrproject.org/2.6.0/_images/nucleo_l432kc_arduino_nano.png

จากภาพที่ 2 จะพบว่ามีขาสำหรับ ADC และ DAC ดังนี้

  • Analogin หรือ ADC อยู่ที่ D3 หรือขา PB_0
  • AnalogOut หรือ DAC อยู่ที่ขา A3 และ A4 หรือขา PA_4 และ PA_5

การตั้งค่าสำหรับบอร์ด Neucleo L432KC เป็นตามภาพที่ 3

ภาพที่ 3 การตั้งค่าบอร์ดใน Arduino IDE

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

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

กราฟฟันปลา

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

#include <Arduino.h>
#include <math.h>

#define pinSpk A3 // PA4
#define pinMic D3 // PB0

#define ADC_BITS 12
#define DAC_BITS 12
#define MAX_VALUE pow(2,DAC_BITS)

int adcValue;

void setup() {
  Serial.begin(115200);
  analogReadResolution(ADC_BITS);
  analogWriteResolution(DAC_BITS);
}

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

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

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

#include <Arduino.h>
#include <math.h>

#define pinSpk A3 // PA4
#define pinMic D3 // PB0

#define ADC_BITS 12
#define DAC_BITS 12
#define MAX_VALUE pow(2,DAC_BITS)

int adcValue;

void setup() {
  Serial.begin(115200);
  analogReadResolution(ADC_BITS);
  analogWriteResolution(DAC_BITS);
}

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

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

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

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

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

#include <Arduino.h>
#include <math.h>

#define pinSpk A3 // PA4
#define pinMic D3 // PB0

#define ADC_BITS 12
#define DAC_BITS 12
#define MAX_VALUE pow(2,DAC_BITS)

int adcValue;

void setup() {
  Serial.begin(115200);
  analogReadResolution(ADC_BITS);
  analogWriteResolution(DAC_BITS);
}

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) * ((MAX_VALUE/2)-1));
    analogWrite( pinSpk, dValue );
    adcValue = analogRead(pinMic);
    Serial.println(adcValue);
  } 
}
ภาพที่ 6 ตัวอย่างผลลัพธ์กราฟรูปไซน์จาก STM32L432

สรุป

จากบทความนี้จะพบว่า ADC ของ STM32L432 มี 1 ช่องสัญญาณ แต่ให้ DAC มาอีก 2 ช่อง พร้อมความละเอียดในการทำงานที่ 12 บิต ทำให้เหมาะกับการประมวลผลหรือสร้างเสียงเพื่อออกเป็นลำโพงซ้ายและขวาที่มีความละเอียดสูงกว่าไมโครคอนโทรลเลอร์ตัวอื่น ๆ ที่ได้เขียนถึงมาก่อนหน้านี้ สุดท้าย ขอให้สนุกกับการเขียนโปรแกรมครับ

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