Multirelay sketch-help with modification
-
Hi all
I have this sketch which support working with multi relay and buttons on Arduino Mega 2560.
All is ok and works with Domoticz and Home Assistant. Now sketch after reboot or power lost , read latest state from eeprom.
But is any chance to anybody can modification this sketch to user can define option which can be use after power lost:- read latest state from eeprom
- relay ON
- relay OFF
And good will be if user can define this oprtion separate to each relay ex:
// CONFIGURE ONLY THIS ARRAY!
// Row params: relay pin, button pin, relay trigger [HIGH|LOW], button type [MONO_STABLE|BI_STABLE], state relay [EEPROM|ON|OFF]
RelayButton myRelayButtons[] = {
{4, A0, HIGH, MONO_STABLE, EEPROM},
{5, A1, HIGH, MONO_STABLE, ON},
{6, A2, HIGH, MONO_STABLE, OFF},
{7, A3, HIGH, MONO_STABLE, OFF},
{8, A4, HIGH, MONO_STABLE, EEPROM},
};this is sketch:
// Enable debug prints to serial monitor //#define USE_EXPANDER #define MY_DEBUG #define MY_GATEWAY_SERIAL #define MY_INCLUSION_MODE_FEATURE #define MY_INCLUSION_BUTTON_FEATURE #define MY_INCLUSION_MODE_DURATION 60 #define MY_INCLUSION_MODE_BUTTON_PIN 3 #include <MySensors.h> #include <Bounce2.h> #ifdef USE_EXPANDER #include <Wire.h> // Required for I2C communication #include "PCF8574.h" // Required for PCF8574 PCF8574 expander0; // Expander constants #define E00 0x0100 #define E01 0x0101 #define E02 0x0102 #define E03 0x0103 #define E04 0x0104 #define E05 0x0105 #define E06 0x0106 #define E07 0x0107 #endif // No Button Constant #define NOB -1 #define MULTI_RELAY_VERSION 7 #define RELAY_STATE_STORAGE 1 #define RELAY_ON 1 #define RELAY_OFF 0 enum ButtonType { MONO_STABLE = 0, BI_STABLE = 1, DING_DONG = 3 // HIGH state immediatly after push, LOW state after release }; typedef struct { int relay; int button; uint8_t relayTrigger; ButtonType buttonType; } RelayButton; // CONFIGURE ONLY THIS ARRAY! // Row params: relay pin, button pin, relay trigger [HIGH|LOW], button type [MONO_STABLE|BI_STABLE] RelayButton myRelayButtons[] = { {4, A0, HIGH, MONO_STABLE}, {5, A1, HIGH, MONO_STABLE}, {6, A2, HIGH, MONO_STABLE}, {7, A3, HIGH, MONO_STABLE}, {8, A4, HIGH, MONO_STABLE}, {9, A5, HIGH, MONO_STABLE}, {10, A6, HIGH, MONO_STABLE}, {11, A7, HIGH, MONO_STABLE}, }; const int numberOfRelayButtons = sizeof(myRelayButtons) / sizeof(RelayButton); typedef struct { int firstButton; int nextButton; } RelayMultiButtons; RelayMultiButtons relayMultiButtons[numberOfRelayButtons]; // MySensors - Sending Data // To send data you have to create a MyMessage container to hold the information. MyMessage msgs[numberOfRelayButtons]; Bounce myButtonDebouncer[numberOfRelayButtons]; // MySensors - This will execute before MySensors starts up void before() { Serial.begin(115200); #ifdef USE_EXPANDER /* Start I2C bus and PCF8574 instance */ expander0.begin(0x20); #endif // initialize multiple buttons list structure for (int i = 0; i < numberOfRelayButtons; i++) { relayMultiButtons[i].firstButton = -1; relayMultiButtons[i].nextButton = -1; } // find multiple buttons for the same relay (uni-directional list) for (int i = 0; i < numberOfRelayButtons-1; i++) { if (relayMultiButtons[i].firstButton == -1) { int prevRelayButton = i; for (int j = i+1; j < numberOfRelayButtons; j++) { if (myRelayButtons[i].relay == myRelayButtons[j].relay) { relayMultiButtons[prevRelayButton].firstButton = i; relayMultiButtons[prevRelayButton].nextButton = j; relayMultiButtons[j].firstButton = i; prevRelayButton = j; } } } } // if version has changed, reset state of all relays int versionChangeResetState = 0; if (MULTI_RELAY_VERSION != loadState(0) ) for (int i = 0; i < numberOfRelayButtons; i++) { // if this relay has multiple buttons, load only first if (relayMultiButtons[i].firstButton == -1 || relayMultiButtons[i].firstButton == i) { // Then set relay pins in output mode #ifdef USE_EXPANDER if ( myRelayButtons[i].relay >= 0x0100 ) { // EXPANDER expander0.pinMode(myRelayButtons[i].relay & 0xf, OUTPUT); } else { #endif pinMode(myRelayButtons[i].relay, OUTPUT); #ifdef USE_EXPANDER } #endif uint8_t isTurnedOn = 0; if (versionChangeResetState) { saveRelayState(i, 0); } else { // Set relay to last known state (using eeprom storage) isTurnedOn = loadRelayState(i); // 1 - true, 0 - false } uint8_t state = isTurnedOn ? myRelayButtons[i].relayTrigger : ! myRelayButtons[i].relayTrigger; digitalWrite(myRelayButtons[i].relay, state); } } } // executed AFTER mysensors has been initialised void setup() { // Setup locally attached sensors delay(5000); // Setup Relays for(int i = 0; i < numberOfRelayButtons; i++) { // if this relay has multiple buttons, send only first if (relayMultiButtons[i].firstButton == -1 || relayMultiButtons[i].firstButton == i) { msgs[i] = MyMessage(i, V_LIGHT); send(msgs[i].set(loadRelayState(i))); // send current state } } // Setup buttons for(int i = 0; i < numberOfRelayButtons; i++) { if (myRelayButtons[i].button >= 0) { // No Expander support for buttons (de-bouncing) pinMode(myRelayButtons[i].button, INPUT_PULLUP); // HIGH state when button is not pushed // After setting up the button, setup debouncer. myButtonDebouncer[i] = Bounce(); myButtonDebouncer[i].attach(myRelayButtons[i].button); myButtonDebouncer[i].interval(50); } } //presentation(); } void loop() { for(int i = 0; i < numberOfRelayButtons; i++) { if (myRelayButtons[i].button >= 0 && myButtonDebouncer[i].update()) { int buttonState = myButtonDebouncer[i].read(); #ifdef MY_DEBUG Serial.print("Button "); Serial.print(i); Serial.print(" changed to: "); Serial.println(buttonState); #endif int nextButton = (relayMultiButtons[i].firstButton == -1) ? i : relayMultiButtons[i].firstButton; if (myRelayButtons[i].buttonType == DING_DONG) { if (buttonState == LOW) { // button pressed digitalWrite(myRelayButtons[nextButton].relay, myRelayButtons[nextButton].relayTrigger); send(msgs[nextButton].set(1)); } else { // button released digitalWrite(myRelayButtons[nextButton].relay, ! myRelayButtons[nextButton].relayTrigger); send(msgs[nextButton].set(0)); } } else if (myRelayButtons[i].buttonType == BI_STABLE || buttonState == HIGH) { // If button type is BI_STABLE, any change will toggle relay state // For MONO_STABLE, button must be pushed and released (HIGH) uint8_t isTurnedOn = ! loadRelayState(nextButton); // 1 - true, 0 - false uint8_t newState = isTurnedOn ? myRelayButtons[nextButton].relayTrigger : ! myRelayButtons[nextButton].relayTrigger; digitalWrite(myRelayButtons[nextButton].relay, newState); send(msgs[nextButton].set(isTurnedOn)); // update state in eeprom for all buttons do { saveRelayState(nextButton, isTurnedOn); nextButton = relayMultiButtons[nextButton].nextButton; } while (nextButton != -1); } } } } // MySensors - Presentation // Your sensor must first present itself to the controller. // The presentation is a hint to allow controller prepare for the sensor data that eventually will come. // void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool ack); // childSensorId - The unique child id you want to choose for the sensor connected to this Arduino. Range 0-254. // sensorType - The sensor type you want to create. // description An optional textual description of the attached sensor. // ack - Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Multi Relay", "1.1"); // Register every relay as separate sensor for (int i = 0; i < numberOfRelayButtons; i++) { // if this relay has multiple buttons, register only first if (relayMultiButtons[i].firstButton == -1 || relayMultiButtons[i].firstButton == i) { // Register all sensors to gw (they will be created as child devices) present(i, S_BINARY); } } } // MySensors - Handling incoming messages // Nodes that expects incoming data, such as an actuator or repeating nodes, // must implement the receive() - function to handle the incoming messages. // Do not sleep a node where you expect incoming data or you will lose messages. void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type == V_STATUS) { uint8_t isTurnedOn = message.getBool(); // 1 - true, 0 - false uint8_t newState = isTurnedOn ? myRelayButtons[message.sensor].relayTrigger : ! myRelayButtons[message.sensor].relayTrigger; // Change relay state digitalWrite(myRelayButtons[message.sensor].relay, newState); // Store state in eeprom if changed if (loadRelayState(message.sensor) != isTurnedOn) { saveRelayState(message.sensor, isTurnedOn); } send(msgs[message.sensor].set(isTurnedOn)); // support for OPTIMISTIC=FALSE (Home Asistant) } } uint8_t loadRelayState(int relayNum) { return(loadState(RELAY_STATE_STORAGE + relayNum)); } void saveRelayState(int relayNum, uint8_t state) { saveState(RELAY_STATE_STORAGE + relayNum, state); }```