บทความนี้กล่าวถึงการใช้งาน GPIO ของ ESP32 เพื่อทำหน้าที่เป็นการนำเข้าสัญญาณดิจิทัล โดยใช้วงจรของคีย์แพดที่เป็นสวิตช์จำนวน 8 ตัวที่ทำมาต่อให้เป็นเหมือนเกมแพ็ดดังภาพที่ 1

Switches Game Pad
ภาพที่ 1 สวิตช์ที่นำมาใช้ประกอบบทความ

โครงสร้างของโครงงาน

โครงสร้างของโครงงานของ ESP-IDF เป็นดังภาพที่ 2 คือ ในไดเร็กทอรีหรือโฟลเดอร์ของโครงงานจะมีไฟล์ CMakeList.txt และ sdkconfig กับไดเร็กทอรีชื่อ main สำหรับเก็บรหัสต้นฉบับของโครงงาน โดยในไดเร็กทอรีดังกล่าวมีไฟล์ภาษา C และ CMakeLists.txt

EP5 File Structure
ภาพที่ 2 โครงสร้างของโครงงาน

จากโครงสร้างในภาพที่ 2 ต้องสร้างโค้ดของไฟล์ CMakeLists.txt ดังนี้ ซึ่งเนื้อหาในโค้ดได้กำหนดรุ่นขั้นต่ำของโปรแกรม cmake และกำหนดค่าการใช้งานของ cmake เบื้องต้นตามจ้นฉบับที่มากับ ESP-IDF พร้อมทั้งตั้งชื่อโครงงานเป็น ep05

cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ep05)

สิ่งที่เขียน 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 หลังจากนั้นบันทึกและออกจากการตั้งค่า

ภาพที่ 3 ตั้งค่า Tick rate (Hz)

คำสั่ง

การใช้งาน GPIO จะต้องนำเข้าไฟล์ส่วนหัวชื่อ gpio.h ซึ่งอยู่ในโฟลเดอร์ย่อย driver ของ ESP-IDF ซึ่งสามารถนำเข้าดั้วยคำสั่ง include ดังนี้

#include <driver/gpio.h>

การเลือกใช้ขาต้องระบุด้วยคำสั่งต่อไปนี้

gpio_pad_select_gpio( หมายเลขขา )

คำสั่งสำหรับกำหนดหน้าที่การทำงานของขา มีรูปแบบดังนี้ โดยโหมดของขาเป็น GPIO_MODE_INPUT หรือ GPIO_MODE_OUTPUT

gpio_set_direction( หมายเลขขา, โหมดของขา )

คำสั่งสำหรับอ่านค่าสัญญาณดิจิทัลจากหมายเลขขาที่ระบุมีรูปแบบของคำสั่งดังนี้

ระดับสัญญาณดิจิทัล = gpio_get_level( หมายเลขขา )

สุดท้าย คำสั่งสำหรับกำหนดรูปแบบของขานำเข้าสัญญาณในกรณีที่เป็น PULL UP จะใช้คำสั่งดังนี้

gpio_pullup_en( หมายเลขขา )

ถ้าต้องการยกเลิก PULL UP ให้เรียกใช้ gpio_pullup_dis() ดังนี้

gpio_pullup_dis( หมายเลขขา )

กรณีที่ต้องการใช้งาน GPIO แบบอื่น ๆ สามารถเข้าไปอ่านบทความต่าง ๆ ดังต่อไปนี้เพิ่มเติม

  1. นำออกข้อมูลสัญญาณดิจิทัล
  2. นำเข้าสัญญาณดิจิทัล
  3. นำเข้าสัญญาณแอนาล็อก
  4. นำออกสัญญาณแอนาล็อก

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

วงจรแอลอีดีที่ใช้ในการทดลองครั้งนี้เป็นดังภาพที่ 4 อุปกรณ์ที่ใช้ในการทดลองได้แก่

  1. บอร์ด esp32
  2. บอร์ดทดลอง
  3. สวิตช์
  4. ตัวต้านทาน
switch with pull up resistor
ภาพที่ 4 วงจรนำเข้าสัญญาณดิจิทัล

ดังตัวอย่างโปรแกรมต่อไปนี้

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define swC 35
#define swD 34
#define swA 33
#define swB 32
#define keL 19
#define keU 18
#define keD 17
#define keR 16
gpio_num_t keys[] = {keL, keU, keD, keR, swC, swD, swA, swB};

void app_main(void)
{  
  printf("Ep.05 Keypad\n"); 
  for (int i=0; i<8; i++) {
    gpio_pad_select_gpio(keys[i]);
    gpio_pullup_en(keys[i]);
    if (gpio_set_direction(keys[i], GPIO_MODE_INPUT) == ESP_OK) {
      printf("GPIO%02d ... Success.\n",keys[i]);
    } else {
      printf("GPIO%02d ... Parameter error.\n",keys[i]);
    }
  }
  vTaskDelay( 1000/portTICK_PERIOD_MS );

  while(1) {
    printf("%d:%d:%d:%d %d-%d %d-%d\n",
      gpio_get_level(keys[0]),
      gpio_get_level(keys[1]),
      gpio_get_level(keys[2]),
      gpio_get_level(keys[3]),
      gpio_get_level(keys[4]),
      gpio_get_level(keys[5]),
      gpio_get_level(keys[6]),
      gpio_get_level(keys[7])
    );
    vTaskDelay( 100/portTICK_PERIOD_MS );
  }
}

คอมไพล์และอัพโหลด

ทำการคอมไพล์ หลังจากนั้น flash ลงชิพ และเข้าโปรแกรม Serial Monitor สั่งงานดังนี้

idf.py -p /dev/ttyUSB0 build flash monitor

ตัวอย่างผลลัพธ์ของโปรแกรมที่แสดงผลจะเป็นดังภาพที่ 5

idf.py -p /dev/ttyUSB0 flash

EP5 result
ภาพที่ 5 ผลลัพธ์จากโปรแกรม ep5

สรุป

จากบทความนี้จะพบว่า การนำเข้าสัญญาณดิจิทัลนั้นทำด้วยการใช้คำสั่ง gpio_get_level() และเมื่อใช้วงจรแบบมี pull up ให้เรียกคำสั่ง gpio_pullup_en() และยกเลิกด้วยคำสั่ง gpio_pullup_dis() สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ

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

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

  1. ESP-IDF : GPIO & RTC GPIO

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