Đo mực nước bồn và tự bật tắt máy bơm bằng ESP32: cảm biến siêu âm, chống chạy khô, báo lỗi

Làm bồn nước tự bơm bằng ESP32: so sánh cách đo mực nước trong bồn, cảm biến siêu âm, bật 30 % tắt 90 %, chống bơm chạy khô, giới hạn thời gian bơm, báo lỗi; code và mô phỏng 24 giờ.

Bài này làm một hệ thống đo mực nước bồn và tự bật tắt máy bơm bằng ESP32: cảm biến siêu âm chống nước gắn trên nắp bồn đo mực nước liên tục, ESP32 bật bơm khi bồn xuống 30 % và tắt khi lên 90 %, kèm các lớp bảo vệ mà rơ le phao cơ không có: không bơm khi bể ngầm cạn, dừng khi bơm quá lâu, dừng khi bơm chạy mà nước không lên, dừng khi mất tín hiệu cảm biến. Bài có so sánh các cách đo mực nước trong bồn (phao, que đo điện cực, siêu âm, áp suất), chương trình ESP32, bảng nối dây và mô phỏng 24 giờ để chọn đúng các con số cài đặt.

1. Hệ thống gồm những gì

Sơ đồ khối hệ thống bơm nước tự động: bể ngầm có phao, máy bơm 220 V đẩy nước lên bồn trên mái có cảm biến siêu âm A02YYUW trên nắp; ESP32 điều khiển relay, relay đóng cuộn contactor có aptomat cấp điện cho bơm
Relay chỉ đóng cuộn contactor; contactor mới đóng điện cho bơm.
  • Cảm biến mực bồn trên: siêu âm chống nước A02YYUW (hoặc JSN-SR04T) gắn trên nắp bồn, đo khoảng cách tới mặt nước.
  • Phao bể ngầm: công tắc phao báo bể ngầm hoặc giếng còn nước, để bơm không chạy khô.
  • ESP32: đọc cảm biến, quyết định bật tắt, báo lỗi.
  • Relay và contactor: module relay đóng cuộn hút của contactor (khởi động từ); tiếp điểm contactor đóng điện cho bơm. Bơm từ khoảng 0,5 HP trở lên có dòng khởi động lớn, nên không cho tiếp điểm relay nhỏ đóng trực tiếp. Phía trước có aptomat và chống giật theo đúng quy định điện dân dụng.

2. Các cách đo mực nước trong bồn

Bảng so sánh cách đo mực nước trong bồn: phao điện, phao từ nhiều mức, cảm biến siêu âm chống nước, cảm biến áp suất thủy tĩnh 4-20 mA, que đo điện cực; biết được gì, ưu điểm, nhược điểm
Bồn nước sinh hoạt: siêu âm cho bồn trên, phao cho bể ngầm là cách gọn nhất.

Rơ le phao cơ (phao điện) bán sẵn chỉ biết đầy hoặc cạn và tự đóng ngắt bơm, rất rẻ. Dùng ESP32 với cảm biến đo liên tục thì biết bồn còn bao nhiêu phần trăm, xem từ xa được, và thêm được các bảo vệ ở mục 4. Que đo mực nước kiểu điện cực rẻ nhưng bị ăn mòn, đóng cặn sau vài tháng. Cảm biến áp suất thủy tĩnh đặt dưới đáy bồn chính xác nhất, hợp bồn kín hoặc bồn có nhiều hơi nước. Cách đọc cảm biến siêu âm chống nước, khung dữ liệu UART và cách lắp đầu dò trên nắp bồn có ở bài cùng cụm về JSN-SR04T, A02YYUW; nguyên lý các loại cảm biến mức có ở bài cảm biến mức: phao, điện cực, thủy tĩnh, siêu âm.

3. Nối dây

Bảng nối dây: cảm biến A02YYUW VCC 3V3, TX vào GPIO16; module relay VCC 5V, IN GPIO26 kích mức thấp đóng cuộn contactor; phao bể ngầm GPIO27 và GND; nút nhấn GPIO4 và GND
Phần điện 220 V do thợ điện đấu; ESP32 chỉ nối phía điều khiển.

Chuẩn bị ESP32 DevKit V1 và module relay 1 kênh 5 V. Cách chọn relay kích mức thấp hay cao có ở bài module relay 1, 2, 4 kênh. Nếu contactor đóng làm ESP32 khởi động lại, xem bài đóng relay làm ESP32 bị reset: thường do nguồn chung và nhiễu từ cuộn hút.

