The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_pidctrl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2017,  Jeffrey Roberson <jeff@freebsd.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/kernel.h>
   34 #include <sys/systm.h>
   35 #include <sys/sysctl.h>
   36 #include <sys/pidctrl.h>
   37 
   38 void
   39 pidctrl_init(struct pidctrl *pc, int interval, int setpoint, int bound,
   40     int Kpd, int Kid, int Kdd)
   41 {
   42 
   43         bzero(pc, sizeof(*pc));
   44         pc->pc_setpoint = setpoint;
   45         pc->pc_interval = interval;
   46         pc->pc_bound = bound * setpoint * Kid;
   47         pc->pc_Kpd = Kpd;
   48         pc->pc_Kid = Kid;
   49         pc->pc_Kdd = Kdd;
   50 }
   51 
   52 void
   53 pidctrl_init_sysctl(struct pidctrl *pc, struct sysctl_oid_list *parent)
   54 {
   55 
   56         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "error", CTLFLAG_RD,
   57             &pc->pc_error, 0, "Current difference from setpoint value (P)");
   58         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "olderror", CTLFLAG_RD,
   59             &pc->pc_olderror, 0, "Error value from last interval");
   60         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "integral", CTLFLAG_RD,
   61             &pc->pc_integral, 0, "Accumulated error integral (I)");
   62         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "derivative", CTLFLAG_RD,
   63             &pc->pc_derivative, 0, "Error derivative (D)");
   64         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "input", CTLFLAG_RD,
   65             &pc->pc_input, 0, "Last controller process variable input");
   66         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "output", CTLFLAG_RD,
   67             &pc->pc_output, 0, "Last controller output");
   68         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "ticks", CTLFLAG_RD,
   69             &pc->pc_ticks, 0, "Last controller runtime");
   70         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "setpoint", CTLFLAG_RW,
   71             &pc->pc_setpoint, 0, "Desired level for process variable");
   72         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "interval", CTLFLAG_RD,
   73             &pc->pc_interval, 0, "Interval between calculations (ticks)");
   74         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "bound", CTLFLAG_RW,
   75             &pc->pc_bound, 0, "Integral wind-up limit");
   76         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "kpd", CTLFLAG_RW,
   77             &pc->pc_Kpd, 0, "Inverse of proportional gain");
   78         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "kid", CTLFLAG_RW,
   79             &pc->pc_Kid, 0, "Inverse of integral gain");
   80         SYSCTL_ADD_INT(NULL, parent, OID_AUTO, "kdd", CTLFLAG_RW,
   81             &pc->pc_Kdd, 0, "Inverse of derivative gain");
   82 }
   83 
   84 int
   85 pidctrl_classic(struct pidctrl *pc, int input)
   86 {
   87         int output, error;
   88         int Kpd, Kid, Kdd;
   89 
   90         error = pc->pc_setpoint - input;
   91         pc->pc_ticks = ticks;
   92         pc->pc_olderror = pc->pc_error;
   93 
   94         /* Fetch gains and prevent divide by zero. */
   95         Kpd = MAX(pc->pc_Kpd, 1);
   96         Kid = MAX(pc->pc_Kid, 1);
   97         Kdd = MAX(pc->pc_Kdd, 1);
   98 
   99         /* Compute P (proportional error), I (integral), D (derivative). */
  100         pc->pc_error = error;
  101         pc->pc_integral =
  102             MAX(MIN(pc->pc_integral + error, pc->pc_bound), -pc->pc_bound);
  103         pc->pc_derivative = error - pc->pc_olderror;
  104 
  105         /* Divide by inverse gain values to produce output. */
  106         output = (pc->pc_error / Kpd) + (pc->pc_integral / Kid) +
  107             (pc->pc_derivative / Kdd);
  108         /* Save for sysctl. */
  109         pc->pc_output = output;
  110         pc->pc_input = input;
  111 
  112         return (output);
  113 }
  114 
  115 int
  116 pidctrl_daemon(struct pidctrl *pc, int input)
  117 {
  118         int output, error;
  119         int Kpd, Kid, Kdd;
  120 
  121         error = pc->pc_setpoint - input;
  122         /*
  123          * When ticks expires we reset our variables and start a new
  124          * interval.  If we're called multiple times during one interval
  125          * we attempt to report a target as if the entire error came at
  126          * the interval boundary.
  127          */
  128         if ((u_int)ticks - pc->pc_ticks >= pc->pc_interval) {
  129                 pc->pc_ticks = ticks;
  130                 pc->pc_olderror = pc->pc_error;
  131                 pc->pc_output = pc->pc_error = 0;
  132         } else {
  133                 /* Calculate the error relative to the last call. */
  134                 error -= pc->pc_error - pc->pc_output;
  135         }
  136 
  137         /* Fetch gains and prevent divide by zero. */
  138         Kpd = MAX(pc->pc_Kpd, 1);
  139         Kid = MAX(pc->pc_Kid, 1);
  140         Kdd = MAX(pc->pc_Kdd, 1);
  141 
  142         /* Compute P (proportional error), I (integral), D (derivative). */
  143         pc->pc_error += error;
  144         pc->pc_integral =
  145             MAX(MIN(pc->pc_integral + error, pc->pc_bound), 0);
  146         pc->pc_derivative = pc->pc_error - pc->pc_olderror;
  147 
  148         /* Divide by inverse gain values to produce output. */
  149         output = (pc->pc_error / Kpd) + (pc->pc_integral / Kid) +
  150             (pc->pc_derivative / Kdd);
  151         output = MAX(output - pc->pc_output, 0);
  152         /* Save for sysctl. */
  153         pc->pc_output += output;
  154         pc->pc_input = input;
  155 
  156         return (output);
  157 }

Cache object: 39cdeff1289f3fe8f530ae33d97fbe4b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.