Boost Control - Closed Loop Setup Mode

General support questions and announcements for MS3. See also MS3 manuals.

Moderators: jsmcortina, muythaibxr

NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Sorry follow up. I've been doing some elements when just get chance but I can't really see any sign of the closed loop control algorithm making any significant adjustment from the bias duty, certainly not enough to prevent boost overtaking target by well over 20kPa (well over 10%). It really doesn't look like the proportional component is proportional, or it is far too small to make any impact.
Is the closed loop boost control duty algorithm documented somewhere? I need to understand the results I've been getting before doing more boost experimentation.
CRSTune
Experienced MS/Extra'er
Posts: 338
Joined: Thu Oct 20, 2016 9:12 pm
Location: Manassas, Virginia

Re: Boost Control - Closed Loop Setup Mode

Post by CRSTune »

Here's the code pulled directly from the PID file. Boost control uses the generic ideal PID routine. An understanding of PID algorithms helps to understand the code.

Code: Select all

/* $Id: ms3_pid.c,v 1.14 2014/09/23 01:23:53 culverk Exp $
 * Copyright 2007, 2008, 2009, 2010, 2011 James Murray and Kenneth Culver
 *
 * This file is a part of Megasquirt-3.
 *
 * Origin: Kenneth Culver
 * Majority: Kenneth Culver
 *
 * You should have received a copy of the code LICENSE along with this source, please
 * ask on the www.msextra.com forum if you did not.
 *
 */

#include "ms3.h"

void convert_unitless_percent(int min, int max, int targ, int raw_PV,
                              long *PV, long *SP)
{
    *PV = (((long)raw_PV - min) * 10000L) /
         (max - min);
    *SP = (((long)targ - min) * 10000L) /
          (max - min);
}

long generic_pid_routine(int min, int max, int targ, int raw_PV,
                         int set_Kp, int set_Ki, int set_Kd, int looptime,
                         long *PV_last_arg, long *last_error, 
                         unsigned char config)
{
    long Kp, Ki, Kd, PV, SP, error, pid_deriv, tmp1;
    int pid_divider, pid_multiplier;

    if (config & PID_LOOPTIME_RTC) {
        pid_divider = 7812;
        pid_multiplier = 781;
    } else {
        pid_divider = 1000;
        pid_multiplier = 100;
    }

    convert_unitless_percent(min, max, targ, raw_PV, &PV, &SP);
   
    error = SP - PV;

    /* Reset previous PV vals to same as PV to avoid
     * bad behavior on the first time through the loop
     */
    if (config & PID_INIT) {
        PV_last_arg[0] = PV_last_arg[1] = PV;
        *last_error = error;
    }

    pid_deriv = PV - (2 * PV_last_arg[0]) + PV_last_arg[1];

    if (config & PID_TYPE_C) {
        Kp = ((long) ((PV - PV_last_arg[0]) * (long)set_Kp));
    } else {
        Kp = ((long) ((error - *last_error) * (long)set_Kp));
        *last_error = error;
    }
    Ki = ((((long) error * looptime) / (long)pid_divider) * (long)set_Ki);
    Kd = ((long) pid_deriv * (((long) set_Kd * pid_multiplier) / looptime));

    PV_last_arg[1] = PV_last_arg[0];
    PV_last_arg[0] = PV;

    if (config & PID_TYPE_C) {
        tmp1 = Kp - Ki + Kd;
    } else {
        tmp1 = Kp + Ki - Kd;
    }

    return tmp1;
}

