ESP32-C3 น่าใช้มากสำหรับงานที่ไม่ต้องการพลังเยอะ — ราคาถูกกว่า กินไฟน้อยกว่า และมี USB ในตัว แต่ถ้าคิดว่ามันคือ ESP32 ตัวเล็กแล้วยกโค้ดมาทั้งดุ้น จะเจอปัญหาตั้งแต่คอมไพล์ไปจนถึงตอนใช้งานจริง

นี่คือสี่เรื่องที่ผมต้องแก้ทุกครั้ง

1. C3 มี UART แค่ 2 ตัว

ESP32 กับ S3 มี UART สามตัว (0, 1, 2) โค้ดที่ใช้ RS-485 หรือ GPS มักเขียนแบบนี้:

1
HardwareSerial meterSerial(2);   // ❌ C3 ไม่มี UART2

C3 มีแค่ UART0 กับ UART1 ต้องเปลี่ยนเป็น (1)

ถ้าอยากให้โค้ดชุดเดียวใช้ได้ทั้งสองแบบ ใส่เงื่อนไขคอมไพล์ไว้:

1
2
3
4
5
#if defined(CONFIG_IDF_TARGET_ESP32C3) || (defined(SOC_UART_NUM) && SOC_UART_NUM < 3)
  HardwareSerial meterSerial(1);
#else
  HardwareSerial meterSerial(2);
#endif

2. พินที่ใช้ได้จริงมีน้อยกว่าที่เห็นบนบอร์ด

กลุ่มพินหมายเหตุ
ใช้ได้ทั่วไปGPIO 0–10, 20, 21
ห้ามใช้GPIO 11–17ต่อกับแฟลชภายใน
strapping — ระวังGPIO 2, 8, 9ระดับสัญญาณตอนบูตมีผลต่อโหมดการบูต
ใช้ไปแล้วGPIO 9 = ปุ่ม BOOT · GPIO 8 = LED บนบอร์ด (active LOW)
กันไว้GPIO 20, 21 = UART0Serial Monitor

เรื่อง strapping สำคัญกว่าที่คิด — ถ้าเอาอุปกรณ์ไปต่อกับ GPIO2, 8 หรือ 9 แล้วอุปกรณ์นั้นดึงระดับสัญญาณตอนบอร์ดกำลังบูต บอร์ดอาจเข้าโหมดผิดหรือบูตไม่ขึ้นเลย อาการจะออกมาเป็น “บางทีบูตติด บางทีไม่ติด” ซึ่งไล่หาสาเหตุยากมาก

3. ADC ใช้ได้แค่ครึ่งเดียวเมื่อเปิด WiFi

ข้อนี้เจ็บที่สุดสำหรับงานที่มีเซนเซอร์อนาล็อก

ADC2 ใช้ไม่ได้เมื่อ WiFi ทำงาน เพราะวงจร WiFi ใช้ ADC2 อยู่ (ข้อจำกัดนี้มีในตระกูล ESP32 ทั้งหมด ไม่ใช่แค่ C3 แต่ C3 มีพินน้อยอยู่แล้วเลยรู้สึกชัดกว่า)

บน C3 แปลว่าเซนเซอร์อนาล็อกต้องอยู่บน ADC1 = GPIO 0–4 เท่านั้น

และในสี่ขานั้น อย่าใช้ GPIO2 เพราะเป็น strapping pin — เหลือใช้จริง ๆ แค่ GPIO 0, 1, 3, 4

4. ตั้งค่าใน Arduino IDE

ตัวเลือกค่าที่ต้องตั้งถ้าไม่ตั้งจะเป็นยังไง
BoardESP32C3 Dev Module
USB CDC On BootEnabledSerial Monitor ไม่ขึ้นอะไรเลย
Partition SchemeMinimal SPIFFS (1.9MB APP with OTA)เฟิร์มแวร์ที่มี WiFi+MQTT+เว็บ ราว 1.2 MB จะเหลือที่ว่างแค่ ~9% แน่นเกินไปสำหรับ OTA

ถ้าเปิด USB CDC แล้วยังไม่เห็นข้อความตอนบูต ให้ใส่หน่วงหลัง Serial.begin():

1
2
3
Serial.begin(115200);
delay(1500);          // รอให้ USB CDC พร้อมก่อนพิมพ์
Serial.println("เริ่มทำงาน");

เรื่อง partition อ่านเพิ่มได้ที่ ESP32 OTA ขึ้น fail begin ทั้งที่คอมไพล์บอกว่าใช้ไปแค่ 69% ซึ่งอธิบายว่าทำไมเลือก scheme ในเมนูอย่างเดียวไม่พอ

เกร็ดที่ไม่มีในดาต้าชีต