4. Logic điều khiển và các lớp bảo vệ

  • Khoảng trễ: bật khi bồn xuống 30 %, tắt khi lên 90 %. Nếu bật và tắt cùng một ngưỡng, sóng mặt nước làm bơm đóng ngắt liên tục, hỏng contactor và động cơ.
  • Lọc trung vị 5 lần đo: loại số đo sai do giọt nước đọng trên đầu dò.
  • Nghỉ tối thiểu 1 phút giữa hai lần chạy.
  • Bể ngầm cạn (phao hở): không bật bơm; nếu đang bơm thì dừng và báo lỗi.
  • Bơm quá lâu: một lần bơm vượt giới hạn thì dừng, báo lỗi. Thường do ống vỡ, van mở, bồn rò.
  • Không lên nước: bơm chạy 5 phút mà mực không tăng 2 cm thì dừng. Đây là lớp bảo vệ khi phao bể ngầm hỏng, bơm mất mồi, đường ống tắc.
  • Mất tín hiệu cảm biến quá 10 giây: dừng bơm, báo lỗi. Không đoán mực nước khi không đo được.
  • Lỗi giữ nguyên cho đến khi người dùng giữ nút 3 giây để xóa, để có người kiểm tra trước khi bơm chạy lại.

5. Chương trình ESP32

// PYWORLD.VN - Tự bơm nước lên bồn bằng ESP32: đo mực nước bằng cảm biến siêu âm A02YYUW, bật dưới 30 %, tắt trên 90 %
// PYWORLD.VN - Bảo vệ: phao bể ngầm cạn thì không bơm, bơm quá 40 phút hoặc 5 phút không lên nước thì dừng và báo lỗi, cảm biến mất tín hiệu thì dừng
// PYWORLD.VN - A02YYUW TX -> GPIO16; relay (kích mức thấp, điều khiển cuộn contactor) IN -> GPIO26; phao bể ngầm GPIO27; nút GPIO4

const int CHAN_RX2 = 16, CHAN_TX2 = 17;
const int CHAN_RELAY = 26, CHAN_PHAO_NGUON = 27, CHAN_NUT = 4;
const bool RELAY_KICH_MUC_THAP = true;
const bool PHAO_CO_NUOC_MUC = LOW;              // phao đóng (nối GND) khi bể ngầm còn nước

// Kích thước bồn: đo thực tế rồi sửa
const float KHOANG_CACH_TOI_DAY_CM = 150.0f;    // mặt đầu dò tới đáy bồn
const float MUC_DAY_CM = 125.0f;                // chiều cao nước khi đầy (chừa vùng mù trên cùng)
const float BAT_DUOI = 30, TAT_TREN = 90;       // % : khoảng trễ để bơm không bật tắt liên tục

// Giới hạn một lần bơm ≈ 2 × (thể tích × 60 %) / lưu lượng bơm; bồn 1000 L, bơm 30 L/phút: 2 × 600 / 30 = 40 phút
const uint32_t BOM_TOI_DA_MS = 40UL * 60 * 1000;
const uint32_t KIEM_TRA_LEN_MS = 5UL * 60 * 1000;    // sau 5 phút phải lên ít nhất 2 cm
const float LEN_TOI_THIEU_CM = 2.0f;
const uint32_t NGHI_TOI_THIEU_MS = 60UL * 1000;      // nghỉ ít nhất 1 phút giữa hai lần chạy
const uint32_t MAT_CAM_BIEN_MS = 10000;

enum TrangThai { NGHI, BOM, LOI };
TrangThai trangThai = NGHI;
const char *lyDoLoi = "";
float mucCm = NAN, mucLucBatDau = 0;
uint32_t lanDocDuoc = 0, lucBat = 0, lucTat = 0;
bool bomTay = false;

void datBom(bool bat) {
  digitalWrite(CHAN_RELAY, (bat == RELAY_KICH_MUC_THAP) ? LOW : HIGH);
  if (bat) {
    lucBat = millis();
    mucLucBatDau = mucCm;
  } else {
    lucTat = millis();
  }
}