/* outmult needs to be the multiplier to get to 2 decimal places of precision */
long generic_ideal_pid_routine(int min, int max, int targ, int raw_PV,
                               int set_Kp, int set_Ki, int set_Kd,
                               long *I_term_sum, long *last_error, int bias,
                               int minoutput, int maxoutput, int outmult,
                               unsigned char config)
{
    long Kp, Ki, Kd, PV, SP, error, pid_deriv;
    long tmp1;

    convert_unitless_percent(min, max, targ, raw_PV, &PV, &SP);
   
    error = SP - PV;

    if (config & PID_INIT) {
	*I_term_sum = 0;
    }

    *I_term_sum += error;

    /* ensure full range of correction regardless of I term */

    tmp1 = ((maxoutput - bias) * (long)outmult * 100) / (long)set_Ki;
   
    if (tmp1 < 0) {
       tmp1 = 0;
    } 

    if (*I_term_sum > tmp1) {
	*I_term_sum = tmp1;
    }

    tmp1 = ((bias - minoutput) * (long)outmult * 100) / (long)set_Ki;

    if (tmp1 < 0) {
        tmp1 = 0;
    }

    if (*I_term_sum < -tmp1) {
	*I_term_sum = -tmp1;
    }

    pid_deriv = error - *last_error;
    *last_error = error;

    Kp = (long)set_Kp * error;
    Ki = (long)set_Ki * *I_term_sum;
    Kd = (long)set_Kd * pid_deriv;

    return Kp + Ki + Kd;
}

void generic_pid()
{
    int i;

    RPAGE = tables[27].rpg;

    for (i = 0; i < 2; i++) {
        /* Figure out if it's time for generic PID to run on this channel */
        if (ram_window.pg27.generic_pid_flags[i] & GENERIC_PID_ON) {
            if (flagbyte22 & (twopow[i])) {
                int load, target, PV;
                long pidout;
                char pidflags = PID_TYPE_C, ctmp;

                DISABLE_INTERRUPTS;
                flagbyte22 &= ~(twopow[i]);
                ENABLE_INTERRUPTS;

                /* Figure out load axis for PID target lookup */
                load = calc_outpc_input(ram_window.pg27.generic_pid_load_sizes[i],
                        ram_window.pg27.generic_pid_load_offsets[i]);

                /* Do PID target lookup */
                target = intrp_2ditable(outpc.rpm, load, 8, 8,
                        ram_window.pg27.generic_pid_axes3d[i][0],
                        ram_window.pg27.generic_pid_axes3d[i][1],
                        &ram_window.pg27.generic_pid_targets[i][0][0],
                        27);

                /* Figure out PV input (similar to load lookup) */
                PV = calc_outpc_input(ram_window.pg27.generic_pid_PV_sizes[i],
                        ram_window.pg27.generic_pid_PV_offsets[i]);

                /* Run PID routine with appropriate flags */
                ctmp = ram_window.pg27.generic_pid_flags[i] & GENERIC_PID_TYPE;
                if (ctmp == GENERIC_PID_TYPE_B) {
                    pidflags = PID_TYPE_B;
                } else if (ctmp == GENERIC_PID_TYPE_C) {
                    pidflags = PID_TYPE_C;
                } else {
                    pidflags = PID_TYPE_C;
                }
                pidout = generic_pid_routine(ram_window.pg27.generic_pid_lower_inputlims[i],
                                             ram_window.pg27.generic_pid_upper_inputlims[i],
                                             target, PV,
                                             ram_window.pg27.generic_pid_P[i],
                                             ram_window.pg27.generic_pid_I[i],
                                             ram_window.pg27.generic_pid_D[i],
                                             ram_window.pg27.generic_pid_control_intervals[i],
                                             generic_PID_PV_last[i], &generic_PID_last_error[i],
                                             pidflags) / 1000;

                /* Bound outputs to upper/lower limits */

                if (ctmp == GENERIC_PID_TYPE_B) {
                    pidout += generic_pidouts_100[i];
                } else {
                    pidout = generic_pidouts_100[i] - pidout;
                }

                if (pidout < (ram_window.pg27.generic_pid_output_lowerlims[i] * 100)) {
                    pidout = ram_window.pg27.generic_pid_output_lowerlims[i] * 100;
                } else if (pidout > (ram_window.pg27.generic_pid_output_upperlims[i] * 100)) {
                    pidout = ram_window.pg27.generic_pid_output_upperlims[i] * 100;
                }

                generic_pidouts_100[i] = pidout;
                /* divide down by 100 to get commanded duty */

                outpc.generic_pid_duty[i] = pidout / 100;
            }
        }
    }
}
I'm in the VA/DC area! Let me know if I can help you locally! I offer tuning and troubleshooting services.
http://www.msextra.com/forums/viewtopic ... 37&t=64269
Email me directly at CRSTune@gmail.com

