Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. Help with multiple servos

Help with multiple servos

Scheduled Pinned Locked Moved Troubleshooting
8 Posts 4 Posters 109 Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bsmtdweller
    wrote on last edited by
    #1

    I'm hoping someone can nudge me in the right direction. I'm struggling to understand how to make the servo controller sketch control multiple servos, individually. I have added 'for' loops - modeled after the "relay controller" sketch - to get the controller to see the different servos. The node and gw are communicating, and the controller (Domoticz) sees and wants to command 3 servos, but only 1 pin responds.

    I'm sure its the 'void receive' part of the code but I'm stuck trying to get the myservo.attach(?????) part right.

    Any help is greatly appreciated! Heres the sketch:

    / Enable debug prints to serial monitor
    #define MY_DEBUG 
    #define MY_RF24_CE_PIN 49
    #define MY_RF24_CS_PIN 53
    #define MY_RF24_IRQ_PIN 2
    #define MY_RF24_PA_LEVEL RF24_PA_LOW
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    //#define MY_RADIO_RFM69
    
    #include <MySensors.h>
    #include <Servo.h> 
    
    #define SERVO_DIGITAL_OUT_PIN 39
    #define NUMBER_OF_SERVOS 3 
    #define SERVO_MIN 0 // Fine tune your servos min. 0-180
    #define SERVO_MAX 180  // Fine tune your servos max. 0-180
    #define DETACH_DELAY 900 // Tune this to let your movement finish before detaching the servo
    #define CHILD_ID 13   // Id of the sensor child
    MyMessage msg(CHILD_ID, V_DIMMER);
    Servo myservo;  // create servo object to control a servo 
                    // a maximum of eight servo objects can be created Sensor gw(9,10);
    unsigned long timeOfLastChange = 0;
    bool attachedServo = false;
    
    void before()
    {
      for (int sensor=1, pin=SERVO_DIGITAL_OUT_PIN; sensor<=NUMBER_OF_SERVOS; sensor++, pin++) {
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
      }
    }
    void setup() 
    { 
      for (int sensor=1, pin=SERVO_DIGITAL_OUT_PIN; sensor<=NUMBER_OF_SERVOS; sensor++, pin++) {
      // Request last servo state at startup
      request(CHILD_ID, V_DIMMER);
      }
    } 
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Servo", "1.0");
    for (int sensor=1, pin=SERVO_DIGITAL_OUT_PIN; sensor<=NUMBER_OF_SERVOS; sensor++, pin++) {
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID, S_COVER);
    }
    }
    
    void loop() 
    { 
      if (attachedServo && millis() - timeOfLastChange > DETACH_DELAY) {
         myservo.detach();
         attachedServo = false;
      }
    } 
    
    void receive(const MyMessage &message) {
      myservo.attach(SERVO_DIGITAL_OUT_PIN);
      attachedServo = true;
    
      if (message.type==V_DIMMER) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
         int val = message.getInt();
         myservo.write(SERVO_MAX + (SERVO_MIN-SERVO_MAX)/100 * val); // sets the servo position 0-180
         // Write some debug info
         Serial.print("Servo changed. new state: ");
         Serial.println(val);
       } else if (message.type==V_UP) {
         Serial.println("Servo UP command");
         myservo.write(SERVO_MIN);
         send(msg.set(100));
       } else if (message.type==V_DOWN) {
         Serial.println("Servo DOWN command");
         myservo.write(SERVO_MAX); 
         send(msg.set(0));
       } else if (message.type==V_STOP) {
         Serial.println("Servo STOP command");
         myservo.detach();
         attachedServo = false;
    
       }
       timeOfLastChange = millis();
    }
    
    Nca78N 1 Reply Last reply
    0
    • B bsmtdweller

      I'm hoping someone can nudge me in the right direction. I'm struggling to understand how to make the servo controller sketch control multiple servos, individually. I have added 'for' loops - modeled after the "relay controller" sketch - to get the controller to see the different servos. The node and gw are communicating, and the controller (Domoticz) sees and wants to command 3 servos, but only 1 pin responds.

      I'm sure its the 'void receive' part of the code but I'm stuck trying to get the myservo.attach(?????) part right.

      Any help is greatly appreciated! Heres the sketch:

      / Enable debug prints to serial monitor
      #define MY_DEBUG 
      #define MY_RF24_CE_PIN 49
      #define MY_RF24_CS_PIN 53
      #define MY_RF24_IRQ_PIN 2
      #define MY_RF24_PA_LEVEL RF24_PA_LOW
      // Enable and select radio type attached
      #define MY_RADIO_RF24
      //#define MY_RADIO_RFM69
      
      #include <MySensors.h>
      #include <Servo.h> 
      
      #define SERVO_DIGITAL_OUT_PIN 39
      #define NUMBER_OF_SERVOS 3 
      #define SERVO_MIN 0 // Fine tune your servos min. 0-180
      #define SERVO_MAX 180  // Fine tune your servos max. 0-180
      #define DETACH_DELAY 900 // Tune this to let your movement finish before detaching the servo
      #define CHILD_ID 13   // Id of the sensor child
      MyMessage msg(CHILD_ID, V_DIMMER);
      Servo myservo;  // create servo object to control a servo 
                      // a maximum of eight servo objects can be created Sensor gw(9,10);
      unsigned long timeOfLastChange = 0;
      bool attachedServo = false;
      
      void before()
      {
        for (int sensor=1, pin=SERVO_DIGITAL_OUT_PIN; sensor<=NUMBER_OF_SERVOS; sensor++, pin++) {
          // Then set relay pins in output mode
          pinMode(pin, OUTPUT);
        }
      }
      void setup() 
      { 
        for (int sensor=1, pin=SERVO_DIGITAL_OUT_PIN; sensor<=NUMBER_OF_SERVOS; sensor++, pin++) {
        // Request last servo state at startup
        request(CHILD_ID, V_DIMMER);
        }
      } 
      
      void presentation()  {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("Servo", "1.0");
      for (int sensor=1, pin=SERVO_DIGITAL_OUT_PIN; sensor<=NUMBER_OF_SERVOS; sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(CHILD_ID, S_COVER);
      }
      }
      
      void loop() 
      { 
        if (attachedServo && millis() - timeOfLastChange > DETACH_DELAY) {
           myservo.detach();
           attachedServo = false;
        }
      } 
      
      void receive(const MyMessage &message) {
        myservo.attach(SERVO_DIGITAL_OUT_PIN);
        attachedServo = true;
      
        if (message.type==V_DIMMER) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
           int val = message.getInt();
           myservo.write(SERVO_MAX + (SERVO_MIN-SERVO_MAX)/100 * val); // sets the servo position 0-180
           // Write some debug info
           Serial.print("Servo changed. new state: ");
           Serial.println(val);
         } else if (message.type==V_UP) {
           Serial.println("Servo UP command");
           myservo.write(SERVO_MIN);
           send(msg.set(100));
         } else if (message.type==V_DOWN) {
           Serial.println("Servo DOWN command");
           myservo.write(SERVO_MAX); 
           send(msg.set(0));
         } else if (message.type==V_STOP) {
           Serial.println("Servo STOP command");
           myservo.detach();
           attachedServo = false;
      
         }
         timeOfLastChange = millis();
      }
      
      Nca78N Offline
      Nca78N Offline
      Nca78
      Hardware Contributor
      wrote on last edited by
      #2

      @bsmtdweller said in Help with multiple servos:

      myservo.attach(SERVO_DIGITAL_OUT_PIN);
      

      Hello, isn't the problem on this line ? You need to change the pin that will control the wanted servo based on the sensor id in the message.

      B 1 Reply Last reply
      1
      • skywatchS Offline
        skywatchS Offline
        skywatch
        wrote on last edited by
        #3

        @bsmtdweller

        @Nca78 Has this nailed I think. You need a separate output pin for each servo.

        Also, you need a separate power supply for the servos with the ground connected to the arduio ground. Arduino can not supply enough power from its pins and interference will be an issue if you don't.

        1 Reply Last reply
        0
        • Nca78N Nca78

          @bsmtdweller said in Help with multiple servos:

          myservo.attach(SERVO_DIGITAL_OUT_PIN);
          

          Hello, isn't the problem on this line ? You need to change the pin that will control the wanted servo based on the sensor id in the message.

          B Offline
          B Offline
          bsmtdweller
          wrote on last edited by
          #4

          Thanks @Nca78! Thats exactly it! But how? I dug through the messages.h and found a "getSensor()" command. Prior to discovering that, I went through and re-wrote the code with no arrays hoping that it would simplify my understanding of whats going on. The new code is below. I feel it is close, but I'm still missing something - when a command is received all three servo pins respond, so while I think I have the root of the problem identified I'm struggling with syntax to make it work properly.

          Also thanks to @skywatch for chiming in - I was reading through his 2019 topic with @mfalkvidd - which seems applicable too regarding formatting the 'void receive' function. With such a jumbled, non-array-simplified code, my next step was to try and put chunks together in a separate function and then combine that into the void receive function. My gut tells me that won't help and I better get a more thorough understanding of simplifying with arrays first!

          Another question - I read somewhere that in order to accurately test this, there needs to be physical servos connected? My project where I have the servos installed, it out in the shop, far away from my computer -- so I've been simply testing the output of the pins with my voltmeter during this preliminary testing.

          Heres the non-array written code:

          #define MY_DEBUG
          #define MY_RF24_CE_PIN 49
          #define MY_RF24_CS_PIN 53
          #define MY_RF24_IRQ_PIN 2
          #define MY_RF24_PA_LEVEL RF24_PA_LOW
          // Enable and select radio type attached
          #define MY_RADIO_RF24
          //#define MY_RADIO_RFM69
          
          #include <MySensors.h>
          #include <Servo.h>
          
          #define SERVO_MIN 0
          #define SERVO_MAX 180
          #define DETACH_DELAY 900
          #define CHILD_ID1  13
          #define CHILD_ID2  14
          #define CHILD_ID3  15
          Servo servos1;
          Servo servos2;
          Servo servos3;
          #define servoPin1  39
          #define servoPin2  40
          #define servoPin3  41
          
          MyMessage msg1(CHILD_ID1, V_DIMMER);
          MyMessage msg2(CHILD_ID2, V_DIMMER);
          MyMessage msg3(CHILD_ID3, V_DIMMER);
          
          unsigned long timeOfLastChange = 0;
          bool attachedServo = false;
          
          
          void setup()
          {
            // Request last servo state at startup
          
            request(CHILD_ID1, V_DIMMER);
            request(CHILD_ID2, V_DIMMER);
            request(CHILD_ID3, V_DIMMER);
          
          
          }
          
          
          void presentation()  {
            // Send the sketch version information to the gateway and Controller
            sendSketchInfo("Servo", "1.0");
          
            // Register all sensors to gw (they will be created as child devices)
          
            present(CHILD_ID1, S_COVER);
            present(CHILD_ID2, S_COVER);
            present(CHILD_ID3, S_COVER);
          }
          
          
          void loop()
          {
          
            if (attachedServo && millis() - timeOfLastChange > DETACH_DELAY) {
              servos1.detach();
              servos2.detach();
              servos3.detach();
              attachedServo = false;
          
            }
          }
          
          void receive(const MyMessage &message) {
            Serial.println("   This is the Id of the Message     ");
            Serial.println(message.getSensor());
          
          
            if (message.type == V_DIMMER && message.getSensor() == CHILD_ID1) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
              servos1.attach(servoPin1);
              int val = message.getInt();
              servos1.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * val); // sets the servo position 0-180
              // Write some debug info
              Serial.print("Servo changed. new state: ");
              Serial.println(val);
            } else if (message.type == V_UP) {
              Serial.println("Servo UP command");
              servos1.write(SERVO_MIN);
              send(msg1.set(100));
            } else if (message.type == V_DOWN) {
              Serial.println("Servo DOWN command");
              servos1.write(SERVO_MAX);
              send(msg1.set(0));
            } else if (message.type == V_STOP) {
              Serial.println("Servo STOP command");
              servos1.detach();
              attachedServo = false;
            }
          
            if (message.type == V_DIMMER && message.getSensor() == CHILD_ID2) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
              servos2.attach(servoPin2);
              int val = message.getInt();
              servos2.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * val); // sets the servo position 0-180
              // Write some debug info
              Serial.print("Servo changed. new state: ");
              Serial.println(val);
            } else if (message.type == V_UP) {
              Serial.println("Servo UP command");
              servos2.write(SERVO_MIN);
              send(msg2.set(100));
            } else if (message.type == V_DOWN) {
              Serial.println("Servo DOWN command");
              servos2.write(SERVO_MAX);
              send(msg2.set(0));
            } else if (message.type == V_STOP) {
              Serial.println("Servo STOP command");
              servos2.detach();
              attachedServo = false;
            }
          
            if (message.type == V_DIMMER && message.getSensor() == CHILD_ID3) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
              servos3.attach(servoPin3);
              int val = message.getInt();
              servos3.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * val); // sets the servo position 0-180
              // Write some debug info
              Serial.print("Servo changed. new state: ");
              Serial.println(val);
            } else if (message.type == V_UP) {
              Serial.println("Servo UP command");
              servos3.write(SERVO_MIN);
              send(msg3.set(100));
            } else if (message.type == V_DOWN) {
              Serial.println("Servo DOWN command");
              servos3.write(SERVO_MAX);
              send(msg3.set(0));
            } else if (message.type == V_STOP) {
              Serial.println("Servo STOP command");
              servos3.detach();
              attachedServo = false;
            }
          
            timeOfLastChange = millis();
          
          
          }
          
          mfalkviddM 1 Reply Last reply
          0
          • B bsmtdweller

            Thanks @Nca78! Thats exactly it! But how? I dug through the messages.h and found a "getSensor()" command. Prior to discovering that, I went through and re-wrote the code with no arrays hoping that it would simplify my understanding of whats going on. The new code is below. I feel it is close, but I'm still missing something - when a command is received all three servo pins respond, so while I think I have the root of the problem identified I'm struggling with syntax to make it work properly.

            Also thanks to @skywatch for chiming in - I was reading through his 2019 topic with @mfalkvidd - which seems applicable too regarding formatting the 'void receive' function. With such a jumbled, non-array-simplified code, my next step was to try and put chunks together in a separate function and then combine that into the void receive function. My gut tells me that won't help and I better get a more thorough understanding of simplifying with arrays first!

            Another question - I read somewhere that in order to accurately test this, there needs to be physical servos connected? My project where I have the servos installed, it out in the shop, far away from my computer -- so I've been simply testing the output of the pins with my voltmeter during this preliminary testing.

            Heres the non-array written code:

            #define MY_DEBUG
            #define MY_RF24_CE_PIN 49
            #define MY_RF24_CS_PIN 53
            #define MY_RF24_IRQ_PIN 2
            #define MY_RF24_PA_LEVEL RF24_PA_LOW
            // Enable and select radio type attached
            #define MY_RADIO_RF24
            //#define MY_RADIO_RFM69
            
            #include <MySensors.h>
            #include <Servo.h>
            
            #define SERVO_MIN 0
            #define SERVO_MAX 180
            #define DETACH_DELAY 900
            #define CHILD_ID1  13
            #define CHILD_ID2  14
            #define CHILD_ID3  15
            Servo servos1;
            Servo servos2;
            Servo servos3;
            #define servoPin1  39
            #define servoPin2  40
            #define servoPin3  41
            
            MyMessage msg1(CHILD_ID1, V_DIMMER);
            MyMessage msg2(CHILD_ID2, V_DIMMER);
            MyMessage msg3(CHILD_ID3, V_DIMMER);
            
            unsigned long timeOfLastChange = 0;
            bool attachedServo = false;
            
            
            void setup()
            {
              // Request last servo state at startup
            
              request(CHILD_ID1, V_DIMMER);
              request(CHILD_ID2, V_DIMMER);
              request(CHILD_ID3, V_DIMMER);
            
            
            }
            
            
            void presentation()  {
              // Send the sketch version information to the gateway and Controller
              sendSketchInfo("Servo", "1.0");
            
              // Register all sensors to gw (they will be created as child devices)
            
              present(CHILD_ID1, S_COVER);
              present(CHILD_ID2, S_COVER);
              present(CHILD_ID3, S_COVER);
            }
            
            
            void loop()
            {
            
              if (attachedServo && millis() - timeOfLastChange > DETACH_DELAY) {
                servos1.detach();
                servos2.detach();
                servos3.detach();
                attachedServo = false;
            
              }
            }
            
            void receive(const MyMessage &message) {
              Serial.println("   This is the Id of the Message     ");
              Serial.println(message.getSensor());
            
            
              if (message.type == V_DIMMER && message.getSensor() == CHILD_ID1) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
                servos1.attach(servoPin1);
                int val = message.getInt();
                servos1.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * val); // sets the servo position 0-180
                // Write some debug info
                Serial.print("Servo changed. new state: ");
                Serial.println(val);
              } else if (message.type == V_UP) {
                Serial.println("Servo UP command");
                servos1.write(SERVO_MIN);
                send(msg1.set(100));
              } else if (message.type == V_DOWN) {
                Serial.println("Servo DOWN command");
                servos1.write(SERVO_MAX);
                send(msg1.set(0));
              } else if (message.type == V_STOP) {
                Serial.println("Servo STOP command");
                servos1.detach();
                attachedServo = false;
              }
            
              if (message.type == V_DIMMER && message.getSensor() == CHILD_ID2) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
                servos2.attach(servoPin2);
                int val = message.getInt();
                servos2.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * val); // sets the servo position 0-180
                // Write some debug info
                Serial.print("Servo changed. new state: ");
                Serial.println(val);
              } else if (message.type == V_UP) {
                Serial.println("Servo UP command");
                servos2.write(SERVO_MIN);
                send(msg2.set(100));
              } else if (message.type == V_DOWN) {
                Serial.println("Servo DOWN command");
                servos2.write(SERVO_MAX);
                send(msg2.set(0));
              } else if (message.type == V_STOP) {
                Serial.println("Servo STOP command");
                servos2.detach();
                attachedServo = false;
              }
            
              if (message.type == V_DIMMER && message.getSensor() == CHILD_ID3) { // This could be M_ACK_VARIABLE or M_SET_VARIABLE
                servos3.attach(servoPin3);
                int val = message.getInt();
                servos3.write(SERVO_MAX + (SERVO_MIN - SERVO_MAX) / 100 * val); // sets the servo position 0-180
                // Write some debug info
                Serial.print("Servo changed. new state: ");
                Serial.println(val);
              } else if (message.type == V_UP) {
                Serial.println("Servo UP command");
                servos3.write(SERVO_MIN);
                send(msg3.set(100));
              } else if (message.type == V_DOWN) {
                Serial.println("Servo DOWN command");
                servos3.write(SERVO_MAX);
                send(msg3.set(0));
              } else if (message.type == V_STOP) {
                Serial.println("Servo STOP command");
                servos3.detach();
                attachedServo = false;
              }
            
              timeOfLastChange = millis();
            
            
            }
            
            mfalkviddM Offline
            mfalkviddM Offline
            mfalkvidd
            Mod
            wrote on last edited by
            #5

            @bsmtdweller an alternative to voltmeter could be to hook up a led (with matching resistor) to each servo pin. The led will then light up proportional to the servo signal.

            B 1 Reply Last reply
            1
            • mfalkviddM mfalkvidd

              @bsmtdweller an alternative to voltmeter could be to hook up a led (with matching resistor) to each servo pin. The led will then light up proportional to the servo signal.

              B Offline
              B Offline
              bsmtdweller
              wrote on last edited by
              #6

              Hi @mfalkvidd - thanks! That definitely makes it more fun! I set it up without resistors as the voltages produced on the servo pins are millivolts (hopefully not enough to burn an led). I'm re-working the code again with some arrays and will hopefully be able to report back with success:grimacing:

              1 Reply Last reply
              1
              • B Offline
                B Offline
                bsmtdweller
                wrote on last edited by
                #7

                I finally got it!! Staring me in the face the whole time! Forgetting the arrays portion, because I still can't figure that out with multiple servos and messages.

                My problem was that in the void receive 'if' conditions, I needed to specify from which child ID - right, we knew that part - but I ALSO needed to add the child ID conditional statement to ALL the 'else if' statements!

                Thanks to everyone for their help!!

                skywatchS 1 Reply Last reply
                2
                • B bsmtdweller

                  I finally got it!! Staring me in the face the whole time! Forgetting the arrays portion, because I still can't figure that out with multiple servos and messages.

                  My problem was that in the void receive 'if' conditions, I needed to specify from which child ID - right, we knew that part - but I ALSO needed to add the child ID conditional statement to ALL the 'else if' statements!

                  Thanks to everyone for their help!!

                  skywatchS Offline
                  skywatchS Offline
                  skywatch
                  wrote on last edited by
                  #8

                  @bsmtdweller Yay! - You got there - well done and thanks for sharing the knowledge.

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  12

                  Online

                  11.7k

                  Users

                  11.2k

                  Topics

                  113.1k

                  Posts


                  Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • MySensors
                  • OpenHardware.io
                  • Categories
                  • Recent
                  • Tags
                  • Popular