💬 AC-DC double solid state relay module
-
good to know clearence isn't there ... something i could correct though
An i2c and capacity touch could work great.. but i can't find any cleanly designed front panel that I could use in place of my light switches.
-
So if I understanded right the device needs also neutral to work? That's a problem because here in Finland we only circulate the phase through light switches. Neutral goes straight to the lamps.
@Misna said in 💬 AC-DC double solid state relay module:
So if I understanded right the device needs also neutral to work? That's a problem because here in Finland we only circulate the phase through light switches. Neutral goes straight to the lamps.
Yes it does. Same problem for most people, even here in Vietnam it's the same.
Solution is to put it in ceiling connected directly to the lights, and use radio switch to control it. -
Hi,
first of all you had an great idea to user a small layout with this functions.
The protection at the AC site is very good I think.Today I get ten boards with your current gerber files (v3.3.2).
But I think it does not work as expected:- Using a 5 V Arduino and the NRF without a level switcher with 3.3 V it will be break in the future.
- The big relay routes have no protection (I don't know if solder resist is the correct word).
- Maybe as pulldown resistor to the relay input could be useful.
- The three GND and Vcc Pins are not connected to each other.
- Maybe it could usefull to use fuse sockets for the not resetable fuse.
For the voltage problem we could use an 3.3 V Arduino mini pro with 8 MHz crystal.
In this case we don't need the LDO and could use LDO from the Arduino board. -
Sorry I forgot something.
For a 3.3 V Arduino we need a MOSFET or so to drive the SSR.
But there are cheep and small SMD packages available.@hugch no you don't need MOSFET for those SSR, the high level of input is below 3.3V. I've made a board with those and a 3.3V Arduino and didn't have any problem.
For this board it's missing fuses on the SSRs, if they fail and shortcut nothing will stop the short circuit at the moment.
-
@hugch no you don't need MOSFET for those SSR, the high level of input is below 3.3V. I've made a board with those and a 3.3V Arduino and didn't have any problem.
For this board it's missing fuses on the SSRs, if they fail and shortcut nothing will stop the short circuit at the moment.
@Nca78 My SSRs are with 5 V level but one with 3.3 V level would be better. You are right.
And the fuses are important but i think the step down have an over current protection, but a PTC could useful.
But a MOSFET or equal is also required:
It is not a good idea to drive current intensive peripheral directly with an micro controller.
The absolute maximum ratings for an ATmega328p is 40 mA. And a SSR is using 25 mA or so.
The better choice is using a driver or a simple transistor circuit.To drive the SSR directly would not damage the controller at this moment, but your are decrease the lifetime.
And the lifetime for an in wall module or so is very important. -
Hello!!, my name is Alejandro, I'm from Spain and I have been working on something quite similar to this project. I would like to contribute to reach a final design. What I have done until now is a prototype board similar than yours and I would like to add a top board with touch buttons to fit into Livolo glass panel switch.
https://es.aliexpress.com/store/product/Free-Shipping-Livolo-Luxury-White-Pearl-Crystal-Glass-151mm-80mm-EU-standard-Double-Glass-Panel-VL/500715_1684198410.html?spm=2114.12010608.0.0.6cyWwJAnd try to do something like this also including ws2812 rgb led for touchpad and a small speaker just to sound someting when touch the button.
https://z-uno.z-wave.me/projects/sensor-wall-switch-based-on-livolo-glass/
My development is based on ESP8266 without rf communication but as I have progressed I have checked that Wifi connection is a complex system compared to rf so I am thinking to change to arduino or esp + nrf.
-
What's happening if you switch it on then off in domoticz ?
-
This is my sketch
// MySensor Debug #define MY_DEBUG // Enables repeater functionality (relays messages from other nodes) #define MY_REPEATER_FEATURE // Comment line below if you don't want to use the temperature sensor #define MY_RADIO_NRF24 #define MY_TRANSPORT_WAIT_READY_MS #define MY_PARENT_NODE_ID 2 #define MY_RADIO_NRF24 #include <MySensors.h> #include <SPI.h> #include <Bounce2.h> #define RELAY_PIN_1 3 // Arduino Digital I/O pin number for relay #define RELAY_PIN_2 5 #define BUTTON_PIN_1 4 // Arduino Digital I/O pin number for button #define BUTTON_PIN_2 7 #define CHILD_ID_1 8 // Id of the sensor child for 1st relay #define CHILD_ID_2 9 // Id of the sensor child for 2nd relay // Relay status #define RELAY_ON 1 #define RELAY_OFF 0 // Source of state change (used when printing debug information) #define CHANGE_STATE_SOURCE_RADIO 0 #define CHANGE_STATE_SOURCE_SWITCH 1 Bounce debouncer1 = Bounce(); int oldValue; bool state1; Bounce debouncer2 = Bounce(); int oldValue2; bool state2; MyMessage msg(CHILD_ID_1, V_LIGHT); MyMessage msg2(CHILD_ID_2, V_LIGHT); void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Double Relay & Button", "0.2"); // Register all sensors to gw (they will be created as child devices) present(CHILD_ID_1, S_LIGHT); present(CHILD_ID_2, S_LIGHT); } void setup() { // Setup the button pinMode(BUTTON_PIN_1, INPUT); // Activate internal pull-up digitalWrite(BUTTON_PIN_1, HIGH); // Setup the button pinMode(BUTTON_PIN_2, INPUT); // Activate internal pull-up digitalWrite(BUTTON_PIN_2, HIGH); // After setting up the button, setup debouncer debouncer1.attach(BUTTON_PIN_1); debouncer1.interval(5); debouncer2.attach(BUTTON_PIN_2); debouncer2.interval(5); // Set the initial values of oldValue/oldValue2 variables from status of physical switches // if this is not done the loop() will detect status change and switch the relays on or off debouncer1.update(); debouncer2.update(); oldValue = debouncer1.read(); oldValue2 = debouncer2.read(); // Make sure relays are off when starting up setRelayState(RELAY_PIN_1, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_PIN_1, OUTPUT); digitalWrite(RELAY_PIN_2, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_PIN_2, OUTPUT); // Set relay to last known state (using eeprom storage) state1 = loadState(CHILD_ID_1); setRelayState(RELAY_PIN_1, state1); state2 = loadState(CHILD_ID_2); setRelayState(RELAY_PIN_2, state2); } /* Example on how to asynchronously check for new messages from gw */ void loop() { debouncer1.update(); debouncer2.update(); // Get the update value int value1 = debouncer1.read(); int value2 = debouncer2.read(); if (value1 != oldValue) { send(msg.set(state1 ? false : true), true); // Send new state and request ack back // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_1, value1); } oldValue = value1; if (value2 != oldValue2) { send(msg2.set(state2 ? false : true), true); // Send new state and request ack back // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_2, value2); } oldValue2 = value2; } void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.isAck()) { #ifdef MY_DEBUG Serial.println(F("This is an ack from gateway")); #endif } else if (message.type == V_LIGHT && message.sensor == CHILD_ID_1) { // Change relay state state1 = message.getBool(); setRelayState(RELAY_PIN_1, state1); // Store state in eeprom saveState(CHILD_ID_1, state1); // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_1, state1); } else if (message.type == V_LIGHT && message.sensor == CHILD_ID_2) { state2 = message.getBool(); setRelayState(RELAY_PIN_2, state2); // Store state in eeprom saveState(CHILD_ID_2, state2); // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_2, state2); } } // Set status of a relay pin void setRelayState(byte relayPin, bool value) { digitalWrite(relayPin, value ? RELAY_ON : RELAY_OFF); } // Print debug info, centralized in one place to minimize memory usage and have only one #ifdef MY_DEBUG for all state change messages void printStateChangedDebug(int source, int sensorID, bool value) { #ifdef MY_DEBUG Serial.print(F("Sensor value changed, source=")); Serial.print(source == CHANGE_STATE_SOURCE_RADIO ? F("Radio") : F("Physical switch")); Serial.print(F(", Sensor=")); Serial.print(sensorID); Serial.print(F(", New status: ")); Serial.println(value); #endif } -
This is my sketch
// MySensor Debug #define MY_DEBUG // Enables repeater functionality (relays messages from other nodes) #define MY_REPEATER_FEATURE // Comment line below if you don't want to use the temperature sensor #define MY_RADIO_NRF24 #define MY_TRANSPORT_WAIT_READY_MS #define MY_PARENT_NODE_ID 2 #define MY_RADIO_NRF24 #include <MySensors.h> #include <SPI.h> #include <Bounce2.h> #define RELAY_PIN_1 3 // Arduino Digital I/O pin number for relay #define RELAY_PIN_2 5 #define BUTTON_PIN_1 4 // Arduino Digital I/O pin number for button #define BUTTON_PIN_2 7 #define CHILD_ID_1 8 // Id of the sensor child for 1st relay #define CHILD_ID_2 9 // Id of the sensor child for 2nd relay // Relay status #define RELAY_ON 1 #define RELAY_OFF 0 // Source of state change (used when printing debug information) #define CHANGE_STATE_SOURCE_RADIO 0 #define CHANGE_STATE_SOURCE_SWITCH 1 Bounce debouncer1 = Bounce(); int oldValue; bool state1; Bounce debouncer2 = Bounce(); int oldValue2; bool state2; MyMessage msg(CHILD_ID_1, V_LIGHT); MyMessage msg2(CHILD_ID_2, V_LIGHT); void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Double Relay & Button", "0.2"); // Register all sensors to gw (they will be created as child devices) present(CHILD_ID_1, S_LIGHT); present(CHILD_ID_2, S_LIGHT); } void setup() { // Setup the button pinMode(BUTTON_PIN_1, INPUT); // Activate internal pull-up digitalWrite(BUTTON_PIN_1, HIGH); // Setup the button pinMode(BUTTON_PIN_2, INPUT); // Activate internal pull-up digitalWrite(BUTTON_PIN_2, HIGH); // After setting up the button, setup debouncer debouncer1.attach(BUTTON_PIN_1); debouncer1.interval(5); debouncer2.attach(BUTTON_PIN_2); debouncer2.interval(5); // Set the initial values of oldValue/oldValue2 variables from status of physical switches // if this is not done the loop() will detect status change and switch the relays on or off debouncer1.update(); debouncer2.update(); oldValue = debouncer1.read(); oldValue2 = debouncer2.read(); // Make sure relays are off when starting up setRelayState(RELAY_PIN_1, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_PIN_1, OUTPUT); digitalWrite(RELAY_PIN_2, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_PIN_2, OUTPUT); // Set relay to last known state (using eeprom storage) state1 = loadState(CHILD_ID_1); setRelayState(RELAY_PIN_1, state1); state2 = loadState(CHILD_ID_2); setRelayState(RELAY_PIN_2, state2); } /* Example on how to asynchronously check for new messages from gw */ void loop() { debouncer1.update(); debouncer2.update(); // Get the update value int value1 = debouncer1.read(); int value2 = debouncer2.read(); if (value1 != oldValue) { send(msg.set(state1 ? false : true), true); // Send new state and request ack back // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_1, value1); } oldValue = value1; if (value2 != oldValue2) { send(msg2.set(state2 ? false : true), true); // Send new state and request ack back // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_2, value2); } oldValue2 = value2; } void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.isAck()) { #ifdef MY_DEBUG Serial.println(F("This is an ack from gateway")); #endif } else if (message.type == V_LIGHT && message.sensor == CHILD_ID_1) { // Change relay state state1 = message.getBool(); setRelayState(RELAY_PIN_1, state1); // Store state in eeprom saveState(CHILD_ID_1, state1); // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_1, state1); } else if (message.type == V_LIGHT && message.sensor == CHILD_ID_2) { state2 = message.getBool(); setRelayState(RELAY_PIN_2, state2); // Store state in eeprom saveState(CHILD_ID_2, state2); // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_2, state2); } } // Set status of a relay pin void setRelayState(byte relayPin, bool value) { digitalWrite(relayPin, value ? RELAY_ON : RELAY_OFF); } // Print debug info, centralized in one place to minimize memory usage and have only one #ifdef MY_DEBUG for all state change messages void printStateChangedDebug(int source, int sensorID, bool value) { #ifdef MY_DEBUG Serial.print(F("Sensor value changed, source=")); Serial.print(source == CHANGE_STATE_SOURCE_RADIO ? F("Radio") : F("Physical switch")); Serial.print(F(", Sensor=")); Serial.print(sensorID); Serial.print(F(", New status: ")); Serial.println(value); #endif }@johnym30 Can't see anything wrong with the sketch that causes the 2 outputs toggle at the same time. However, I have 2 remarks:
- Don't you need to set the pins to output before you set them low?
- You are not updating your gateway when you toggle the output with the switch.
-
@johnym30 Can't see anything wrong with the sketch that causes the 2 outputs toggle at the same time. However, I have 2 remarks:
- Don't you need to set the pins to output before you set them low?
- You are not updating your gateway when you toggle the output with the switch.
-
hmm im having a hard time fitting these modules behind my lamp buttoms couse its swedish standar 70mm holes and the nrfmodule sticks out to much anyone know a good mod?
-
Hi everyone.Its me again!!!!
Everything seems to be working just fine when i am using domoticz interface, but when i am using the hardware switches the icons in domoticz update from off to on but my lights wont turn on. If i turn my hardware switch to off, the state in domoticz stays to on.What am i doing wrong????
My sketch below ./** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * DESCRIPTION * * Script for double SSR relay board by Aproxx * https://www.openhardware.io/view/77/AC-DC-double-solid-state-relay-module * https://forum.mysensors.org/topic/3671/ac-dc-double-solid-state-relay-module * Control 2 circuits either from controller or from physical buttons connected on pins 4 & 7 * Optional DS18b20 is connected on pin 8 * * HISTORY : * xx/xx/2016 original version by Aproxx * 08/02/2016 upgraded to MySensors 2.0 by mr_const * 08/30/2016 changes by Nca78 : * - fixed initialization of physical buttons/debouncer status * - centralized pin status change for relays in setRelayState method * - centralized debug information for state changes in one method + added debug info when changed by physical switches * - added #ifdef MY_DEBUG before each Serial.print (saves prog memory when not in debug mode) and F() macros for debug strings (saves RAM when in debug mode) * - added #define USE_TEMP_SENSOR to make temperature sensor optional (not used if line is commented) * - put back #define for repeater feature * - add #define TEMPERATURE_ROUNDING for custom temperature rounding **/ // MySensor Debug //#define MY_DEBUG // Enables repeater functionality (relays messages from other nodes) //#define MY_REPEATER_FEATURE // Comment line below if you don't want to use the temperature sensor #define USE_TEMP_SENSOR #define MY_RADIO_NRF24 #include <MySensors.h> #include <SPI.h> #include <Bounce2.h> #define RELAY_PIN 3 // Arduino Digital I/O pin number for relay #define RELAY_PIN_2 5 #define BUTTON_PIN 4 // Arduino Digital I/O pin number for button #define BUTTON_PIN_2 7 #define CHILD_ID 8 // Id of the sensor child for 1st relay #define CHILD_ID_2 9 // Id of the sensor child for 2nd relay // Relay status #define RELAY_ON 1 #define RELAY_OFF 0 // Source of state change (used when printing debug information) #define CHANGE_STATE_SOURCE_RADIO 0 #define CHANGE_STATE_SOURCE_SWITCH 1 // Temperature sensor definitions #ifdef USE_TEMP_SENSOR #include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 8 #define CHILD_DSB_ID 13 // Id of the sensor child for temperature sensor #define TEMPERATURE_ROUNDING 10.f // Change value to change rounding of temperature value: 10.f for 0.1°C change, 5.f for 0.2°C change, 2.f for 0.5°C change #endif Bounce debouncer = Bounce(); int oldValue; bool state; Bounce debouncer2 = Bounce(); int oldValue2; bool state2; MyMessage msg(CHILD_ID, V_LIGHT); MyMessage msg2(CHILD_ID_2, V_LIGHT); #ifdef USE_TEMP_SENSOR MyMessage msgTemp(CHILD_DSB_ID, V_TEMP); OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. #endif void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Double Relay & Button", "0.2"); // Register all sensors to gw (they will be created as child devices) present(CHILD_ID, S_LIGHT); present(CHILD_ID_2, S_LIGHT); #ifdef USE_TEMP_SENSOR present(CHILD_DSB_ID, S_TEMP); #endif } void setup() { #ifdef USE_TEMP_SENSOR sensors.begin(); sensors.setWaitForConversion(false); #endif // Setup the button pinMode(BUTTON_PIN, INPUT); // Activate internal pull-up digitalWrite(BUTTON_PIN, HIGH); // Setup the button pinMode(BUTTON_PIN_2, INPUT); // Activate internal pull-up digitalWrite(BUTTON_PIN_2, HIGH); // After setting up the button, setup debouncer debouncer.attach(BUTTON_PIN); debouncer.interval(5); debouncer2.attach(BUTTON_PIN_2); debouncer2.interval(5); // Set the initial values of oldValue/oldValue2 variables from status of physical switches // if this is not done the loop() will detect status change and switch the relays on or off debouncer.update(); debouncer2.update(); oldValue = debouncer.read(); oldValue2 = debouncer2.read(); // Make sure relays are off when starting up setRelayState(RELAY_PIN, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN_2, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_PIN_2, OUTPUT); // Set relay to last known state (using eeprom storage) state = loadState(CHILD_ID); setRelayState(RELAY_PIN, state); state2 = loadState(CHILD_ID_2); setRelayState(RELAY_PIN_2, state2); } /* Example on how to asynchronously check for new messages from gw */ void loop() { #ifdef USE_TEMP_SENSOR static float prevTemp = 0; #endif debouncer.update(); debouncer2.update(); // Get the update value int value = debouncer.read(); int value2 = debouncer2.read(); if (value != oldValue) { send(msg.set(state ? false : true), true); // Send new state and request ack back // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID, value); } oldValue = value; if (value2 != oldValue2) { send(msg2.set(state2 ? false : true), true); // Send new state and request ack back // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_SWITCH, CHILD_ID_2, value2); } oldValue2 = value2; // Fetch temperatures from Dallas sensors #ifdef USE_TEMP_SENSOR sensors.requestTemperatures(); // Fetch and round temperature to one decimal float temperature = static_cast<float>(static_cast<int>(sensors.getTempCByIndex(0) * TEMPERATURE_ROUNDING)) / TEMPERATURE_ROUNDING; if (temperature != -127.00f && temperature != 85.00f && prevTemp != temperature) { // Send in the new temperature send(msgTemp.set(temperature, 1)); #ifdef MY_DEBUG Serial.print("Sent temperature: "); Serial.println(temperature); #endif prevTemp = temperature; } #endif } void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.isAck()) { #ifdef MY_DEBUG Serial.println(F("This is an ack from gateway")); #endif } else if (message.type == V_LIGHT && message.sensor == CHILD_ID) { // Change relay state state = message.getBool(); setRelayState(RELAY_PIN, state); // Store state in eeprom saveState(CHILD_ID, state); // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID, state); } else if (message.type == V_LIGHT && message.sensor == CHILD_ID_2) { state2 = message.getBool(); setRelayState(RELAY_PIN_2, state2); // Store state in eeprom saveState(CHILD_ID_2, state2); // Write some debug info printStateChangedDebug(CHANGE_STATE_SOURCE_RADIO, CHILD_ID_2, state2); } } // Set status of a relay pin void setRelayState(byte relayPin, bool value) { digitalWrite(relayPin, value ? RELAY_ON : RELAY_OFF); } // Print debug info, centralized in one place to minimize memory usage and have only one #ifdef MY_DEBUG for all state change messages void printStateChangedDebug(int source, int sensorID, bool value) { #ifdef MY_DEBUG Serial.print(F("Sensor value changed, source=")); Serial.print(source == CHANGE_STATE_SOURCE_RADIO ? F("Radio") : F("Physical switch")); Serial.print(F(", Sensor=")); Serial.print(sensorID); Serial.print(F(", New status: ")); Serial.println(value); #endif }