Helper (วางบนสุดของทุกสเก็ตช์)

C++
// ==== ESP32 PWM helper ====
#if defined(ESP32)
void pwmAttach(uint8_t pin, uint32_t freq=5000, uint8_t res=8, uint8_t ch=0){
  ledcSetup(ch, freq, res); ledcAttachPin(pin, ch);
}
void pwmWrite(uint8_t pin, uint8_t val, uint8_t ch=0){
  ledcWrite(ch, val);
}
#else
void pwmAttach(uint8_t pin, uint32_t freq=490, uint8_t res=8, uint8_t ch=0){ pinMode(pin, OUTPUT); }
void pwmWrite(uint8_t pin, uint8_t val, uint8_t ch=0){ analogWrite(pin, val); }
#endif

Lab 1 — LED + ปุ่ม (debounce + INPUT_PULLUP)

วงจร: LED_PIN → R330Ω → LED → GND, ปุ่ม: BTN1 → GND (ตั้ง INPUT_PULLUP)
งานโค้ด: อ่านปุ่มแบบดีบาวน์ → สลับสถานะ LED

C++
#include <Arduino.h>
const uint8_t LED_PIN=23, BTN1=25;
unsigned long tDeb=0; bool last=HIGH, led=LOW;

void setup(){
  pinMode(LED_PIN, OUTPUT);
  pinMode(BTN1, INPUT_PULLUP);
  digitalWrite(LED_PIN, led);
}
void loop(){
  bool r=digitalRead(BTN1);           // LOW = กด
  if (r!=last && millis()-tDeb>25){   // debounce 25ms
    tDeb=millis(); last=r;
    if (r==LOW){ led=!led; digitalWrite(LED_PIN, led); }
  }
}

Lab 2 — ขับโหลดผ่านทรานซิสเตอร์ (Low-side switch)

วงจร: GPIO → R1k → Base BJT, Emitter→GND, Collector→โหลด→+5V (+ SS14 คร่อมถ้าเป็นคอยล์)
งานโค้ด: เปิดปิดโหลดเป็นจังหวะ และ/หรือกดปุ่มเพื่อสั่งทำงาน

C++
#include <Arduino.h>
const uint8_t LOAD_PIN=23, BTN1=25;
void setup(){ pinMode(LOAD_PIN, OUTPUT); pinMode(BTN1, INPUT_PULLUP); }
void loop(){
  if (digitalRead(BTN1)==LOW){ digitalWrite(LOAD_PIN, HIGH); }  // HIGH = เปิด BJT
  else { digitalWrite(LOAD_PIN, LOW); }
}

UNO: ทำเหมือนกัน (เปลี่ยนเลขพินให้ตรง)


Lab 3 — โพเทนชิโอมิเตอร์ → ADC → PWM หรี่ไฟ

วงจร: POT: 3V3—Wiper→POT_PIN—GND และ LED_PIN → R330Ω → LED → GND
งานโค้ด: อ่าน ADC 0–4095 (ESP32) → map เป็น 0–255 → PWM หรี่ LED

C++
#include <Arduino.h>
const uint8_t POT_PIN=32, LED_PIN=23;
void setup(){ pwmAttach(LED_PIN); }
void loop(){
  int adc = analogRead(POT_PIN);          // 0..4095
  uint8_t duty = map(adc, 0, 4095, 0, 255);
  pwmWrite(LED_PIN, duty);
  delay(5);
}

Lab 4 — DHT11 + ปุ่มปรับ Setpoint + Hysteresis

วงจร: DHT11: VCC→3V3, GND, DATA→DHT_PIN(4) (+pull-up 10k ถ้าโมดูลเปลือย),
LED/บัซเซอร์สถานะที่ LED_PIN และปุ่ม BTN1/BTN2 (UP/DOWN→GND)

