#include #include #include #include #include // กำหนดขา I2C ของ ESP32 (ปรับเปลี่ยนได้ตามสะดวก) #define I2C_SDA 21 #define I2C_SCL 22 // I2C Addresses ของ PCF8574 ทั้ง 6 ตัว (เรียงจาก ซ้าย ไป ขวา) // HR_TENS (สิบชั่วโมง), HR_ONES (หน่วยชั่วโมง), MIN_TENS, MIN_ONES, SEC_TENS, SEC_ONES const uint8_t pcf_addresses[6] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25}; String vname = "101"; // กำหนด Channel ที่ต้องการล็อกให้ตรงกับ Master const int WIFI_CHANNEL = 10; // ====================================================================== // โครงสร้างข้อมูลที่ใช้รับ (ต้องตรงกับฝั่ง Master 100%) // ====================================================================== typedef struct struct_message { uint8_t h_tens[8]; // ชั่วโมง หลักสิบ uint8_t h_units[8]; // ชั่วโมง หลักหน่วย uint8_t m_tens[8]; // นาที หลักสิบ uint8_t m_units[8]; // นาที หลักหน่วย uint8_t s_tens[8]; // วินาที หลักสิบ uint8_t s_units[8]; // วินาที หลักหน่วย char namex[32]; // ✅ ตรงกับ Master ที่แก้ไขแล้ว uint8_t din; } struct_message; struct_message timeData; // ฟังก์ชันช่วยแปลง Array 7 ตัว (0 หรือ 1) ให้เป็น 1 Byte (Bitmask) สำหรับ PCF8574 uint8_t convertSegmentsToByte(uint8_t segments[7]) { uint8_t outByte = 0; for (int i = 0; i < 8; i++) { if (segments[i] == 1) { // ทำการเลื่อนบิต (Bit Shift) ตามลำดับขาที่ต่อเข้า PCF8574 // สมมติว่า segments[0] (ขา A) ต่อกับ P0, segments[1] (ขา B) ต่อกับ P1 ไปเรื่อยๆ outByte |= (1 << i); } } // ⚠️ หมายเหตุ: ถ้าบอร์ดรีเลย์หรือ PCF8574 ของคุณเป็นแบบ Active LOW (ส่ง 0 แล้วติด) // ให้เอาเครื่องหมาย // หน้าบรรทัดข้างล่างนี้ออกเพื่อกลับลอจิก // outByte = ~outByte; return outByte; } // ฟังก์ชันสำหรับส่งข้อมูลไปยัง PCF8574 เจาะจงตัว void writeToPCF8574(uint8_t address, uint8_t data) { Wire.beginTransmission(address); Wire.write(data); Wire.endTransmission(); } // ====================================================================== // Callback เมื่อได้รับข้อมูลจาก Master // ====================================================================== #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) void OnDataRecv(const esp_now_recv_info_t *esp_now_info, const uint8_t *incomingData, int len) { #else void OnDataRecv(const uint8_t *mac_addr, const uint8_t *incomingData, int len) { #endif // คัดลอกข้อมูลที่ได้รับเข้า struct memcpy(&timeData, incomingData, sizeof(timeData)); Serial.print("Received Namex: "); Serial.println(timeData.namex); Serial.print("Received din: "); Serial.println(timeData.din); // ตรวจสอบเงื่อนไขชื่อบอร์ด if (String(timeData.namex) == vname) { Serial.print("Received Namex: "); Serial.println(convertSegmentsToByte(timeData.h_tens)); // สร้าง Array เก็บค่า Byte ที่จะส่งให้ PCF8574 ทั้ง 6 ตัว uint8_t display_bytes[6]; // แปลงข้อมูล Array 7 เซกเมนต์ของแต่ละหลัก ให้เป็น 1 Byte ด้วยฟังก์ชันที่สร้างไว้ display_bytes[0] = convertSegmentsToByte(timeData.h_tens); // ชั่วโมง (หลักสิบ) display_bytes[1] = convertSegmentsToByte(timeData.h_units); // ชั่วโมง (หลักหน่วย) display_bytes[2] = convertSegmentsToByte(timeData.m_tens); // นาที (หลักสิบ) display_bytes[3] = convertSegmentsToByte(timeData.m_units); // นาที (หลักหน่วย) display_bytes[4] = convertSegmentsToByte(timeData.s_tens); // วินาที (หลักสิบ) display_bytes[5] = convertSegmentsToByte(timeData.s_units); // วินาที (หลักหน่วย) // ส่งข้อมูลออกไปยัง PCF8574 ทั้ง 6 ตัวผ่าน I2C for (int i = 0; i < 6; i++) { writeToPCF8574(pcf_addresses[i], display_bytes[i]); } } } void setup() { Serial.begin(115200); Wire.begin(I2C_SDA, I2C_SCL); // ตั้งค่าขา Relay ทั้งหมดเป็น OUTPUT // ตั้งค่า Wi-Fi และล็อก Channel WiFi.mode(WIFI_STA); esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE); if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_register_recv_cb((esp_now_recv_cb_t)OnDataRecv); Serial.print("Slave Node Started on Channel "); Serial.println(WIFI_CHANNEL); } void loop() { delay(100); }