// Gói A02YYUW: 0xFF, cao, thấp, tổng (byte thấp của 0xFF + cao + thấp); khoảng cách mm
bool docA02(uint16_t &mm) {
  static uint8_t goi[4], n = 0;
  while (Serial2.available()) {
    uint8_t b = Serial2.read();
    if (n == 0 && b != 0xFF) continue;
    goi[n++] = b;
    if (n == 4) {
      n = 0;
      if (((goi[0] + goi[1] + goi[2]) & 0xFF) == goi[3]) {
        mm = (goi[1] << 8) | goi[2];
        return true;
      }
    }
  }
  return false;
}

float trungVi5(float moi) {
  static float vung[5];
  static int dem = 0;
  vung[dem % 5] = moi;
  dem++;
  int n = dem < 5 ? dem : 5;
  float s[5];
  memcpy(s, vung, sizeof(s));
  for (int i = 1; i < n; i++)
    for (int j = i; j > 0 && s[j - 1] > s[j]; j--) {
      float t = s[j];
      s[j] = s[j - 1];
      s[j - 1] = t;
    }
  return s[n / 2];
}

void baoLoi(const char *lyDo) {
  datBom(false);
  trangThai = LOI;
  lyDoLoi = lyDo;
  Serial.printf("LOI: %s -> giu nut 3 giay de xoa\n", lyDo);
}

void docNut() {
  static bool truoc = HIGH;
  static uint32_t lucNhan = 0;
  bool nay = digitalRead(CHAN_NUT);
  if (nay == LOW && truoc == HIGH) lucNhan = millis();
  if (nay == HIGH && truoc == LOW && millis() - lucNhan > 30) {
    if (millis() - lucNhan >= 3000) {
      if (trangThai == LOI) {
        trangThai = NGHI;
        Serial.println("Da xoa loi");
      }
    } else if (trangThai == NGHI) {
      bomTay = true;                         // bấm ngắn: bơm tay tới khi đầy
    } else if (trangThai == BOM) {
      datBom(false);                         // bấm ngắn khi đang bơm: dừng
      trangThai = NGHI;
      bomTay = false;
    }
  }
  truoc = nay;
}

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, CHAN_RX2, CHAN_TX2);
  pinMode(CHAN_RELAY, INPUT);                // gói esp32 3.x bỏ qua digitalWrite trước pinMode:
  digitalWrite(CHAN_RELAY, RELAY_KICH_MUC_THAP ? HIGH : LOW);   // ghi mức tắt khi chân còn là ngõ vào
  pinMode(CHAN_RELAY, OUTPUT);               // rồi mới chuyển thành ngõ ra, relay không đóng lúc khởi động
  pinMode(CHAN_PHAO_NGUON, INPUT_PULLUP);
  pinMode(CHAN_NUT, INPUT_PULLUP);
  lucTat = millis() - NGHI_TOI_THIEU_MS;
}

void loop() {
  uint16_t mm;
  if (docA02(mm) && mm > 0) {
    float muc = KHOANG_CACH_TOI_DAY_CM - trungVi5(mm / 10.0f);
    mucCm = constrain(muc, 0.0f, KHOANG_CACH_TOI_DAY_CM);
    lanDocDuoc = millis();
  }
  docNut();
  float phanTram = 100.0f * mucCm / MUC_DAY_CM;
  bool nguonCoNuoc = digitalRead(CHAN_PHAO_NGUON) == PHAO_CO_NUOC_MUC;

  if (trangThai != LOI && millis() - lanDocDuoc > MAT_CAM_BIEN_MS) baoLoi("mat tin hieu cam bien");
  if (trangThai == NGHI) {
    bool canBom = bomTay || phanTram <= BAT_DUOI;
    if (canBom && !isnan(mucCm) && phanTram < TAT_TREN && nguonCoNuoc && millis() - lucTat >= NGHI_TOI_THIEU_MS) {
      datBom(true);
      trangThai = BOM;
    }
  } else if (trangThai == BOM) {
    uint32_t daChay = millis() - lucBat;
    if (phanTram >= TAT_TREN) {
      datBom(false);
      trangThai = NGHI;
      bomTay = false;
    } else if (!nguonCoNuoc) {
      baoLoi("be ngam can nuoc");
    } else if (daChay > BOM_TOI_DA_MS) {
      baoLoi("bom qua lau (ro ri, ong vo?)");
    } else if (daChay > KIEM_TRA_LEN_MS && mucCm - mucLucBatDau < LEN_TOI_THIEU_CM) {
      baoLoi("bom chay nhung khong len nuoc");
    }
  }

  static uint32_t lanIn = 0;
  if (millis() - lanIn >= 2000) {
    lanIn = millis();
    const char *ten[] = {"nghi", "bom", "loi"};
    Serial.printf("Muc %.1f cm (%.0f %%), be ngam %s, %s%s%s\n", mucCm, phanTram, nguonCoNuoc ? "co nuoc" : "CAN",
                  ten[trangThai], trangThai == LOI ? ": " : "", lyDoLoi);
  }
}

