Use one sensor two time, for heating and cooling heated chamber

Hi,

I actually work on my Voron 2.4 R2 (from a Siboor KIT) and all it work bu i need to try somes customs things and make this simple kit more complicated just becauseeeee i’m dumb.

Actually i want to get more control on the chamber temp. I’ve add a temperature sensor on the air of the chamber. I have added a fan under the bed to control to heating and an exaust fan to control the cooling.

So i try to control two fan with a single sensor and with this configuration:

[heater_generic heater_chamber]
heater_pin: PA8
max_power: 1.0
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF4
control: watermark
max_delta: 1.0
min_temp: -100
max_temp: 70
gcode_id: C

[verify_heater heater_chamber]
max_error: 300
check_gain_time: 480
hysteresis: 5
heating_gain: 1


[temperature_fan cooling_chamber]
pin: PD13
max_power: 1.0
shutdown_speed: 0.0
kick_start_time: 5.0
cycle_time:0.01
off_below:0.1
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF5
min_temp: 0
max_temp: 70
target_temp: 0
control: watermark

I use PF4 and PF5 but it’s a single sensor in parallel in two pin, this configuration divide the resistance og the sensor and the temp is equaly divided

And if i try to use only one pin Klipper say that:
“pin PF4 used multiple times in config”

So how to use the same pin two time ?
Or how to manipulate the value of the sensor when i plug it in two pin?

Thank by advance for all

RESOLUTION!
The good configuration:

#--------------------------SET THE SENSOR USABLE MUTIPLI------------------------------------------
[duplicate_pin_override]
pins: PF4
#####################################################################
#                          NEVERMORE PA8 T0
#####################################################################
#--------------------------MANUAL CONTROL------------------------------------------
#[fan_generic Nevermore]
#pin: PA8
#kick_start_time: 0.5
#off_below: 0.10
#--------------------------TEMP TARGETING CONTROL------------------------------------------
[heater_generic heater_chamber]
heater_pin: PA8
max_power: 1.0
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF4
control: watermark
max_delta: 1.0
min_temp: -100
max_temp: 70
gcode_id: C

[verify_heater heater_chamber]
max_error: 300
check_gain_time: 480
hysteresis: 5
heating_gain: 1

#####################################################################
#                          BED FAN (EXHAUST) PD13 T0
#####################################################################
#--------------------------MANUAL CONTROL------------------------------------------
#[fan_generic Exaust]     # exhaust_fan
#pin: PD13                    # FAN-4
#kick_start_time: 0.5
#off_below: 0.10
#--------------------------TEMP TARGETING CONTROL------------------------------------------
[temperature_fan cooling_chamber]
pin: PD13
max_power: 1.0
shutdown_speed: 0.0
kick_start_time: 5.0
cycle_time:0.01
off_below:0.1
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF4
min_temp: 0
max_temp: 70
target_temp: 0
control: watermark


#####################################################################
#                          CHAMBER TEMP MACCRO
#####################################################################
[gcode_macro M141]
gcode:
  {% set CHAMBER_TARGET_TEMP = params.S|default(0)|int %}
  { action_respond_info('Chamber temp set to %.1fC.' % (CHAMBER_TARGET_TEMP)) }
  {% set TARGET_BED_TEMP = printer.heater_bed.target %}
  {% set MINIMAL_DELTA_AIR_BED = 20 %} 

  {% if TARGET_BED_TEMP < (CHAMBER_TARGET_TEMP+MINIMAL_DELTA_AIR_BED) %} ## Judging the actual targeted bed temperature
    { action_respond_info('Impossible de régler la température de la chambre a %.1fC , la valeur demandée est trop haute par rapport à celle du plateau. Merci de régler celle ci en respectant un écart de %.1fC.' % (CHAMBER_TARGET_TEMP, TARGET_BED_TEMP, MINIMAL_DELTA_AIR_BED)) }
  {% endif %}

  SET_HEATER_TEMPERATURE HEATER=heater_chamber TARGET={CHAMBER_TARGET_TEMP}
  SET_TEMPERATURE_FAN_TARGET temperature_fan="cooling_chamber" target={S}

The solution is fin here: Configuration reference - Klipper documentation

Thanks @TheFuzzyGiggler <3

Hello @vistorx !

Don’t you have a spare sensor that you can connect separately?

This is what you want…

https://www.klipper3d.org/Config_Reference.html?h=dupli#duplicate_pin_override

Edit: I’ve thought about submitting a change to allow temp sensors to be read without needing to be set as a duplicate pin, but Kevin would need to double check it to make sure there are no unforseen consequences.

From a naive standpoint though, what’s the harm in using the temp for multiple things? Unless there is some kind of read contention.

1 Like

I already thought about this when I read Sineos article about the fans.
It came to my mind: Why not do it like in OOP, declare read only items (sensors, switches, etc) as an “object” to what every macro has access.

1 Like

I actually changed my testing setup of Klipper a while ago to allow ADC_Temperature pins to be defined multiple places without throwing a warning. I haven’t had any issues yet but it’s not something I tested in a lot of various scenarios.

    def lookup_pin(self, pin_desc, can_invert=False, can_pullup=False,
                   share_type=None):
        pin_params = self.parse_pin(pin_desc, can_invert, can_pullup)
        pin = pin_params['pin']
        share_name = "%s:%s" % (pin_params['chip_name'], pin)
        if share_name in self.active_pins:
            share_params = self.active_pins[share_name]
            if share_name in self.allow_multi_use_pins or pin == 'ADC_TEMPERATURE':
                pass
            elif share_type is None or share_type != share_params['share_type']:
                raise error("pin %s used multiple times in config" % (pin,))
            elif (pin_params['invert'] != share_params['invert']
                  or pin_params['pullup'] != share_params['pullup']):
                raise error("Shared pin %s must have same polarity" % (pin,))
            return share_params
        pin_params['share_type'] = share_type
        self.active_pins[share_name] = pin_params
        return pin_params

The only part I added was the

or pin == 'ADC_TEMPERATURE':

I’m sure there is a way to do it with GCode Macros too but man I suck at Jinja2.

Ho thanks!!! I’m not a good guy, it’s on the documentation… I need to read more before ask questions.

You’re good, There are so many config options in Klipper it can get overwhelming. Easier to ask a simple question than to spend multiple days beating your head against the wall trying to figure it out.

It’s not just reading the data - at the micro-controller layer one must configure the pin and schedule events to read values from the adc hardware. If using the duplicate pin system then it does these things twice (configures the pin twice and schedules twice as many actions). That can have side effects depending on the hardware. In most cases, it is preferable for the Python host code to configure and schedule one set of events and then propagate the values internally.

Cheers,
-Kevin

That was my assumption, I agree there shouldn’t be two reads for two separate functions. That’s wasteful. The host should query one and hold that value for any function needing that temp and only update on the next scheduled update. If there are conflicting update schedules my, again, very naive assumption, would be to just use the more frequent update schedule and have the others defer to that value.

Either way, It doesn’t come up often enough to worry about. I just ran into it once and kind of scratched my head on it and moved on.