TF MakerMAKER
กลับไปหน้าโปรเจค
IoTปานกลาง

FRAM Data Logger + Buzzer Alarm ด้วย MiniPLC-32uA

ใช้ FRAM FM24C256 บน MiniPLC-32uA บันทึกข้อมูลเซ็นเซอร์อุณหภูมิ + Buzzer แจ้งเตือนเมื่อเกินค่าที่ตั้ง ข้อมูลไม่หายแม้ไฟดับ

2–3 ชั่วโมง5 ชิ้นส่วน78 views

อุปกรณ์ที่ใช้

MiniPLC-32uA CPU Module
เซ็นเซอร์ DHT22 (อุณหภูมิ + ความชื้น)
ตัวต้านทาน 10kΩ (Pull-up)
Breadboard + สาย Jumper
USB-to-Serial Adapter (FTDI / CH340)

วงจร / การต่อสาย

โค้ด

#include <Wire.h>
#include <DHT.h>

// === I2C Pins (FRAM FM24C256) ===
#define SDA_PIN 21
#define SCL_PIN 22
#define FRAM_ADDR 0x50  // FM24C256 I2C Address

// === DHT22 Sensor ===
#define DHT_PIN 27  // ต่อที่ O0 (IO27) บน J4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);

// === Buzzer (บนบอร์ด) ===
#define BUZZER_PIN 23

// === Config ===
#define TEMP_ALARM 35.0    // แจ้งเตือนเมื่ออุณหภูมิเกิน 35°C
#define LOG_INTERVAL 5000  // บันทึกทุก 5 วินาที
#define MAX_RECORDS 1000   // เก็บได้สูงสุด 1000 รายการ

uint16_t recordCount = 0;
unsigned long lastLog = 0;

// === FRAM Functions ===
void framWrite(uint16_t addr, uint8_t data) {
  Wire.beginTransmission(FRAM_ADDR);
  Wire.write((addr >> 8) & 0xFF);
  Wire.write(addr & 0xFF);
  Wire.write(data);
  Wire.endTransmission();
}

uint8_t framRead(uint16_t addr) {
  Wire.beginTransmission(FRAM_ADDR);
  Wire.write((addr >> 8) & 0xFF);
  Wire.write(addr & 0xFF);
  Wire.endTransmission();
  Wire.requestFrom(FRAM_ADDR, 1);
  return Wire.read();
}

void framWriteFloat(uint16_t addr, float val) {
  uint8_t* p = (uint8_t*)&val;
  for (int i = 0; i < 4; i++) framWrite(addr + i, p[i]);
}

float framReadFloat(uint16_t addr) {
  float val;
  uint8_t* p = (uint8_t*)&val;
  for (int i = 0; i < 4; i++) p[i] = framRead(addr + i);
  return val;
}

// บันทึก 1 record = 8 bytes (temp 4 + humi 4)
void logData(float temp, float humi) {
  uint16_t addr = 4 + (recordCount * 8); // offset 4 bytes สำหรับ header
  framWriteFloat(addr, temp);
  framWriteFloat(addr + 4, humi);
  recordCount++;

  // บันทึกจำนวน record ที่ addr 0-1
  framWrite(0, (recordCount >> 8) & 0xFF);
  framWrite(1, recordCount & 0xFF);
}

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN);
  dht.begin();
  pinMode(BUZZER_PIN, OUTPUT);

  Serial.println("=================================");
  Serial.println("MiniPLC-32uA FRAM Data Logger");
  Serial.println("=================================");
  Serial.print("FRAM: FM24C256 (32KB) @ 0x");
  Serial.println(FRAM_ADDR, HEX);

  // อ่านจำนวน record เก่าจาก FRAM
  recordCount = (framRead(0) << 8) | framRead(1);
  if (recordCount > MAX_RECORDS) recordCount = 0;
  Serial.print("Existing records: ");
  Serial.println(recordCount);

  // แสดง record เก่า (ถ้ามี)
  if (recordCount > 0) {
    Serial.println("--- Last 5 records ---");
    int start = (recordCount > 5) ? recordCount - 5 : 0;
    for (int i = start; i < recordCount; i++) {
      uint16_t addr = 4 + (i * 8);
      float t = framReadFloat(addr);
      float h = framReadFloat(addr + 4);
      Serial.printf("#%d  Temp: %.1f C  Humi: %.1f %%\n", i, t, h);
    }
    Serial.println("----------------------");
  }

  Serial.printf("Alarm threshold: %.1f C\n", TEMP_ALARM);
  Serial.println("Logging started...");
  Serial.println();
}

void loop() {
  if (millis() - lastLog >= LOG_INTERVAL) {
    lastLog = millis();

    float temp = dht.readTemperature();
    float humi = dht.readHumidity();

    if (isnan(temp) || isnan(humi)) {
      Serial.println("DHT22 read error!");
      return;
    }

    // บันทึกลง FRAM
    if (recordCount < MAX_RECORDS) {
      logData(temp, humi);
    }

    Serial.printf("#%d  Temp: %.1f C  Humi: %.1f %%", recordCount, temp, humi);

    // Buzzer alarm ถ้าเกินค่า
    if (temp > TEMP_ALARM) {
      Serial.print("  ** ALARM! **");
      tone(BUZZER_PIN, 2000, 500);
    }
    Serial.println();
  }
}

ขั้นตอนการทำ

ต้องการอุปกรณ์สำหรับโปรเจคนี้?

เลือกซื้ออุปกรณ์คุณภาพดีได้ที่ร้านเรา

ดูสินค้า