บอร์ดขยาย หุ่นยนต์ Robot ESP32 38PIN Breakout Board บอร์ดทดลอง Prototype ชุดฝึก Arduino Massmore

ภาพรวม (Overview)

แนะนำ (Introduction)

🔧 บอร์ดขยายหุ่นยนต์ ESP32 38PIN Breakout Board จาก Massmore

บอร์ดทดลองอัจฉริยะ เพื่อสร้างหุ่นยนต์และ IoT อย่างมืออาชีพ

พบกับ ESP32 Breakout Board ที่ออกแบบโดยทีมวิศวกรของ Massmore เพื่อยกระดับการเรียนรู้และการพัฒนาโปรเจกต์หุ่นยนต์ Arduino ให้ใช้งานง่าย ครบ จบในบอร์ดเดียว!

คุณสมบัติ (Features)

🚀 จุดเด่นที่คุณห้ามพลาด:

  • รองรับ ESP32 (38 PIN) พร้อมใช้งานทันที เสียบได้พอดี!

  • 🔌 DC IN (6–12V) พร้อมวงจร Step Down แปลงไฟให้เสถียรที่ 5V 5A เพื่อจ่ายไฟให้ทั้งระบบ

  • 🎛 Driver มอเตอร์ รองรับ TB6612FNG หรือ Compatible 

    • DC Motor 2 ช่อง (2CH)

    • Servo Motor 3 ช่อง (3CH)

  • 🔄 สวิตช์ ON-OFF ควบคุมไฟเลี้ยงสะดวกปลอดภัย

  • 💡 ตัวต้านทานปรับค่าได้ (VR) สำหรับงานควบคุมที่ต้องการความแม่นยำ

  • 🧠 GPIO พอร์ตเต็ม พร้อมใช้งานกับเซ็นเซอร์และอุปกรณ์เสริม

  • 📺 พอร์ตจอแสดงผล (SCREEN) สำหรับต่อ OLED, LCD ฯลฯ

  • 🔄 I²C Interface (PH2.0 4P) รองรับการเชื่อมต่อเซ็นเซอร์และโมดูลต่างๆ ผ่าน I2C ได้อย่างง่ายดาย

  • 🔘 Switch พร้อมใช้งาน ติดตั้งง่าย ใช้ทดสอบโปรแกรมได้ทันที

🎯 เหมาะสำหรับใคร?

  • นักเรียน นักศึกษา ที่ต้องการ ชุดฝึกทดลอง Arduino / ESP32

  • Maker และผู้พัฒนา IoT ที่ต้องการบอร์ดขยายคุณภาพสูง

  • ผู้สอน STEM / Robotics ที่อยากให้การเรียนรู้สนุกและครอบคลุม

📦 ใช้ได้กับ:

  • หุ่นยนต์เดินตามเส้น / หุ่นยนต์เลี้ยวซ้ายขวา

  • ระบบสมาร์ทโฮม / สมาร์ทฟาร์ม

  • โปรเจกต์ IoT ทั่วไปที่ต้องการความเสถียรและง่ายในการต่อวงจร

ข้อมูลสินค้า (Spec Data)

ตารางข้อมูลสินค้า

รายการรายละเอียด
รองรับบอร์ดหลักESP32 (แบบ 38 ขา)
อินพุตไฟฟ้า (DC IN)6–12V (ผ่านแจ็ค 6.5 x 2.1mm)
วงจรจ่ายไฟ (Regulator)Step Down 6–12V ➝ 5V 5A
เอาต์พุตไฟ 5Vรองรับโหลดสูงสุด 5A
ช่องควบคุม DC Motor2 ช่อง (2CH) รองรับ TB6612FNG หรือ Compatible 
ช่องควบคุม Servo Motor3 ช่อง (3CH) 
GPIO Header38 พิน (19 พินต่อฝั่ง)
I²C ConnectorPH2.0 4P สำหรับเชื่อมต่อโมดูลภายนอก
พอร์ตต่อจอแสดงผลสำหรับ OLED / LCD ฯลฯ
VR (Variable Resistor)ตัวต้านทานปรับค่าได้ 1 ตัว
ปุ่มกด (Switch)สำหรับทดสอบ / ควบคุมเบื้องต้น
สวิตช์เปิด-ปิด (ON-OFF Switch)ตัดต่อไฟเลี้ยงจาก DC IN
ขนาดบอร์ดประมาณ 90 x 60 mm
วัสดุ PCBFR4 คุณภาพสูง, เคลือบทองแดง 2 ด้าน
น้ำหนักประมาณ 120 กรัม

