Cách làm máy ấp trứng mini bằng thùng xốp và ESP32: giữ 37,5 °C bằng PI, giữ ẩm, đảo trứng tự động

Cách làm máy ấp trứng gà mini bằng thùng xốp, bóng đèn và ESP32: cấu tạo, lịch 21 ngày, giữ 37,5 °C bằng PI qua SSR, giữ ẩm theo ngày, đảo trứng bằng servo, đếm ngày qua mất điện, còi báo.

Máy ấp trứng mini tự làm chỉ cần một thùng xốp, một bóng đèn sưởi, một quạt nhỏ, khay nước và một mạch điều khiển giữ nhiệt độ thật ổn định. Bài này hướng dẫn cách làm máy ấp trứng gà khoảng 30 quả bằng thùng xốp và ESP32: cấu tạo, lịch nhiệt độ, độ ẩm 21 ngày, cách giữ 37,5 °C bằng bộ điều khiển PI qua SSR (kèm mô phỏng nhiệt để chọn hệ số), giữ ẩm theo ngày, đảo trứng tự động bằng servo, đếm ngày lưu trong flash để mất điện không mất ngày, và còi báo khi nhiệt độ lệch.

An toàn: bóng sưởi và SSR dùng điện 220 V; phần 220 V đặt ngoài thùng, trong hộp kín, có cầu chì. Thùng xốp gần bóng đèn có thể bị nóng chảy: giữ bóng cách thành thùng, dùng chụp bóng bằng kim loại.

1. Cấu tạo

Cấu tạo máy ấp trứng thùng xốp: bóng sưởi 60 W, quạt 12 V trộn gió, DHT22 ngang tầm trứng, khay trứng nghiêng bằng servo, khay nước và máy tạo ẩm, ESP32 với OLED điều khiển SSR bóng sưởi và relay máy tạo ẩm
Quạt trộn gió là thứ hay bị bỏ qua nhưng quan trọng nhất.
  • Thùng xốp 40–60 lít có nắp, khoét một ô kính nhỏ để nhìn và vài lỗ thông gió đường kính 1 cm (phôi cần không khí).
  • Sưởi: bóng sợi đốt 40–60 W hoặc tấm sưởi PTC, điều khiển bằng SSR. Không chiếu thẳng vào trứng.
  • Quạt 12 V chạy liên tục để nhiệt độ đều khắp thùng; không có quạt, chỗ gần bóng có thể nóng hơn chỗ xa 2–3 °C.
  • Cảm biến DHT22 đặt ngang tầm trứng, không gần bóng. Có thêm một nhiệt kế đối chứng đặt cạnh trứng để kiểm tra.
  • Khay trứng gắn trục, servo nghiêng ±45° để đảo; hoặc đảo tay 3–5 lần mỗi ngày nếu không làm servo.
  • Độ ẩm: khay nước rộng; muốn tự động thì thêm máy tạo ẩm siêu âm nhỏ qua relay.

2. Lịch nhiệt độ, độ ẩm 21 ngày

Lịch ấp trứng gà: ngày 1 tới 18 nhiệt độ 37,5 độ C độ ẩm 50 tới 55 phần trăm đảo trứng 2 giờ một lần, soi trứng ngày 7 và 14; ngày 19 tới 21 ẩm 65 tới 70 phần trăm ngừng đảo; nở xong để gà khô lông
Trứng vịt, trứng cút có lịch khác.

Nhiệt độ là yếu tố quan trọng nhất: giữ 37,5 °C, lệch quá 1 °C kéo dài làm tỉ lệ nở giảm rõ; quá 39–40 °C vài giờ có thể làm chết phôi. Từ ngày 19 ngừng đảo, tăng độ ẩm để màng vỏ không khô, gà mổ vỏ dễ hơn; hạn chế mở nắp.

3. Giữ nhiệt bằng PI qua SSR

