บทความนี้กล่าวถึงการใช้งาน GPIO ของ ESP32 เพื่อทำหน้าที่นำออกสัญญาณแอนาล็อกผ่านทางโมดูล DAC ขนาด 8 บิตของไมโครคอนโทรลเลอร์ ESP32 โดยทดลองสร้างเป็นกราฟฟันปลา (ดังภาพที่ 7) เพื่อส่งแรงดันดังกล่าวไปยังโมดูลลำโพงดังภาพที่ 1
โครงสร้างของโครงงาน
โครงสร้างของโครงงานของ ESP-IDF เป็นดังภาพที่ 2 คือ ในไดเร็กทอรีหรือโฟลเดอร์ของโครงงานจะมีไฟล์ CMakeList.txt และ sdkconfig กับไดเร็กทอรีชื่อ main สำหรับเก็บรหัสต้นฉบับของโครงงาน โดยในไดเร็กทอรีดังกล่าวมีไฟล์ภาษา C และ CMakeLists.txt
จากโครงสร้างในภาพที่ 2 ต้องสร้างโค้ดของไฟล์ CMakeLists.txt ดังนี้ ซึ่งเนื้อหาในโค้ดได้กำหนดรุ่นขั้นต่ำของโปรแกรม cmake และกำหนดค่าการใช้งานของ cmake เบื้องต้นตามจ้นฉบับที่มากับ ESP-IDF พร้อมทั้งตั้งชื่อโครงงานเป็น ep07
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ep07)
สิ่งที่เขียน main/CMakeLists.txt เป็นดังงต่อไปนี้ เพื่อกำหนดรายการไฟล์ที่จะต้องคอมไพล์ ซึ่งกำหนดไว้เป็น main.c และกำหนดไดเร็กทอรีที่เก็บไฟล์ส่วนหัวเอาไว้เป็นค่าว่างซึ่งหมายถึงที่เดียวกับ main.c หรือในไดเร็กทอรี main
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "")
เมื่อสร้างโครงสร้างได้เหมือนดังภาพที่ 2 ให้สั่งเลือก target ของระบบเป็น ESP32 ดังนี้
idf.py set-target esp32
ส่วน sdkconfig เกิดจากการเรียกใช้คำสั่งต่อไปนี้ idf.py menuconfig
idf.py menuconfig
จากหน้าจอกำหนดการตั้งค่าให้เข้าไปที่ Component Config –> FreeRTOS และกำหนด Tick rate (Hz) เป็น 1000 ดังภาพที่ 3 หลังจากนั้นบันทึกและออกจากการตั้งค่า
การใช้ DAC
ไมโครคอนโทรลเลอร์ ESP32 มีวงจรแปลงสัญญาณดิจิทัลเป็นแอนาล็อกเพื่อนำออกให้กับวงจรภายนอก หรือ DAC (Digital to Analog) ที่มีความละเอียด 8 บิต และรองรับการทำงานแบบ DMA (Direct Memory Access) ผ่านทางบัส I2S ซึ่งจะต้องใช้โมดูลภายนอก (และจะกล่าวถึงในบทความในตอนถัด ๆ ไป) ทำให้สามารถปรับค่าแรงดันที่ขา DAC ให้เป็น 0 ถึง 3V3 ได้ด้วยการส่งค่า 0 ถึง 255 ไปยังขานั้น ซึ่งตัว ESP32 เตรียมวงจร DAC ให้ใช้งาน 2 ตัว คือ
- DAC1 ผ่านทางขา 25
- DAC2 ผ่านทางขา 26
การใช้งาน DAC จะต้องนำเข้าไฟล์ส่วนหัวดังนี้ เพื่อใช้สำหรับเปิดหรือปิดการทำงานของ I2S
#include <driver/dac.h>
และเรียกใช้งานไฟล์ส่วนหัว dac_common.h สำหรับใช้งานคำสั่งเกี่ยวกับ DAC ของไมโครคอนโทรลเลอร์ ESP32
#include <driver/dac_common.h>
คำสั่ง
การสั่งเปิดหรือปิดการทำงานบัส I2S เพื่อทำการเข้าถึงโมดูลแปลง DAC ภายนอกในแบบ DMA ใช้คำสั่ง dac_i2s_enable() และ dac_i2s_disable() ตามรูปแบบของการใช้งานดังต่อไปนี้
esp_err_t dac_i2s_enable()
esp_err_t dac_i2s_disable()
โดยค่าคืนกลับจากการทำงานของคำสั่ง dac_i2s_enable และ dac_i2s_disable เป็นดังนี้
- ESP_OK
คำสั่งสำหรับเปิดและปิดการทำงานของ DAC ในช่องสัญญาณที่ระบุมีรูปแบบของการใช้งานดังนี้
dac_output_enable( ช่องสัญญาณนำออก )
dac_output_disable( ช่องสัญญาณนำออก )
ซึ่งค่าช่องสัญญาณนำออกมีค่าเป็นดังนี้
- DAC_CHANNEL_1 สำหรับขา 25
- DAC_CHANNEL_2 สำหรับขา 26
สำหรับการนำออกสัญญาณแอนาล็อกจะต้องส่งข้อมูลเป็นค่าในช่วง 0 ถึง 255 เพื่อใช้แทนค่าแรงดันในช่วง 0 ถึง 3V3 ด้วยคำสั่ง dac_output_voltage() ดังรูปแบบต่อไปนี้
dac_output_voltage( หมายเลขช่องสัญญาณ, ค่านำออก )
กรณีที่ต้องการใช้งาน GPIO แบบอื่น ๆ สามารถเข้าไปอ่านบทความต่าง ๆ ดังต่อไปนี้เพิ่มเติม
ตัวอย่างโปรแกรม
วงจรแอลอีดีที่ใช้ในการทดลองครั้งนี้เป็นดังภาพที่ 5 อุปกรณ์ที่ใช้ในการทดลองได้แก่
- บอร์ด esp32
- บอร์ดทดลอง
- โมดูลลำโพง
- ทรานซิสเตอร์
- ตัวต้านทาน 2 ตัว
- บัซเซอร์
ตัวอย่างโปรแกรมสำหรับส่งค่า 0 ถึง 255 ไปยังขา 25 และเมื่อค่าที่เพิ่มขึ้นมีค่ามากกว่า 255 ให้เปลี่ยนค่าเป็น 0 และวนรอบต่อไปนั้นมีโค้ดเป็นดังต่อไปนี้
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include <sdkconfig.h>
#include <driver/gpio.h>
#include <driver/dac.h>
#include <driver/dac_common.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#define pinDAC DAC_CHANNEL_2
void wave1() {
int dValue=0;
printf("Start wave1 ...");
dac_output_enable( pinDAC );
while (true) {
dac_output_voltage( pinDAC, dValue++ );
vTaskDelay( 10/portTICK_PERIOD_MS );
if (dValue > 255) {
break;
}
}
dac_output_disable( pinDAC );
printf("done.\n");
}
void app_main(void)
{
printf("Ep.07 DAC\n");
dac_i2s_enable();
dac_i2s_disable();
while(1) {
wave1();
vTaskDelay( 10/portTICK_PERIOD_MS );
}
}
คอมไพล์และอัพโหลด
ทำการคอมไพล์ หลังจากนั้น flash ลงชิพ และเข้าโปรแกรม Serial Monitor สั่งงานดังนี้
idf.py -p /dev/ttyUSB0 build flash monitor
ตัวอย่างผลลัพธ์ของโปรแกรมเป็นดังภาพที่ 6 และกราฟที่แสดงผลด้วยออสซิโลสโคปเป็นดังภาพที่ 7
สรุป
จากบทความนี้จะพบว่า การนำเข้าสัญญาณแอนาล็อกนั้น มีขั้นตอน 3 ขั้นตอน คือ
- เปิดการทำงานของ DAC1 หรือ DAC2 ด้วยคำสั่ง dac_output_enable()
- นำออกข้อมูลด้วยคำสั่ง dac_output_voltage()
- ปิดการทำงานของ DAC1 หรือ DAC2 ด้วยคำสั่ง dac_output_disable()
แต่อย่างไรก็ดี บทความนี้ได้ข้ามเรื่องของการใช้งาน I2S (พวกเรายังไม่มีโมดูล I2S ใช้งานในขณะที่เขียนบทความน่ะครับ) และชุดคำสั่งเกี่ยวกับการสร้างสัญญาณคลื่น cosine ที่ไลบรารีเตรียมไว้ให้ ซึ่งจะนำมาเขียนถึงในบทความถัด ๆ ไป สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ
ท่านใดต้องการพูดคุยสามารถคอมเมนท์ได้เลยครับ
แหล่งอ้างอิง
- ESP-IDF : DAC
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-10-11, 2021-12-25