ตารางขาใช้งาน Pin table

ข้อมูลขนาดสินค้า

ข้อมูลบอร์ด (Onboard Resources)

ภาพตำแหน่งการต่อใช้งาน

🟩 GPIO

  • พอร์ตขยายขา GPIO (General Purpose Input/Output) ของ ESP32 แบบครบทุกพิน

  • ใช้ต่อกับอุปกรณ์ภายนอก เช่น LED, เซ็นเซอร์, รีเลย์, ปุ่มกด ฯลฯ

  • รองรับทั้งโหมด Input และ Output


🔵 VR (Variable Resistor)

  • ตัวต้านทานปรับค่าได้

  • ใช้สำหรับทดลองหรืออ่านค่าจาก Potentiometer

  • เหมาะกับงานควบคุม เช่น ปรับความสว่าง, ควบคุมความเร็วมอเตอร์ หรือสร้างสัญญาณ Analog


🟧 DC Motor Driver (2CH)

  • ช่องต่อมอเตอร์กระแสตรง 2 ตัว

  • รองรับ TB6612FNG หรือ Compatible 

  • รองรับการควบคุมทิศทางหมุน และความเร็วของมอเตอร์


🟧 Servo Motor Driver (3CH)

  • ช่องต่อเซอร์โวมอเตอร์ 3 ช่อง

  • ขั้วต่อแบบ JST พร้อมไฟเลี้ยงและสัญญาณ

  • ใช้ควบคุมมอเตอร์เซอร์โวในการหมุนตามองศาที่ต้องการ


🔴 ON-OFF Switch

  • สวิตช์ตัดต่อไฟหลักจาก DC IN

  • ใช้งานสะดวก ปลอดภัย ไม่ต้องถอดปลั๊กบ่อย


🔴 DC IN (6–12V)

  • แจ็คขนาด 6.5×2.1mm สำหรับรับไฟเลี้ยงจากอะแดปเตอร์

  • รองรับแรงดันอินพุต 6–12V

  • ป้อนพลังงานให้กับบอร์ดและอุปกรณ์ทั้งหมด


🔷 STEP Down (6–12V to 5V5A)

  • วงจรแปลงแรงดันจาก DC IN (6–12V) ลงเป็น 5V 5A

  • ใช้เลี้ยง ESP32 และอุปกรณ์อื่นอย่างเสถียร

  • จ่ายกระแสสูงเพียงพอสำหรับมอเตอร์และเซอร์โว


🔵 SCREEN (OLED/LCD)

  • พอร์ตสำหรับต่อจอแสดงผล เช่น OLED, LCD

  • ช่วยให้แสดงค่าข้อมูลต่าง ๆ ได้สะดวก


🔷 Switch (ปุ่มกด)

  • ปุ่มกดใช้งานได้ทันที เหมาะกับการทดสอบโปรแกรม

  • ใช้เป็นปุ่มควบคุมหุ่นยนต์หรือฟังก์ชันอื่น ๆ


🟩 I²C (PH2.0 4P)

  • พอร์ตสำหรับอุปกรณ์ที่ใช้โปรโตคอล I²C เช่น เซ็นเซอร์วัดอุณหภูมิ, จอ OLED, RTC ฯลฯ

  • ขั้วต่อแบบ PH2.0 4 พิน: VCC, GND, SDA, SCL


📌 หมายเหตุ:
ตรงกลางคือช่องเสียบ ESP32 (38 PIN) ซึ่งเป็น MCU หลักของบอร์ด โดยบอร์ดนี้ออกแบบมาให้พร้อมใช้งานกับ ESP32 ได้ทันที โดยไม่ต้องต่อวงจรซับซ้อนเพิ่มเติม

ตัวอย่างโปรแกรม (Example Arduino Code)

ตัวอย่างที่ 1 การควบคุมเซอร์โวมอเตอร์และ LED ด้วย ESP32 โดยใช้ ตัวต้านทานปรับค่าได้ (Potentiometer) และสวิตช์ (Switch)

ในบทความนี้ เราจะอธิบายการทำงานของโปรแกรมบนบอร์ด ESP32 ที่ใช้ควบคุมเซอร์โวมอเตอร์ 2 ตัว และไฟ LED ด้วย Potentiometer (VR) และสวิตช์ โดยแสดงข้อมูลทั้งหมดผ่านทาง Serial Monitor โปรแกรมนี้เหมาะสำหรับการเรียนรู้เบื้องต้นเกี่ยวกับการอ่านค่าจำเพาะจาก analog input และ digital input พร้อมการควบคุมอุปกรณ์ output อย่างเซอร์โวและ LED

