#include #include #include #include // ล็อกช่องสัญญาณให้ตรงกับฝั่ง Slave (ใช้ Channel 10) const int WIFI_CHANNEL = 10; String vname = "101"; int vh_tens, vh_units, vm_tens, vm_units, vs_tens, vs_units, vx; // ====================================================================== // โครงสร้างข้อมูลที่ใช้ส่ง (ตรงกับฝั่งรับ 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]; // บัฟเฟอร์ชื่อแบบ char array uint8_t din; uint8_t vs; } struct_message; struct_message timeData; // ====================================================================== // ตัวแปรสำหรับจำลองเวลาและรับค่าเสียง // ====================================================================== int sim_hour = 0; int sim_min = 0; int sim_sec = 0; int vnum; const int soundAnalogPin = 34; const int sampleWindow = 20; // 20 มิลลิวินาที unsigned long lastTimeUpdate = 0, vmin; // Broadcast MAC Address (ส่งกระจายให้สเลฟทุกตัวรับพร้อมกัน) uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; esp_now_peer_info_t peerInfo; // ข้อมูลอาเรย์มีทั้งหมด 48 แถว (8 ชุด ชุดละ 6 แถว แถวละ 8 ตัวเลข) const uint8_t datax[][8] = { {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, // 0 {0,0,0,0,0,0,0,1}, {0,0,0,0,0,0,0,1}, {0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0}, {1,0,0,0,0,0,0,0}, {1,0,0,0,0,0,0,0}, // 1 {0,0,0,0,0,0,1,1}, {0,0,0,0,0,0,1,1}, {0,0,0,0,0,0,1,1}, {1,1,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0}, // 2 {0,0,0,0,0,1,1,1}, {0,0,0,0,0,1,1,1}, {0,0,0,0,0,1,1,1}, {1,1,1,0,0,0,0,0}, {1,1,1,0,0,0,0,0}, {1,1,1,0,0,0,0,0}, // 3 {0,0,0,0,1,1,1,1}, {0,0,0,0,1,1,1,1}, {0,0,0,0,1,1,1,1}, {1,1,1,1,0,0,0,0}, {1,1,1,1,0,0,0,0}, {1,1,1,1,0,0,0,0}, // 4 {0,0,0,1,1,1,1,1}, {0,0,0,1,1,1,1,1}, {0,0,0,1,1,1,1,1}, {1,1,1,1,1,0,0,0}, {1,1,1,1,1,0,0,0}, {1,1,1,1,1,0,0,0}, // 5 {0,0,1,1,1,1,1,1}, {0,0,1,1,1,1,1,1}, {0,0,1,1,1,1,1,1}, {1,1,1,1,1,1,0,0}, {1,1,1,1,1,1,0,0}, {1,1,1,1,1,1,0,0}, // 6 {0,1,1,1,1,1,1,1}, {0,1,1,1,1,1,1,1}, {0,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,0}, {1,1,1,1,1,1,1,0}, {1,1,1,1,1,1,1,0} // 7 }; // ====================================================================== // Callback เมื่อทำการส่งข้อมูลผ่าน ESP-NOW // ====================================================================== #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) void OnDataSent(const wifi_tx_info_t *info, esp_now_send_status_t status) { #else void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { #endif // สามารถเปิด Serial ดูสถานะได้หากต้องการทดสอบ } void setup() { Serial.begin(115200); pinMode(13, INPUT_PULLUP); pinMode(soundAnalogPin, INPUT); WiFi.mode(WIFI_STA); // บังคับล็อกช่องสัญญาณวิทยุของตัวส่งให้เป็น Channel 10 ทันที 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_send_cb((esp_now_send_cb_t)OnDataSent); memset(&peerInfo, 0, sizeof(peerInfo)); memcpy(peerInfo.peer_addr, broadcastAddress, 6); peerInfo.channel = WIFI_CHANNEL; peerInfo.encrypt = false; if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } Serial.print("Master Node Started on Channel: "); Serial.println(WIFI_CHANNEL); } void pros1() { if (millis() - vmin > 80) { vmin = millis(); unsigned long startMillis = millis(); unsigned int signalMax = 0; unsigned int signalMin = 4095; while (millis() - startMillis < sampleWindow) { unsigned int sample = analogRead(soundAnalogPin); if (sample < 4096) { if (sample > signalMax) signalMax = sample; if (sample < signalMin) signalMin = sample; } } unsigned int peakToPeak = signalMax - signalMin; // ✅ แก้ไข: ปรับลดระดับแมปให้อยู่ในช่วง 0-7 เพื่อให้สมดุลกับข้อมูลใน array datax // หากต้องการใช้ 0-16 คุณจำเป็นต้องไปเพิ่มชุดข้อมูลใน datax ให้มีถึงดัชนีที่ต้องการ (เช่น สูงสุดเคส 7*6 = 42) int vuLevel = map(peakToPeak, 50, 500, 0, 7); vuLevel = constrain(vuLevel, 0, 7); vnum = vuLevel; switch (vx) { case 0: memcpy(timeData.h_tens, datax[vnum*6+0], 8); memcpy(timeData.h_units, datax[0], 8); memcpy(timeData.m_tens, datax[0], 8); memcpy(timeData.m_units, datax[vnum*6+3], 8); memcpy(timeData.s_tens, datax[0], 8); memcpy(timeData.s_units, datax[0], 8); break; case 1: memcpy(timeData.h_tens, datax[0], 8); memcpy(timeData.h_units, datax[vnum*6+1], 8); memcpy(timeData.m_tens, datax[0], 8); memcpy(timeData.m_units, datax[0], 8); memcpy(timeData.s_tens, datax[vnum*6+4], 8); memcpy(timeData.s_units, datax[0], 8); break; case 2: memcpy(timeData.h_tens, datax[0], 8); memcpy(timeData.h_units, datax[0], 8); memcpy(timeData.m_tens, datax[vnum*6+2], 8); memcpy(timeData.m_units, datax[0], 8); memcpy(timeData.s_tens, datax[0], 8); memcpy(timeData.s_units, datax[vnum*6+5], 8); break; case 3: memcpy(timeData.h_tens, datax[vnum*6+0], 8); memcpy(timeData.h_units, datax[0], 8); memcpy(timeData.m_tens, datax[0], 8); memcpy(timeData.m_units, datax[0], 8); memcpy(timeData.s_tens, datax[vnum*6+4], 8); memcpy(timeData.s_units, datax[0], 8); break; case 4: // ปรับจากดัชนีตายตัว 8*6 (ซึ่งไม่มีอยู่จริง) มาใช้ 7*6 (ดัชนีชุดที่ 7 ตัวสุดท้าย) memcpy(timeData.h_tens, datax[7*6], 8); memcpy(timeData.h_units, datax[0], 8); memcpy(timeData.m_tens, datax[0], 8); memcpy(timeData.m_units, datax[7*6], 8); memcpy(timeData.s_tens, datax[0], 8); memcpy(timeData.s_units, datax[0], 8); break; case 5: memcpy(timeData.h_tens, datax[0], 8); memcpy(timeData.h_units, datax[7*6], 8); memcpy(timeData.m_tens, datax[0], 8); memcpy(timeData.m_units, datax[0], 8); memcpy(timeData.s_tens, datax[7*6], 8); memcpy(timeData.s_units, datax[0], 8); break; case 6: memcpy(timeData.h_tens, datax[0], 8); memcpy(timeData.h_units, datax[0], 8); memcpy(timeData.m_tens, datax[7*6], 8); memcpy(timeData.m_units, datax[0], 8); memcpy(timeData.s_tens, datax[0], 8); memcpy(timeData.s_units, datax[7*6], 8); break; case 7: memcpy(timeData.h_tens, datax[7*6], 8); memcpy(timeData.h_units, datax[7*6], 8); memcpy(timeData.m_tens, datax[7*6], 8); memcpy(timeData.m_units, datax[7*6], 8); memcpy(timeData.s_tens, datax[7*6], 8); memcpy(timeData.s_units, datax[7*6], 8); break; case 8: memcpy(timeData.h_tens, datax[0], 8); memcpy(timeData.h_units, datax[0], 8); memcpy(timeData.m_tens, datax[0], 8); memcpy(timeData.m_units, datax[0], 8); memcpy(timeData.s_tens, datax[0], 8); memcpy(timeData.s_units, datax[0], 8); break; } vname.toCharArray(timeData.namex, sizeof(timeData.namex)); // ✅ แก้ไข: กำหนดค่าเข้าโครงสร้างข้อมูลโดยตรง (ไม่ต้องใช้ฟังก์ชันแปลง) timeData.din = (uint8_t)vnum; timeData.vs = (uint8_t)vx; esp_now_send(broadcastAddress, (uint8_t *) &timeData, sizeof(timeData)); } } void loop() { if (digitalRead(13) == 0) { vx = vx + 1; if (vx > 8) vx = 0; while (digitalRead(13) == 0) delay(10); // Debounce สวิตช์ } pros1(); }