Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 15:46 23 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : PID in MMBasic

Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9100
Posted: 11:38am 17 Sep 2024
Copy link to clipboard 
Print this post

The Pico2 gives more power than we had previously and potentially opens up new applications. I note that we have serious users of control type technologies so I thought it might be helpful to embed some semi-automatic PID functionality in MMbasic that could run multiple PID loops in parallel.

The concept could be as follows:

DEVICE PID INIT channel%, pid_params!(), callback_function


pid_params!()
float Kp
float Ki
float Kd

' Derivative low-pass filter time constant
float tau

'Output limits
float limMin
float limMax

'Integrator limits
float limMinInt
float limMaxInt

'Sample time (in milliseconds)
float T

'Controller "memory"
float integrator
float prevError 'Required for integrator'
float differentiator
float prevMeasurement 'Required for differentiator

'Controller output
float out

DEVICE PID START channel

DEVICE PID STOP channel

output! = DEVICE(PID channel, setpoint!, measurement!)


The PID init would set up a MMBasic function to be called every T milliseconds.

Following DEVICE PID START the callback function (MMBasic interrupt) would be called as requested and the Basic program should update the algorithm using the DEVICE(PID function.
It is left to the MMBasic user to derive the measurement (e.g. ADC input) and set the output (e.g. adjust PWM duty) in the callback function (NB: slow measurements like ADC input could be run in the main program so the value is always available for the PID callback).

Does this make sense? Would it be useful?
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 856
Posted: 11:53am 17 Sep 2024
Copy link to clipboard 
Print this post

Oh Wonderful    

If we want to include feedforwards (PID only reacts to error, FF anticipates), this can be added to the output    
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1236
Posted: 11:59am 17 Sep 2024
Copy link to clipboard 
Print this post

Yes, it is useful!

Best regards
Michael
causality ≠ correlation ≠ coincidence
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6768
Posted: 12:06pm 17 Sep 2024
Copy link to clipboard 
Print this post

I'd have killed for something like that for temperature controllers before I retired. :)  It was a real pain getting something usable on cheap PLCs at the time.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 856
Posted: 12:30pm 17 Sep 2024
Copy link to clipboard 
Print this post

  Mixtel90 said  I'd have killed for something like that for temperature controllers before I retired. :)  It was a real pain getting something usable on cheap PLCs at the time.


You need to come out of retirement....opportunity abounds  
You have a secret weapon that others will turn their nose up at.
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 856
Posted: 12:58pm 17 Sep 2024
Copy link to clipboard 
Print this post

Pete,

When someone recommended being very specific when asking a question of ChatGPT, I asked it for Galil Motion Control's notch filter in Basic code.

Apparently, it can be used if one encounters a resonant frequency on a machine axis that the PID can't eliminate.
Never experienced the problem, myself so I can't vouch for its efficacy.


' BASIC-style pseudocode for a notch filter
' Initialize parameters
center_freq = 50         ' Center frequency in Hz (f_0)
sampling_rate = 1000      ' Sampling rate in Hz
bandwidth = 5             ' Bandwidth in Hz
attenuation = -20         ' Attenuation in dB

' Derived constants
omega_0 = 2 * PI * center_freq / sampling_rate    ' Digital radian frequency
bw = bandwidth / sampling_rate                    ' Bandwidth in terms of the sampling rate
d = -attenuation / 20                             ' Attenuation factor
alpha = sin(omega_0) / (2 * bw)                   ' Filter sharpness

' Filter coefficients
b0 =  1
b1 = -2 * cos(omega_0)
b2 =  1
a0 =  1 + alpha
a1 = -2 * cos(omega_0)
a2 =  1 - alpha

' Normalize coefficients
b0 = b0 / a0
b1 = b1 / a0
b2 = b2 / a0
a1 = a1 / a0
a2 = a2 / a0

' Variables for storing past input/output values
x_1 = 0
x_2 = 0
y_1 = 0
y_2 = 0

'Main loop (input is the signal you want to filter)
DO WHILE (true)

   'Assume input_signal is the current sample of the input signal
   input_signal = GET_INPUT()  ' Get input signal value
   
   'Apply the notch filter difference equation
   output_signal = b0 * input_signal + b1 * x_1 + b2 * x_2 - a1 * y_1 - a2 * y_2
       
   'Update past values
   x_2 = x_1
   x_1 = input_signal
   y_2 = y_1
   y_1 = output_signal
   
   print input_signal
   print output_signal
   'Output the filtered signal
   SEND_OUTPUT(output_signal)
   
LOOP

 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9100
Posted: 01:16pm 17 Sep 2024
Copy link to clipboard 
Print this post

OK, I'll give it a go. Thinking about it the functions should be MATH not DEVICE but otherwise the concept will do for a first cut.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9100
Posted: 04:41pm 17 Sep 2024
Copy link to clipboard 
Print this post

Have a play with this VGARP2350 only for the moment.
C code and example courtesy of Philip Salmony https://github.com/pms67/PID


VGARP2350.zip


Example code - should be self-explanatory

Option explicit
'
' Array positions for PID parameters and working variables
'
Const Kp=0
Const Ki=1
Const Kd=2
Const tau=3
Const limMin=4
Const limMax=5
Const limMinInt=6
Const limMaxInt=7
Const T=8
Const integrator=9
Const prevError=10
Const differentiator=11
Const prevMeasurement=12
Const out=13
'
Dim pid_params(13)
'
pid_params(Kp)=2.0
pid_params(Ki)=0.5
pid_params(Kd)=0.25

' Derivative low-pass filter time constant
pid_params(tau)=0.02

'Output limits
pid_params(limMin)=-10.0
pid_params(limMax)=10.0

'Integrator limits
pid_params(limMinInt)=-5.0
pid_params(limMaxInt)=5.0

'Sample time (in seconds)
pid_params(T)=0.01

'Controller "memory"
pid_params(integrator)=0.0
pid_params(prevError)=0.0 'Required for integrator'
pid_params(differentiator)=0.0
pid_params(prevMeasurement)=0.0 'Required for differentiator

'Controller output
pid_params(out)=0.0


Dim float setpoint=1.0
Dim integer near_enough=0
Timer =0
'
' Initialise a PID loop with a 10mSec loop time
'
Math PID INIT 1,pid_params(),pidint
'
' Start the PID controller
'
Math pid start 1
Do
Loop Until near_enough
Print "test over"
Math pid stop 1
Math pid close 1
End

'
'Subroutine called every 10mSec
'
Sub pidint
 Local float measurement=test(pid_params(out)) 'simulate an input measurement
 Local float output=Math(PID 1,setpoint,measurement) 'update the controller
 Print Int(Timer),Str$(measurement,8,5),Str$(output,8,5)
 If Abs(measurement-setpoint)<0.00001 Then near_enough=1
End Sub

Function test(inp As float) As float
 Static float output=0.0
 Const alpha=0.02
 output=(pid_params(T)*inp + output)/(1.0 + alpha * pid_params(T))
 test=output
End Function


Tested with T at 0.001 seconds and it still works fine. Of course you wouldn't have a print statement in the interrupt routine in a real-world application
Edited 2024-09-18 02:54 by matherp
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 856
Posted: 06:28pm 17 Sep 2024
Copy link to clipboard 
Print this post

Can't test atm but to give an idea:

I have:

Full PID
Offset (DAC bias)
Integrator limit
Feedforward
Velocity calc
Velocity profiler (accel, slew, decel)

All happening ~400 usec

No PWM writing (dog slow)

How do we compare?

Incidentally, I disagree with pretty much everyone who claims to be experienced in this field.
The I term has no business being deployed during motion; feed forward does a much better job of keeping following error to a minimum.
The I term should be deployed at ~steady state to eliminate any remaining error.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6768
Posted: 06:45pm 17 Sep 2024
Copy link to clipboard 
Print this post

Did your system cost £5? I thought not. :)