อุปกรณ์ที่ใช้ในโปรเจกต์

  • บอร์ด ESP32 38PIN Massmore

  • เซอร์โวมอเตอร์ Servo motor 2 ตัว (รุ่นใดก็ได้)

  • Potentiometer (VR) Onboard

  • Push Button (SW) Onboard

  • LED Onboard

Arduino IDE Code

  • อย่าลืมติดตั้ง Library ***ESP32Servo*** จากไฟล์บน Github
				
					#include <ESP32Servo.h>

#define VR_PIN 34      // ขาอ่านค่า VR (Potentiometer)
#define SW_PIN 36      // ขาอ่านค่าสวิตช์
#define LED_PIN 2      // ขา LED
#define SERVO1_PIN 19  // ขา Servo 1
#define SERVO2_PIN 32  // ขา Servo 2

Servo servo1, servo2;
bool ledState = false;
bool lastButtonState = HIGH;

void setup() {
    Serial.begin(115200);
    pinMode(VR_PIN, INPUT);
    pinMode(SW_PIN, INPUT_PULLUP);
    pinMode(LED_PIN, OUTPUT);
    
    servo1.attach(SERVO1_PIN);
    servo2.attach(SERVO2_PIN);
}

void loop() {
    // อ่านค่าจาก VR และแปลงเป็นองศา (0 - 180)
    int vrValue = analogRead(VR_PIN);
    int angle = map(vrValue, 0, 4095, 0, 180);
    
    // ควบคุมเซอร์โว
    servo1.write(angle);
    servo2.write(180 - angle);
    
    // อ่านค่าจากสวิตช์
    bool buttonState = digitalRead(SW_PIN);
    
    // เช็คการเปลี่ยนแปลงของปุ่มเพื่อทำ Toggle
    if (buttonState == LOW && lastButtonState == HIGH) {
        ledState = !ledState;
        digitalWrite(LED_PIN, ledState);
        delay(200); // กันสัญญาณกดเด้ง (Debounce)
    }
    lastButtonState = buttonState;
    
    // แสดงค่าผ่าน Serial Monitor
    Serial.print("VR Volume: ");
    Serial.print(vrValue);
    Serial.print(" | Servo Angle: ");
    Serial.print(angle);
    Serial.print(" | SW State: ");
    Serial.println(buttonState ? "HIGH" : "LOW");
    
    delay(100);
}
				
			

อธิบายการทำงานของโค้ด

1. การกำหนดขาเชื่อมต่อ
กำหนดขาเชื่อมต่อของแต่ละอุปกรณ์เข้ากับขา GPIO บน ESP32

				
					#define VR_PIN 34      // ขาอ่านค่า VR (Potentiometer)
#define SW_PIN 36      // ขาอ่านค่าสวิตช์
#define LED_PIN 2      // ขา LED
#define SERVO1_PIN 19  // ขา Servo 1
#define SERVO2_PIN 32  // ขา Servo 2

				
			

2. การตั้งค่าในฟังก์ชัน setup()

				
					void setup() {
    Serial.begin(115200);
    pinMode(VR_PIN, INPUT);
    pinMode(SW_PIN, INPUT_PULLUP);
    pinMode(LED_PIN, OUTPUT);
    
    servo1.attach(SERVO1_PIN);
    servo2.attach(SERVO2_PIN);
}

				
			
  • เริ่มต้น Serial Monitor เพื่อดูค่าผลลัพธ์

  • ตั้งค่าโหมดของขาอินพุตและเอาต์พุต

  • กำหนดให้เซอร์โวมอเตอร์แต่ละตัวทำงานกับขาที่กำหนด

3. การทำงานในลูปหลัก loop()

				
					int vrValue = analogRead(VR_PIN);
int angle = map(vrValue, 0, 4095, 0, 180);
				
			
  • อ่านค่าจาก VR (0 – 4095) แล้วแปลงให้เป็นองศา (0 – 180)

  • ส่งค่ามุมไปควบคุมเซอร์โวมอเตอร์

				
					servo1.write(angle);
servo2.write(180 - angle);
				
			
  • เซอร์โวตัวที่ 1 หมุนตามค่าที่ได้

  • เซอร์โวตัวที่ 2 หมุนสวนทาง (180 – ค่าเดิม)

