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

    Pressured air cooling controlled with servo and ball valve

    Scheduled Pinned Locked Moved
    General Discussion
    11
    61
    3.8k
    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.
    • o_lampeundefined
      o_lampe @MaxGyver
      last edited by

      @maxgyver said in Pressured air cooling controlled with servo and ball valve:

      Can a demon.g be used to translate the M106 Fan speed into a Servo position?
      In my case I need 0%-100% fan speed to equal 0°-90° Servo position. (Or stepper position as an alternative? )

      It would be nice if we could write a macro called 'M106' and put all the math required there. When gcode contains a M106 command, the macro is called instead of the fan definition in config.g
      I'm currently in a similar position, where I want to change retract/unretract behaviour and use a servo or solenoid for Z-hop.

      Phaedruxundefined 1 Reply Last reply Reply Quote 0
      • Phaedruxundefined
        Phaedrux Moderator @o_lampe
        last edited by

        @o_lampe said in Pressured air cooling controlled with servo and ball valve:

        It would be nice if we could write a macro called 'M106' and put all the math required there. When gcode contains a M106 command, the macro is called instead of the fan definition in config.g

        I've suggested that before. while it's currently possible to add a macro to create a new gcode, it's a bit harder to do for an existing gcode function that the firmware expects to behave a certain way.

        In this specific case it's been requested to allow M106 to function with things other than fans and it's on the wishlist for now.

        Z-Bot CoreXY Build | Thingiverse Profile

        o_lampeundefined MaxGyverundefined 2 Replies Last reply Reply Quote 2
        • o_lampeundefined
          o_lampe @Phaedrux
          last edited by

          @phaedrux said in Pressured air cooling controlled with servo and ball valve:

          it's a bit harder to do for an existing gcode function that the firmware expects to behave a certain way.

          I see, it would be necessary to find the original M106 code snipped in the source and process the same odds and ends in a custom macro.

          1 Reply Last reply Reply Quote 0
          • MaxGyverundefined
            MaxGyver @Phaedrux
            last edited by

            @phaedrux
            Can you please post the link to the wishlist post? I would like to follow the thread.

            -Max

            Phaedruxundefined 1 Reply Last reply Reply Quote 0
            • Phaedruxundefined
              Phaedrux Moderator @MaxGyver
              last edited by

              @maxgyver The main wishlist forum is here: https://forum.duet3d.com/category/8/firmware-wishlist

              I'm not sure where the thread in question was though. It may not have been a request there. But if you want to make it more official you can create a thread there about it.

              Z-Bot CoreXY Build | Thingiverse Profile

              1 Reply Last reply Reply Quote 0
              • MikeDCundefined
                MikeDC
                last edited by

                i did this with limited success for a servo on out7 with ballvalve,

                i created a macro called airservovalve with the below

                ; AirValveServo
                if fans[0].actualValue = 0
                M280 P1 S0 ; Close the valve
                elif fans[0].actualValue >= 0.01 && fans[0].actualValue <= 0.10
                M280 P1 S18 ; Open valve 10%
                elif fans[0].actualValue >= 0.11 && fans[0].actualValue <= 0.20
                M280 P1 S36 ; Open valve 20%
                elif fans[0].actualValue >= 0.21 && fans[0].actualValue <= 0.30
                M280 P1 S54 ; Open valve 30%
                elif fans[0].actualValue >= 0.31 && fans[0].actualValue <= 0.40
                M280 P1 S72 ; Open valve 40%
                elif fans[0].actualValue >= 0.41 && fans[0].actualValue <= 0.50
                M280 P1 S90 ; Open valve 50%
                elif fans[0].actualValue >= 0.51 && fans[0].actualValue <= 0.60
                M280 P1 S108 ; Open valve 60%
                elif fans[0].actualValue >= 0.61 && fans[0].actualValue <= 0.70
                M280 P1 S126 ; Open valve 70%
                elif fans[0].actualValue >= 0.71 && fans[0].actualValue <= 0.80
                M280 P1 S144 ; Open valve 80%
                elif fans[0].actualValue >= 0.81 && fans[0].actualValue <= 0.90
                M280 P1 S162 ; Open valve 90%
                elif fans[0].actualValue >= 0.91 && fans[0].actualValue <= 1.0
                M280 P1 S180 ; Open valve 100%

                Then in Daemon.g added this
                M98 P"0:/macros/Special Scripts/AirValveServo"

                The only issue was it was a bit slow responding to fan speed changes

                MaxGyverundefined o_lampeundefined 2 Replies Last reply Reply Quote 2
                • MaxGyverundefined
                  MaxGyver @MikeDC
                  last edited by

                  @mikedc

                  Hey, thank you very much for sharing this. I will give it a try!

                  -Max

                  1 Reply Last reply Reply Quote 1
                  • o_lampeundefined
                    o_lampe @MikeDC
                    last edited by o_lampe

                    @mikedc
                    Isn't it better to 'scale' the incoming PWM value to the required servo-angle?
                    You need to know: min_in, max_in, min_out, max_out.

                    [**pseudo** code]
                    var scale_factor = {(max_out - min_out) / (max_in - min_in)}
                    var servo_out = {scale_factor * (fans[0].actualValue - min_in) + min_out}
                    

                    There's a standard formula to scale variables, but I couldn't write it down from memory.. Have to google it..
                    //edit This should work, just have to put it in clean gcode-meta

                    MikeDCundefined 1 Reply Last reply Reply Quote 1
                    • MikeDCundefined
                      MikeDC @o_lampe
                      last edited by

                      @o_lampe maybe yes, but when i was trying this it was the only way i could get it working

                      1 Reply Last reply Reply Quote 0
                      • MaxGyverundefined
                        MaxGyver
                        last edited by MaxGyver

                        @o_lampe

                        So just to recap, these are my values:

                        • min_in = 0 (M106 S0 ->Fan off)
                        • max_in = 255 (M106 S255 -> Fan full on)
                        • min_out = 0 (M280 P0 S0 -> Servo at 0° -> valve closed)
                        • max_out =90 (M280 P0 S90 -> Servo at 90° -> valve fully open)

                        So my code should look like this ?

                        [**pseudo** code]
                        var scale_factor = {(90 - 0) / (255 - 0)}
                        var servo_out = {scale_factor * (fans[0].actualValue - 0) + 90}
                        
                        M280 P0 S{var.servo_out}
                        

                        I have not used G-Code meta commands before, so I would need a little help here to put this in clean meta code and make this work.

                        -Max

                        o_lampeundefined OwenDundefined 3 Replies Last reply Reply Quote 0
                        • o_lampeundefined
                          o_lampe @MaxGyver
                          last edited by o_lampe

                          @maxgyver
                          I haven't written anything in Meta-code yet, but I read a little.
                          E.g. the waved brackets {} are mandatory for the outmost math-expressions.
                          If you want to test it, you can replace M280...with a harmless echo P"var.servo_out"

                          I believe, there is a way to call daemon.g more often to get a faster response, maybe the experts can chime in here?

                          For later editing it could be useful to put the min/max values in variables too, otherwise you can cut a few corners, where a value is zero.

                          1 Reply Last reply Reply Quote 0
                          • OwenDundefined
                            OwenD @MaxGyver
                            last edited by OwenD

                            @maxgyver

                            @maxgyver
                            You would probably be better off declaring global variables in config.g then updating the value in your macro ( or daemon.g)
                            If you're running in daemon.g it just seems counter productive to be declaring and freeing variables constantly.

                            Config.g

                            ; create variables - must be after servo is created 
                            global scale_factor = {(90 - 0) / (1 - 0)} ; no need for the math in this instance but it makes it clear how you arrive at the value.
                            global servo_out = 0 ; set to zero initially 
                             M280 P0 S{global.servo_out} ; start with valve closed
                            

                            Daemon.g

                            set global.servo_out = {global.scale_factor * (fans[0].actualValue - 0) + 0} ; calculate position required 
                            M280 P0 S{global.servo_out} ; adjust valve position. 
                            

                            You could optionally use an IF statement to only adjust when required, which I suppose would reduce the traffic and cpu time by a tiny amount.

                            1 Reply Last reply Reply Quote 0
                            • OwenDundefined
                              OwenD @MaxGyver
                              last edited by OwenD

                              @maxgyver said in Pressured air cooling controlled with servo and ball valve:

                              @o_lampe

                              So just to recap, these are my values:

                              • min_in = 0 (M106 S0 ->Fan off)
                              • max_in = 255 (M106 S255 -> Fan full on)
                              • min_out = 0 (M280 P0 S0 -> Servo at 0° -> valve closed)
                              • max_out =90 (M280 P0 S90 -> Servo at 90° -> valve fully open)

                              Actually , thinking about this, the value you get back from fans[0].actualValue will be in the range 0-1, not 0-255
                              You will need to change your code accordingly.

                              1 Reply Last reply Reply Quote 0
                              • OwenDundefined
                                OwenD
                                last edited by

                                It's a rainy day here, so for something to do I decided to fully test this.
                                Using a YM2763 13kg/cm hobby servo (externally powered so as to not risk damaging the duet).
                                This has an input range of 0-180 which corresponds to the angle.

                                Please refer to the notes for M280 as other servos may require different values

                                It's not really necessary to create variables for all settings, but it makes adjustment and readability easier.

                                in config.g

                                ;Valve Control
                                ; Set up scaling variables {(output_end - output_start) / (input_end - input_start)}
                                M950 S1 C"exp.heater4"  ; assign GPIO port 1 to heater4 on expansion connector, servo mode
                                global InputStart = 0 
                                global InputEnd = 1
                                global OutputStart = 0
                                global OutputEnd = 90
                                global ScaleFactor = (global.OutputEnd - global.OutputStart) / (global.InputEnd - global.InputStart) ; no need for the math in this instance but it makes it clear how you arrive at the value.
                                global ServoOut = floor(global.ScaleFactor * (fans[0].actualValue - global.InputStart) + 0.5) + global.OutputStart ; calculate position required on sevo - use floor() to apply rounding
                                M280 P1 S{global.servo_out} ; adjust valve position to reflect fan speed.
                                

                                in daemon.g or macro

                                set global.ServoOut = floor((global.ScaleFactor * (fans[0].actualValue - global.InputStart)) + 0.5) + global.OutputStart ; calculate position required - use floor() to apply rounding to nearest whole number
                                ;echo {global.ServoOut}
                                M280 P1 S{global.ServoOut} ; adjust valve attached to servo on P1 to reflect scaled fan speed. 
                                
                                o_lampeundefined MaxGyverundefined 2 Replies Last reply Reply Quote 2
                                • o_lampeundefined
                                  o_lampe @OwenD
                                  last edited by

                                  @owend
                                  Thank you for chiming in!
                                  Can you confirm that in math formulas no waved brackets are necessary, but when I call eg. M280 the parameter has to be wrapped in {}?
                                  How do I know, I have enough free memory to write longer meta-code? (AI for TicTacToe can get quite voluminous)

                                  OwenDundefined 1 Reply Last reply Reply Quote 0
                                  • OwenDundefined
                                    OwenD @o_lampe
                                    last edited by

                                    @o_lampe said in Pressured air cooling controlled with servo and ball valve:

                                    @owend
                                    Thank you for chiming in!
                                    Can you confirm that in math formulas no waved brackets are necessary, but when I call eg. M280 the parameter has to be wrapped in {}?

                                    Correct on both counts

                                    How do I know, I have enough free memory to write longer meta-code? (AI for TicTacToe can get quite voluminous)

                                    You can use M122 to see how much of the heap is used.
                                    See here

                                    o_lampeundefined 1 Reply Last reply Reply Quote 0
                                    • o_lampeundefined
                                      o_lampe @OwenD
                                      last edited by

                                      @owend
                                      I just found this thread, please see my reply there

                                      1 Reply Last reply Reply Quote 0
                                      • o_lampeundefined
                                        o_lampe
                                        last edited by o_lampe

                                        @OwenD and @MaxGyver
                                        Thinking further and having pity with the servo, it would be better to add a 'hysteresis' in the code, such as

                                        [pseudo code]
                                        If (abs(new_fan_value - old_fan_value) > hysteresis)
                                           go on
                                        else
                                          break
                                        
                                        

                                        That's not necessarily a problem with fan-values changing in big numbers, but a Servo also has a'deadband' which you have to keep in mind. (and for further reference, if someone wants to reuse the code for something else)

                                        1 Reply Last reply Reply Quote 0
                                        • MaxGyverundefined
                                          MaxGyver @OwenD
                                          last edited by

                                          @owend

                                          I am getting the following error after inserting your code in my config.g

                                          "Error: Failed to read code from macro config.g: Failed to parse major G-code number (lobal) in line 85"

                                          To me, it looks like the global variable are not recognized by the firmware:

                                          I am using firmware version 3.3-b2.

                                          screen.PNG

                                          1 Reply Last reply Reply Quote 0
                                          • o_lampeundefined
                                            o_lampe
                                            last edited by

                                            You have written servoout and also servo_out.

                                            MaxGyverundefined OwenDundefined 2 Replies Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Unless otherwise noted, all forum content is licensed under CC-BY-SA