Sửa KHOANG_CACH_TOI_DAY_CM (từ mặt đầu dò tới đáy bồn) và MUC_DAY_CM (chiều cao nước khi đầy, chừa vùng mù khoảng 3–25 cm tùy cảm biến) theo bồn thật. Trong setup(), chân relay được đặt mức tắt khi còn là ngõ vào rồi mới chuyển thành ngõ ra: với gói esp32 3.x, lệnh digitalWrite() gọi trước pinMode() bị bỏ qua, relay kích mức thấp sẽ đóng ngay khi khởi động nếu viết theo thứ tự ngược lại. Serial Monitor (115200) in mỗi 2 giây dòng dạng Muc 62.0 cm (50 %), be ngam co nuoc, nghi.

6. Mô phỏng 24 giờ để chọn con số cài đặt

Script dưới đây chạy đúng logic trên với một bồn 1000 L, bơm 30 L/phút và lượng dùng thay đổi theo giờ (sáng 6–8 giờ và tối 18–21 giờ dùng nhiều).

# PYWORLD.VN - Mô phỏng 24 giờ bồn nước tự bơm theo đúng logic của chương trình ESP32: bật dưới 30 %, tắt trên 90 %
# PYWORLD.VN - Có giờ cao điểm dùng nước, nghỉ tối thiểu 1 phút, giới hạn một lần bơm, lỗi khi 5 phút không lên 2 cm (bể ngầm cạn lúc 20 giờ)
# PYWORLD.VN - Chạy: python mo_phong_bon.py [--the-tich 1000] [--luu-luong-bom 30] [--bom-toi-da 40]
"""Bồn trụ đứng: mực nước tăng khi bơm, giảm theo lượng dùng; in các lần bật, tắt và lỗi."""
from __future__ import annotations

import argparse

MUC_DAY_CM, BAT_DUOI, TAT_TREN = 125.0, 30, 90
KIEM_TRA_LEN, LEN_TOI_THIEU, NGHI_TOI_THIEU = 5 * 60, 2.0, 60


def dung_nuoc(giay: int) -> float:
    """Lít/phút dùng theo giờ trong ngày: sáng 6–8 giờ và tối 18–21 giờ nhiều, đêm gần như không."""
    h = giay / 3600 % 24
    if 6 <= h < 8:
        return 12.0
    if 18 <= h < 21:
        return 10.0
    if 0 <= h < 5:
        return 0.2
    return 2.5


def mo_phong(the_tich_l: float, bom_l_phut: float, bom_toi_da_phut: float = 40, can_tu_gio: float = 20.0, buoc: int = 10):
    cm_moi_l = MUC_DAY_CM / the_tich_l
    muc, trang_thai, luc_bat, luc_tat, muc_bat_dau = 0.6 * MUC_DAY_CM, "nghi", 0, -NGHI_TOI_THIEU, 0.0
    vet, su_kien = [], []
    for t in range(0, 24 * 3600 + 1, buoc):
        nguon_co_nuoc = t / 3600 < can_tu_gio      # bể ngầm cạn từ 20 giờ; giả sử phao bể ngầm hỏng (không báo),
                                                    # nên chỉ lớp bảo vệ "không lên nước" phát hiện được
        vao = bom_l_phut if (trang_thai == "bom" and nguon_co_nuoc) else 0.0
        muc = min(MUC_DAY_CM, max(0.0, muc + (vao - dung_nuoc(t)) * buoc / 60 * cm_moi_l))
        pt = 100 * muc / MUC_DAY_CM
        if trang_thai == "nghi" and pt <= BAT_DUOI and t - luc_tat >= NGHI_TOI_THIEU:
            trang_thai, luc_bat, muc_bat_dau = "bom", t, muc
            su_kien.append((t, "bat bom", pt))
        elif trang_thai == "bom":
            if pt >= TAT_TREN:
                trang_thai, luc_tat = "nghi", t
                su_kien.append((t, "tat bom (day)", pt))
            elif t - luc_bat > bom_toi_da_phut * 60:
                trang_thai = "loi"
                su_kien.append((t, "LOI: bom qua lau", pt))
            elif t - luc_bat > KIEM_TRA_LEN and muc - muc_bat_dau < LEN_TOI_THIEU:
                trang_thai = "loi"
                su_kien.append((t, "LOI: khong len nuoc", pt))
        vet.append((t, pt, trang_thai))
    return vet, su_kien