Đồ thị mô phỏng nhiệt độ máy ấp trứng: từ 28 độ C lên 37,5 độ C sau khoảng 28 phút, cao nhất 37,67 độ C, ổn định trong khoảng 0,1 độ C; mở nắp ở giờ thứ 3 tụt 3 độ C rồi hồi phục; đường công suất sưởi
Mô phỏng một thùng xốp 30 trứng với bóng 60 W.

Bật tắt bóng đèn theo ngưỡng (dưới 37,3 bật, trên 37,7 tắt) cũng chạy được, nhưng nhiệt độ dao động lên xuống liên tục vì bóng còn nóng sau khi tắt. Chương trình dùng bộ PI: tính phần trăm công suất cần cấp từ độ lệch nhiệt độ và tổng độ lệch theo thời gian, rồi bật SSR đúng phần đó của mỗi chu kỳ 10 giây. SSR (relay bán dẫn) đóng cắt êm, chịu được hàng triệu lần; relay cơ đóng cắt mỗi 10 giây sẽ mòn tiếp điểm nhanh.

  • Kp = 0,5: lệch 1 °C thì thêm 50 % công suất. Ki = 0,001: phần tích phân bù dần độ lệch còn lại.
  • Phần tích phân chỉ cộng khi nhiệt độ đã gần mức đặt (lệch dưới 1,5 °C) và công suất chưa bão hòa, để lúc khởi động từ nhiệt độ phòng nhiệt độ không vọt quá nhiều.
  • Mất cảm biến 3 lần liên tiếp thì tắt sưởi và kêu còi: thà để trứng nguội một lúc còn hơn nấu chín.

Hệ số trên chọn bằng mô phỏng nhiệt dưới đây. Thùng thật khác (thùng to, nhiều trứng, bóng khác công suất): đo xem từ nhiệt độ phòng mất bao lâu để nóng lên khi bật bóng liên tục, ước lượng hai thông số thùng rồi chạy lại script để kiểm tra:

# PYWORLD.VN - Mô phỏng nhiệt máy ấp trứng thùng xốp với bộ điều khiển PI giống chương trình ESP32: Kp 0,5, Ki 0,001, cửa sổ SSR 10 giây
# PYWORLD.VN - Mô hình một khối nhiệt: C dT/dt = P_sưởi − UA (T − T_phòng); cảm biến trễ bậc nhất 30 giây; mở nắp ở giờ thứ 3 làm tụt 3 °C
# PYWORLD.VN - Chạy: python mo_phong_nhiet.py [C J/K] [UA W/K] [P W]      (mặc định 8000 1.2 60: thùng xốp 50 L, 30 trứng, bóng 60 W)
"""Số liệu thùng, trứng, bóng đèn là giả định để chọn Kp, Ki; thùng thật nên đo thời gian nóng lên rồi chỉnh lại."""
import sys

DAT, KP, KI, VUNG, CUA_SO, CHU_KY = 37.5, 0.50, 0.001, 1.5, 10.0, 2.5


def mo_phong(c=8000.0, ua=1.2, p_max=60.0, t_phong=28.0, gio=5.0, dt=0.2, mo_nap_gio=3.0):
    t_thung = t_cam_bien = t_phong
    tich_phan, cong_suat, ds = 0.0, 0.0, []
    lan_cuoi = 0.0
    k = 0
    while k * dt <= gio * 3600:
        t = k * dt
        if abs(t - mo_nap_gio * 3600) < dt / 2:
            t_thung -= 3.0                                   # mở nắp xem trứng
        if t - lan_cuoi >= CHU_KY - 1e-9:                    # như loop(): đọc cảm biến, tính PI mỗi 2,5 s
            giay, lan_cuoi = t - lan_cuoi, t
            sai = DAT - t_cam_bien
            thu = KP * sai + KI * (tich_phan + sai * giay)
            if 0 < thu < 1 and abs(sai) < VUNG:
                tich_phan += sai * giay
            cong_suat = min(1.0, max(0.0, KP * sai + KI * tich_phan))
        bat = (t % CUA_SO) < cong_suat * CUA_SO
        t_thung += ((p_max if bat else 0.0) - ua * (t_thung - t_phong)) * dt / c
        t_cam_bien += (t_thung - t_cam_bien) * dt / 30.0      # cảm biến trễ khoảng 30 giây
        if k % 150 == 0:                                     # lưu mỗi 30 giây
            ds.append((t, t_thung, cong_suat))
        k += 1
    return ds