4. การควบคุม LED ด้วยสวิตช์

				
					bool buttonState = digitalRead(SW_PIN);

if (buttonState == LOW && lastButtonState == HIGH) {
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState);
    delay(200);
}
lastButtonState = buttonState;
				
			
  • เมื่อกดปุ่ม (สถานะจาก HIGH → LOW) จะสลับสถานะของ LED (เปิด/ปิด)

  • มีการหน่วงเวลาเล็กน้อย (debounce) เพื่อกันการสั่นของสัญญาณปุ่ม

5. การแสดงค่าผ่าน Serial Monitor

				
					Serial.print("VR Volume: ");
Serial.print(vrValue);
Serial.print(" | Servo Angle: ");
Serial.print(angle);
Serial.print(" | SW State: ");
Serial.println(buttonState ? "HIGH" : "LOW");
				
			
  • แสดงค่าที่อ่านได้จาก VR, มุมของเซอร์โว และสถานะของปุ่มบน Serial Monitor

สรุป

โค้ดนี้เป็นตัวอย่างที่ดีในการใช้ ESP32 ร่วมกับอุปกรณ์อินพุตและเอาต์พุตพื้นฐาน โดยเราสามารถ:

  • ควบคุมเซอร์โวแบบเรียลไทม์ด้วย VR

  • สลับเปิด/ปิดไฟ LED ด้วยปุ่ม

  • แสดงค่าทั้งหมดผ่าน Serial Monitor เพื่อการดีบั๊กหรือศึกษาพฤติกรรมของระบบ

หากคุณต้องการพัฒนาเพิ่มเติม เช่น เพิ่มการควบคุมผ่าน Wi-Fi หรือจอแสดงผล OLED ก็สามารถต่อยอดจากพื้นฐานนี้ได้เลย

ตัวอย่างที่ 2 การควบคุมมอเตอร์ 2CH พร้อมวิธีการตั้งค่า (ใช้งานกับไดร์ฟ Pluto TB6612FNG V2 ใช้ชิพ TB67H450FNG)

ในบทความนี้ เราจะอธิบายการทำงานของโปรแกรมบนบอร์ด ESP32 ที่ใช้ควบคุมดีซีมอเตอร์ Brush DC motor 2 ตัว โปรแกรมนี้เหมาะสำหรับการเรียนรู้เบื้องต้นเกี่ยวกับการควบคุมอุปกรณ์ Output DC motor

อุปกรณ์ที่ใช้ในโปรเจกต์

  • บอร์ด ESP32 38PIN Massmore

  • ดีซีมอเตอร์ Brush DC motor 2 ตัว (รุ่นใดก็ได้)

  • บอร์ดขับมอเตอร์ TB6612FNG หรือ Pluto (รุ่นใดก็ได้)

1. TB6612FNG – รุ่นยอดนิยม ใช้งานง่าย

รายการรายละเอียด
โหมดควบคุมPWM 2 ขา (PWMA, PWMB) + IN1, IN2 (4 ขา)
จำนวนมอเตอร์ขับได้ 2 ตัว (2CH)
แรงดันใช้งาน2.5V – 13.5V
กระแสสูงสุดต่อช่อง1.2A (สูงสุด 3.2A burst)
พินควบคุมAIN1, AIN2, BIN1, BIN2 + PWMA, PWMB
เหมาะกับรถบังคับ, หุ่นยนต์ 2 ล้อ, โปรแกรมง่าย

ข้อดี:

  • ใช้งานง่าย เหมาะสำหรับผู้เริ่มต้น

  • ใช้พิน PWM ควบคุมเพียง 2 ขา

  • มีวงจรเบรกในตัว


2. TB67H450FNG (Pluto) – พลังสูง ทนทาน

รายการรายละเอียด
โหมดควบคุมPWM แยก 4 ขา (PWM1, PWM2, PWM3, PWM4)
จำนวนมอเตอร์ขับได้ 2 ตัว (2CH)
แรงดันใช้งาน4.5V – 28V
กระแสสูงสุด3.5A (สูงสุดถึง 5A burst)
พินควบคุมIN1, IN2, IN3, IN4
เหมาะกับมอเตอร์ใหญ่, หุ่นยนต์รับน้ำหนัก, แข่งขันหุ่นยนต์