def main() -> None:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("--the-tich", type=float, default=1000, help="lít khi đầy")
    ap.add_argument("--luu-luong-bom", type=float, default=30, help="lít/phút")
    ap.add_argument("--bom-toi-da", type=float, default=40, help="phút cho một lần bơm")
    a = ap.parse_args()
    vet, su_kien = mo_phong(a.the_tich, a.luu_luong_bom, a.bom_toi_da)
    for t, ten, pt in su_kien:
        print(f"{t // 3600:02d}:{t % 3600 // 60:02d}  {ten:22s} muc {pt:5.1f} %")
    phut_bom = sum(10 for _, _, tt in vet if tt == "bom") / 60
    print(f"Tong thoi gian bom: {phut_bom:.0f} phut, so lan bat: {sum(1 for s in su_kien if s[1] == 'bat bom')}")


if __name__ == "__main__":
    main()
Đồ thị mô phỏng 24 giờ mực nước bồn 1000 lít với bơm 30 lít mỗi phút: bơm bật 6 lần trong ngày khi mực xuống 30 phần trăm và tắt ở 90 phần trăm; lúc 20 giờ 17 báo lỗi không lên nước khi bể ngầm cạn
Kết quả của script với tham số mặc định (mô phỏng).
  • Bơm bật 6 lần trong ngày, tổng khoảng 144 phút.
  • Lúc 20:12 bơm bật nhưng bể ngầm đã cạn (giả sử phao hỏng). Đến 20:17 mực không tăng 2 cm: chương trình dừng bơm, báo "khong len nuoc". Bơm không chạy khô cả đêm.
  • Giới hạn thời gian bơm phải tính theo bồn và bơm. Chạy script với --bom-toi-da 20: lúc 06:27 chương trình báo "bom qua lau" khi bồn mới 66 %, vì giờ cao điểm vừa bơm vừa dùng 12 L/phút nên bơm từ 30 % lên 90 % mất hơn 30 phút. Công thức trong chương trình: giới hạn ≈ 2 × (thể tích × 60 %) / lưu lượng bơm; bồn 1000 L, bơm 30 L/phút là 40 phút.

Lưu lượng thật của bơm khi đẩy lên mái thấp hơn số ghi trên nhãn (phụ thuộc chiều cao đẩy). Cách đo: ghi thời gian bơm từ 30 % lên 90 % vào lúc ít dùng nước, rồi tính lại.

7. Lỗi hay gặp

Hiện tượngNguyên nhânCách xử lý
Mực nước nhảy lung tungGiọt nước đọng trên đầu dò, đầu dò sát thành bồn, sóng khi đang bơmĐặt đầu dò giữa nắp, xa ống xả; tăng số lần lọc trung vị
Báo "bom qua lau" dù bồn bình thườngGiới hạn thời gian nhỏ hơn thời gian bơm thậtĐo thời gian bơm, tính lại theo mục 6
Báo "mat tin hieu cam bien"Dây tín hiệu dài bị nhiễu, đứt; cảm biến hỏngDùng cáp có vỏ chống nhiễu, kiểm tra nguồn cảm biến
Relay đóng một lúc khi cấp điệnĐặt mức chân relay sau pinMode(OUTPUT)Làm theo thứ tự trong setup() của bài
ESP32 khởi động lại khi bơm đóngNhiễu từ cuộn contactor, nguồn yếuNguồn riêng cho ESP32, mạch dập RC hoặc varistor cho cuộn hút
Bồn đầy rồi vẫn báo thấpMực nước lên tới vùng mù của cảm biếnĐặt đầu dò cao hơn hoặc giảm MUC_DAY_CM

8. Mở rộng

Bài cùng cụm chủ đề: cảm biến siêu âm chống nước JSN-SR04T, A02YYUW đo mực nước; tưới vườn nhiều vùng bằng van điện từ.


Tin tức liên quan