if __name__ == "__main__":
    c, ua, p = (float(sys.argv[1]), float(sys.argv[2]), float(sys.argv[3])) if len(sys.argv) > 3 else (8000.0, 1.2, 60.0)
    ds = mo_phong(c, ua, p)
    toi = next((t for t, x, _ in ds if x >= DAT - 0.1), None)
    on_dinh = [x for t, x, _ in ds if 2 * 3600 <= t < 3 * 3600]
    sau_nap = [x for t, x, _ in ds if t >= 3 * 3600]
    hoi_phuc = next((t for t, x, _ in ds if t > 3 * 3600 + 60 and x >= DAT - 0.2), None)
    tb = sum(cs for t, _, cs in ds if 2 * 3600 <= t < 3 * 3600) / len(on_dinh)
    print(f"Thung C {c:g} J/K, UA {ua:g} W/K, bong {p:g} W")
    print(f"Toi {DAT - 0.1:.1f} C sau {toi / 60:.0f} phut; cao nhat {max(x for _, x, _ in ds):.2f} C")
    print(f"Gio 2-3: {min(on_dinh):.2f} .. {max(on_dinh):.2f} C, cong suat trung binh {tb * 100:.0f} %")
    print(f"Mo nap gio 3: thap nhat {min(sau_nap):.2f} C, hoi phuc ve {DAT - 0.2:.1f} C sau {(hoi_phuc - 3 * 3600) / 60:.0f} phut")

Về PID và cách chỉnh hệ số có thêm ở bài giữ tốc độ động cơ ổn định bằng PID.

4. Chương trình ESP32

Bảng nối dây máy ấp trứng: DHT22 GPIO27, SSR sưởi GPIO26, relay tạo ẩm GPIO33 kích mức thấp, servo GPIO13, còi GPIO25, nút mẻ mới GPIO4, OLED D21 D22
ESP32 DevKit V1.

Chương trình đọc DHT22 không cần thư viện (cách đọc giải thích ở bài DHT11, DHT22 với ESP32 không cần thư viện), dùng thêm thư viện Adafruit SSD1306 cho màn hình.

// PYWORLD.VN - Máy ấp trứng gà tự làm với ESP32: giữ 37,5 °C bằng PI qua SSR, giữ ẩm theo ngày, đảo trứng 2 giờ một lần bằng servo
// PYWORLD.VN - Ngày 1-18: ẩm 50-55 %, đảo trứng; ngày 19-21: ẩm 65-70 %, ngừng đảo; đếm ngày lưu flash nên mất điện không mất ngày
// PYWORLD.VN - DHT22 GPIO27 (kéo lên 10 kΩ); SSR sưởi GPIO26; relay tạo ẩm GPIO33 (kích mức thấp); servo GPIO13; còi GPIO25; nút GPIO4; OLED D21, D22

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

