@leader21 added @sweebee,@mwittig and @sweetpi as contributors to mysensors plugin. hope this helps in rapid/better development of plugin
-
mysensors-node shutter device
-
@dpressle Hi, I’m pretty new to arduino and was looking for a rollershutter sketch when I found your sketch. I compiled it and loaded it on my UNO with a relay board connected. The sketch is working fine but the relays are on when nothing is moving and turn off when a command is received. I tried to turn the behavior of the relays but I was not successful. My board is active low afaik, is that a problem? I’m not sure where to begin. Thanks
-
@ihtgtwtd Doesn’t the relay board have jumper to make it active high?
if not then you just need to change:#define RELAY_ON 1
#define RELAY_OFF 0to:
#define RELAY_ON 0
#define RELAY_OFF 1Also there is a new version of scketch with percentage time control and some other stuff.
-
Hey depressle,
I testet your sketch and it looks good for me thank you for that!
but two things are not working for me (could be my flault)First: you build in a timer (default: 15 seconds) and the rollershutter stops correct. but it stopped not in pimatic. the button down or up is aktivatet although the shutter is stopped. is it possible to send the information to pimatic?
Second: I want to see the percentage of the rollershutter if I read the scetch correctly, this should be possible, but for me I only see the two buttons “up” and “down”. maybe you could explain for me, how i can see the percentage.
thank you!
(actually for me its not a real rollershutter. only two leds instead of the relays for tests)
-
Hey,
in the last two month i have spend some time in the rollershutter node. Maybe some of you can use the sketch (it`s an upgrade from depressles sketch).
Some Points to the Sketch:
-send periodically the position and the temperature of the node
-two button (when the shutter ist moving any button stops)
-two times for moving (my Shutters are faster, when they moving down)
-sending up&down time from pimatic
-sending the wantet position from pimaticIf you have any idea to improve it, please tell me!
// Enable debug prints to serial monitor // //#define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 #define MY_RF24_PA_LEVEL RF24_PA_HIGH // _LOW _MAX empfindlichkeit und sendestärke des Funkmoduls #define MY_RF24_IRQ_PIN (2) // zwischenspeichern von empfangenen Informationen #define MY_RX_MESSAGE_BUFFER_FEATURE #define MY_RX_MESSAGE_BUFFER_SIZE (10) #define MY_REPEATER_FEATURE //Repeaterfunktion eingeschaltet #define USE_TEMP_SENSOR //Auskommentieren, wenn keine Temperatur übertragen werden soll. #define MY_TRANSPORT_WAIT_READY_MS 3000 //set how long to wait for transport ready. // uncomment if we want to manually assign an ID //#define MY_NODE_ID 1 / #include <Bounce2.h> #include <MySensors.h> #include <SPI.h> // Temperature sensor definitions #ifdef USE_TEMP_SENSOR #include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 8 //Dallas Sensor #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 #define TEMPERATURE_THRESHOLD 2.0 // If threshold is reached, new temperature value will be sent #define TEMPERATURE_INTERVAL_MS 900000 // Temperature will be sent every 15 minutes #endif #define BUTTON_UP_PIN 5 // Arduino Digital I/O pin number for up button #define BUTTON_DOWN_PIN 3 // Arduino Digital I/O pin number for down button #define RELAY_DIR_PIN 6 // Arduino Digital I/O pin number for direction relay #define RELAY_POWER_PIN 7 // Arduino Digital I/O pin number for power relay #define RELAY_ON 1 #define RELAY_OFF 0 #define DIRECTION_DOWN 1 #define DIRECTION_UP 0 #define SKETCH_NAME "roller shutter" #define SKETCH_VER "2.1" #define CHILD_ID 1 // sensor Id of the sensor child #define CHILD_ID_SET_UP 2 // sensor Id of the sensor child to init the roll time up #define CHILD_ID_SET_DOWN 3 // sensor Id of the sensor child to init the roll time down #define PRESENT_MESSAGE "sensor for roller shutter" const int LEVELS = 100; //the number of levels float rollTimeUp = 39.0; //the overall rolling time of the shutter for going up -> changed by V_VAR1 float rollTimeDown = 36.0; //the overall rolling time of the shutter for going down -> changed by V_VAR2 const bool IS_ACK = false; //is to acknowlage #define CHILD_ID_LIGHT 6 //Child ID for sending level // debouncing parameters int value = 0; int oldValueUp = 0; int oldValueDown = 0; int oldValueStop = 0; static unsigned long last_interrupt_time_up = 0; static unsigned long last_interrupt_time_down = 0; static unsigned long debounce_time = 200; Bounce debouncerUp = Bounce(); Bounce debouncerDown = Bounce(); Bounce debouncerStop = Bounce(); // shutter position parameters float timeOneLevelUp = rollTimeUp / LEVELS; //time for one level up float timeOneLevelDown = rollTimeDown / LEVELS; //time for one level down int requestedShutterLevel = 0; int currentShutterLevel = 0; int currentShutterLevelold = 0; unsigned long lastLevelTime = 0; bool isMoving = false; int directionUpDown; #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 MyMessage msgUp(CHILD_ID, V_UP); MyMessage msgDown(CHILD_ID, V_DOWN); MyMessage msgStop(CHILD_ID, V_STOP); MyMessage msgPercentage(CHILD_ID, V_PERCENTAGE); MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL); void print_debug(String message) { #ifdef MY_DEBUG Serial.println(message); #endif } // moves shutters up void shuttersUp(void) { print_debug("Shutters going up."); directionUpDown = DIRECTION_UP; isMoving = true; digitalWrite(RELAY_DIR_PIN, RELAY_OFF); //wait(100); digitalWrite(RELAY_POWER_PIN, RELAY_ON); send(msgUp, IS_ACK); //wait(100); } // moves shutters down void shuttersDown(void) { print_debug("Shutters going down."); directionUpDown = DIRECTION_DOWN; isMoving = true; digitalWrite(RELAY_DIR_PIN, RELAY_ON); wait(200); digitalWrite(RELAY_POWER_PIN, RELAY_ON); send(msgDown, IS_ACK); //wait(100); } // stops shutters at current position and saves it to currentShutterLevel void shuttersHalt(void) { isMoving = false; directionUpDown = DIRECTION_UP; digitalWrite(RELAY_POWER_PIN, RELAY_OFF); wait(200); digitalWrite(RELAY_DIR_PIN, RELAY_OFF); print_debug("Shutters halted."); saveState(CHILD_ID, currentShutterLevel); print_debug("saving level to: "); print_debug(String(currentShutterLevel)); requestedShutterLevel = currentShutterLevel; //wait(100); } void changeShuttersLevel(int LEVELS) { if ((LEVELS < 0) || (LEVELS > 100)) { print_debug("level is out of range calling InitShutters: "); print_debug(String(LEVELS)); InitShutters(); LEVELS = 0; } else { int dir = (LEVELS > currentShutterLevel) ? DIRECTION_DOWN : DIRECTION_UP; if ((isMoving == true) && (dir != directionUpDown)) { shuttersHalt(); } else { print_debug("setting requested level to:"); print_debug(String(LEVELS)); requestedShutterLevel = LEVELS; } } } void InitShutters() { if (LEVELS < 0 || LEVELS > 100) { print_debug("Current level unsure, calibrating..."); print_debug("Init Shutters"); shuttersUp(); print_debug("delaying for: "); print_debug(String((rollTimeUp + timeOneLevelUp * LEVELS) * 1000)); delay((rollTimeUp + timeOneLevelUp * LEVELS) * 1000); print_debug("ended delay rolltime"); currentShutterLevel = 0; requestedShutterLevel = currentShutterLevel; return true; } else { print_debug("No clibration needed. setting to: "); print_debug(String(LEVELS)); currentShutterLevel = LEVELS; changeShuttersLevel(currentShutterLevel); return false; } } void receive(const MyMessage &message) { print_debug("recieved incomming message"); print_debug("Recieved message for sensor: "); print_debug(String(message.sensor)); switch (message.sensor) { case CHILD_ID: switch (message.type) { case V_UP: print_debug(", New status: V_UP"); changeShuttersLevel(0); print_debug("Done shutterAction procedure"); send(msgUp, IS_ACK); break; case V_DOWN: print_debug(", New status: V_DOWN"); changeShuttersLevel(100); print_debug("Done shutterAction procedure"); send(msgDown, IS_ACK); break; case V_STOP: print_debug(", New status: V_STOP"); shuttersHalt(); print_debug("Done shutterAction procedure"); send(msgStop, IS_ACK); send(msg.set(currentShutterLevel)); currentShutterLevelold = currentShutterLevel; requestedShutterLevel = currentShutterLevel; saveState(CHILD_ID, currentShutterLevel); break; case V_PERCENTAGE: print_debug(", New status: V_PERCENTAGE"); changeShuttersLevel(message.getInt()); //InitShutters(message.getInt());//send value < 0 or > 100 to calibrate print_debug("Done shutterAction procedure"); send(msgPercentage, IS_ACK); break; } case CHILD_ID_SET_UP: switch (message.type) { case V_VAR1: print_debug(", New status: V_VAR1, with payload: "); rollTimeUp = message.getFloat(); print_debug("rolltimeUp value: "); print_debug(String(rollTimeUp)); saveState(CHILD_ID_SET_UP, rollTimeUp); timeOneLevelUp = rollTimeUp / LEVELS; break; case V_VAR3: print_debug(", New status: "); print_debug("V_VAR3, with payload: "); print_debug(String(message.getInt())); InitShutters(); break; } case CHILD_ID_SET_DOWN: switch (message.type) { case V_VAR2: print_debug(", New status: V_VAR2, with payload: "); rollTimeDown = message.getFloat(); print_debug("rolltimeDown value: "); print_debug(String(rollTimeDown)); saveState(CHILD_ID_SET_DOWN, rollTimeDown); timeOneLevelDown = rollTimeDown / LEVELS; break; } } print_debug("exiting incoming message"); return; } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo(SKETCH_NAME, SKETCH_VER); // Register all sensors to gw (they will be created as child devices) present(CHILD_ID, S_COVER, PRESENT_MESSAGE, IS_ACK); present(CHILD_ID_SET_UP, S_CUSTOM, PRESENT_MESSAGE, IS_ACK); present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); #ifdef USE_TEMP_SENSOR present(CHILD_DSB_ID, S_TEMP); #endif } void before() { // Setup the button pinMode(BUTTON_UP_PIN, INPUT_PULLUP); //Activate internal pull-up digitalWrite(BUTTON_UP_PIN, HIGH); pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP); //Activate internal pull-up digitalWrite(BUTTON_DOWN_PIN, HIGH); /*pinMode(BUTTON_STOP_PIN, INPUT_PULLUP); //Activate internal pull-up digitalWrite(BUTTON_STOP_PIN, HIGH); */ // After setting up the button, setup debouncer debouncerUp.attach(BUTTON_UP_PIN); debouncerUp.interval(10); // After setting up the button, setup debouncer debouncerDown.attach(BUTTON_DOWN_PIN); debouncerDown.interval(10); /* // After setting up the button, setup debouncer debouncerStop.attach(BUTTON_STOP_PIN); debouncerStop.interval(10); */ // Make sure relays are off when starting up digitalWrite(RELAY_DIR_PIN, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_DIR_PIN, OUTPUT); // Make sure relays are off when starting up digitalWrite(RELAY_POWER_PIN, RELAY_OFF); // Then set relay pins in output mode pinMode(RELAY_POWER_PIN, OUTPUT); } void setup(void) { Serial.begin(115200); Serial.println("StartUP"); //set up roll time up if the saved value is not 255 print_debug("getting rolltime from eeprom: "); int tmpRollTimeUp = loadState(CHILD_ID_SET_UP); if (tmpRollTimeUp < 255) { rollTimeUp = tmpRollTimeUp; timeOneLevelUp = rollTimeUp / LEVELS; } print_debug(String(rollTimeUp)); //set up roll time down if the saved value is not 255 print_debug("getting rolltime from eeprom: "); int tmpRollTimeDown = loadState(CHILD_ID_SET_DOWN); if (tmpRollTimeDown < 255) { rollTimeDown = tmpRollTimeDown; timeOneLevelDown = rollTimeDown / LEVELS; } print_debug(String(rollTimeDown)); print_debug("getting state from eeprom: "); int state = loadState(CHILD_ID); print_debug(String(state)); currentShutterLevel = state; requestedShutterLevel = state; //changeShuttersLevel(state); #ifdef USE_TEMP_SENSOR sensors.begin(); sensors.setWaitForConversion(false); #endif } void loop(void) { #ifdef USE_TEMP_SENSOR static float prevTemp = 0; static unsigned long lastSentTimestamp = 0; #endif #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; // Check if temperature is valid if (temperature != -127.00f && temperature != 85.00f) { // Check threshold if (((temperature >= (prevTemp + TEMPERATURE_THRESHOLD)) || (temperature <= (prevTemp - TEMPERATURE_THRESHOLD)))) { // Send in the new temperature send(msgTemp.set(temperature, true)); #ifdef MY_DEBUG Serial.print("Sent temperature: "); Serial.println(temperature); #endif prevTemp = temperature; } // Check interval if ((millis() - lastSentTimestamp) > TEMPERATURE_INTERVAL_MS) { // Send in the new temperature send(msgTemp.set(temperature, true)); send(msg.set(currentShutterLevel, true)); lastSentTimestamp = millis(); #ifdef MY_DEBUG Serial.print("Sent temperature: "); Serial.println(temperature); #endif } } #endif debouncerUp.update(); value = debouncerUp.read(); if ((value == 0) && (value != oldValueUp) && (isMoving == false)) { changeShuttersLevel(0); } else if ((value == 0) && (value != oldValueUp) && (isMoving == true)) { requestedShutterLevel = currentShutterLevel; } oldValueUp = value; debouncerDown.update(); value = debouncerDown.read(); if ((value == 0) && (value != oldValueDown) && (isMoving == false)) { changeShuttersLevel(100); } else if ((value == 0) && (value != oldValueDown) && (isMoving == true)) { requestedShutterLevel = currentShutterLevel; } oldValueDown = value; if ((currentShutterLevel == requestedShutterLevel) && (isMoving == true)) { shuttersHalt(); send(msg.set(currentShutterLevel)); currentShutterLevelold = currentShutterLevel; //send(msgStop, IS_ACK); saveState(CHILD_ID, currentShutterLevel); } else if ((currentShutterLevel != requestedShutterLevel) && (isMoving == true)) { unsigned long _now = millis(); if ((directionUpDown == DIRECTION_DOWN)) { if (_now - lastLevelTime >= timeOneLevelDown * 1000) { //print_debug("3"); currentShutterLevel += 1; lastLevelTime = millis(); } } else { if (_now - lastLevelTime >= timeOneLevelUp * 1000) { //print_debug("4"); currentShutterLevel -= 1; lastLevelTime = millis(); } } } else if ((requestedShutterLevel != currentShutterLevel) && (isMoving == false)) { //print_debug("6"); if (requestedShutterLevel < currentShutterLevel) { //print_debug("7"); shuttersUp(); } else { // print_debug("8"); shuttersDown(); } lastLevelTime = millis(); } // Statusposition in 5% Schritten senden, falls sich der Wert vom alten unterscheidet if ((currentShutterLevel != currentShutterLevelold) && ((currentShutterLevel % 5) == 0)) { send(msg.set(currentShutterLevel), false); currentShutterLevelold = currentShutterLevel; } }