C++
#include <Arduino.h>
#include <DHT.h>
const uint8_t DHT_PIN=4, LED_PIN=23, BTN_UP=25, BTN_DN=26; 
DHT dht(DHT_PIN, DHT11);
float setC=30.0, hys=1.0; unsigned long last=0;

void setup(){
  dht.begin(); pinMode(LED_PIN, OUTPUT);
  pinMode(BTN_UP, INPUT_PULLUP); pinMode(BTN_DN, INPUT_PULLUP);
  Serial.begin(115200);
}
void loop(){
  if(digitalRead(BTN_UP)==LOW){ setC+=0.5; delay(150); }
  if(digitalRead(BTN_DN)==LOW){ setC-=0.5; delay(150); }
  if (millis()-last>1500){
    last=millis();
    float t=dht.readTemperature();
    if(!isnan(t)){
      static bool on=false;
      if(!on && t>=setC) on=true;
      if(on && t<=setC-hys) on=false;
      digitalWrite(LED_PIN, on?HIGH:LOW);
      Serial.printf("T=%.1fC set=%.1f fan=%d\n", t, setC, on);
    }
  }
}

Lab 5 — ตรวจสอบเกตลอจิกด้วย MCU (AND/OR/XOR เทียบจริง)

วงจรฮาร์ดแวร์: ใช้ 7408/7432/7486 สร้างเอาต์พุต Y_AND, Y_OR, Y_XOR
MCU ป้อนอินพุต A,B ผ่านพิน OUT_A/OUT_B และอ่าน Y_* กลับ

C++
#include <Arduino.h>
// กำหนดพินตามการต่อจริง
const uint8_t OUT_A=23, OUT_B=22;           // ไปอินพุตของเกต (ผ่าน R330Ω ซีรีส์)
const uint8_t Y_AND=32, Y_OR=33, Y_XOR=25;  // อ่านกลับจากเอาต์พุตเกต

void setup(){
  pinMode(OUT_A, OUTPUT); pinMode(OUT_B, OUTPUT);
  pinMode(Y_AND, INPUT); pinMode(Y_OR, INPUT); pinMode(Y_XOR, INPUT);
  Serial.begin(115200);
}
void test(bool a,bool b){
  digitalWrite(OUT_A, a); digitalWrite(OUT_B, b); delay(5);
  bool ya=digitalRead(Y_AND), yo=digitalRead(Y_OR), yx=digitalRead(Y_XOR);
  Serial.printf("A=%d B=%d | AND=%d OR=%d XOR=%d (expect %d %d %d)\n",
    a,b,ya,yo,yx, a&&b, a||b, a^b);
}
void loop(){ test(0,0); delay(300); test(0,1); delay(300); test(1,0); delay(300); test(1,1); delay(1000); }

Lab 6 — เคาน์เตอร์ 7493 + ถอดรหัสด้วย CD4511 + MCU คุม/อ่าน

วงจร:

  • MCU ส่ง Clock ไป 7493 ที่ CLK_7493 และ Reset ที่ RST_7493
  • อ่าน Q0..Q3 ที่ BCD_Q* (ต่อ pull-down 10k ถ้าจำเป็น)
  • 7493 → CD4511 → LED 7 ดวง (ผ่าน R330Ω) แสดงตัวเลข 0–9
C++
#include <Arduino.h>
const uint8_t CLK_7493=18, RST_7493=19;
const uint8_t Q0=33, Q1=32, Q2=25, Q3=26;

void pulse(){ digitalWrite(CLK_7493, HIGH); delayMicroseconds(50); digitalWrite(CLK_7493, LOW); }
uint8_t readBCD(){ return (digitalRead(Q3)<<3)|(digitalRead(Q2)<<2)|(digitalRead(Q1)<<1)|(digitalRead(Q0)<<0); }