const int CHAN_DHT = 27, CHAN_SSR = 26, CHAN_AM = 33, CHAN_SERVO = 13, CHAN_COI = 25, CHAN_NUT = 4;
const float NHIET_DAT = 37.5f;                     // °C cho trứng gà
const float KP = 0.50f, KI = 0.001f;               // phần công suất trên 1 °C; trên 1 °C·giây
const float VUNG_TICH_PHAN = 1.5f;                 // °C: chỉ tích phân khi gần nhiệt độ đặt, giảm vọt nhiệt lúc khởi động
const uint32_t CUA_SO_MS = 10000;                  // SSR bật một phần của mỗi 10 giây
const uint32_t DAO_MS = 2UL * 3600 * 1000;         // đảo trứng mỗi 2 giờ
const int NGAY_KHOA = 19, NGAY_NO = 21;            // từ ngày 19 ngừng đảo, tăng ẩm

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
Preferences nvs;
portMUX_TYPE khoaNgat = portMUX_INITIALIZER_UNLOCKED;
float nhietDo = NAN, doAm = NAN, tichPhan = 0, congSuat = 0;
uint32_t phutDaAp = 0, lucPhut = 0, lucDoc = 0, lucCuaSo = 0, lucDao = 0, lucNhanNut = 0;
int loiDoc = 0, gocDao = 45;
bool amBat = false;

static int32_t choHetMuc(int muc, uint32_t toiDa) {
  uint32_t batDau = micros();
  while (digitalRead(CHAN_DHT) == muc)
    if (micros() - batDau > toiDa) return -1;
  return (int32_t)(micros() - batDau);
}

bool docDht22() {                                   // như bài đọc DHT22 không cần thư viện
  uint8_t du[5] = {0}, cao[40];
  pinMode(CHAN_DHT, OUTPUT);
  digitalWrite(CHAN_DHT, LOW);
  delay(2);
  pinMode(CHAN_DHT, INPUT_PULLUP);
  bool ok = true;
  portENTER_CRITICAL(&khoaNgat);
  if (choHetMuc(HIGH, 100) < 0 || choHetMuc(LOW, 100) < 0 || choHetMuc(HIGH, 100) < 0) ok = false;
  for (int i = 0; i < 40 && ok; i++) {
    int32_t c = (choHetMuc(LOW, 80) < 0) ? -1 : choHetMuc(HIGH, 100);
    if (c < 0) ok = false; else cao[i] = c;
  }
  portEXIT_CRITICAL(&khoaNgat);
  if (!ok) return false;
  for (int i = 0; i < 40; i++) du[i / 8] = (du[i / 8] << 1) | (cao[i] > 48 ? 1 : 0);
  if (((du[0] + du[1] + du[2] + du[3]) & 0xFF) != du[4]) return false;
  doAm = ((du[0] << 8) | du[1]) * 0.1f;
  nhietDo = (((du[2] & 0x7F) << 8) | du[3]) * 0.1f * ((du[2] & 0x80) ? -1 : 1);
  return true;
}

void datServo(int goc) {                            // 0,5-2,5 ms trong chu kỳ 20 ms, độ phân giải 14 bit
  uint32_t us = 500 + (uint32_t)goc * 2000 / 180;
  ledcWrite(CHAN_SERVO, us * 16383 / 20000);
}

void datAm(bool bat) {
  amBat = bat;
  digitalWrite(CHAN_AM, bat ? LOW : HIGH);          // relay kích mức thấp
}

int ngayHienTai() { return phutDaAp / 1440 + 1; }

void tinhPI(float giay) {
  float sai = NHIET_DAT - nhietDo;
  float thu = KP * sai + KI * (tichPhan + sai * giay);
  if (thu > 0 && thu < 1 && fabsf(sai) < VUNG_TICH_PHAN) tichPhan += sai * giay;   // chống tích phân quá mức
  congSuat = constrain(KP * sai + KI * tichPhan, 0.0f, 1.0f);
}

void hienThi() {
  int ngay = ngayHienTai();
  bool dao = ngay < NGAY_KHOA;
  uint32_t conLai = dao ? (DAO_MS - (millis() - lucDao)) / 60000 : 0;
  oled.clearDisplay();
  oled.setCursor(0, 0);
  oled.printf("Ngay %d/%d  ", ngay, NGAY_NO);
  if (dao) oled.printf("dao %lu:%02lu", (unsigned long)(conLai / 60), (unsigned long)(conLai % 60)); else oled.print("khoa trung");
  oled.setCursor(0, 16);
  oled.printf("T %.1f C (dat %.1f)", nhietDo, NHIET_DAT);
  oled.setCursor(0, 32);
  oled.printf("Am %.0f %% (dat %s)", doAm, ngay < NGAY_KHOA ? "50-55" : "65-70");
  oled.setCursor(0, 48);
  oled.printf("Suoi %3.0f%%  Am %s", congSuat * 100, amBat ? "BAT" : "TAT");
  oled.display();
}