ข้อดี:

  • ทนกระแสสูง เหมาะกับมอเตอร์กินกระแสหนัก

  • มีระบบป้องกันกระแสเกิน / ความร้อน

  • ขับมอเตอร์ได้ลื่นแม่นยำ ควบคุมแรงบิดได้ดี

  • ใช้พินควบคุมน้อย

Arduino IDE Code

โปรแกรมนี้เขียนด้วยภาษา Arduino โดยมีจุดประสงค์เพื่อ ควบคุมการทำงานของมอเตอร์ DC 2 ตัว ผ่านขา GPIO ของ ESP32 โดยใช้ PWM (Pulse Width Modulation) เพื่อควบคุมทิศทางและความเร็วของมอเตอร์

				
					
// Motor
int motor1Pin1 = 16;
int motor1Pin2 = 17;
int motor2Pin1 = 27;
int motor2Pin2 = 26;

// the setup routine runs once when you press reset:
void setup()
{
  Serial.begin(115200);
  delay(10);

  ledcAttachPin(motor1Pin1, 1); // assign RGB led pins to channels
  ledcAttachPin(motor1Pin2, 2);
  ledcAttachPin(motor2Pin1, 3);
  ledcAttachPin(motor2Pin2, 4);

  // Initialize channels
  // channels 0-15, resolution 1-16 bits, freq limits depend on resolution
  // ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
  ledcSetup(1, 12000, 8); // 12 kHz PWM, 8-bit resolution
  ledcSetup(2, 12000, 8);
  ledcSetup(3, 12000, 8);
  ledcSetup(4, 12000, 8);

  Serial.print("Testing DC Motor...");
}
// void loop runs over and over again
void loop()
{
    // Stop the DC motor
  Serial.println("Motor stopped");
  ledcWrite(1, 0);
  ledcWrite(2, 0);
  ledcWrite(3, 0);
  ledcWrite(4, 0);
  delay(1000);
  // Move the DC motor forward at maximum speed
  Serial.println("Moving Forward");
  ledcWrite(1, 255);
  ledcWrite(2, 0);
  ledcWrite(3, 255);
  ledcWrite(4, 0);
  delay(3000);

  // Move DC motor backwards at maximum speed
  Serial.println("Moving Backwards");
  ledcWrite(1, 0);
  ledcWrite(2, 255);
  ledcWrite(3, 0);
  ledcWrite(4, 255);
  delay(3000);

  // Stop the DC motor
  Serial.println("Motor stopped");
  ledcWrite(1, 0);
  ledcWrite(2, 0);
  ledcWrite(3, 0);
  ledcWrite(4, 0);
  delay(1000);
  
  // Stop the DC motor
  Serial.println("Motor Speed+");
  ledcWrite(1, 100);
  ledcWrite(2, 0);
  ledcWrite(3, 100);
  ledcWrite(4, 0);
  delay(1000);

    // Stop the DC motor
  Serial.println("Motor Speed+");
  ledcWrite(1, 125);
  ledcWrite(2, 0);
  ledcWrite(3, 125);
  ledcWrite(4, 0);
  delay(1000);

    // Stop the DC motor
  Serial.println("Motor Speed+");
  ledcWrite(1, 200);
  ledcWrite(2, 0);
  ledcWrite(3, 200);
  ledcWrite(4, 0);
  delay(1000);

  
    // Stop the DC motor
  Serial.println("Motor Speed+");
  ledcWrite(1, 255);
  ledcWrite(2, 0);
  ledcWrite(3, 255);
  ledcWrite(4, 0);
  delay(1000);

}

				
			

อธิบายการทำงานของโค้ด

1. การกำหนดขาเชื่อมต่อ การตั้งค่าในฟังก์ชัน setup()

				
					int motor1Pin1 = 16;
int motor1Pin2 = 17;
int motor2Pin1 = 27;
int motor2Pin2 = 26;
				
			
  • กำหนดขา GPIO ที่ใช้ควบคุมมอเตอร์ 2 ตัว (แต่ละตัวใช้ 2 ขา – หมุนซ้าย/ขวา)

				
					ledcAttachPin(motor1Pin1, 1);
ledcAttachPin(motor1Pin2, 2);
ledcAttachPin(motor2Pin1, 3);
ledcAttachPin(motor2Pin2, 4);
				
			
  • ผูกขา GPIO กับ ช่องสัญญาณ PWM (channel) ของ ESP32 เพื่อส่งความถี่ PWM ไปควบคุมมอเตอร์

				
					ledcSetup(1, 12000, 8);
