Problem with multiple relays and delays



  • Hi, I am building shutters controler.
    My motorized shutters are very basics. There are 3 cables for each motors.
    One hot for the ascend the second hot for descent and the neutral.

    To automate shutters I have an opening delay.
    When I command the opening, the relay is operated until the opening delay is ended.

    This works well when I command one shutter. But in this room there are 3 shutters on the same sensors node.
    When I use several shutters at the same time there is problems (it seems like delays were added together ).
    Some relays are activated during too much time.

    Should i use some kind of threads for each shutter?

    Cheers

    /* ===============================================================
          Project: Store Test
           Author: Lucas van Rossum
          Created: 14/02/2016
      Arduino IDE: 1.7.8
    
    ================================================================== */
    
    
    #include <MySensor.h>
    #include <SPI.h>
    #include <Bounce2.h> 
    #define RELAY_ON 0
    #define RELAY_OFF 1 
    
    // relay shutter pin
    #define RELAY_UP1  2    
    #define RELAY_DWN1  3  
    #define RELAY_UP2  4
    #define RELAY_DWN2  5
    #define RELAY_UP3  6
    #define RELAY_DWN3  7
    
    //button pin
    #define BUTUP1  8 
    #define BUTDWN1  A5
    #define BUTUP2  A4
    #define BUTDWN2  A6 
    #define BUTUP3  A7 
    #define BUTDWN3  A0 
    
    //switch door pin
    #define DOORSWITCH1 A3 
    #define DOORSWITCH2 A2 
    
    // CHILD ID
    #define CHILD_ID_STORE1 1
    #define CHILD_ID_STORE2 2
    #define CHILD_ID_STORE3 3
    #define CHILD_ID_WINDOWS1 4
    #define CHILD_ID_WINDOWS2 5
    
    //Secure delay
    int securedelay=0;
    
    //openclose delay
    int ouverturedelay=10000;
    
    
    // to store button value
    int ValBUTUP1=0;
    int ValBUTDWN1=0;
    int ValBUTUP2=0;
    int ValBUTDWN2=0;
    int ValBUTUP3=0;
    int ValBUTDWN3=0;
    
    //to store last shutter action
    int oldActionA=0;
    int oldActionB=0;
    int oldActionC=0;
    
    bool state;
    
    //// Construct MySensors library
    MySensor gw; 
    
    MyMessage msgAUp(CHILD_ID_STORE1,V_UP);
    MyMessage msgADwn(CHILD_ID_STORE1,V_DOWN);
    MyMessage msgAStp(CHILD_ID_STORE1,V_STOP);
    MyMessage msgApor(CHILD_ID_STORE1,V_PERCENTAGE);
    
    MyMessage msgBUp(CHILD_ID_STORE2,V_UP);
    MyMessage msgBDwn(CHILD_ID_STORE2,V_DOWN);
    MyMessage msgBStp(CHILD_ID_STORE2,V_STOP);
    MyMessage msgBpor(CHILD_ID_STORE2,V_PERCENTAGE);
    
    MyMessage msgCUp(CHILD_ID_STORE3,V_UP);
    MyMessage msgCDwn(CHILD_ID_STORE3,V_DOWN);
    MyMessage msgCStp(CHILD_ID_STORE3,V_STOP);
    MyMessage msgCpor(CHILD_ID_STORE3,V_PERCENTAGE);
    
    
    //switch
    
    Bounce debouncer1 = Bounce();
    Bounce debouncer2 = Bounce();
    
    int oldValDOORSWITCH1=-1;
    int oldValDOORSWITCH2=-1;
    
    MyMessage msgSWITCH1(CHILD_ID_WINDOWS1,V_TRIPPED);
    MyMessage msgSWITCH2(CHILD_ID_WINDOWS2,V_TRIPPED);
    
    
    
    
    
    void setup(){
       // Initialize library and add callback for incoming messages
       gw.begin(incomingMessage, AUTO, true);
        // Send the sketch version information to the gateway and Controller
       gw.sendSketchInfo("Store_Salon ", "1.0");
    
       // Register all sensors to gw (they will be created as child devices)
       gw.present(CHILD_ID_STORE1, S_COVER);
       gw.present(CHILD_ID_STORE2, S_COVER);
       gw.present(CHILD_ID_STORE3, S_COVER);
       
       gw.present(CHILD_ID_WINDOWS1, S_BINARY);
       gw.present(CHILD_ID_WINDOWS2, S_BINARY);
       
       //Setup all the Arduino Pins
       
       
       //relay
       pinMode(RELAY_UP1, OUTPUT);
       pinMode(RELAY_DWN1, OUTPUT);
       pinMode(RELAY_UP2, OUTPUT);
       pinMode(RELAY_DWN2, OUTPUT);
       pinMode(RELAY_UP3, OUTPUT);
       pinMode(RELAY_DWN3, OUTPUT);
       
       //switch
       pinMode(DOORSWITCH1,INPUT);
       pinMode(DOORSWITCH2,INPUT);
       
       // pullup
       digitalWrite(DOORSWITCH1,HIGH);
       digitalWrite(DOORSWITCH2,HIGH);
       
       
       debouncer1.attach(DOORSWITCH1);
       debouncer2.attach(DOORSWITCH2);
       
       debouncer1.interval(5);
       debouncer2.interval(5);
       
       //Turn OFF any power to the Relay channels
       digitalWrite(RELAY_UP1,RELAY_OFF);
       digitalWrite(RELAY_DWN1,RELAY_OFF);
       digitalWrite(RELAY_UP2,RELAY_OFF);
       digitalWrite(RELAY_DWN2,RELAY_OFF);
       digitalWrite(RELAY_UP3,RELAY_OFF);
       digitalWrite(RELAY_DWN3,RELAY_OFF);
       
       pinMode(BUTUP1, INPUT);
       pinMode(BUTDWN1, INPUT);
       pinMode(BUTUP2, INPUT);
       pinMode(BUTDWN2, INPUT);
       pinMode(BUTUP3, INPUT);
       pinMode(BUTDWN3, INPUT);
       
       // pullup
       digitalWrite(BUTUP1,HIGH);
       digitalWrite(BUTDWN1,HIGH);
       digitalWrite(BUTUP2,HIGH);
       //digitalWrite(BUTDWN2,HIGH); only analog A6
       //digitalWrite(BUTUP3,HIGH); only analog A7
       digitalWrite(BUTDWN3,HIGH);
       
       
     }
     
     void loop(){
       
       // Alway process incoming messages whenever possible
       gw.process();
       //Get buton value
       ValBUTUP1 = digitalRead(BUTUP1);
       ValBUTDWN1 = digitalRead(BUTDWN1);
       ValBUTUP2 = digitalRead(BUTUP2);
       ValBUTDWN2 = analogRead(BUTDWN2) < 500 ? LOW : HIGH;
       ValBUTUP3 = analogRead(BUTUP3) < 500 ? LOW : HIGH;
       ValBUTDWN3 = digitalRead(BUTDWN3);
       
       //Get Magnetic Door Switch Sensor
       
       debouncer1.update();
       // Get the update value
       int value1 = debouncer1.read();
     
       if (value1 != oldValDOORSWITCH1) {
         // Send in the new value
         gw.send(msgSWITCH1.set(value1==HIGH ? 1 : 0));
         oldValDOORSWITCH1 = value1;
       }
       
       debouncer2.update();
       // Get the update value
       int value2 = debouncer2.read();
     
       if (value2 != oldValDOORSWITCH2) {
         // Send in the new value
         gw.send(msgSWITCH2.set(value2==HIGH ? 1 : 0));
         oldValDOORSWITCH2 = value2;
       }
       
       ////////// button
       //shutter1
       //UP
       if (ValBUTUP1 == LOW && ValBUTDWN1 == HIGH  ){
         int action=1;                                 //action: 1 up,2 down, 0 stop
         if (action!=oldActionA) {
           //if (oldAction==2){
           digitalWrite(RELAY_DWN1, RELAY_OFF);
           digitalWrite(RELAY_UP1, RELAY_OFF);  
           gw.wait(securedelay);//}
           Serial.print(", up relay1 ");
           digitalWrite(RELAY_UP1,RELAY_ON);
           digitalWrite(RELAY_DWN1,RELAY_OFF);
           gw.send(msgAUp.set(1), false);}            // back to domoticz
         oldActionA=action;}
       //DOWN
       if (ValBUTDWN1 == LOW && ValBUTUP1 == HIGH ){
         int action=2;     //1 monté,2descente, 0stop
         if (action!=oldActionA) {
           //if (oldAction==1){
           digitalWrite(RELAY_DWN1, RELAY_OFF);
           digitalWrite(RELAY_UP1, RELAY_OFF);  
           gw.wait(securedelay);//}
           Serial.print(", down relay1 ");
           digitalWrite(RELAY_DWN1,RELAY_ON);
           digitalWrite(RELAY_UP1,RELAY_OFF);
           gw.send(msgADwn.set(1), false);}          // back to domoticz
         oldActionA=action;
        } 
         
        //OFF
           if (ValBUTDWN1 == HIGH && ValBUTUP1 == HIGH ){
         int action=0;                               //action: 1 up,2 down, 0 stop
         if (action!=oldActionA){
           Serial.print(", none ");
           digitalWrite(RELAY_UP1,RELAY_OFF);
           digitalWrite(RELAY_DWN1,RELAY_OFF);
           gw.send(msgAStp.set(1), false);}           // back to domoticz
         oldActionA=action; 
       }
       
       if (ValBUTDWN1 == LOW && ValBUTUP1 == LOW ){
         int action=0;                               //action: 1 up,2 down, 0 stop
         if (action!=oldActionA){
           Serial.print(", none ");
           digitalWrite(RELAY_UP1,RELAY_OFF);
           digitalWrite(RELAY_DWN1,RELAY_OFF);
           gw.send(msgAStp.set(1), false);}          // back to domoticz
         oldActionA=action; 
       } 
         
         
       //shutter2
       //UP
       if (ValBUTUP2 == LOW && ValBUTDWN2 == HIGH  ){
         int action=1;                                 //action: 1 up,2 down, 0 stop
         if (action!=oldActionB) {
           //if (oldAction==2){
           digitalWrite(RELAY_DWN2, RELAY_OFF);
           digitalWrite(RELAY_UP2, RELAY_OFF);  
           gw.wait(securedelay);//}
           Serial.print(", up relay2 ");
           digitalWrite(RELAY_UP2,RELAY_ON);
           digitalWrite(RELAY_DWN2,RELAY_OFF);
           gw.send(msgBUp.set(1), false);}              // back to domoticz
         oldActionB=action;}
       //DOWN
       if (ValBUTDWN2 == LOW && ValBUTUP2 == HIGH ){
         int action=2;                                   //action: 1 up,2 down, 0 stop
         if (action!=oldActionB) {
           //if (oldAction==1){
           digitalWrite(RELAY_DWN2, RELAY_OFF);
           digitalWrite(RELAY_UP2, RELAY_OFF);  
           gw.wait(securedelay);//}
           Serial.print(", down relay2 ");
           digitalWrite(RELAY_DWN2,RELAY_ON);
           digitalWrite(RELAY_UP2,RELAY_OFF);
           gw.send(msgBDwn.set(1), false);}             // back to domoticz
         oldActionB=action;
        }
        //OFF
           if (ValBUTDWN2 == HIGH && ValBUTUP2 == HIGH ){
         int action=0;                  //1 monté,2descente, 0stop
         if (action!=oldActionB){
           Serial.print(", stop Stor2 2b ");
           digitalWrite(RELAY_UP2,RELAY_OFF);
           digitalWrite(RELAY_DWN2,RELAY_OFF);
           gw.send(msgBStp.set(1), false);}             // back to domoticz
         oldActionB=action; 
       }
       
       if (ValBUTDWN2 == LOW && ValBUTUP2 == LOW ){
         int action=0;                                  //action: 1 up,2 down, 0 stop
         if (action!=oldActionB){
           Serial.print(", stop Stor2 0b ");
           digitalWrite(RELAY_UP2,RELAY_OFF);
           digitalWrite(RELAY_DWN2,RELAY_OFF);
           gw.send(msgBStp.set(1), false);}            // back to domoticz
         oldActionB=action; 
       }
       
       //shutter3
       //UP
       if (ValBUTUP3 == LOW && ValBUTDWN3 == HIGH  ){
         int action=1;                                 //action: 1 up,2 down, 0 stop
         if (action!=oldActionC) {
           //if (oldAction==2){
           digitalWrite(RELAY_DWN3, RELAY_OFF);
           digitalWrite(RELAY_UP3, RELAY_OFF);  
           gw.wait(securedelay);//}
           Serial.print(", up relay3 ");
           digitalWrite(RELAY_UP3,RELAY_ON);
           digitalWrite(RELAY_DWN3,RELAY_OFF);
           gw.send(msgCUp.set(1), false);}            // back to domoticz
         oldActionC=action;}
       //DOWN
       if (ValBUTDWN3 == LOW && ValBUTUP3 == HIGH ){
         int action=2;                                 //action: 1 up,2 down, 0 stop
         if (action!=oldActionC) {
           //if (oldAction==1){
           digitalWrite(RELAY_DWN3, RELAY_OFF);
           digitalWrite(RELAY_UP3, RELAY_OFF);  
           gw.wait(securedelay);//}
           Serial.print(", down relay3 ");
           digitalWrite(RELAY_DWN3,RELAY_ON);
           digitalWrite(RELAY_UP3,RELAY_OFF);
           gw.send(msgCDwn.set(1), false);}            // back to domoticz
         oldActionC=action;
        }
        //OFF
           if (ValBUTDWN3 == HIGH && ValBUTUP3 == HIGH ){
         int action=0;                                 //action: 1 up,2 down, 0 stop
         if (action!=oldActionC){
           Serial.print(", none ");
           digitalWrite(RELAY_UP3,RELAY_OFF);
           digitalWrite(RELAY_DWN3,RELAY_OFF);
           gw.send(msgCStp.set(1), false);}            //back to domoticz
         oldActionC=action; 
       }
       
       if (ValBUTDWN3 == LOW && ValBUTUP3 == LOW ){
         int action=0;                                //action: 1 up,2 down, 0 stop
         if (action!=oldActionC){
           Serial.print(", none ");
           digitalWrite(RELAY_UP3,RELAY_OFF);
           digitalWrite(RELAY_DWN3,RELAY_OFF);
           gw.send(msgCStp.set(1), false);}            //back to domoticz
         oldActionC=action; 
       } 
    }
    
    
    
    void incomingMessage(const MyMessage &message) {
      // Write some debug info
         Serial.println("[incomingMessage]");
         Serial.print("Incoming change for sensor:");
         Serial.print(message.sensor);
         Serial.print("messagetype");
         Serial.print(message.type);
         Serial.print(", New status: ");
         Serial.println(message.getBool());
         
      // shutter1   
      if (message.sensor ==1){
          
          if (message.type == 29) {
             // open shutter
             state = message.getBool();
             if(state == 0){
                digitalWrite(RELAY_DWN1, RELAY_OFF);
                digitalWrite(RELAY_UP1, RELAY_OFF);
                gw.wait(securedelay);
                digitalWrite(RELAY_UP1, RELAY_ON);
                digitalWrite(RELAY_DWN1, RELAY_OFF);
                gw.wait(ouverturedelay);
                digitalWrite(RELAY_DWN1, RELAY_OFF);
                digitalWrite(RELAY_UP1, RELAY_OFF);
             
                }
          }      
          if (message.type == 30) {
             // close shutter
             state = message.getBool();
             if(state == 0){
               digitalWrite(RELAY_DWN1, RELAY_OFF);
               digitalWrite(RELAY_UP1, RELAY_OFF);
               gw.wait(securedelay);
               digitalWrite(RELAY_DWN1, RELAY_ON);
               digitalWrite(RELAY_UP1, RELAY_OFF);
               gw.wait(ouverturedelay);
               digitalWrite(RELAY_DWN1, RELAY_OFF);
               digitalWrite(RELAY_UP1, RELAY_OFF);
                
                }  
             
          }   
          if (message.type == 31) {
             // stop shutter
             state = message.getBool();
             if(state == 0){
                digitalWrite(RELAY_DWN1, RELAY_OFF);
                digitalWrite(RELAY_UP1, RELAY_OFF); 
               
             
          }   
             
        }  
      }
    // shutter2   
    if (message.sensor ==2){
          
          if (message.type == 29) {
             // open shutter
             state = message.getBool();
             if(state == 0){
                digitalWrite(RELAY_DWN2, RELAY_OFF);
                digitalWrite(RELAY_UP2, RELAY_OFF);
                gw.wait(securedelay);
                digitalWrite(RELAY_UP2, RELAY_ON);
                digitalWrite(RELAY_DWN2, RELAY_OFF);
                gw.wait(ouverturedelay);
                digitalWrite(RELAY_DWN2, RELAY_OFF);
                digitalWrite(RELAY_UP2, RELAY_OFF);
             
                }
          }      
          if (message.type == 30) {
             // close shutter
             state = message.getBool();
             if(state == 0){
               digitalWrite(RELAY_DWN2, RELAY_OFF);
               digitalWrite(RELAY_UP2, RELAY_OFF);
               gw.wait(securedelay);
               digitalWrite(RELAY_DWN2, RELAY_ON);
               digitalWrite(RELAY_UP2, RELAY_OFF);
               gw.wait(ouverturedelay);
               digitalWrite(RELAY_DWN2, RELAY_OFF);
               digitalWrite(RELAY_UP2, RELAY_OFF);
                
                }  
             
          }   
          if (message.type == 31) {
             // stop shutter
             state = message.getBool();
             if(state == 0){
                digitalWrite(RELAY_DWN2, RELAY_OFF);
                digitalWrite(RELAY_UP2, RELAY_OFF); 
               
             
          }   
             
        }  
         
    }
    // shutter3 
    if (message.sensor ==3){
          
          if (message.type == 29) {
             // open shutter
             state = message.getBool();
             if(state == 0){
                digitalWrite(RELAY_DWN3, RELAY_OFF);
                digitalWrite(RELAY_UP3, RELAY_OFF);
                gw.wait(securedelay);
                digitalWrite(RELAY_UP3, RELAY_ON);
                digitalWrite(RELAY_DWN3, RELAY_OFF);
                gw.wait(ouverturedelay);
                digitalWrite(RELAY_DWN3, RELAY_OFF);
                digitalWrite(RELAY_UP3, RELAY_OFF);
             
                }
          }      
          if (message.type == 30) {
             // close shutter
             state = message.getBool();
             if(state == 0){
               digitalWrite(RELAY_DWN3, RELAY_OFF);
               digitalWrite(RELAY_UP3, RELAY_OFF);
               gw.wait(securedelay);
               digitalWrite(RELAY_DWN3, RELAY_ON);
               digitalWrite(RELAY_UP3, RELAY_OFF);
               gw.wait(ouverturedelay);
               digitalWrite(RELAY_DWN3, RELAY_OFF);
               digitalWrite(RELAY_UP3, RELAY_OFF);
                
                }  
             
          }   
          if (message.type == 31) {
             // stop shutter
             state = message.getBool();
             if(state == 0){
                digitalWrite(RELAY_DWN3, RELAY_OFF);
                digitalWrite(RELAY_UP3, RELAY_OFF); 
               
             
          }   
             
        }  
         
    }
    
    
      
    }
    
    

  • Hardware Contributor

    hi.
    It's maybe not the best section, hardware section is better...
    you should use asynchronous coding, sort of "thread" if you prefer. you could use millis, timer, and "if" statement for this..here your code is using gw.wait but it's blocking if you want to use multiple relays at same time.
    For learning : https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
    or use this lib : https://github.com/marvinroger/arduino-shutters
    and create multiple shutters objects for your shutters if there are on same node. I don't know what you will get for memory usage but if you have not too much shutters by node that should work I guess..



  • Thank you that's exactly what i am looking for!



  • Hi, I'm very intersted in your project, because the mine is the same. I have 12 shutters ton control with an arduino Mega.
    I 've read marvinroger's sketch, but how to make the link with the relays ?
    I did not see where/how to do that.

    @Lucas-van-rossum Would you mind sharing the progress of your work, so I can progress too ?



  • @Poupoune1974 no problems, i will post my progress here...



  • @Lucas-van-rossum
    Hi,
    I had a similar challenge with my rollershutters and I think most standard ones do exactly the same, they have one neutral pin and two for the directions (up, down). I started a few months ago building the first prototype which was controlled via WIFI and worked very well. I did not find much examples and all was build up myself. However WIFI didn't seem to be the best and I did not want to pollute my wireless therefore I searched for alternatives which I found here. Still struggling with the stability of the sensor network but besides that I am very happy with my solution.
    I also thought that I need to build an intelligent device which drives the shutters up, down and to intermediate positions. Played a lot with timers and stuff and eventually found the arduino-shutters of marvinroger with which I wasted another few days until I gave up and found out the code does not work for me - at least the latest version. Someone (I guess it was you) pointed out that earlier release seems to be working.
    By the time I decided, that I do not want any intelligence in my hardware and instead put the logic into the controller (I am using openhab). There it is quite easy to work with threads and move one down for 20 sec and then stop. It even shows me the position where it is when driving from the physical buttons. Another point which played a role, my shutters need different time for up and down (up mostly 54sec, down 50) and I do have various variations. some of the rollos only take 35 sec and my automated windows even just 25 sec for a full cycle. And instead of making the code more complicated and potentially send an update or setup parameter via the air to the note, I maintain it centrally in the controller.

    I have build shutter controllers for 1, 2 and 3 shutters on one board and all have the same logic.
    I do need to have full control via the physical buttons all the time. So when the controller decides to send them down and I do not want, I can go to the swich and stop it immediately. So basically, my logic is checking the pysical state of the swiches and what is sent from contoller and whatever is latest wins.
    I also thought maybe I should implement a possibility to block the controller from activation and overrule it by e.g. having the physical button pressed in but then I did not want to have them all the time in neutral or blocking the controller activation.
    Anyhow, my code is based on the relay example. It needs some cleanup for the physical button evaluations but I was too lazy to do this as most of my shutters are single nodes anyway and I have only 2 with 2 shutters on one board and 1 with 3. So for the moment there is some spaghettiy code.
    I am not working with timers, delays etc. in order to find the end spots, the shutters stop anyway at their end if properly installed and the physical buttons do not do anything differently - so why bother? I only have delays of 200ms when going from up to down etc. So basically before I trigger the relay for "down" I disable the one for "up" wait for 200ms and then trigger "down" just making sure there will never be power on both directions to save my motors.
    And finally, in order to "save" my relays I trigger from my controller a "stop" every now and then to all shutters in the house. In worst case, it might interfere with one rule but I can live with that.

    Here is the code based on mysensors for a node with 6 relays for 3 rollershutters attached to physical buttons:

    /**
       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.
    
     *******************************
    
       REVISION HISTORY
       Version 1.0 - Henrik Ekblad
    
       DESCRIPTION
       Example sketch showing how to control physical relays.
       This example will remember relay state after power failure.
       http://www.mysensors.org/build/relay
    */
    #include <MySigningNone.h>
    #include <MyTransportNRF24.h>
    #include <MyTransportRFM69.h>
    #include <MyHwATMega328.h>
    #include <MySensor.h>
    #include <SPI.h>
    
    #define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 6 // Total number of attached relays
    #define RELAY_ON 1  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
    
    MyMessage sensorMsg0(0, V_DIMMER);
    MyMessage sensorMsg1(1, V_DIMMER);
    MyMessage sensorMsg2(2, V_DIMMER);
    
    static int currentLevel0 = 0;  // Current dim level...
    static int currentLevel1 = 0;  // Current dim level...
    
    int upPin0 = 14;   // choose the input pin (for a up)
    int downPin0 = 15;   // choose the input pin (for a down)
    int motorUp0 = 0;     // variable for reading the pin status
    int motorDown0 = 0;     // variable for reading the pin status
    
    int upPin1 = 16;   // choose the input pin (for a up)
    int downPin1 = 17;   // choose the input pin (for a down)
    int motorUp1 = 0;     // variable for reading the pin status
    int motorDown1 = 0;     // variable for reading the pin status
    
    int upPin2 = 18;   // choose the input pin (for a up)
    int downPin2 = 19;   // choose the input pin (for a down)
    int motorUp2 = 0;     // variable for reading the pin status
    int motorDown2 = 0;     // variable for reading the pin status
    
    int switchState0 = 0; //0=off, 1=up, 2=down
    int tempSwitchState0 = 0; //0=off, 1=up, 2=down
    int rUnitPos0 = 0;
    
    int switchState1 = 0; //0=off, 1=up, 2=down
    int tempSwitchState1 = 0; //0=off, 1=up, 2=down
    int rUnitPos1 = 0;
    
    int switchState2 = 0; //0=off, 1=up, 2=down
    int tempSwitchState2 = 0; //0=off, 1=up, 2=down
    int rUnitPos2 = 0;
    
    // NRFRF24L01 radio driver (set low transmit power by default)
    MyTransportNRF24 radio(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
    //MyTransportRFM69 radio;
    // Message signing driver (none default)
    //MySigningNone signer;
    // Select AtMega328 hardware profile
    MyHwATMega328 hw;
    // Construct MySensors library
    MySensor gw(radio, hw);
    
    
    void shuttersUp(int shutter)
    {
      if (shutter == 0) {
        Serial.println("A Shutter 0 going up.");
        digitalWrite (RELAY_1 + 1, LOW);
        delay(100);
        digitalWrite (RELAY_1, HIGH);
        gw.send( sensorMsg0.set(0) );
      }
      else if (shutter == 1){
        Serial.println("A Shutter 1 going up.");
        digitalWrite (RELAY_1 + 3, LOW);
        delay(100);
        digitalWrite (RELAY_1 + 2, HIGH);
        gw.send( sensorMsg1.set(0) );
      }
      else if (shutter == 2){
        Serial.println("A Shutter 2 going up.");
        digitalWrite (RELAY_1 + 5, LOW);
        delay(100);
        digitalWrite (RELAY_1 + 4, HIGH);
        gw.send( sensorMsg2.set(0) );
      }
    
    }
    
    void shuttersDown(int shutter)
    {
      if (shutter == 0) {
        Serial.println("A Shutter 0 going down.");
        digitalWrite (RELAY_1, LOW);
        delay(100);
        digitalWrite (RELAY_1 + 1, HIGH);
        gw.send( sensorMsg0.set(100) );
      }
      else if (shutter == 1){
        Serial.println("A Shutter 1 going down.");
        digitalWrite (RELAY_1 + 2, LOW);
        delay(100);
        digitalWrite (RELAY_1 + 3, HIGH);
        gw.send( sensorMsg1.set(100) );
    
      }
      else if (shutter == 2){
        Serial.println("A Shutter 2 going down.");
        digitalWrite (RELAY_1 + 4, LOW);
        delay(100);
        digitalWrite (RELAY_1 + 5, HIGH);
        gw.send( sensorMsg2.set(100) );
    
      }
    }
    
    void shuttersStop(int shutter)
    {
      if (shutter == 0) {
        Serial.println("A Shutter 0 halted.");
        digitalWrite (RELAY_1, LOW);
        digitalWrite (RELAY_1 + 1, LOW);
      }
      else if (shutter == 1){
        Serial.println("A Shutter 1 halted.");
        digitalWrite (RELAY_1 + 2, LOW);
        digitalWrite (RELAY_1 + 3, LOW);
      }
        else if (shutter == 2){
        Serial.println("A Shutter 2 halted.");
        digitalWrite (RELAY_1 + 4, LOW);
        digitalWrite (RELAY_1 + 5, LOW);
      }
    }
    
    void setup()
    {
      pinMode(upPin0, INPUT);    // declare pushbutton as input
      pinMode(downPin0, INPUT);    // declare pushbutton as input
    
      
        pinMode(upPin1, INPUT);    // declare pushbutton as input
        pinMode(downPin1, INPUT);    // declare pushbutton as input
    
        pinMode(upPin2, INPUT);    // declare pushbutton as input
        pinMode(downPin2, INPUT);    // declare pushbutton as input
      
      // Initialize library and add callback for incoming messages
      gw.begin(incomingMessage, AUTO, true);
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("RollerShutter Atrium", "1.0");
    
      // Fetch relay status
      for (int sensor = 1, pin = RELAY_1; sensor <= NUMBER_OF_RELAYS; sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        gw.present(sensor, S_COVER);
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
    
      }
    }
    
    
    void loop()
    {
      // Alway process incoming messages whenever possible
      gw.process();
    
      motorUp0   = digitalRead(upPin0);  // read input value
      motorDown0 = digitalRead(downPin0);  // read input value
       //relay 2
        motorUp1   = digitalRead(upPin1);  // read input value
        motorDown1 = digitalRead(downPin1);  // read input value
    
        motorUp2   = digitalRead(upPin2);  // read input value
        motorDown2 = digitalRead(downPin2);  // read input value
    
    
    //evaluate switch positions
      // GROUP 0
      if (motorUp0 == LOW && motorDown0 == HIGH) {
        switchState0 = 1;
        //Serial.println("SWITCH: " + String(switchState0)); //switch position
      }
      else if (motorDown0 == LOW && motorUp0 == HIGH) {
        switchState0 = 2;
        //Serial.println("SWITCH: " + String(switchState0)); //switch position
      }
      else if (motorDown0 == HIGH && motorUp0 == HIGH)
      {
        switchState0 = 0;
        //Serial.println("SWITCH: " + String(switchState0)); //switch position
      }
      // GROUP 1
        if (motorUp1 == LOW && motorDown1 == HIGH) {
          switchState1 = 1;
          //Serial.println("SWITCH: " + String(switchState1)); //switch position
        }
        else if (motorDown1 == LOW && motorUp1 == HIGH) {
          switchState1 = 2;
          //Serial.println("SWITCH: " + String(switchState1)); //switch position
        }
        else if (motorDown1 == HIGH && motorUp1 == HIGH)
        {
          switchState1 = 0;
          //Serial.println("SWITCH: " + String(switchState1)); //switch position
        }
    // GROUP 2
        if (motorUp2 == LOW && motorDown2 == HIGH) {
          switchState2 = 1;
          //Serial.println("SWITCH: " + String(switchState2)); //switch position
        }
        else if (motorDown2 == LOW && motorUp2 == HIGH) {
          switchState2 = 2;
          //Serial.println("SWITCH: " + String(switchState2)); //switch position
        }
        else if (motorDown2 == HIGH && motorUp2 == HIGH)
        {
          switchState2 = 0;
          //Serial.println("SWITCH: " + String(switchState2)); //switch position
        }
    
    
     //GROUP 0
      if (tempSwitchState0 != switchState0) //man only needed in case of changed switch state
      {
    
        if (motorUp0 == LOW && rUnitPos0 != 1) //man up
        {
          switchState0 = 1;
          tempSwitchState0 = 1;
          delay(200);
          shuttersUp(0);
          rUnitPos0 = 1;
          Serial.println("//////////////man 0 up");
          gw.send( sensorMsg0.set(0) );
        }
    
        if (motorDown0 == LOW && rUnitPos0 != 2) // man down
        {
          switchState0 = 2;
          tempSwitchState0 = 2;
          delay(200);
          shuttersDown(0);
          rUnitPos0 = 2;
          Serial.println("//////////////man 0 down");
          gw.send( sensorMsg0.set(100) );
        }
    
        if (motorUp0 == HIGH && motorDown0 == HIGH && rUnitPos0 != 0) //man stopp
        {
          switchState0 = 0;
          tempSwitchState0 = 0;
          delay(200);
          shuttersStop(0);
          rUnitPos0 = 0;
          Serial.println("//////////////man 0 stopp");
        }
    
      }
    
    
      //GROUP 1 
    
        if (tempSwitchState1 != switchState1) //man only needed in case of changed switch state
        {
    
        if (motorUp1 == LOW && rUnitPos1 != 1) //man up
        {
          switchState1 = 1;
          tempSwitchState1 = 1;
          shuttersUp(1);
          rUnitPos1 = 1;
          Serial.println("//////////////man 1 up");
          gw.send( sensorMsg1.set(0) );
        }
    
        if (motorDown1 == LOW && rUnitPos1 != 2) // man down
        {
          switchState1 = 2;
          tempSwitchState1 = 2;
          shuttersDown(1);
          rUnitPos1 = 2;
          Serial.println("//////////////man 1 down");
          gw.send( sensorMsg1.set(100) );
        }
    
        if (motorUp1 == HIGH && motorDown1 == HIGH && rUnitPos1 != 0) //man stopp
        {
          switchState1 = 0;
          tempSwitchState1 = 0;
          shuttersStop(1);
          rUnitPos1 = 0;
          Serial.println("//////////////man 1 stopp");
        }
    
        }
       //GROUP 2 
    
        if (tempSwitchState2 != switchState2) //man only needed in case of changed switch state
        {
    
        if (motorUp2 == LOW && rUnitPos2 != 1) //man up
        {
          switchState2 = 1;
          tempSwitchState2 = 1;
          shuttersUp(2);
          rUnitPos2 = 1;
          Serial.println("//////////////man 2 up");
          gw.send( sensorMsg2.set(0) );
        }
    
        if (motorDown2 == LOW && rUnitPos2 != 2) // man down
        {
          switchState2 = 2;
          tempSwitchState2 = 2;
          shuttersDown(2);
          rUnitPos2 = 2;
          Serial.println("//////////////man 2 down");
          gw.send( sensorMsg2.set(100) );
        }
    
        if (motorUp2 == HIGH && motorDown2 == HIGH && rUnitPos2 != 0) //man stop
        {
          switchState2 = 0;
          tempSwitchState2 = 0;
          shuttersStop(2);
          rUnitPos2 = 0;
          Serial.println("//////////////man 2 stopp");
        }
    
        }
    
    }
    
    void incomingMessage(const MyMessage &message) {
      // Let's check for the message type.
      if (message.type == V_DIMMER) {
    
        //  Retrieve the power or dim level from the incoming request message
        int requestedLevel = atoi( message.data );
    
        // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
        requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 );
    
        // Clip incoming level to valid range of 0 to 100
        requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
        requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
    
        Serial.print( "Changing level to " );
        Serial.print( requestedLevel );
    
        Serial.print( ", from " );
    
        Serial.println("NodeID:" + String(message.sensor) + " " + currentLevel0 );
    
        if (requestedLevel == 0) {
          // move up
          shuttersUp(message.sensor);
        }
        else if (requestedLevel == 100) {
          // move down
          shuttersDown(message.sensor);
        }
        else {
          // move percentage
          // Serial.println("currentLevel" + String(shutters.currentLevel()));
          Serial.println("move to desired postion");
          //NOT IMPLEMENTED HERE
        }
    
        currentLevel0 = requestedLevel;
    
      }
      else if (message.type == V_UP) {
        shuttersUp(message.sensor);
        Serial.println("going up:" + String(message.type));
      }
      else if (message.type == V_DOWN) {
        shuttersDown(message.sensor);
        Serial.println("going down:" + String(message.type));
      }
      else if (message.type == V_STOP) {
        shuttersStop(message.sensor);
        Serial.println("stopping:" + String(message.type));
      }
      else {
        Serial.println("wrong data received:" + String(message.type));
      }
    }
    
    

    Cheers
    SJ



  • hi friends which works for 3 motorized shutters and how Arduino thank you



  • @zrom69 is this a question or statement?



  • I'm sorry for my English, I'm French
    I try to control node 3 and motorized shutters which card must be used aduino thank you
    :smiley:



  • @zrom69 no worries.
    I am using arduino Nano but others will work too. The Nano is small enough and easy to program (it has USB). The Pro Mini is also a good option, but needs extra programer (it has only serial connectors).
    I am using those and all work very well:
    http://www.banggood.com/5Pcs-ATmega328P-Nano-V3-Controller-Board-For-Arduino-Improved-Version-p-951797.html
    In addition you need the relays - you either could build that yourself or use ready to use ones:
    http://www.banggood.com/5V-4-Channel-Relay-Module-For-Arduino-PIC-ARM-DSP-AVR-MSP430-Blue-p-87987.html

    If you want to control shutters, you usually need 1 relay per direction. so for your 3 shutters it would be 6 relays. I am not sure if there are products out there, you could take one with 8 relays if you do have the space or make them yourself.

    The code I posted above is "ready" for 3 shutters (up/down each) and manual control buttons on an Arduino Nano.
    you need to connect the relays on digital pins 3/4 & 5/6 & 7/8 and the manual inputs on analog A0/A1, A2/A3, A4/A5 (note: pin 14 makes out of Analog A0, a digital D14)
    Besides this, connect the radio and power and you should be ready to go.



  • Hi friends
    thank you for your help I have try the code on Arduino pro mini touts the relay they work or even monument must change something in the code Arduino
    I am newbie in Arduino
    there is detection of door opening
    thanks for the help



  • hi @parachutesj hi @all
    i tried the sketch posted above. it works but my relay board is active low and the relays are on when they should be off. #define RELAY_ON 0 and #define RELAY_OFF 1 do not change the behavior. the relays stay on. do you have an idea what is happening? thx



  • @ihtgtwtd
    change in the code in the routines shutters UP/DOWN/STOP

    the parts

    digitalWrite(RELAYxxx, HIGH);
    

    HIGH to LOW and vice versa

    SJ



  • thanks for the quick reply. I did what you suggested and the switches work the right way but when I reset the arduino all relay contacts turn on and stay on until I give a command. this is a major problem, it will destroy the shutter motor. i think there is no defined case when the arduino powers on.



  • @ihtgtwtd
    put this into the setup routine within the "for"

    digitalWrite (pin, HIGH);
    

    e.g. like this:

     for (int sensor = 1, pin = RELAY_1; sensor <= NUMBER_OF_RELAYS; sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        gw.present(sensor, S_COVER);
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
        digitalWrite (pin, HIGH);
    
      }
    


  • @parachutesj
    thank you very much. looks good now.


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.