void setup() {
  Serial.begin(115200);
  pinMode(CHAN_AM, INPUT);                          // gói esp32 3.x: đặt mức tắt trước khi chuyển sang OUTPUT
  digitalWrite(CHAN_AM, HIGH);
  pinMode(CHAN_AM, OUTPUT);
  pinMode(CHAN_SSR, OUTPUT);
  digitalWrite(CHAN_SSR, LOW);
  pinMode(CHAN_COI, OUTPUT);
  pinMode(CHAN_NUT, INPUT_PULLUP);
  ledcAttach(CHAN_SERVO, 50, 14);
  datServo(gocDao);
  Wire.begin(21, 22);
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextColor(SSD1306_WHITE);
  nvs.begin("aptrung", false);
  phutDaAp = nvs.getUInt("phut", 0);               // tiếp tục đếm sau khi mất điện
  lucPhut = lucCuaSo = lucDao = millis();
  Serial.printf("Bat dau o ngay %d (%u phut)\n", ngayHienTai(), (unsigned)phutDaAp);
}

void loop() {
  uint32_t bayGio = millis();
  // Giữ nút 3 giây: bắt đầu mẻ trứng mới (đếm lại từ ngày 1)
  if (digitalRead(CHAN_NUT) == LOW) {
    if (lucNhanNut == 0) lucNhanNut = bayGio;
    if (bayGio - lucNhanNut >= 3000) {
      phutDaAp = 0;
      nvs.putUInt("phut", 0);
      lucNhanNut = 0;
      Serial.println("Me trung moi: ngay 1");
      while (digitalRead(CHAN_NUT) == LOW) delay(10);
    }
  } else {
    lucNhanNut = 0;
  }
  if (bayGio - lucPhut >= 60000) {                  // đếm phút; ghi flash mỗi 10 phút
    lucPhut += 60000;
    if (++phutDaAp % 10 == 0) nvs.putUInt("phut", phutDaAp);
  }
  if (bayGio - lucDoc >= 2500) {                    // DHT22 cần ít nhất 2 giây giữa hai lần đọc
    float giay = (bayGio - lucDoc) / 1000.0f;
    lucDoc = bayGio;
    if (docDht22()) {
      loiDoc = 0;
      tinhPI(giay);
      int ngay = ngayHienTai();
      float amDuoi = ngay < NGAY_KHOA ? 50 : 65, amTren = ngay < NGAY_KHOA ? 55 : 70;
      if (doAm < amDuoi) datAm(true);
      else if (doAm > amTren) datAm(false);
      Serial.printf("Ngay %d | T %.1f C | am %.0f %% | suoi %.0f %% | tao am %s\n", ngay, nhietDo, doAm, congSuat * 100, amBat ? "BAT" : "TAT");
    } else if (++loiDoc >= 3) {
      congSuat = 0;                                 // mất cảm biến: tắt sưởi để không nấu chín trứng
      Serial.println("Loi doc DHT22 3 lan lien tiep: tat suoi");
    }
    hienThi();
  }
  // Sưởi theo cửa sổ thời gian: bật SSR trong congSuat × 10 giây đầu mỗi cửa sổ
  if (bayGio - lucCuaSo >= CUA_SO_MS) lucCuaSo += CUA_SO_MS;
  digitalWrite(CHAN_SSR, (bayGio - lucCuaSo) < congSuat * CUA_SO_MS ? HIGH : LOW);
  // Đảo trứng tới ngày 18
  if (ngayHienTai() < NGAY_KHOA && bayGio - lucDao >= DAO_MS) {
    lucDao = bayGio;
    gocDao = (gocDao == 45) ? 135 : 45;
    datServo(gocDao);
    Serial.printf("Dao trung sang %d do\n", gocDao);
  }
  bool baoDong = loiDoc >= 3 || (!isnan(nhietDo) && (nhietDo < 36.5f || nhietDo > 38.5f) && phutDaAp > 60);
  digitalWrite(CHAN_COI, baoDong && (bayGio / 500) % 2 ? HIGH : LOW);
}
  • Đếm ngày: mỗi phút cộng một, ghi vào flash mỗi 10 phút (Preferences). Mất điện rồi có điện lại, máy tiếp tục từ ngày đang ấp, chỉ có thể lùi tối đa 10 phút.
  • Mẻ mới: giữ nút 3 giây để đếm lại từ ngày 1.
  • Độ ẩm: bật máy tạo ẩm khi dưới mức thấp, tắt khi trên mức cao của giai đoạn đó.
  • Đảo trứng: servo đổi giữa 45° và 135° mỗi 2 giờ, ngừng từ ngày 19.
  • Còi kêu khi nhiệt độ ngoài 36,5–38,5 °C (sau giờ đầu khởi động) hoặc mất cảm biến.
  • Relay tạo ẩm kích mức thấp được đặt về mức tắt trước khi chuyển chân sang ngõ ra, để relay không đóng lúc ESP32 khởi động.