ledcSetup(2, 12000, 8);
ledcSetup(3, 12000, 8);
ledcSetup(4, 12000, 8);
				
			
  • กำหนดคุณสมบัติของ PWM:

    • ความถี่ 12 kHz

    • ความละเอียด 8 บิต (ค่าความแรง 0–255)

2. การทำงานในลูปหลัก loop()

				
					ledcWrite(1, 0); ledcWrite(2, 0); ledcWrite(3, 0); ledcWrite(4, 0);

				
			
  • หยุดมอเตอร์ (Motor stopped) ส่งค่า 0 ทุกช่อง = มอเตอร์ไม่หมุน

3. การทำงานในลูปหลัก loop()

				
					ledcWrite(1, 255); ledcWrite(2, 0);
ledcWrite(3, 255); ledcWrite(4, 0);
				
			
  • หมุนเดินหน้า (Moving Forward) มอเตอร์ทั้ง 2 ตัวหมุนในทิศทางเดียวกัน เดินหน้าเต็มความเร็ว

				
					ledcWrite(1, 0); ledcWrite(2, 255);
ledcWrite(3, 0); ledcWrite(4, 255);
				
			
  • หมุนถอยหลัง (Moving Backwards) กลับทิศหมุนเพื่อถอยหลัง

				
					ledcWrite(1, 100); // ความเร็วระดับ 1
...
ledcWrite(1, 125); // ระดับ 2
...
ledcWrite(1, 200); // ระดับ 3
...
ledcWrite(1, 255); // เต็มสปีด
				
			
  • เพิ่มความเร็วทีละขั้น (Motor Speed+)

    • ทดสอบการปรับระดับความเร็วของมอเตอร์

    • ใช้เพื่อดูผลของ PWM ที่มีต่อความเร็วในการหมุน

  • ตัวอย่างการทำงาน ไฟแสดงสถานะ LED ดับ = มอเตอร์หยุดหมุน
  • ตัวอย่างการทำงาน ไฟแสดงสถานะ LED สีแดง = มอเตอร์หมุนไปข้างหน้า
  • ตัวอย่างการทำงาน ไฟแสดงสถานะ LED สีเขียว = มอเตอร์หมุนไปข้างหลัง

สรุป

  • ใช้ PWM (Pulse Width Modulation) จาก ESP32 ควบคุมความเร็วของมอเตอร์

  • ใช้ 2 ขา GPIO ต่อมอเตอร์ 1 ตัว เพื่อกำหนดทิศทางการหมุน

  • สามารถ ควบคุมเดินหน้า ถอยหลัง และปรับระดับความเร็วได้

  • เหมาะกับการใช้งานร่วมกับ Driver เช่น TB6612FNG หรือ TB67H450FNG (Pluto) ที่รองรับการสั่งงานด้วย PWM

การใช้งานหน้าจอแสดงผล LCD 240x240 ST7789 และ หน้าจอ OLED 128x64 Pixel Driver SSD1306 Size 0.96"

ตัวบอร์ดรองรับการใช้งานหน้าจอทั้งสองรูปแบบโดยมีตัวอย่างดังนี้

ตัวอย่างที่ 3 การแสดงผลจาก INPUT ไปที่หน้าจอ LCD 240x240 ST7789

อุปกรณ์ที่ใช้ในโปรเจกต์

  • บอร์ด ESP32 38PIN Massmore

  • หน้าจอ LCD 240×240 ST7789 1.3 นิ้ว

  • เซ็นเซอร์จับเส้น Massmore (รุ่นไหนก็ได้)

Arduino IDE Code

โปรแกรม ESP32 อ่านค่า Analog 5 ช่อง และแสดงบนจอ LCD ST7789 (240×240) โดยใช้ไลบรารี TFT_eSPI

				
					#include <TFT_eSPI.h>  // ใช้ไลบรารี TFT_eSPI (ตั้งค่าใน User_Setup.h ก่อนใช้งาน)

TFT_eSPI tft = TFT_eSPI();  // สร้างอ็อบเจ็กต์สำหรับควบคุมจอ

// กำหนดขา Analog Input
const int analogPins[5] = {13, 12, 14, 15, 5};
int analogValues[5];  // ตัวแปรเก็บค่าที่อ่านได้

