示例#1
0
    def output_limits(self, limits):
        if limits is None:
            self._min_output, self._max_output = None, None
            return

        min_output, max_output = limits

        if None not in limits and max_output < min_output:
            raise ValueError('lower limit must be less than upper limit')

        self._min_output = min_output
        self._max_output = max_output

        self._integral = Helpers.clamp(self._integral, self.output_limits)
        self._last_output = Helpers.clamp(self._last_output,
                                          self.output_limits)
示例#2
0
    def __call__(self, _input, dt=None):
        if not self.auto_mode:  # if we are in manual mode, dont calculate.
            return self._last_output

        now = Helpers.get_current_time()  # getting current time.

        if dt is None:
            dt = now - self._last_time if now - self._last_time else 1e-16
        elif dt <= 0:
            raise ValueError(
                'dt has a non-positive value {}. Value Must be non-negative.'.
                format(dt))

        if self.update_t is not None and dt < self.update_t and self._last_output is not None:
            # only update every update_t seconds
            return self._last_output

        # COMPUTING ERROR TERM, reducing from the setpoint our current input (how far are we from the setpoint).
        error = self.set_point - _input
        d_input = _input - (self._last_input
                            if self._last_input is not None else _input)

        # COMPUTING PROPORTIONAL TERM.
        self._proportional = self.kp * error

        # COMPUTING INTEGRAL TERM.
        self._integral += self.ki * error * dt
        self._integral = Helpers.clamp(self._integral, self.output_limits)

        # COMPUTING DERIVATIVE TERM.
        self._derivative = -self.kd * d_input / dt

        # final output, summing all values together.
        output = self._proportional + self._integral + self._derivative
        output = Helpers.clamp(output, self.output_limits)

        # keep track of state
        self._last_output = output
        self._last_input = _input
        self._last_time = now

        return output
示例#3
0
    def set_auto_mode(self, enabled, last_output=None):
        """
        Enable or disable the PID controller, optionally setting the last output value.
        This is useful if some system has been manually controlled and if the PID should take over.
        In that case, pass the last output variable (the control variable) and it will be set as
        the starting I-term when the PID is set to auto mode.
        :param enabled: Whether auto mode should be enabled, True or False
        :param last_output: The last output, or the control variable, that the PID should start
            from when going from manual mode to auto mode
        """
        if enabled and not self.auto_mode:
            # switching from manual mode to auto, reset
            self.reset()

            self._integral = last_output if last_output is not None else 0
            self._integral = Helpers.clamp(self._integral, self.output_limits)

        self.auto_mode = enabled