Helper (วางบนสุดของทุกสเก็ตช์)
// ==== 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
#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 คร่อมถ้าเป็นคอยล์)
งานโค้ด: เปิดปิดโหลดเป็นจังหวะ และ/หรือกดปุ่มเพื่อสั่งทำงาน
#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
#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)
#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_* กลับ
#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
#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 ปรับค่าต่าง ๆ
// ใช้สเก็ตช์ Lab 4 แล้วเปลี่ยน digitalWrite(LOAD_PIN, on?HIGH:LOW);
Lab 8 — Self-test & Logger
วงจร: เหมือน Lab 7
งานโค้ด: เพิ่มการ บันทึกค่า Temp/Setpoint/สถานะลง Serial ทุก 2 วินาที, ปุ่มค้าง 2 วินาที = reset setpoint
// ต่อจาก 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 ครั้งแล้วเฉลี่ย
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