void setup() {
  Serial.begin(115200);

  // เริ่มต้นจอแสดงผล
  tft.init();
  tft.setRotation(0);  // หมุนหน้าจอได้ 0-3 แล้วแต่การติดตั้ง
  tft.fillScreen(TFT_BLACK);  // เคลียร์หน้าจอด้วยสีดำ
  tft.setTextSize(2);
  tft.setTextColor(TFT_GREEN, TFT_BLACK);  // ตัวอักษรสีเขียว พื้นหลังดำ

  // แสดงข้อความเริ่มต้น
  tft.setCursor(20, 10);
  tft.println("Analog Monitor");
  delay(1000);
}

void loop() {
  // อ่านค่า Analog ทุกช่อง
  for (int i = 0; i < 5; i++) {
    analogValues[i] = analogRead(analogPins[i]);
  }

  // เคลียร์พื้นหลังบางส่วนก่อนเขียนค่าใหม่
  tft.fillRect(0, 40, 240, 200, TFT_BLACK);

  // แสดงผลค่า Analog
  for (int i = 0; i < 5; i++) {
    tft.setCursor(10, 50 + i * 30);
    tft.printf("AIN%d (GPIO%d): %4d", i + 1, analogPins[i], analogValues[i]);
  }

  delay(500);  // หน่วงเวลา 0.5 วินาที
}

				
			

อธิบายการทำงานของโค้ด

1. การเรียกใช้ไลบรารี

				
					#include <TFT_eSPI.h>
				
			
  • ใช้ไลบรารี TFT_eSPI สำหรับควบคุมจอ ST7789

  • ไลบรารีนี้ต้องตั้งค่าขา GPIO ในไฟล์ User_Setup.h ให้ตรงกับบอร์ดก่อนใช้งาน

2. การกำหนดตัวแปรสำคัญ

				
					TFT_eSPI tft = TFT_eSPI();  // สร้างวัตถุควบคุมจอ
const int analogPins[5] = {13, 12, 14, 15, 5}; // GPIO สำหรับอ่าน Analog
int analogValues[5]; // ตัวแปรเก็บค่าที่อ่านได้จากแต่ละช่อง
				
			
  • กำหนดขา GPIO 5 ขา ที่จะใช้สำหรับรับค่า Analog จากอุปกรณ์ภายนอก (เช่น VR, เซ็นเซอร์)

  • สร้างตัวแปร array สำหรับเก็บค่า analogRead แต่ละช่อง

3. การตั้งค่าจอและ Serial Monitor ใน setup()

				
					tft.init();             // เริ่มต้นหน้าจอ
tft.setRotation(0);     // หมุนจอตามการใช้งานจริง (0-3)
tft.fillScreen(TFT_BLACK); // เคลียร์หน้าจอด้วยสีดำ
tft.setTextSize(2);     // ขนาดตัวอักษร
tft.setTextColor(TFT_GREEN, TFT_BLACK); // สีตัวอักษร (เขียวพื้นดำ)

tft.setCursor(20, 10);
tft.println("Analog Monitor");
				
			
  • เริ่มต้นหน้าจอ LCD และตั้งค่าการแสดงผล เช่น สี ขนาด ฟอนต์

  • แสดงข้อความต้อนรับ “Analog Monitor”

4. อ่านค่า Analog และแสดงผลใน loop()

				
					for (int i = 0; i < 5; i++) {
  analogValues[i] = analogRead(analogPins[i]);
}
				
			
  • วนลูปอ่านค่าจากขา GPIO แต่ละขา (เป็นค่าตัวเลข 0-4095 บน ESP32)

				
					tft.fillRect(0, 40, 240, 200, TFT_BLACK);
				
			
  • ลบพื้นที่แสดงผลเดิม (เพื่อล้างข้อความก่อนพิมพ์ค่าใหม่)

				
					for (int i = 0; i < 5; i++) {
  tft.setCursor(10, 50 + i * 30);
  tft.printf("AIN%d (GPIO%d): %4d", i + 1, analogPins[i], analogValues[i]);
}
				
			
  • วนลูปแสดงค่าที่อ่านได้ลงบนหน้าจอ

  • จะแสดงชื่อช่อง AIN1-AIN5 พร้อมกับเลข GPIO และค่าที่อ่านได้

				
					delay(500);
				
			
  • หน่วงเวลา 0.5 วินาทีเพื่อให้อ่านง่าย ไม่กระพริบไวเกินไป

สรุป

  • โปรแกรมนี้ใช้ ESP32 อ่านค่า Analog จาก GPIO 5 ช่อง แล้วนำไปแสดงผลบนจอ LCD ST7789 ขนาด 240×240 พิกเซล ด้วยไลบรารี TFT_eSPI โดยแสดงผลค่าที่ได้แบบเรียลไทม์พร้อมข้อความกำกับอย่างชัดเจน