Personal Vehicle:
'92 Nissan 240sx, KA24DET, GT2860RS, MS3X, Coil-on-Plug
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Thanks.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Finally had time and weather to spend a few minutes trying things out and finally got some logs where I can see the boost control changing the duty in some meaningfully way when hitting the throttle with transients from cruise at mid and higher RPM. For my experiments today I started by reducing the bias table values by 5 across the board. I then set the slider to max, the P term to max and the I and D terms to 0. Lower limit delta was 60. At these settings I could feel the boost control oscillating the boost and I hit boost cut, so I dropped the P term to 100 from 200. Again boost oscillation and cut. I set slider to 300, this got rid of the oscillation, so I upped slider to 400 and P term to max (200). This seems to work much better, no oscillating and no overboost, so I reduced the delta to 30, again an improvement and no boost cut...
Looking at the logs of the last experiment I see that MAP never reaches target. It peaks just below and then droops slightly then has a slight oscillation remaining below target.

I'm not sure whether I should try increasing the bias values, or add I and D terms to try to reach target. Or maybe try with the slider set slightly higher? Will attach log and MSQ tomorrow if helpful.

P.s. does 1.5 introduce any boost control behaviour changes? Wonder if it makes sense to update before continuing experimenting.

Thanks.


Sent from my iPad using Tapatalk
muythaibxr
Site Admin
Posts: 8230
Joined: Thu Oct 14, 2004 12:48 pm

Re: Boost Control - Closed Loop Setup Mode

Post by muythaibxr »

P term does not correct error over time. You need I term for that.
Megasquirt is not for use on pollution controlled vehicles. Any advice I give is for off road use only.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Thanks, I understand that. The thing that puzzled me is that the I term never reaches target, and MAP ends up oscillating slightly, slightly below target.
Would you be able to help me with an experimentation strategy for introducing I term? I'll post msq and log when I've booked the laptop.


Sent from my iPad using Tapatalk
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Well I should have read more of the log before saying it never reaches target, but it does immediately droop below it and oscillates slightly below target. I guess some I term should help with this.
muythaibxr
Site Admin
Posts: 8230
Joined: Thu Oct 14, 2004 12:48 pm

Re: Boost Control - Closed Loop Setup Mode

Post by muythaibxr »

Yeah, P term responds to immediate error, and may get you close to target, but if you're sitting somewhat close to target over a period of time and it never corrects to the target, then the only solution is more I term. You may need to readjust P after that too since you were probably trying to mess with P to correct something that shouldn't be corrected that way.
Megasquirt is not for use on pollution controlled vehicles. Any advice I give is for off road use only.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Thanks. I was just running experiments because I simply had seen no evidence that closed loop was influencing the duty at all. Primitive as it is, the current configuration is working much better, I did see duty changes and with mid-high rpm (full boost available) sudden transients to WOT there is almost no overshoot and really not far off target, and I've been able to reduce my lower limit delta too.
I currently have slider at 400 and P at 200. Is there any way I can retain the current behavior but lower the P term to give me some adjustability - pegged at max seems limiting. Thanks again.
muythaibxr
Site Admin
Posts: 8230
Joined: Thu Oct 14, 2004 12:48 pm

Re: Boost Control - Closed Loop Setup Mode

Post by muythaibxr »

I will have to look at the slider max. I may have to increase it and see about any overflows that might cause. Also, what MAP lag are you using?
Megasquirt is not for use on pollution controlled vehicles. Any advice I give is for off road use only.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