The I term is used a heck of a lot in H&V systems, particularly heating. At least it used to be - I'm out of touch now.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 856
Posted: 07:04pm 17 Sep 2024
Copy link to clipboard 
Print this post

Ah, you got me there. No, my Pico cost me £1.75

You can't compare heating with motion.

I have been spinning motors since Volhout gave us quad decode.

Dead nuts repeatability and stability...
Even when I crank it down to a 4ms loop-rate.
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 856
Posted: 07:26pm 17 Sep 2024
Copy link to clipboard 
Print this post

  Mixtel90 said  Did your system cost £5? I thought not. :)

The I term is used a heck of a lot in H&V systems, particularly heating. At least it used to be - I'm out of touch now.


Imagine being in your car and the shock absorber blows.
You just set your D term to zero and you're bouncing all over the place due to the spring which is the P term but this spring becomes extra aggressive and puts you into a violent oscillation...that's your I term.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 6768
Posted: 07:45pm 17 Sep 2024
Copy link to clipboard 
Print this post

I is used for bang-bang control of heating, where the heating pulse rate is changed to control the heater rather than a linear controller. It used to be quite common in kilns where the high current was difficult (or even impossible) to control with linear devices.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 856
Posted: 08:12pm 17 Sep 2024
Copy link to clipboard 
Print this post

Well it ain't your friend during a motion profile.
I have read countless papers where they specify an I term...did they ever run a motor actually coupled to a drive train?

I highly doubt it.

The proportional term reacts to a difference between command and actual and so, naturally, there is a lag.

The most effective method of compensating for this is a feed forward term, external to the PID filter.
Unlike the I term, loop stability can never be affected.

Steady state, apply the I term and any residual error is wiped out.
My error is not +1 count or -1 count, it's absolute zero. So geeked  
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024