You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/sphinx/source/software/sw_description.rst
+41-8Lines changed: 41 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -72,7 +72,7 @@ The *Speed Helper* block effectively sets the setpoint of the controller accordi
72
72
For feedback the back EMF voltage *V_EMF* is measured via voltage divider and ADC. *V_EMF* is proportional to the motor speed.
73
73
74
74
75
-
While the central component is the PID controller, there is an additional block called `Feed-forward <https://en.wikipedia.org/wiki/Feed_forward_(control)>`_ that has an impact on the control output variable. The Feed-forward block adds an additional offset to the output depending on the setpoint; this is done to achieve better control. A more detailed explanation regarding Feed-forward can be found below. The speed helper block corresponds to the ``speed_helper()`` function, which delays changing the setpoint according to the configured deceleration/acceleration rates.
75
+
While the central component is the PID controller, there is an additional block called `Feed-forward <https://en.wikipedia.org/wiki/Feed_forward_(control)>`_ that has an impact on the control output variable. The Feed-forward block adds an additional offset to the output depending on the setpoint; this is done to achieve better control. A more detailed explanation regarding Feed-forward can be found below. The speed helper block corresponds to the :c:func:`speed_helper()` function, which delays changing the setpoint according to the configured deceleration/acceleration rates.
@@ -90,16 +90,35 @@ This means the actual output of the PID controller is the sum of the PID output
90
90
The benefit of doing this is that the PID controller does not have to work in the non linear friction region of the motor, improving control performance.
91
91
92
92
93
+
Speed Table Initialization
94
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
95
+
96
+
The speed table is a crucial component of the motor control system, as it translates the 128 speed steps received from the DCC controller into specific setpoints for the PID controller. This table is initialized once at startup in the :c:func:`init_controller` function. The shape of the speed curve can be configured using three CV values: `V_min` (CV2), `V_mid` (CV6), and `V_max` (CV5).
97
+
98
+
- **V_min (CV2):** Defines the starting voltage (setpoint) for the first speed step.
99
+
- **V_mid (CV6):** Sets the voltage at the midpoint of the speed range (speed step 64).
100
+
- **V_max (CV5):** Determines the maximum voltage at the highest speed step (126).
101
+
102
+
The speed table is calculated with two linear interpolations: one from `V_min` to `V_mid` and another from `V_mid` to `V_max`. This creates a two-segment linear speed curve, which allows for a non-linear relationship between the speed step and the motor voltage. For example, you can have a gentle acceleration at low speeds and a more aggressive one at higher speeds.
103
+
104
+
The :c:func:`speed_helper` function then uses this table to gradually adjust the setpoint based on the configured acceleration and deceleration rates.
105
+
106
+
93
107
Startup Controller
94
108
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
95
109
96
-
Used on startup, meaning when the motor is not moving. First the startup controller retrieves the last `BASE_PWM_ARR_LEN` base PWM levels.
97
-
The base pwm levels are not retained on a power cycle. That means when there is no previous base PWM level saved, the startup controller will start ramping up from 0.
98
-
When there is less than `BASE_PWM_ARR_LEN` base PWM levels saved, the startup controller will ramp up from the average of the saved base PWM levels.
110
+
The startup controller is used when the motor is stationary to find the minimum PWM level required to overcome static friction. This process is not retained on a power cycle.
111
+
112
+
The initial PWM level for the startup sequence is determined as follows:
113
+
114
+
- If previous successful startup levels are saved in memory, the controller calculates their average, :math:`\bar{b}`, and sets the initial PWM level to :math:`\frac{2}{3} \cdot\bar{b}`.
115
+
- If no previous levels are saved, the ramp-up starts from a PWM level of 0.
116
+
117
+
From this starting point, the controller progressively ramps up the duty cycle until motor movement is detected. The ramp-up is not smooth but occurs in steps, with the step size determined by the maximum PWM level (which is a function of the PWM frequency).
99
118
100
-
After the startup controller retrieved the average of the last base pwm levels :math:`\bar{b}` it sets a PWM duty cycle level of :math:`\frac{2}{3} \cdot\bar{b}` and then ramps up the duty cycle/PWM level until the motor starts moving.
101
-
When no previous startup PWM levels are saved the startup controller begins ramping up from 0.
102
-
The actual value at which the motor started moving is multiplied by `K_FF` and used as a reference for the :ref:`feed forward <feed_forward>` block.
119
+
If the PWM level reaches its maximum without motor movement, the controller reduces the starting level by half and retries, preventing excessive power to a stalled motor.
120
+
121
+
Once movement is detected (via back-EMF voltage), the current PWM `level` is saved as a new base value for future startups. This value is also multiplied by `K_FF` (from CV47) and used as the feed-forward term for the PID controller.
103
122
104
123
105
124
@@ -156,6 +175,10 @@ Gain Scheduling
156
175
157
176
Another aspect to consider is the implementation of `gain scheduling <https://en.wikipedia.org/wiki/Gain_scheduling>`_. K\ :sub:`P` is a function of the current setpoint. Often it is favorable to have a higher proportional gain K\ :sub:`P` for slow speeds, achieving better control results. The illustration above shows the default setting for K\ :sub:`P`. CV_54 & CV_55 are used to set K\ :sub:`P` @ x\ :sub:`0`, CV_56 & CV_57 for K\ :sub:`P` @ x\ :sub:`1`, and CV_58 & CV_59 for K\ :sub:`P` @ x\ :sub:`2`. Additionally, CV_60 is used to shift x\ :sub:`1` from the leftmost point (0% = 0/255) to the rightmost point (100% = 255/255).
158
177
178
+
The :c:func:`get_kp()` function implements this gain scheduling. It calculates the proportional gain `K_p` based on the current setpoint `sp`. The function uses two different linear equations to determine `K_p`, depending on whether the setpoint is above or below the `k_p_x_1` threshold. This creates a piecewise linear function for `K_p`, allowing for different gain characteristics at different speed ranges.
179
+
180
+
The parameters for these linear equations (`k_p_m_1`, `k_p_m_2`, `k_p_y_0`, `k_p_y_1`) are pre-calculated in the :c:func:`init_controller` function based on the corresponding CV values.
181
+
159
182
160
183
.. _feed_forward:
161
184
@@ -167,10 +190,20 @@ In essence this means that the output of the PID controller is not only the sum
167
190
The base PWM level is set by the startup controller and is the PWM level at which the motor starts moving.
168
191
169
192
193
+
Speed Helper
194
+
^^^^^^^^^^^^^^^^^^
195
+
196
+
The :c:func:`speed_helper` function is responsible for implementing smooth acceleration and deceleration. It is called by a repeating timer, with the interval configured by CV175. This function acts as a temporal filter for the speed setpoint.
197
+
198
+
Instead of instantly changing the motor's setpoint to the new target speed step, the :c:func:`speed_helper` function gradually increments or decrements the current setpoint based on the acceleration (CV3) and deceleration (CV4) rates. These CVs determine how many calls to :c:func:`speed_helper` are needed for a single speed step change. For example, if the acceleration rate is set to 5, the :c:func:`speed_helper` must be called 5 times before the setpoint is incremented to the next speed step. This creates a time-based acceleration/deceleration curve.
199
+
200
+
The function also handles direction changes. If a direction change is detected, it will immediately jump to the new target speed without any delay, ensuring a responsive change in direction.
201
+
202
+
170
203
Back-EMF voltage measurement
171
204
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172
205
173
-
To provide a feedback signal proportional to the motor speed, the ADC is used to measure the `Back-EMF voltage <https://en.wikipedia.org/wiki/Counter-electromotive_force>`_. The measurement works by setting the PWM duty cycle to 0%, waiting for a certain delay time (CV_62), and then measuring x times (x = CV_63). While measuring, the array with measurement values is sorted using insertion sort. Afterwards, y elements (y = CV_63) from the left (lowest values) and z elements (z = CV_64) from the right (highest values) will be dismissed to mitigate the impact of potential outliers in measurement. The average value of the remaining values will be computed and fed back into the control algorithm. Considering default settings (100us delay, 100 samples, ~2µs sampling time), the complete measurement run, including averaging, takes about 0.3ms to 0.35ms, which effectively reduces the maximum possible duty cycle to about 93% to 94%.
206
+
To provide a feedback signal proportional to the motor speed, the ADC is used to measure the `Back-EMF voltage <https://en.wikipedia.org/wiki/Counter-electromotive_force>`_. The measurement works by setting the PWM duty cycle to 0%, waiting for a certain delay time (CV_62), and then measuring x times (x = CV_61). The ADC input channel is selected based on the motor's direction (forward or reverse). While measuring, the array with measurement values is sorted using insertion sort. Afterwards, y elements (y = CV_63) from the left (lowest values) and z elements (z = CV_64) from the right (highest values) will be dismissed to mitigate the impact of potential outliers in measurement. The average value of the remaining values will be computed and fed back into the control algorithm. Considering default settings (100us delay, 100 samples, ~2µs sampling time), the complete measurement run, including averaging, takes about 0.3ms to 0.35ms, which effectively reduces the maximum possible duty cycle to about 93% to 94%.
0 commit comments