I started with slider at 500, P 200 but that caused a weird pulsing in the power delivery. I changed to slider 500, P 100 and the pulsing seemed almost identical. I then changed to slider 400, P 200 and immediately things were much better. All of this is with 0 for I and D terms. I was wondering if in this special case there was a relationship between P and slider that would allow me to reduce P, increase slider and get the same degree of control?
I'm sorry but I don't understand what MAP lag is. The msq is attached a few posts back if that is any help.
Thanks again.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

MAP Averaging Lag Factor is set to 90 in General Settings. Is this too low?
muythaibxr
Site Admin
Posts: 8230
Joined: Thu Oct 14, 2004 12:48 pm

Re: Boost Control - Closed Loop Setup Mode

Post by muythaibxr »

No that should be ok.
Megasquirt is not for use on pollution controlled vehicles. Any advice I give is for off road use only.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Thanks. As I'm running just a P algorithm currently, is the final boost duty calculated as P * slider / <some constant> essentially?
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Just been re-reading the closed loop boost control section in the setting up manual. I find the description for proportional confusing, particularly:
  • While tuning Proportional gain, higher numbers mean slower boost climb and lower final boost. For safety, start with a very high gain (100% should
    be sufficient).
My understanding must be way off because I understood that the proportional term was proportional to the current error. So when the error is large the proportional component is large - to kick things toward the target. As the error comes down then so does the proportional component, and if it overshoots then the error goes "negative" and so the proportional component of the gain (manipulated variable) acts to reduce the gain, bringing the error down again. If the gain cannot be finely controlled enough to cause the output to exactly hit target then target may never be reached. This could potentially happen if the P term was too small a component of the calculation of gain. Why would this cause "higher numbers mean slower boost climb and lower final boost"?

I did look at the code fragment kindly included in this topic, but I guess I need more code context (or tribal knowledge) to be able to fully understand it. I was particularly confused by convert_unitless_percent which appears to subtract the max and min duty percentages from what would presumably be the measured MAP and Target values. I'm just guessing what the variables and parameters actually represent though.

I was wondering if the apparent improvements in control I have seen are largely attributable to giving the controller a steady state error to work on by lowering the bias by 5% (of total theoretical MV range) below what I initially determined was needed for hitting target in "steady state" operation in setup mode.

Thanks.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Still fighting against the boost control. It almost seems like the PID output has too little authority over the boost duty to me. I keep making incremental changes but I don't seem to get similarly incremental responses to the changes. I have very little time to tune, often just a chance when sing the car to commute, so each set of changes is not necessarily being tested in consistent conditions, particularly of air temperature, density and humidity.

Latest run threw up a couple of overboost oddities. First happened on coming off the throttle an acceleration run. The second while at full throttle, but with MAP below target + tolerance. Tune and logs attached.

Any pointers would be much appreciated.

Thanks,
Nigel.
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Hi guys,
Am I right in thinking that the PID algorithm output is added to the bias duty value rather than being a multiplier?
Thanks,
Nigel.
Matt Cramer
Super MS/Extra'er
Posts: 17507
Joined: Thu Apr 16, 2009 8:08 pm

Re: Boost Control - Closed Loop Setup Mode

Post by Matt Cramer »

NigeT wrote:Hi guys,
Am I right in thinking that the PID algorithm output is added to the bias duty value rather than being a multiplier?
Thanks,
Nigel.
Correct.
Matt Cramer -1966 Dodge Dart slant six running on MS3X
NigeT
Master MS/Extra'er
Posts: 419
Joined: Wed Apr 08, 2015 1:14 pm

Re: Boost Control - Closed Loop Setup Mode

Post by NigeT »

Bringing this back from the dead I'm afraid.

By luck and constantly reading threads here and elsewhere, I seem to have boost control largely working. So much that I was surprised to get over boost fuel cut at the weekend. When I inspected the log it was the falling throttle issue again. Throttle was released and dropped to a much lower boost target immediately, but MAP couldn't keep up, causing over boost to be triggered.

So how do I prevent the over boost detection triggering on falling throttle and boost target?

Will post a log snippet... tomorrow hopefully.

Thanks, Nigel.

Sent from my SM-T800 using Tapatalk
Post Reply