กลับไปหน้าโปรเจค
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();
}
}