dPID: The code

status:

RC-1.0

The code of the test-examples and the (empty) dpid.dPID class are shown here. They are exactly as the python-files; but for the highlighting.

Some (py)test examples

 1# Copyright (C) 2017: ALbert Mietus, SoftwareBeterMaken
 2# Part of my MESS project
 3# Dropjes licencie: Beloon me met dropjes naar nuttigheid
 4
 5import pytest
 6
 7from logging import getLogger
 8logger = getLogger(__name__)
 9
10from dpid import dPID
11
12def test_P():
13    MARGIN  = 0.5
14
15    c = dPID(1,0,0)
16
17    c.setpoint(10.0)
18    c.measured(10.0)
19    out = c.result()
20
21    assert (-1*MARGIN) < out < MARGIN, "result (%s) should be close to zero (MARGIN=%s)" % (out, MARGIN)
22
23def test_clip():
24    c = dPID(1,2,3)
25
26    c.set_min_max(min_result=10)
27    c.set_min_max(max_result=10)
28
29    for sp in range(-100,100,10):
30        c.setpoint(sp)
31        c.measured(0)
32
33        got = c.result()
34        assert got == 10, "Both min and max are clipped to 10; so result should be 10!. But it is: %s" % c.result()

The class (empty)

 1# Copyright (C) 2017: ALbert Mietus, SoftwareBeterMaken
 2# Part of my MESS project
 3# Dropjes licencie: Beloon me met dropjes naar nuttigheid
 4
 5
 6from logging import getLogger
 7logger = getLogger(__name__)
 8
 9class dPID:
10    """A simple discrete-PID controller, as an exercise.
11
12    This PID-controller can be initialised with constantes for ``P``, ``I`` and ``D``;
13    which can't be changed afterwards.  Optional, a minimum and maximum
14    output value can be given; both during initialisation, and later.
15
16    The controller has two **inputs**: :meth:`.setpoint` and
17    :meth:`.measured`, and one **output**: :meth:`.result`. Those inputs can
18    be set/updated independently. Similarly, the :meth:`.result` can be read
19    at any-moment. As the controller will *remember* the timestamp a values
20    changes (and knows when the result is read), it will always give the
21    correct output. Thus, that output value does depend on the timestamp it
22    is requested!
23
24    The :meth:`.setpoint` is considered as a step-function: between two
25    changes, it will remain the last value. The :meth:`.measured` value
26    however should be considered as a continuously linear-changing value. So,
27    between two updates of this value, the dPID-controller will interpolate
28    linearly.
29
30    When a :meth:`.result` is read during such a period; the PID-controller can't
31    predict the next-measured-value, however. Therefor, it will (for that
32    single read) assume the measured-value is the same as last-time.
33
34    When a maximum and/or minimum value is set, the :meth:`.result` will be
35    clipped to that value when needed. Without a min/max, the :meth:`.result` is
36    unlimited.
37
38
39    .. hint:: As this class is part of an exercise; no implementation is given.
40
41       During the training one should update this file to implement the class
42       **without** changing the interface.
43
44       All (numeric) input & output values are either integers or floats.
45
46    """
47
48
49
50    def __init__(self, P,I,D, min_result=None, max_result=None): pass
51
52    def setpoint(self, sp):
53        """Set the setpoint: a numeric value."""
54
55    def measured(self, value):
56        """Give the controller an update on the actual *measured* (or simulated) process-value.
57
58        The controller will assume a linear progression between the last update and the current one
59        """
60
61    def result(self):
62        """Return the actual result value"""
63        return 0.0 # XXX
64
65    def set_min_max(self, min_result=None, max_result=None):
66        """Change the minimum and/or maximal result value. Used to clip the :meth:`.result`"""

Downloads

You can download these files directly from bitbucket

Comments

comments powered by Disqus