Increment an output between two output states

I have process that I control that relies on a setpoint to calculate an output (% of max) based on the eFL fuzzy library. The fuzzy bit is easy and I get out of it what I intended.

My challenge is the following. The process starts with a default "output". Then a 10000 ms timed loop calculates a new output based on an input. The new output (newOP), if different from the old output (oldOP), then controls a pump (Don't worry, that part is SCADA based and under control). My intention is to increment to the new output in say 5 equal steps, i.e. starting with "oldOP" then incrementing in 5 equal steps to the newly calculated, "newOP". The slope or difference between the newOP and oldOP may be positive or negative. While this is happening, the output calculation loop may receive a new setpoint, but only fires the output once the increment loop is complete.

To recap;

  1. New setpoint may be set at any time.
  2. Calculate new output every 10000 ms.
  3. Take output (newOP) and increment from oldOP to newOP in 5 steps before the new 10000 ms loop starts.
  4. Calculate a new output.
  5. Loop

I can get parts of it to work, i.e. the main 10000 ms loop, the calcs are correct, but I cant do the incrementing part- I spent my whole weekend to no avail. Simply not there yet from a programming point of view. I use a lot of floats, but no problems there.

Could anyone please assist to point me in the right direction? I would really really appreciate it.

Below is a code snippet of void loop(). The declarations are all fine as the basic calcs etc are correct. It is simply a case of getting the timing part to work.

void loop() {

  mb.task();

  
  SP = mb.Hreg(SP_HREG);
  COD = mb.Hreg(COD_HREG);
  

  if (millis() > tproc + 10000) {
    tproc = millis();

    ////////////// Calculate VFA ///////////////////////

    Q = Qave * output / 100;
    OLR = Q * COD / V * 24 / 1000;
    VFA = 106.21 * exp(0.109 * OLR);

    ///////////////// Error derivative/////////////////

    e1 = VFA - SP;
    de_dt_in = (e1 - e2) / (tdt / 1000); //derivative

    /////////// Fuzzification and de-fuzzification////////////

    fuzzy->setInput(1, e1);
    fuzzy->setInput(2, de_dt_in);
    fuzzy->fuzzify();
    float output = (fuzzy->defuzzify(1));
    newOP = output;
    e2 = e1;

    //Serial.print (e1);
    //Serial.print (" , ");
    //Serial.print (e2);
    //Serial.print (" , ");
    //Serial.println (de_dt_in);
  }

if (millis() > tcalc + 1000) {
      tcalc = millis();
      //////////Recalculate VFA////////////////
      if (oldOP > newOP) {
        oldOP -= 1;
        Q = Qave * newOP / 100;
        OLR = Q * COD / V * 24 / 1000;
        VFA = 106.21 * exp(0.109 * OLR);
      }
        else if (oldOP < newOP) {
        oldOP += 1;
        Q = Qave * newOP / 100;
        OLR = Q * COD / V * 24 / 1000;
        VFA = 106.21 * exp(0.109 * OLR);
      }
      oldOP = newOP;

      
    }

This is not the proper way to use millis() because it won't work if millis() overflows

if (millis() > tcalc + 1000) {

Always use subtraction like this

if (millis() - tcalc > 1000) {

I don't see any code that calculate the step size as 1/5th of the interval between oldOP and newOP

I think you need a 3rd variable (let's call it workingOP) that starts at oldOP and increments in steps up to newOP

Something like this pseudo code

if there is a new value for newOP
    workingOP = oldOP
    opIncrement = (newOP - oldOP) / 5;
    tcalc = millis() // start the clock
}

if (millis() - tcalc > 1000) {
   tcalc = millis();
   workingOP += opIncrement;
}

...R