ตัวอย่างที่ 4 การแสดงผลหน้าจอ OLED 128x64 Pixel Driver SSD1306 Size 0.96"

อุปกรณ์ที่ใช้ในโปรเจกต์

  • บอร์ด ESP32 38PIN Massmore

  • หน้าจอ OLED 128×64 Pixel Driver SSD1306 Size 0.96″

Arduino IDE Code

โปรแกรมนี้เขียนด้วยภาษา Arduino โดยมีจุดประสงค์เพื่อแสดงผลหน้าจอ ผ่านขา GPIO ของ ESP32 โดยใช้ I2C Port

*** จำเป็นต้องติดตั้ง Library Adafruit_GFX.h และ Adafruit_SSD1306.h

				
					#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

void setup() {
  Serial.begin(115200);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();      // Draw many lines

  testdrawrect();      // Draw rectangles (outlines)

  testfillrect();      // Draw rectangles (filled)

  testdrawcircle();    // Draw circles (outlines)

  testfillcircle();    // Draw circles (filled)

  testdrawroundrect(); // Draw rounded rectangles (outlines)

  testfillroundrect(); // Draw rounded rectangles (filled)

  testdrawtriangle();  // Draw triangles (outlines)

  testfilltriangle();  // Draw triangles (filled)

  testdrawchar();      // Draw characters of the default font

  testdrawstyles();    // Draw 'stylized' characters

  testscrolltext();    // Draw scrolling text

  testdrawbitmap();    // Draw a small bitmap image

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE);
    display.display();
    delay(1);
  }

  delay(2000); // Pause for 2 seconds
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=3) {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, INVERSE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE);
    display.display(); // Update screen with each newly-drawn circle
    delay(1);
  }

  delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(BLACK, WHITE); // Draw 'inverse' text
  display.println(3.141592);

  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

  display.display();
  delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for(f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS]   = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for(;;) { // Loop forever...
    display.clearDisplay(); // Clear the display buffer

    // Draw each snowflake:
    for(f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
    }

    display.display(); // Show the display buffer on the screen
    delay(200);        // Pause for 1/10 second

    // Then update coordinates of each flake...
    for(f=0; f< NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height()) {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS]   = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}
				
			

สรุป

    1. เริ่มต้นใช้งานจอ OLED

      • ตั้งค่าการเชื่อมต่อจอผ่าน I2C ที่ Address 0x3C

      • ล้างหน้าจอ (clear)

    2. แสดงกราฟิกต่าง ๆ ทีละขั้น

      • วาดเส้น (line), สี่เหลี่ยม (rectangle), วงกลม (circle), สามเหลี่ยม (triangle)

      • วาดตัวอักษรธรรมดา และแบบสไตล์ต่าง ๆ

      • แสดงข้อความแบบ scroll ซ้ายขวา

      • แสดงรูปภาพ (bitmap)

      • แสดงภาพเคลื่อนไหว (animation) แบบเกล็ดหิมะตกลงหน้าจอ

อ้างอิง (reference)

Arduino Code

ให้คะแนน 0 ตั้งแต่ 1-5 คะแนน

Development Board - บอร์ดพัฒนา

บอร์ด ESP32 38PIN ชิพแท้จาก Espressif Node32s ESP32S USB Type-C Massmore

🎉บอร์ด ESP32 38PIN ชิพแท้จาก E...

฿350.00

ให้คะแนน 0 ตั้งแต่ 1-5 คะแนน

Development Board - บอร์ดพัฒนา

เซ็นเซอร์จับเส้น Sensor Line Follower เซ็นเซอร์หุ่นยนต์วิ่งตามเส้น Phototransistor รุ่น Ruby
ให้คะแนน 0 ตั้งแต่ 1-5 คะแนน

Robotics - หุ่นยนต์

โมดูลหน้าจอ OLED ขนาด 0.91 0.96 นิ้ว I2C Display Module Driver SSD1306 12864 128x64 Pixel
ให้คะแนน 0 ตั้งแต่ 1-5 คะแนน

Displays - หน้าจอ

โมดูลหน้าจอ OLED ขนาด 0.91 0.96 นิ้ว I2C Display Module Driver SSD1306 12864 128x64 Pixel

🔥ชื่อสินค้า: โมดูลแสดงผล OLED ...

฿65.00฿69.00

แสดงความคิดเห็น