void setup(){
  pinMode(CLK_7493, OUTPUT); pinMode(RST_7493, OUTPUT);
  pinMode(Q0, INPUT); pinMode(Q1, INPUT); pinMode(Q2, INPUT); pinMode(Q3, INPUT);
  Serial.begin(115200);
  digitalWrite(RST_7493, HIGH); delay(2); digitalWrite(RST_7493, LOW);
}
void loop(){
  pulse(); uint8_t v=readBCD(); Serial.printf("BCD=%u\n", v); delay(300);
}

Lab 7 — Mini-Project: พัดลมอัจฉริยะ (รวม DHT11 + ปุ่ม + สวิตช์โหลด BJT)

วงจร: รวม Lab 2 + 4 (โหลดอาจเป็นพัดลมหรือ LED โหลด)
งานโค้ด: เหมือน Lab 4 แต่แทน LED_PIN ด้วย LOAD_PIN (บิตสั่งทรานซิสเตอร์) และเพิ่ม Serial menu ปรับค่าต่าง ๆ

C++
// ใช้สเก็ตช์ Lab 4 แล้วเปลี่ยน digitalWrite(LOAD_PIN, on?HIGH:LOW);

Lab 8 — Self-test & Logger

วงจร: เหมือน Lab 7
งานโค้ด: เพิ่มการ บันทึกค่า Temp/Setpoint/สถานะลง Serial ทุก 2 วินาที, ปุ่มค้าง 2 วินาที = reset setpoint

C++
// ต่อจาก Lab 4
unsigned long logTick=0, pressT=0;
void loop(){
  // ... ส่วนปุ่มปรับ setpoint เหมือนเดิม
  if(digitalRead(BTN_UP)==LOW && pressT==0) pressT=millis();
  if(digitalRead(BTN_UP)==HIGH && pressT && millis()-pressT>2000){ setC=30.0; pressT=0; }

  if (millis()-logTick>2000){ logTick=millis(); Serial.printf("LOG,%.1f,%.1f,%d\n", /*T*/, setC, /*fan*/0); }
  // (ย้ายตัวแปร T/fan จากบล็อกอ่าน DHT มา print จริง)
}

Lab 9 — Schematic → PCB 2-Layer (เวอร์ชัน TH หรือ SMD)

วงจรที่ต้องลง PCB: DHT11 + ปุ่ม + สวิตช์โหลด (BJT หรือ MOSFET) + จุดทดสอบ (3V3/5V/GND/DATA/LOAD) + คอนเน็กเตอร์
งานโค้ด: ใช้สเก็ตช์จาก Lab 7 เป็น “Firmware หลัก” สำหรับทดสอบบอร์ดหลังประกอบ
เป้า DRC: สัญญาณ ≥0.4 mm, กำลัง ≥0.8–1.0 mm, เคลียแรนซ์ ≥0.4 mm, GND plane 2 หน้า + via stitching


Lab 10 — Bring-up บอร์ดจริง + Checklist

วงจร: บอร์ดที่ประกอบจริง (uPCB590 หรือ PCB 2-Layer)
งานโค้ด: เพิ่ม Self-check ก่อนเริ่ม: เช็คปุ่ม, LED/โหลด, อ่าน DHT 3 ครั้งแล้วเฉลี่ย

C++
bool selfCheck(){
  // กระพริบโหลด 3 ครั้ง
  for(int i=0;i<3;i++){ digitalWrite(23, HIGH); delay(150); digitalWrite(23, LOW); delay(150); }
  // อ่าน DHT 3 ครั้งเก็บค่าสมเหตุสมผล
  // คืนค่า true ถ้าผ่าน
  return true;
}

หมายเหตุสำหรับ UNO

  • เปลี่ยนพินให้ตรง (A0 สำหรับ POT, D2 สำหรับ DHT — library DHT รองรับ), analogWrite() ใช้ได้ตรง ๆ บน UNO
  • ถ้าใช้ I²C OLED ในงานต่อยอด: UNO = A4/A5, ESP32 = GPIO21/22