problem with implementation of my sensors in rollershutter sketch



  • hello,
    I found a nice rollershutter sketch in the german arduino forum (http://forum.arduino.cc/index.php?topic=247811.60). I tried to implement mysensors but i'm stuck somehow.
    my arduino gets a node ID and the 3 rollershutters are registered, I can send commands and they show up in the serial monitor but I don't know how to route the commands to the relays.
    If it matters, the controller is domoticz.

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    #include <SPI.h>
    
    // Rollladensteuerung by jurs for German Arduino-Forum
    #define BUTTONPRESSED LOW
    #define RELAYACTIVE LOW
    
    MyMessage sensorMsg0(0,V_DIMMER);
    MyMessage sensorMsg1(1,V_DIMMER);
    MyMessage sensorMsg2(2,V_DIMMER);
    
    enum {NOACTION, UPACTION, DOWNACTION};
    
    struct roll_t{byte downPin; byte upPin; boolean downPressed; boolean upPressed; byte action; unsigned long actionStarttime; unsigned long actionTimeout; byte relayOnePin; byte relayTwoPin;};
    
    roll_t rollladen[]={
      {2,3,false, false, NOACTION,0,60000L, A0, A1}, // Button-Pins 2, 3, Relay-Pins A0, A1, Timeout 60 secons
      {4,5,false, false, NOACTION,0,45000L, A2, A3}, // Button-Pins 4, 5, Relay-Pins A2, A3, Timeout 45 secons
      {6,7,false, false, NOACTION,0,45000L, A4, A5}, // Button-Pins 6, 7, Relay-Pins A4, A5, Timeout 45 secons
    };
    
    #define ANZAHLROLLLADEN sizeof(rollladen)/sizeof(rollladen[0])
    
    
    void setup()
    {
      Serial.begin(115200);
      for (int i=0;i<ANZAHLROLLLADEN;i++)
      {
        if (BUTTONPRESSED==HIGH)
        {
          pinMode(rollladen[i].downPin,INPUT);
          pinMode(rollladen[i].upPin,INPUT);
        }
        else
        {
          pinMode(rollladen[i].downPin,INPUT_PULLUP);
          pinMode(rollladen[i].upPin,INPUT_PULLUP);
        }
        if (RELAYACTIVE==LOW)
        {
           digitalWrite(rollladen[i].relayOnePin,HIGH);
           digitalWrite(rollladen[i].relayTwoPin,HIGH);
        }
        pinMode(rollladen[i].relayOnePin,OUTPUT);
        pinMode(rollladen[i].relayTwoPin,OUTPUT);
      }
    }
    
    
    void switchRelay(byte i)
    {
      Serial.print("Schalte Rolladen-");
      Serial.print(i);
      switch (rollladen[i].action)
      {
        case NOACTION: // STOP
          digitalWrite(rollladen[i].relayOnePin,!RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin,!RELAYACTIVE);
          Serial.println(" STOP");
          break;
        case UPACTION: // UP
          digitalWrite(rollladen[i].relayOnePin,RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin,!RELAYACTIVE);
          Serial.println(" UP");
          break;
        case DOWNACTION: // DOWN
          digitalWrite(rollladen[i].relayOnePin,!RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin,RELAYACTIVE);
          Serial.println(" DOWN");
          break;
      }
    }
    
    
    
    void loop(void) 
    {
      byte state;
      for (int i=0;i<ANZAHLROLLLADEN;i++)
      {
        // Prüfen, ob Down gedrückt wurde
        state=digitalRead(rollladen[i].downPin);
        if (BUTTONPRESSED==LOW) state=!state;
        if (state && !rollladen[i].downPressed)
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=DOWNACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
          }
        }
        rollladen[i].downPressed=state;
        
        // Prüfen, ob Up gedrückt wurde
        state=digitalRead(rollladen[i].upPin);
        if (BUTTONPRESSED==LOW) state=!state;
        if (state && !rollladen[i].upPressed)
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=UPACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
          }
        }
        rollladen[i].upPressed=state;
        
        // Prüfen auf Timeout
        if (rollladen[i].action!=NOACTION && millis()-rollladen[i].actionStarttime>=rollladen[i].actionTimeout)
        {
          rollladen[i].action=NOACTION;
          switchRelay(i);
        }
      }
      delay(5); // kleines Delay zum Entprellen der Buttons
    }
    
    void presentation()
    {
    
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Test", "1.0");
    
      // Fetch relay status
       for (int sensor = 1, pin = A0; sensor <= ANZAHLROLLLADEN; sensor++, pin++) {
      
        // Register all sensors to gw (they will be created as child devices)
          present(sensor, S_COVER);
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
      } 
    }
    
    
    void receive(const MyMessage &message) {
      if (message.type == V_UP) {
        byte (message.sensor);
        Serial.println("going up:" + String(message.type));
      }
      else if (message.type == V_DOWN) {
        byte (message.sensor);
        Serial.println("going down:" + String(message.type));
      }
      else if (message.type == V_STOP) {
        byte (message.sensor);
        Serial.println("stopping:" + String(message.type));
      }
    }
    
    
    

    I don`t know how to fill out the last part of the sketch (void receive) so I just wrote something to make it compile.

    I would really appreciate your help.

    THX


  • Hero Member

    @ihtgtwtd The sketch works with a statemachine. i.e the rollladen[i].action!=,<ACTION> determines the what each of the rollershutters i is doing.. What you should do is fill that action in receive() similar to what is done after a buttonpress for that action. i.e. assign the action for the respective shutter and set the timeout.

    You can read look at the MySensors examples for rollershutter to find out how to get the values in the receive() routine.



  • @AWI
    thank you, that helped a lot.
    I received my first arduino 3 weeks ago and since then I'm constantly learning. Getting things explained helps a lot.

    the code receives my commands now but when I press down, all the down relays switch on/off and the other way around. I thought the line for (int i=0;i<ANZAHLROLLLADEN;i++) declares the number of the rollershutter.

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    #include <SPI.h>
    
    // Rollladensteuerung by jurs for German Arduino-Forum
    #define BUTTONPRESSED LOW
    #define RELAYACTIVE LOW
    
    MyMessage sensorMsg0(0,V_DIMMER);
    MyMessage sensorMsg1(1,V_DIMMER);
    MyMessage sensorMsg2(2,V_DIMMER);
    
    enum {NOACTION, UPACTION, DOWNACTION};
    
    struct roll_t{byte downPin; byte upPin; boolean downPressed; boolean upPressed; byte action; unsigned long actionStarttime; unsigned long actionTimeout; byte relayOnePin; byte relayTwoPin;};
    
    roll_t rollladen[]={
      {2,3,false, false, NOACTION,0,60000L, A0, A1}, // Button-Pins 2, 3, Relay-Pins A0, A1, Timeout 60 secons
      {4,5,false, false, NOACTION,0,45000L, A2, A3}, // Button-Pins 4, 5, Relay-Pins A2, A3, Timeout 45 secons
      {6,7,false, false, NOACTION,0,45000L, A4, A5}, // Button-Pins 6, 7, Relay-Pins A4, A5, Timeout 45 secons
    };
    
    #define ANZAHLROLLLADEN sizeof(rollladen)/sizeof(rollladen[0])
    
    
    void setup()
    {
      Serial.begin(115200);
      for (int i=0;i<ANZAHLROLLLADEN;i++)
      {
        if (BUTTONPRESSED==HIGH)
        {
          pinMode(rollladen[i].downPin,INPUT);
          pinMode(rollladen[i].upPin,INPUT);
        }
        else
        {
          pinMode(rollladen[i].downPin,INPUT_PULLUP);
          pinMode(rollladen[i].upPin,INPUT_PULLUP);
        }
        if (RELAYACTIVE==LOW)
        {
           digitalWrite(rollladen[i].relayOnePin,HIGH);
           digitalWrite(rollladen[i].relayTwoPin,HIGH);
        }
        pinMode(rollladen[i].relayOnePin,OUTPUT);
        pinMode(rollladen[i].relayTwoPin,OUTPUT);
      }
    }
    
    
    void switchRelay(byte i)
    {
      Serial.print("Schalte Rolladen-");
      Serial.print(i);
      switch (rollladen[i].action)
      {
        case NOACTION: // STOP
          digitalWrite(rollladen[i].relayOnePin,!RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin,!RELAYACTIVE);
          Serial.println(" STOP");
          break;
        case UPACTION: // UP
          digitalWrite(rollladen[i].relayOnePin,RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin,!RELAYACTIVE);
          Serial.println(" UP");
          break;
        case DOWNACTION: // DOWN
          digitalWrite(rollladen[i].relayOnePin,!RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin,RELAYACTIVE);
          Serial.println(" DOWN");
          break;
      }
    }
    
    
    
    void loop(void) 
    {
      byte state;
      for (int i=0;i<ANZAHLROLLLADEN;i++)
      {
        // Prüfen, ob Down gedrückt wurde
        state=digitalRead(rollladen[i].downPin);
        if (BUTTONPRESSED==LOW) state=!state;
        if (state && !rollladen[i].downPressed)
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=DOWNACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
          }
        }
        rollladen[i].downPressed=state;
        
        // Prüfen, ob Up gedrückt wurde
        state=digitalRead(rollladen[i].upPin);
        if (BUTTONPRESSED==LOW) state=!state;
        if (state && !rollladen[i].upPressed)
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=UPACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
          }
        }
        rollladen[i].upPressed=state;
        
        // Prüfen auf Timeout
        if (rollladen[i].action!=NOACTION && millis()-rollladen[i].actionStarttime>=rollladen[i].actionTimeout)
        {
          rollladen[i].action=NOACTION;
          switchRelay(i);
        }
      }
      delay(5); // kleines Delay zum Entprellen der Buttons
    }
    
    void presentation()
    {
    
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Test", "1.0");
    
      // Fetch relay status
       for (int sensor = 1, pin = A0; sensor <= ANZAHLROLLLADEN; sensor++, pin++) {
      
        // Register all sensors to gw (they will be created as child devices)
          present(sensor, S_COVER);
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
      } 
    }
    
    
    void receive(const MyMessage &message) {
      byte state;
      for (int i=0;i<ANZAHLROLLLADEN;i++)
     
      if (message.type == V_UP) {
      {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=UPACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
          }
        }
        rollladen[i].upPressed=state;
        
        Serial.println("going up:" + String(message.type));
      }
      else if (message.type == V_DOWN) {
    {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=DOWNACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
          }
        }
        rollladen[i].downPressed=state;
        
        Serial.println("going down:" + String(message.type));
      }
      else if (message.type == V_STOP) {
        {
          switch (rollladen[i].action)
          {
            case DOWNACTION: rollladen[i].action=NOACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
    
            case UPACTION: rollladen[i].action=NOACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
          }
        }
        Serial.println("stopping:" + String(message.type));
      }
    }
    
    

    Do you have any idea whats wrong?
    thx


  • Hero Member

    @ihtgtwtd in your receive() routine you are explicitly executing the action for all shutters in the for(.....) loop. What you should do is execute the action only for the shutter with the Id received . I.e. i = message.sensor



  • @AWI
    I don't get it. I inserted for (int i=0;i<message.sensor;i++) and the result is
    switch 1 up= relay 1; switch 1 down= relay 2
    switch 2 up= relay 1+3 ; switch 2 down=relay 2+4
    switch 3 up= relay 1+3+5; switch 3 down=relay 2+4+6

    shouldn't i++ give each following message.sensor it's own number?

    maybe I am just too tired to get it.

    thanks for your help, I'm going to sleep now


  • Hero Member

    @ihtgtwtd something for when you wake up... 😄

    Remove the whole for loop. When you want to switch only 1 shutter only 1 should be activated. So replace the whole for loop with only i = message.sensor.

    Btw.. I think the behavior of you last action is creative at least :bowtie:



  • @AWI
    😄 the result was indeed interesting and fun to watch.

    void receive(const MyMessage &message) {
      byte state;
      i = message.sensors
      
      if (message.type == V_UP) {
      {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=UPACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
        
         }
        }
        rollladen[i].upPressed=state;
        
        Serial.println("going up:" + String(message.type));
      }
      else if (message.type == V_DOWN) {
    {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action=DOWNACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
            default: if (rollladen[i].action!=NOACTION)
                     {
                       rollladen[i].action=NOACTION;
                       switchRelay(i);
                     }
          }
        }
        rollladen[i].downPressed=state;
        
        Serial.println("going down:" + String(message.type));
      }
      else if (message.type == V_STOP) {
        {
          switch (rollladen[i].action)
          {
            case DOWNACTION: rollladen[i].action=NOACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
    
            case UPACTION: rollladen[i].action=NOACTION;
                           rollladen[i].actionStarttime=millis();
                           switchRelay(i);
                           break;
          }
        }
        Serial.println("stopping:" + String(message.type));
        } 
      }
    

    I replaced the for loop with i = sensor.message , now i get "exit status 1
    'i' was not declared in this scope". Do I have to declare the variable?


  • Hero Member

    @ihtgtwtd int i = message.sensors ; would be the right syntax



  • @AWI
    thx, I tried that. it exits with 'const class MyMessage' has no member named 'sensors'.


  • Hero Member

    @ihtgtwtd typo ... int i = message.sensor ; would be the right syntax, leave out the 's'



  • @AWI
    thanks, still small problems to figure out though.
    when I send a command to rollershutter 1 then rollershutter 2 receives the command. I can not control shutter 1, only 2 and 3 (with the buttons of 1 and 2)

    output in serial monitor is right and physical buttons work the right way too

    is there a problem in the registration or am I missing something (again)?
    the physical buttons work the right way.

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <MySensors.h>
    #include <SPI.h>
    
    // Rollladensteuerung by jurs for German Arduino-Forum
    #define BUTTONPRESSED LOW
    #define RELAYACTIVE LOW
    
    MyMessage sensorMsg0(0, V_DIMMER);
    MyMessage sensorMsg1(1, V_DIMMER);
    MyMessage sensorMsg2(2, V_DIMMER);
    
    enum {NOACTION, UPACTION, DOWNACTION};
    
    struct roll_t {
      byte downPin;
      byte upPin;
      boolean downPressed;
      boolean upPressed;
      byte action;
      unsigned long actionStarttime;
      unsigned long actionTimeout;
      byte relayOnePin;
      byte relayTwoPin;
    };
    
    roll_t rollladen[] = {
      {2, 3, false, false, NOACTION, 0, 60000L, A0, A1}, // Button-Pins 2, 3, Relay-Pins A0, A1, Timeout 60 secons
      {4, 5, false, false, NOACTION, 0, 45000L, A2, A3}, // Button-Pins 4, 5, Relay-Pins A2, A3, Timeout 45 secons
      {6, 7, false, false, NOACTION, 0, 45000L, A4, A5}, // Button-Pins 6, 7, Relay-Pins A4, A5, Timeout 45 secons
    };
    
    #define ANZAHLROLLLADEN sizeof(rollladen)/sizeof(rollladen[0])
    
    
    void setup()
    {
      Serial.begin(115200);
      for (int i = 0; i < ANZAHLROLLLADEN; i++)
      {
        if (BUTTONPRESSED == HIGH)
        {
          pinMode(rollladen[i].downPin, INPUT);
          pinMode(rollladen[i].upPin, INPUT);
        }
        else
        {
          pinMode(rollladen[i].downPin, INPUT_PULLUP);
          pinMode(rollladen[i].upPin, INPUT_PULLUP);
        }
        if (RELAYACTIVE == LOW)
        {
          digitalWrite(rollladen[i].relayOnePin, HIGH);
          digitalWrite(rollladen[i].relayTwoPin, HIGH);
        }
        pinMode(rollladen[i].relayOnePin, OUTPUT);
        pinMode(rollladen[i].relayTwoPin, OUTPUT);
      }
    }
    
    
    void switchRelay(byte i)
    {
      Serial.print("Schalte Rolladen-");
      Serial.print(i);
      switch (rollladen[i].action)
      {
        case NOACTION: // STOP
          digitalWrite(rollladen[i].relayOnePin, !RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin, !RELAYACTIVE);
          Serial.println(" STOP");
          break;
        case UPACTION: // UP
          digitalWrite(rollladen[i].relayOnePin, RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin, !RELAYACTIVE);
          Serial.println(" UP");
          break;
        case DOWNACTION: // DOWN
          digitalWrite(rollladen[i].relayOnePin, !RELAYACTIVE);
          digitalWrite(rollladen[i].relayTwoPin, RELAYACTIVE);
          Serial.println(" DOWN");
          break;
      }
    }
    
    
    
    void loop(void)
    {
      byte state;
      for (int i = 0; i < ANZAHLROLLLADEN; i++)
      {
        // Prüfen, ob Down gedrückt wurde
        state = digitalRead(rollladen[i].downPin);
        if (BUTTONPRESSED == LOW) state = !state;
        if (state && !rollladen[i].downPressed)
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action = DOWNACTION;
              rollladen[i].actionStarttime = millis();
              switchRelay(i);
              break;
            default: if (rollladen[i].action != NOACTION)
              {
                rollladen[i].action = NOACTION;
                switchRelay(i);
              }
          }
        }
        rollladen[i].downPressed = state;
    
        // Prüfen, ob Up gedrückt wurde
        state = digitalRead(rollladen[i].upPin);
        if (BUTTONPRESSED == LOW) state = !state;
        if (state && !rollladen[i].upPressed)
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action = UPACTION;
              rollladen[i].actionStarttime = millis();
              switchRelay(i);
              break;
            default: if (rollladen[i].action != NOACTION)
              {
                rollladen[i].action = NOACTION;
                switchRelay(i);
              }
          }
        }
        rollladen[i].upPressed = state;
    
        // Prüfen auf Timeout
        if (rollladen[i].action != NOACTION && millis() - rollladen[i].actionStarttime >= rollladen[i].actionTimeout)
        {
          rollladen[i].action = NOACTION;
          switchRelay(i);
        }
      }
      delay(5); // kleines Delay zum Entprellen der Buttons
    }
    
    void presentation()
    {
    
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Test", "1.0");
    
      // Fetch relay status
      for (int sensor = 1, pin = A0; sensor <= ANZAHLROLLLADEN; sensor++, pin++) {
    
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_COVER);
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
      }
    }
    
    
    void receive(const MyMessage &message) {
      byte state;
      int i = message.sensor ;
    
      if (message.type == V_UP) {
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action = UPACTION;
              rollladen[i].actionStarttime = millis();
              switchRelay(i);
              break;
            default: if (rollladen[i].action != NOACTION)
              {
                rollladen[i].action = NOACTION;
                switchRelay(i);
              }
    
          }
        }
        rollladen[i].upPressed = state;
    
        Serial.println("going up:" + String(message.type));
      }
      else if (message.type == V_DOWN) {
        {
          switch (rollladen[i].action)
          {
            case NOACTION: rollladen[i].action = DOWNACTION;
              rollladen[i].actionStarttime = millis();
              switchRelay(i);
              break;
            default: if (rollladen[i].action != NOACTION)
              {
                rollladen[i].action = NOACTION;
                switchRelay(i);
              }
          }
        }
        rollladen[i].downPressed = state;
    
        Serial.println("going down:" + String(message.type));
      }
      else if (message.type == V_STOP) {
        {
          switch (rollladen[i].action)
          {
            case DOWNACTION: rollladen[i].action = NOACTION;
              rollladen[i].actionStarttime = millis();
              switchRelay(i);
              break;
    
            case UPACTION: rollladen[i].action = NOACTION;
              rollladen[i].actionStarttime = millis();
              switchRelay(i);
              break;
          }
        }
        Serial.println("stopping:" + String(message.type));
      }
    }
    

    hope it's clear what I mean. It is a bit weird...


  • Hero Member

    @ihtgtwtd that is caused in the presentation part of your routine. You did not create a switch for shutter 0. (started with 1)



  • well thanks, I already tried that because it looked suspicious 😉
    but i was sending on switch 1 in domoticz and did not create a switch for 0.

    So it seems this thing works, thanks again for your help and the patience to deal with my noob questions 🙂


 

336
Online

7.9k
Users

8.8k
Topics

93.8k
Posts