Làm gateway LoRa sang MQTT bằng ESP32: node cảm biến chạy pin gửi dữ liệu về broker
Làm gateway LoRa sang MQTT bằng ESP32: node cảm biến chạy pin gửi dữ liệu về broker

Hướng dẫn làm hệ thống LoRa hoàn chỉnh với ESP32 và SX1278: node chạy pin đo điện áp, gửi gói rồi ngủ sâu; gateway nhận gói LoRa và publish dữ liệu JSON lên broker MQTT qua Wi-Fi.

Cảm biến lưu lượng nước YF-S201 với ESP32: nối dây 3,3 V, đếm xung, lít/phút, tổng lít, hiệu chuẩn
Cảm biến lưu lượng nước YF-S201 với ESP32: nối dây 3,3 V, đếm xung, lít/phút, tổng lít, hiệu chuẩn

Dùng cảm biến lưu lượng YF-S201 với ESP32: nguyên lý tua bin Hall, F = 7,5 × Q, nối dây an toàn 3,3 V bằng diode, đếm xung bằng ngắt, tính lít/phút, tổng lít lưu flash, hiệu chuẩn bằng xô đo.

LED ma trận MAX7219 và LED 7 đoạn TM1637 với ESP32: chữ chạy 32 × 8 và đồng hồ, không cần thư viện
LED ma trận MAX7219 và LED 7 đoạn TM1637 với ESP32: chữ chạy 32 × 8 và đồng hồ, không cần thư viện

So sánh LED ma trận MAX7219 và LED 7 đoạn TM1637, nối với ESP32 an toàn mức điện áp, giải thích khung 16 bit và ba lệnh TM1637, hai chương trình chữ chạy và đồng hồ không cần thư viện.

Hướng dẫn dùng ngắt GPIO trên ESP32: đọc nút nhấn, chống dội và đếm xung
Hướng dẫn dùng ngắt GPIO trên ESP32: đọc nút nhấn, chống dội và đếm xung

Hướng dẫn dùng ngắt GPIO trên ESP32 với Arduino IDE: attachInterrupt, các kiểu kích ngắt, chống dội nút nhấn, đếm xung đo tần số và quy tắc viết hàm ngắt an toàn.

Tự làm máy vẽ (pen plotter) 2 trục bằng ESP32 và động cơ bước, tự viết bộ đọc G-code
Tự làm máy vẽ (pen plotter) 2 trục bằng ESP32 và động cơ bước, tự viết bộ đọc G-code

Tự làm máy vẽ 2 trục với ESP32, hai A4988, NEMA 17 và servo nhấc bút; chương trình tự đọc G-code G0 G1 G2 G3, nội suy Bresenham có tăng tốc, script Python gửi file G-code.

Tưới cây tự động với ESP32: cảm biến độ ẩm đất, relay và bơm mini, ngưỡng có trễ
Tưới cây tự động với ESP32: cảm biến độ ẩm đất, relay và bơm mini, ngưỡng có trễ

Làm hệ thống tưới cây tự động với ESP32: cảm biến độ ẩm đất điện dung, hiệu chỉnh khô ướt, relay điều khiển bơm mini, ngưỡng có trễ, giới hạn thời gian bơm và thí nghiệm STEM.

Cảm biến siêu âm HC-SR04: nguyên lý, sai số theo nhiệt độ, nối ESP32 3,3 V và code đo khoảng cách
Cảm biến siêu âm HC-SR04: nguyên lý, sai số theo nhiệt độ, nối ESP32 3,3 V và code đo khoảng cách

Cảm biến siêu âm HC-SR04 đo khoảng cách thế nào, nối với ESP32 3,3 V qua cầu chia ở chân Echo, sai số theo nhiệt độ và cách bù, chương trình đo có lọc trung vị, khi nào cảm biến đo sai.

ADS1256 với ESP32: tự làm data logger nhiều kênh ADC 24 bit, lệnh SPI tự viết, ghi CSV ra thẻ SD
ADS1256 với ESP32: tự làm data logger nhiều kênh ADC 24 bit, lệnh SPI tự viết, ghi CSV ra thẻ SD

Tự làm data logger nhiều kênh với ESP32 và ADC 24 bit ADS1256: nối dây chung SPI với thẻ SD, chọn PGA và tốc độ, lệnh SPI tự viết theo datasheet, quét kênh đơn và vi sai, ghi CSV.


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