การใช้งาน ADC และการใช้งานไลบรารี่ simpleTimer
ADC ( analog-to-digital converter) เป็นวงจรแปลงสัญญาณแอนะล็อกเป็นสัญญาณดิจัทัล ESP32 มีขาพอร์ตที่สามารถรับสัญญาณที่เป็นแอนะล็อกได้หลายช่อง (ในขณะที่รับสัญญาณแอนะล็อกจะไม่สามารถใช้งานเป็นพอร์ตปกติได้) วงจร ADC เป็นวงจรขนาด 12 บิตซึ่งจะให้ค่าหลังการแปลงระหว่าง 0-4095 (สามารถกำหนดค่าจำนวนบิตได้ตั้งแต่ 9-12 บิต หากผู้ใช้งานต้องการ)
การใช้งานไลบรารี่ simpleTimer เป็นเครื่องมือช่วยให้เขียนโปรแกรมที่มีการวนทำงานในเวลาที่แน่นอนสะดวกขึ้นโดยไม่ต้องเขียนโปรแกรมวนทำงานในฟังก์ชั่น void loop()
วงจรที่ใช้ทดลอง
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/1.png)
ขาพอร์ต ADC ที่มีใช้งาน
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/2.png)
การใช้ฟังก์ชั่นลดทอนสัญญาณ
ค่าปกติของ ADC เมื่ออ่านค่าที่มีแรงดันประมาณไฟเลี้ยงของวงจรจะได้ค่าการแปลงอยู่ที่ 4096 แต่ผู้ใช้งานสามารถกำหนดการลดทอนสัญญาณได้ 4 ระดับดังรูป
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/4.png)
https://espressif-docs.readthedocs-hosted.com/projects/esp-idf/en/v2.1.1/api-reference/peripherals/adc.html (https://espressif-docs.readthedocs-hosted.com/projects/esp-idf/en/v2.1.1/api-reference/peripherals/adc.html)
ความเป็นเชิงเส้นของการแปลงในการลดทอนค่าต่าง ๆ
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/5.png)
https://www.researchgate.net/figure/ADC-linearity-test-at-12-bit-resolution_fig4_320273388 (https://www.researchgate.net/figure/ADC-linearity-test-at-12-bit-resolution_fig4_320273388)
ตัวอย่างฟังก์ชั่นการใช้งานลดทอนสัญญาณในระดับต่าง ๆ
adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_0db);
adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_2_5db);
adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_6db);
adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_11db);
วงจร ADC
วงจรแปลงสัญญาณแอนาล็อกมี 2 วงจรแต่ละวงจรก็มีหลายช่องสัญญาณ การกำหนดชื่อขาพอร์ดกับวงจรแปลงสัญญาณเป็นดังรูป
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/3.png)
การใช้งานไลบรารี่ SimpleTimer
การเขียนโค้ดในหลายกรณีจำเป็นต้องมีการวนไปทำงานตามคาบเวลาที่เหมาะสมอยู่เรื่อย ๆ การเขียนไว้ใน void loop() จะทำให้คาบเวลาในการวนทำงานไม่แน่นอนและทำให้ดูโปรแกรมรก ๆ ไลบรารี่ simpleTimer นี้เป็นทางออกที่ดีโดยสามารถคาบเวลาที่ต้องการให้วนไปทำงานฟังก์ชั่นที่ต้องการได้ค่อนข้างเที่ยงตรงและสะดวกในการใช้งาน ขั้นตอนมีดังนี้
1. ดาวน์โหลดไลบรารี่โดยเข้าไปที่เวปไซต์ https://github.com/jfturcot/SimpleTimer (https://github.com/jfturcot/SimpleTimer) คลิกดาวน์โหลด
(http://www.praphas.com/PhotoForum/iot/Lab-06-ADC/3.png)
2. ทำการติดตั้งไลบรารี่ที่ดาวน์โหลดมา ดำเนินการดังรูป
(http://www.praphas.com/PhotoForum/iot/Lab-06-ADC/4.png)
3. การใช้งานไลบรารี่ ตัวอย่างต้องการให้ทำงานฟังก์ชั่น ReadADC ทุก ๆ 2 วินาที
(1) เพิ่มไลบรารี่ simpleTimer ลงในโปรแกรม
(2) ประกาศใช้งานไลบรารี่โดยใช้ชื่อออปเจค (ตัวอย่างนี้ใช้ชื่อว่า timer)
(3) ฟังก์ชั่นย่อยที่ต้องการให้ทำงาน (ชื่อเดียวกับที่ตั้งค่าไว้)
(4) ตั้งค่าคาบเวลาและฟังก์ชั่นย่อยที่ต้องการทำงานเมื่อครบเวลาที่กำหนด (ตั้งค่าใน setup)
(5) ฟังก์ชั่นเริ่มทำงานซึ่งต้องวางไว้ใน loop()
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/9.png)
ตัวอย่าง โปรแกรมอ่านค่าแอนะล็อกพื้นฐาน
โปรแกรมอ่านค่าสัญญาณแอนะล็อกพื้นฐาน สามารถอ่านได้โดยใช้ฟังก์ชั่น analogRead จากตัวอย่างโปรแกรมเป็นการอ่านจากขา A0 ดังรูป
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/7.png)
โค้ด
void setup() {
Serial.begin(9600);
}
void loop() {
int adc=analogRead(A0);
Serial.printf("Value of ADC from A0 :%u \n",adc);
delay(500);
}
ตัวอย่าง โปรแกรมอ่านค่าแอนะล็อกแบบใช้ฟังก์ชั่นลดทอน
การอ่านค่าสัญญาณแอนะล็อกแบบต้องการใช้ฟังก์ชั่นลดทอนสามารถทำได้โดย
-เพิ่มไลบรารี่ #include <driver/adc.h>
-ประกาศฟังก์ชั่นลดทอนสัญญาณก่อนคำสั่งอ่านค่าสัญญาณ
ตัวอย่าง โปรแกรมอ่านค่าสัญญาณแอนาล็อกแบบใช้การลดทอน การใช้งานจะต้องประกาศการลดทอนก่อนการอ่านค่าดังรูป
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/6.png)
โค้ด
#include <driver/adc.h>
void setup() {
Serial.begin(9600);
}
void loop() {
adc2_config_channel_atten(ADC2_CHANNEL_0,ADC_ATTEN_6db);
int adc=analogRead(A10);
Serial.printf("Value of ADC from A10 :%u \n",adc);
delay(500);
}
ตัวอย่าง โปรแกรมอ่านค่าสัญญาณแอนาล็อกแบบใช้การลดทอนหลายค่า และอ่านค่าจากช่องสัญญาณช่องเดียวดังรูป
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/11.png)
โค้ด
#include <driver/adc.h>
void setup() {
Serial.begin(9600);
}
void loop() {
adc2_config_channel_atten(ADC2_CHANNEL_0,ADC_ATTEN_0db);
int adc1=analogRead(A10);
adc2_config_channel_atten(ADC2_CHANNEL_0,ADC_ATTEN_2_5db);
int adc2=analogRead(A10);
adc2_config_channel_atten(ADC2_CHANNEL_0,ADC_ATTEN_6db);
int adc3=analogRead(A10);
adc2_config_channel_atten(ADC2_CHANNEL_0,ADC_ATTEN_11db);
int adc4=analogRead(A10);
Serial.printf("[0dB:%u][2.5dB:%u][6dB:%u][11dB:%u]\n",adc1,adc2,adc3,adc4);
delay(500);
}
ตัวอย่าง โปรแกรมอ่านค่าแอนะล็อกควบคุม LED(พื้นฐาน)
การอ่านค่าสัญญาณแอนะล็อกแล้วนำค่าที่อ่านได้ควบคุมการติดดับของ LED (เขียนแบบวนอ่านค่าสัญญาณ) จากตัวอย่างโปรแกรมเป็นการอ่านจากขา A0
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/8.png)
โค้ด
#define LED1 27
#define LED2 14
#define LED3 12
#define LED4 13
void setup() {
Serial.begin(9600);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
}
void loop() {
int adc = analogRead(A0);
Serial.printf("Value of ADC from A0 :%u \n", adc);
digitalWrite(LED1, adc>3500 ? 1 : 0);
digitalWrite(LED2, adc>2500 ? 1 : 0);
digitalWrite(LED3, adc>1500 ? 1 : 0);
digitalWrite(LED4, adc>500 ? 1 : 0);
delay(500);
}
ตัวอย่าง โปรแกรมอ่านค่าแอนะล็อกควบคุม LED(ใช้ไลบรารี่ simpleTimer)
การอ่านค่าสัญญาณแอนะล็อกแล้วนำค่าที่อ่านได้ควบคุมการติดดับของ LED เป็นโปรแกรมที่ไม่วนอ่านค่าแต่ใช้ไลบรารี่ simpleTimer กำหนดคาบเวลาให้ไปอ่านค่ามาแทน จากตัวอย่างโปรแกรมเป็นการอ่านจากขา A0
(https://www.praphas.com/PhotoForum/ESP32/Lab-06-ADC-SimpleTimer/10.png)
โค้ด
#include <SimpleTimer.h>
const byte ledPin[] = {27, 14, 12, 13};
SimpleTimer timer;
int adc;
void readADC() {
adc = analogRead(A0);
Serial.printf("Value of ADC from A0 :%u \n", adc);
}
void setup() {
Serial.begin(9600);
for (byte i = 0; i < (sizeof(ledPin) / sizeof(byte)); i++)
pinMode(ledPin[i], OUTPUT);
timer.setInterval(1000, readADC);
}
void loop() {
timer.run();
digitalWrite(ledPin[0], adc > 3500 ? 1 : 0);
digitalWrite(ledPin[1], adc > 2500 ? 1 : 0);
digitalWrite(ledPin[2], adc > 1500 ? 1 : 0);
digitalWrite(ledPin[3], adc > 500 ? 1 : 0);
delay(50);
}