RS-485 บน C3 ต้องเลี้ยง 3.3V เท่านั้น

C3 ตัดสินว่าเป็นลอจิก “1” ที่ VIH = 0.75 × VDD = 2.48V ซึ่งสูงกว่าชิปหลายตัว ถ้าใช้โมดูล RS-485 ที่เลี้ยง 5V แล้วลดแรงดันด้วยตัวแบ่งแรงดัน สัญญาณจะไปวนอยู่ใกล้เส้นนี้พอดี

ผลที่ผมวัดได้จริง:

การต่ออ่านสำเร็จ
โมดูล 5V + ตัวแบ่งแรงดัน30% — และเพี้ยนซ้ำแบบเดิมทุกครั้ง (55 AA 5A A5 กลายเป็น 55 95 A9 0B)
โมดูล 3.3V ต่อ RO ตรง100% ไม่พลาดเลย

รายละเอียดเรื่องการเลือกโมดูลอยู่ใน บทความเรื่อง RS-485 กับ ESP32

WiFi.scanNetworks() ต้องล้าง state ก่อน

ถ้าเรียกสแกนติดกับ WiFi.mode() ทันที ไดรเวอร์ยังไม่พร้อม มันจะคืนค่าติดลบ (error) กลับมา

ปัญหาคือถ้าโค้ดของคุณเขียนแบบ int n = WiFi.scanNetworks(); if (n == 0) ... ค่าติดลบจะไม่เข้าเงื่อนไขไหนเลย หรือแย่กว่านั้นคือถูกตีความเป็น “ไม่พบสัญญาณ” ทั้งที่บอร์ดต่อ WiFi ตัวนั้นได้อยู่ดี ๆ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
WiFi.mode(WIFI_STA);
WiFi.disconnect(false, false);
delay(200);

int n = WiFi.scanNetworks();
if (n < 0) {              // ยังไม่พร้อม ลองใหม่อีกครั้ง
  delay(600);
  n = WiFi.scanNetworks();
}

if (n < 0)      Serial.println("สแกนไม่สำเร็จ");     // ไม่ใช่ "ไม่พบสัญญาณ"
else if (n == 0) Serial.println("ไม่พบสัญญาณ");

เครื่องมือวินิจฉัยที่รายงานผิด แย่กว่าไม่มีเครื่องมือเลย — ต้องแยก “วัดไม่ได้” ออกจาก “วัดได้ว่าไม่มี” เสมอ ผมหลงทางเพราะเรื่องนี้มาแล้ว

อย่าย้ายตัวต้านทาน 0Ω ไปฝั่งเสาอากาศนอก ถ้าโมดูลไม่มีขั้ว u.FL

บอร์ด C3 บางรุ่นมีจุดบัดกรี 0Ω ให้เลือกระหว่างเสาในตัวกับเสาภายนอก ถ้าย้ายทั้งที่บอร์ดไม่มีขั้ว u.FL มาให้ เส้นทาง RF จะขาด

ตัวเลขที่ผมวัดได้: บอร์ดที่ย้าย 0Ω วัดได้ −95 dBm สแกนไม่เจอ AP เลยสักตัว ส่วนบอร์ดที่ไม่แตะ วัดจุดเดียวกันได้ −64 dBm เจอ AP สองตัว — ต่างกัน 31 dB ซึ่งไม่ใช่เรื่องสถานที่แล้ว แต่คือวงจรพัง

เทคนิคที่ใช้ได้ทั่วไป: เวลาสงสัยว่า “บอร์ดเสียหรือสัญญาณอ่อน” ให้เอาบอร์ดตัวที่สองไปวัดจุดเดียวกัน รู้ผลใน 2 นาที เร็วกว่าไล่วัดทีละจุดทั้งวัน

C3 ไม่มี PSRAM

ESP.getFreePsram() คืนค่า 0 เป็นเรื่องปกติ ไม่ใช่ของเสีย RAM รวมมี 320 KB ซึ่งพอสำหรับงาน WiFi + MQTT + เว็บเซิร์ฟเวอร์เล็ก ๆ (ใช้จริงตอนบูตราว 13%)

สรุปเช็กลิสต์

  1. HardwareSerial(2) → เปลี่ยนเป็น (1)
  2. เช็คว่าพินที่ใช้อยู่ในช่วง 0–10, 20, 21 และหลบ 2, 8, 9
  3. เซนเซอร์อนาล็อกย้ายไป GPIO 0, 1, 3 หรือ 4
  4. ตั้ง USB CDC On Boot = Enabled และ Partition = Minimal SPIFFS
  5. โมดูล RS-485 เลี้ยง 3.3V เท่านั้น
  6. scanNetworks() ต้องล้าง state ก่อนและแยกกรณี error ออกจาก “ไม่เจอ”