// ==================== MODUL 2 - NAMAKALNI SISTEM ====================
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
// ==================== PIN DEFINICIJE ====================
#define RELAY1_PIN 12
#define RELAY2_PIN 13
#define RELAY3_PIN 14
#define FLOW_SENSOR_1_PIN 4
#define FLOW_SENSOR_2_PIN 5
#define FLOW_SENSOR_3_PIN 6
#define STATUS_LED 2
#define MODULE_ID 2
#define PULSES_PER_LITER 450
#define SEND_INTERVAL 5000
#define FLOW_UPDATE_INTERVAL 1000
// ===== PRAVILEN MAC NASLOV GLAVNEGA SISTEMA =====
uint8_t masterMAC[] = {0xB4, 0x3A, 0x45, 0xF3, 0xEB, 0xF0};
// ==================== STRUKTURE ====================
struct ModuleData {
uint8_t moduleId;
uint8_t moduleType;
unsigned long timestamp;
uint8_t errorCode;
float batteryVoltage;
float flowRate1, flowRate2, flowRate3;
float totalFlow1, totalFlow2, totalFlow3;
bool relay1State, relay2State, relay3State;
};
struct CommandData {
uint8_t targetModuleId;
uint8_t command;
float param1;
float param2;
};
// ==================== GLOBALNE SPREMENLJIVKE ====================
ModuleData sendData;
volatile unsigned long pulseCount1 = 0;
volatile unsigned long pulseCount2 = 0;
volatile unsigned long pulseCount3 = 0;
float flowRate1 = 0.0, flowRate2 = 0.0, flowRate3 = 0.0;
float totalFlow1 = 0.0, totalFlow2 = 0.0, totalFlow3 = 0.0;
unsigned long lastFlowUpdate = 0;
unsigned long oldTime = 0;
bool relay1State = false, relay2State = false, relay3State = false;
// ==================== INTERRUPT HANDLERJI ====================
void IRAM_ATTR pulseCounter1() { pulseCount1++; }
void IRAM_ATTR pulseCounter2() { pulseCount2++; }
void IRAM_ATTR pulseCounter3() { pulseCount3++; }
// ==================== SETUP ====================
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("\n\n=========================================");
Serial.println("MODUL 2 - NAMAKALNI SISTEM");
Serial.println("=========================================");
pinMode(STATUS_LED, OUTPUT);
digitalWrite(STATUS_LED, LOW);
// ===== 1. WIFI INICIALIZACIJA (SAMO STA NAČIN) =====
Serial.println("\n--- WiFi inicializacija ---");
WiFi.mode(WIFI_STA);
delay(100);
String mac = WiFi.macAddress();
Serial.printf("MAC naslov: %s\n", mac.c_str());
if (mac == "00:00:00:00:00:00" || mac == "FF:FF:FF:FF:FF:FF") {
Serial.println("⚠️ Neveljaven MAC naslov! Poskus ponovne inicializacije...");
WiFi.mode(WIFI_OFF);
delay(500);
WiFi.mode(WIFI_STA);
delay(500);
mac = WiFi.macAddress();
Serial.printf("Nov MAC naslov: %s\n", mac.c_str());
}
// NASTAVI KANAL NA 1 (ENAKO KOT GLAVNI SISTEM) - BREZ POSKUSA SPREMINJANJA!
esp_wifi_set_promiscuous(true);
esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE);
esp_wifi_set_promiscuous(false);
Serial.printf("Nastavljen kanal: %d\n", WiFi.channel());
// ===== 2. ESP-NOW INICIALIZACIJA =====
Serial.println("\n--- ESP-NOW inicializacija ---");
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW napaka!");
while(1) {
digitalWrite(STATUS_LED, HIGH);
delay(500);
digitalWrite(STATUS_LED, LOW);
delay(500);
}
}
Serial.println("ESP-NOW inicializiran");
// Registriraj callback za prejemanje ukazov
esp_now_register_recv_cb(onDataRecv);
// ===== 3. DODAJ MASTER PEER =====
esp_now_peer_info_t peerInfo;
memset(&peerInfo, 0, sizeof(peerInfo));
memcpy(peerInfo.peer_addr, masterMAC, 6);
peerInfo.channel = 1; // Kanal 1
peerInfo.encrypt = false;
peerInfo.ifidx = WIFI_IF_STA;
if (esp_now_add_peer(&peerInfo) == ESP_OK) {
Serial.println("Dodajanje master peerja... OK");
} else {
Serial.println("Dodajanje master peerja... NAPAKA!");
}
// ===== 4. INICIALIZACIJA RELEJEV =====
Serial.println("\n--- Inicializacija relejev ---");
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);
digitalWrite(RELAY1_PIN, HIGH);
digitalWrite(RELAY2_PIN, HIGH);
digitalWrite(RELAY3_PIN, HIGH);
// ===== 5. INICIALIZACIJA FLOW SENZORJEV =====
Serial.println("\n--- Inicializacija flow senzorjev ---");
pinMode(FLOW_SENSOR_1_PIN, INPUT_PULLUP);
pinMode(FLOW_SENSOR_2_PIN, INPUT_PULLUP);
pinMode(FLOW_SENSOR_3_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_1_PIN), pulseCounter1, FALLING);
attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_2_PIN), pulseCounter2, FALLING);
attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_3_PIN), pulseCounter3, FALLING);
oldTime = millis();
lastFlowUpdate = millis();
// ===== 6. PRIPRAVI PODATKE ZA POŠILJANJE =====
sendData.moduleId = MODULE_ID;
sendData.moduleType = 2; // MODULE_IRRIGATION
sendData.batteryVoltage = 3.3;
sendData.errorCode = 0;
Serial.println("\n=== MODUL 2 PRIPRAVLJEN ===");
Serial.printf("MAC naslov: %s\n", WiFi.macAddress().c_str());
Serial.printf("Kanal: %d\n", WiFi.channel());
Serial.println("=========================================\n");
// Utripni LED za potrditev zagona
for(int i = 0; i < 3; i++) {
digitalWrite(STATUS_LED, HIGH);
delay(100);
digitalWrite(STATUS_LED, LOW);
delay(100);
}
}
// ==================== FUNKCIJA ZA BRANJE FLOW SENZORJEV ====================
void updateFlowSensors() {
unsigned long currentTime = millis();
if (currentTime - lastFlowUpdate > FLOW_UPDATE_INTERVAL) {
float timeInSeconds = (currentTime - oldTime) / 1000.0;
if (timeInSeconds > 0) {
flowRate1 = (pulseCount1 / PULSES_PER_LITER) / (timeInSeconds / 60.0);
flowRate2 = (pulseCount2 / PULSES_PER_LITER) / (timeInSeconds / 60.0);
flowRate3 = (pulseCount3 / PULSES_PER_LITER) / (timeInSeconds / 60.0);
totalFlow1 += (pulseCount1 / PULSES_PER_LITER);
totalFlow2 += (pulseCount2 / PULSES_PER_LITER);
totalFlow3 += (pulseCount3 / PULSES_PER_LITER);
pulseCount1 = 0;
pulseCount2 = 0;
pulseCount3 = 0;
oldTime = currentTime;
}
lastFlowUpdate = currentTime;
}
}
// ==================== FUNKCIJA ZA POŠILJANJE PODATKOV ====================
void sendSensorData() {
sendData.timestamp = millis();
sendData.flowRate1 = flowRate1;
sendData.flowRate2 = flowRate2;
sendData.flowRate3 = flowRate3;
sendData.totalFlow1 = totalFlow1;
sendData.totalFlow2 = totalFlow2;
sendData.totalFlow3 = totalFlow3;
sendData.relay1State = relay1State;
sendData.relay2State = relay2State;
sendData.relay3State = relay3State;
sendData.errorCode = 0;
Serial.printf("\n--- Pošiljanje podatkov ---\n");
Serial.printf("Flow 1: %.2f L/min (skupaj: %.1f L)\n", flowRate1, totalFlow1);
Serial.printf("Flow 2: %.2f L/min (skupaj: %.1f L)\n", flowRate2, totalFlow2);
Serial.printf("Flow 3: %.2f L/min (skupaj: %.1f L)\n", flowRate3, totalFlow3);
Serial.printf("Releji: R1=%s, R2=%s, R3=%s\n",
relay1State ? "ON" : "OFF",
relay2State ? "ON" : "OFF",
relay3State ? "ON" : "OFF");
Serial.printf("Kanal: %d\n", WiFi.channel());
esp_err_t result = esp_now_send(masterMAC, (uint8_t*)&sendData, sizeof(sendData));
if (result == ESP_OK) {
digitalWrite(STATUS_LED, HIGH);
delay(20);
digitalWrite(STATUS_LED, LOW);
Serial.println("✓ USPEŠNO poslano");
} else {
Serial.printf("✗ Napaka pri pošiljanju: %d\n", result);
}
}
// ==================== FUNKCIJA ZA UPRAVLJANJE RELEJEV ====================
void setRelay(int relayNum, bool state) {
int pin;
switch(relayNum) {
case 1: pin = RELAY1_PIN; relay1State = state; break;
case 2: pin = RELAY2_PIN; relay2State = state; break;
case 3: pin = RELAY3_PIN; relay3State = state; break;
default: return;
}
digitalWrite(pin, state ? LOW : HIGH);
Serial.printf("Rele %d: %s\n", relayNum, state ? "VKLOP" : "IZKLOP");
}
// ==================== CALLBACK ZA PREJEM UKAZOV ====================
void onDataRecv(const esp_now_recv_info_t *recv_info, const uint8_t *incomingData, int len) {
if (len == sizeof(CommandData)) {
CommandData cmd;
memcpy(&cmd, incomingData, sizeof(cmd));
if (cmd.targetModuleId == MODULE_ID) {
Serial.printf("📡 Prejet ukaz: cmd=%d, p1=%.1f, p2=%.1f\n",
cmd.command, cmd.param1, cmd.param2);
if (cmd.command == 1) { // CMD_SET_RELAY
int relayNum = (int)cmd.param1;
bool state = (cmd.param2 > 0);
setRelay(relayNum, state);
}
else if (cmd.command == 2) { // CMD_RESET_TOTALS
totalFlow1 = 0;
totalFlow2 = 0;
totalFlow3 = 0;
Serial.println("Skupne vrednosti resetirane");
}
else if (cmd.command == 3) { // CMD_GET_STATUS
// Takoj pošlji status
sendSensorData();
}
}
}
}
// ==================== GLAVNA ZANKA ====================
void loop() {
static unsigned long lastSend = 0;
unsigned long now = millis();
updateFlowSensors();
if (now - lastSend >= SEND_INTERVAL) {
sendSensorData();
lastSend = now;
}
delay(10);
}
Senzor Pin na modulu Povezava
AHT20 VIN 3.3V 3.3V
AHT20 GND GND GND
AHT20 SDA GPIO4 SDA
AHT20 SCL GPIO5 SCL
BMP280 VIN 3.3V 3.3V
BMP280 GND GND GND
BMP280 SDA GPIO4 SDA
BMP280 SCL GPIO5 SCL
LDR en konec 3.3V 3.3V
LDR drug konec GPIO6 A0
10k upor GPIO6 -> GND Pull-down