Màn hình OLED máy ấp trứng hiện ngày 5 trên 21, thời gian tới lần đảo 1 giờ 12 phút, nhiệt độ 37,5 độ C, độ ẩm 53 phần trăm, công suất sưởi 18 phần trăm, máy tạo ẩm tắt
Số đo giả định.

Trước khi cho trứng vào, chạy máy không tải 1–2 ngày, so số trên màn hình với nhiệt kế đối chứng đặt ở nhiều chỗ trong thùng. Lệch thì dời cảm biến hoặc thêm hệ số bù.

5. Lỗi hay gặp

Hiện tượngNguyên nhânCách xử lý
Nhiệt độ không lên tới 37,5 °CBóng yếu so với thùng, phòng lạnh, lỗ thông gió quá toBóng lớn hơn, bọc thêm xốp, thu nhỏ lỗ thông gió
Nhiệt độ dao động ±0,5 °C trở lênKhông có quạt, cảm biến gần bóngLắp quạt trộn gió; dời cảm biến ngang tầm trứng
Màn hình đúng nhưng trứng không nởCảm biến đọc lệch so với nhiệt độ thật ở trứngSo với nhiệt kế đối chứng đã kiểm tra
Độ ẩm tăng mãi không giảmThùng kín, máy tạo ẩm quá mạnhThêm lỗ thông gió nhỏ; giảm mặt nước
Servo rung, kêu khi đứng yênNguồn yếu, chung nguồn với ESP32Nguồn 5 V riêng cho servo, GND chung
Báo lỗi DHT22 liên tụcDây dài, thiếu điện trở kéo lên, hơi nước đọngDây ngắn, điện trở 10 kΩ; đặt cảm biến tránh chỗ đọng nước

Sản phẩm dùng trong bài: ESP32 DevKit V1 30 chân, module relay, màn hình OLED 0.96 inch.

Xem thêm: nhà kính mini với ESP32: đo nhiệt độ, độ ẩm, tự bật quạt, đèn.

Bài cùng cụm chủ đề: chọn relay hay SSR; an toàn khi tự làm mạch 220 V.


Tin tức liên quan

Ghi dữ liệu ESP32 lên Google Sheets bằng Apps Script: điện áp pin, Wi-Fi, không cần máy chủ riêng
Ghi dữ liệu ESP32 lên Google Sheets bằng Apps Script: điện áp pin, Wi-Fi, không cần máy chủ riêng

