Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login

    Servo control with frequencies other than 50hz and M280

    Scheduled Pinned Locked Moved Solved
    General Discussion
    3
    10
    1.0k
    Loading More Posts
    • 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.
    • ardenpmundefined
      ardenpm
      last edited by ardenpm

      I have a KST DS216MG hobby servo I am trying to control. It has the following basic PWM control specifications:

      • Frequency: 333Hz
      • Pulse Width Range: 800μs - 2200μs

      Other common hobby servos like the SG90 use 50Hz and as stated in the Duet docs various pulse width ranges, usually between 1-2ms. Based on this I setup my servo on my Duet 2 Wifi with Duex 5 connected to PWM 5 and running RRF 3.3 as follows:

      M950 S0 C"duex.pwm5" Q333
      

      Using this setup I have not had any luck getting the servo to do anything other that a few random movements using the M280 command regardless of whether I try using the angle or the pulse width variant of the command. To diagnose this further I have put a scope on the PWM signal output to see what happening (excuse my ignorance, I am not an EE).

      So with the standard configuration setup to the default 50Hz like so:

      M950 S0 C"duex.pwm5"
      

      Then sending the following command to set an explicit pulse width:

      M280 P0 S2200
      

      I get the following PWM signal.

      DS1Z_QuickPrint1.png

      So 50Hz is as expected and the pulse width is at 2.2ms/2200μs exactly as expected. If I now change the configuration to include the frequency and send the same command.

      M950 S0 C"duex.pwm5" Q333
      M280 P0 S2200
      

      I instead get this PWM signal.

      DS1Z_QuickPrint3.png

      So the frequency has definitely come out correctly, however the pulse width is no longer correct. It looks like the pulse width has been divided by the increase in frequency 2200/(333/50) which is what I would expect if RRF isn't factoring in the frequency for the passed in pulse width.

      This would be fine if it were possible to multiply the pulse width in the M280 command artificially to compensate, however it looks like the S parameter in the M280 command is limited (correctly, EDIT: looks like it's just hard coded to a limit of 2400 actually) by the configured frequency (i.e., a pulse width of greater than 3000μs makes no sense when using 333Hz of course). So with M280 I don't seem to have any means of producing the correct range of pulse widths for this servo.

      However I can get the correct pulse widths if I use the M42 command instead and set a duty cycle corresponding to the pulse width that I want to see. So for example if I have the PWM output configured at 333Hz and send the following command:

      M42 P0 S0.73
      

      I then get the following PWM signal.

      DS1Z_QuickPrint4.png

      So now with the correct frequency and pulse width I need. Using that I was then able to determine the duty cycle for the minimum and maximum servo range and move the servo predicably with M42 between those extremes. So I imagine I can use M42 as a work around, however based on these experiments it looks to me like M280 doesn't work as intended for servos running at something other than 50Hz.

      I haven't filed a bug since I am not sure if my interpretation of what is happening here is correct given my fairly basic electronics knowledge. Am I missing something obvious or is this an issue with M280?

      ardenpmundefined 1 Reply Last reply Reply Quote 0
      • ardenpmundefined
        ardenpm @ardenpm
        last edited by

        And in what should have been my first step 🙂 looking at the code for M280 we have the following:

        if (angleOrWidth < MinServoPulseWidth)
        {
            // User gave an angle so convert it to a pulse width in microseconds
            angleOrWidth = (min<float>(angleOrWidth, 180.0) * ((MaxServoPulseWidth - MinServoPulseWidth) / 180.0)) + MinServoPulseWidth;
        }
        else if (angleOrWidth > MaxServoPulseWidth)
        {
            angleOrWidth = MaxServoPulseWidth;
        }
        float pwm = angleOrWidth * (ServoRefreshFrequency/1e6);
        if (invert)
        {
            pwm = 1.0 - pwm;
        }
        IoPort::WriteAnalog(servoPin, pwm, ServoRefreshFrequency);
        ...
        

        And ServoRefreshFrequency is hard coded to 50 in src/Configuration.h and MaxServoPulseWidth is set to 2400 in src/GCodes/GCodes.h. So this explains why I see no effect setting the pulse width above 2400. So in the above code it looks like the frequency is backed out of the pwm value to account for it being passed in to the WriteAnalog call.

        Nowhere in this code is the pins configured PWM frequency taken into account, not sure if it happens deeper in IoPort::WriteAnalog or not, that seems to have two variants, one for expansion and one for regular and the expansion one ignores the frequency (so not sure if my issue is specific to using the Duex5).

        ardenpmundefined 1 Reply Last reply Reply Quote 0
        • ardenpmundefined
          ardenpm @ardenpm
          last edited by

          Doesn’t look like anyone else is having this issue. I’m trying to work out whether to report a bug or not since reading several other issues on Github people are directed to seek support here on the forum first to establish if it is an issue or just not understanding the way something is intended to work.

          fcwiltundefined 1 Reply Last reply Reply Quote 0
          • fcwiltundefined
            fcwilt @ardenpm
            last edited by

            @ardenpm

            Does the servo not work at 50 Hz?

            Frederick

            Printers: a small Utilmaker style, a small CoreXY and a E3D MS/TC setup. Various hotends. Using Duet 3 hardware running 3.4.6

            ardenpmundefined 1 Reply Last reply Reply Quote 0
            • ardenpmundefined
              ardenpm @fcwilt
              last edited by

              @fcwilt no it does not seem to. It just makes some random movements with various commands, presumably when the signal aligns to something it understands.

              I may try again now that I know more about the actual signal that is being output since it does seem to work on an Arduino with the normal Servo library which is strange since that presumably also assumes 50Hz.

              dc42undefined 1 Reply Last reply Reply Quote 0
              • dc42undefined
                dc42 administrators @ardenpm
                last edited by dc42

                @ardenpm are you sure that 333Hz isn't the maximum frequency accepted by that servo?

                I'll look into supporting different PWM frequencies in M280.

                Duet WiFi hardware designer and firmware engineer
                Please do not ask me for Duet support via PM or email, use the forum
                http://www.escher3d.com, https://miscsolutions.wordpress.com

                ardenpmundefined 1 Reply Last reply Reply Quote 0
                • ardenpmundefined
                  ardenpm @dc42
                  last edited by

                  @dc42 definitely not sure given how sketchy the spec sheets are for these types of servos. However it is sold as a ‘digital’ servo rather than an ‘analog’ servo.

                  I wasn’t aware of the distinction previously but from what I understand the digital servos typically do use a higher frequency signal and update their position more frequently.

                  That’s going on chatter on FPV and model plane forums which seems to be where they get the most use. Their controllers seem to require you to specify the frequency.

                  I’ll do some more experiments and see if I can get it to do anything useful at 50Hz, however it definitely worked well at 333Hz once I got it sending the pulse widths in the spec sheet with M42 where as at 50Hz I was only able to get random motions.

                  Frequency support for M280 would be great though.

                  dc42undefined 1 Reply Last reply Reply Quote 0
                  • dc42undefined
                    dc42 administrators @ardenpm
                    last edited by

                    @ardenpm said in Servo control with frequencies other than 50hz and M280:

                    Frequency support for M280 would be great though.

                    I have now implemented and tested this.

                    Duet WiFi hardware designer and firmware engineer
                    Please do not ask me for Duet support via PM or email, use the forum
                    http://www.escher3d.com, https://miscsolutions.wordpress.com

                    ardenpmundefined 1 Reply Last reply Reply Quote 0
                    • ardenpmundefined
                      ardenpm @dc42
                      last edited by

                      @dc42 Wow, fast work! Just took a quick look at the code in the 3.4-dev branch, looking forward to testing it out when ready in a build.

                      ardenpmundefined 1 Reply Last reply Reply Quote 0
                      • ardenpmundefined
                        ardenpm @ardenpm
                        last edited by

                        Just for prosperity if others come across this thread in the future, I finally got around to updating to RRF 3.4.x and the implemented change works great. I can now correctly define the servo with the needed PWM frequency like so:

                        M950 S0 C”duex.pwm5” Q333
                        

                        And then move it with the servo commands like so:

                        M280 P0 S45 ; set servo position to 45 degrees
                        

                        And it moves a sensible amount as expected.

                        1 Reply Last reply Reply Quote 1
                        • dc42undefined dc42 marked this topic as a question
                        • dc42undefined dc42 has marked this topic as solved
                        • First post
                          Last post
                        Unless otherwise noted, all forum content is licensed under CC-BY-SA