Tạo bảng tính, triển khai Apps Script thành web app, đo pin 18650 qua cầu phân áp và chương trình ESP32 gửi JSON lên Google Sheets mỗi phút, kèm bảng xử lý lỗi.

Vẽ đồ thị dữ liệu ESP32 trên ThingSpeak: theo dõi pin 18650, ngủ sâu và ước tính thời gian chạy pin
Vẽ đồ thị dữ liệu ESP32 trên ThingSpeak: theo dõi pin 18650, ngủ sâu và ước tính thời gian chạy pin

ESP32 chạy pin 18650 thức dậy mỗi 10 phút, đo điện áp pin, gửi lên ThingSpeak rồi ngủ sâu; cách tạo kênh, ước tính thời gian chạy pin và giảm dòng lúc ngủ.

Cách nạp code cho ESP-01 và ESP-01S bằng USB-TTL, đế nạp: sơ đồ chân và lỗi thường gặp
Cách nạp code cho ESP-01 và ESP-01S bằng USB-TTL, đế nạp: sơ đồ chân và lỗi thường gặp

Cách nạp code cho ESP-01, ESP-01S: sơ đồ 8 chân, khác nhau giữa hai bản, nối USB-TTL đúng cách, cấp nguồn 3,3 V đủ dòng, chế độ nạp GPIO0, cài Arduino IDE, chương trình đầu tiên và lỗi hay gặp.

Cài ESP32 vào Arduino IDE 2: thêm bo mạch, chọn ESP32 Dev Module và nạp chương trình đầu tiên
Cài ESP32 vào Arduino IDE 2: thêm bo mạch, chọn ESP32 Dev Module và nạp chương trình đầu tiên

Cài gói esp32 của Espressif vào Arduino IDE 2, chọn bo DOIT ESP32 DEVKIT V1 hoặc ESP32 Dev Module, chọn cổng COM, nạp chương trình nháy LED, in thông tin chip và sửa lỗi lần nạp đầu.

Hướng dẫn ESP32 làm web server điều khiển relay 4 kênh qua WiFi
Hướng dẫn ESP32 làm web server điều khiển relay 4 kênh qua WiFi

Hướng dẫn dùng ESP32 DevKit V1 làm web server trong mạng WiFi nội bộ, mở trang trên điện thoại để bật, tắt module relay 4 kênh; có sơ đồ nối dây, code Arduino IDE và lưu ý an toàn.

ESP-NOW nhiều node với ESP32: nhiều mạch gửi về một trạm thu, hiển thị trên OLED
ESP-NOW nhiều node với ESP32: nhiều mạch gửi về một trạm thu, hiển thị trên OLED

Hướng dẫn dựng mô hình ESP-NOW nhiều node: tối đa bốn ESP32 gửi số đo về một trạm thu, trạm thu hiện điện áp, RSSI và tình trạng từng node trên màn hình OLED 0.96 inch.

ESP32 với Firebase Realtime Database qua REST: đăng nhập ẩn danh, làm mới token, điều khiển relay
ESP32 với Firebase Realtime Database qua REST: đăng nhập ẩn danh, làm mới token, điều khiển relay

ESP32 dùng Firebase Realtime Database không cần thư viện Firebase: đăng nhập ẩn danh, tự làm mới token, đọc lệnh relay, ghi trạng thái và lịch sử, Rules theo uid.

Giữ tốc độ động cơ DC ổn định bằng PID trên ESP32: encoder, chỉnh Kp Ki Kd, Serial Plotter
Giữ tốc độ động cơ DC ổn định bằng PID trên ESP32: encoder, chỉnh Kp Ki Kd, Serial Plotter

Hướng dẫn điều khiển vòng kín tốc độ động cơ DC bằng PID trên ESP32: đo tốc độ bằng encoder và PCNT, chu kỳ 20 ms, chống tích phân bão hòa, chỉnh Kp Ki Kd và thí nghiệm STEM.


Bình luận
Đã thêm vào giỏ hàng