br3ttb / Arduino-PID-Library

1.92k stars 1.1k forks source link

Run 2 different PID codes #92

Open Qhergt opened 5 years ago

Qhergt commented 5 years ago

I'd like to run 2 different servos each controlled by a different section of PID code. How do I do this?

br3ttb commented 5 years ago

create two pid classes (myPID1 & myPID2, say) and link them to separate output, input, and setpoint variables.

On Sun, May 5, 2019, 11:43 PM Qhergt notifications@github.com wrote:

I'd like to run 2 different servos each controlled by a different section of PID code. How do I do this?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/92, or mute the thread https://github.com/notifications/unsubscribe-auth/AACYX4VVCGUOP2VAMW25YI3PT6SN7ANCNFSM4HK46ONQ .

Qhergt commented 5 years ago

How would I do that?

Get Outlook for Androidhttps://aka.ms/ghei36


From: br3ttb notifications@github.com Sent: Monday, May 6, 2019 2:49:34 AM To: br3ttb/Arduino-PID-Library Cc: Qhergt; Author Subject: Re: [br3ttb/Arduino-PID-Library] Run 2 different PID codes (#92)

create two pid classes (myPID1 & myPID2, say) and link them to separate output, input, and setpoint variables.

On Sun, May 5, 2019, 11:43 PM Qhergt notifications@github.com wrote:

I'd like to run 2 different servos each controlled by a different section of PID code. How do I do this?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/92, or mute the thread https://github.com/notifications/unsubscribe-auth/AACYX4VVCGUOP2VAMW25YI3PT6SN7ANCNFSM4HK46ONQ .

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/br3ttb/Arduino-PID-Library/issues/92#issuecomment-489565804, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AHY6LR3DZMCTJLIO46BNKNLPT75K5ANCNFSM4HK46ONQ.

lackdaz commented 5 years ago

Hey Brett,

I loved the PID articles you wrote and its really furthered my understanding on the subject. I tried it pushing it further by deploying the code to multiple pid instances. I thought this would be a good example for writing in OO so that the variables are a lot easier to manage for each of the instances, say if I'm looking to scale up to 4 pid instances I've got a heater/thermistor setup for each unit and I wrapped the instantiated object instances into a "Heater" class seen here:

Heater::Heater(
  int analog_read_pin,
  int analog_control_pin,
  int signal_pin) :
    _read_pin(analog_read_pin),
    _control_pin(analog_control_pin),
    _signal_pin(signal_pin),
    pwm_state(0),
    current_temp(0.0),
    pid_output(0),
    crit_temp(CRIT_TEMP),
    threshold_range(THRESHOLD_RANGE),
    thermistor(
      new SmoothThermistor(
        new NTC_Thermistor(
          analog_read_pin,
          REFERENCE_RESISTANCE,
          NOMINAL_RESISTANCE,
          NOMINAL_TEMPERATURE,
          B_VALUE
        ),
        SMOOTH_FACTOR
      )
    ),
    pid(
      new PID(
        &current_temp, 
        &pid_output, 
        &crit_temp, 
        30, 1.0, 1, P_ON_M, DIRECT
      )
    )
    {
      pinMode(_control_pin, OUTPUT);
      pinMode(_signal_pin, OUTPUT);
    }

Heater::~Heater() {
  delete pid;
}

void Heater::begin() {
  pid -> SetMode(AUTOMATIC);
  pid -> SetSampleTime(50);
  pid -> SetOutputLimits(0, get_byte(PWM_PERCENT_MAX));
  digitalWrite(_signal_pin, LOW);

}

double Heater::read_temp() {
  const double celsius = thermistor->readCelsius();
  // Output of information
  // Serial.print("Temp: ");
  // Serial.print(celsius);
  // Serial.println(" ºC, ");
  return celsius;
}

void Heater::auto_pid() {
  pid -> Compute();
  analogWrite(_control_pin, pid_output);
}
... more class methods

and created two heater instances like this:

Heater *heater1 = new Heater(PID1_READ, PID1_CONT);
Heater *heater2 = new Heater(PID2_READ, PID2_CONT);

  heater1 -> begin();
  heater1 -> update();
  heater1 -> auto_pid();
  heater2 -> begin();
  heater2 -> update();
  heater2 -> auto_pid();

  unsigned long now = millis();

  if (now - last_published > PUBLISH_INTERVAL) {
    Serial.print(heater1 -> current_temp);
    Serial.print(",");
    Serial.print(heater1 -> pid_output);
    Serial.print(",");
    Serial.print(heater2 -> current_temp);
    Serial.print(",");
    Serial.print(heater2 -> pid_output);
    Serial.print(",");
    Serial.println(heater1 -> crit_temp);
    last_published = now;
  }

where I have the data output plotted to the Arduino Serial Plotter to see the PID in real-time action.

The only problem is that only the second instance works. I still get thermistor input but pid_output is always zero. I tested each individually to ensure they are both working. But it seems like when I'm creating a new instance for heater2 it declares over the previous instance for heater1. Any clue what might be happening? I'm a novice at writing C++ OO code and would take any advice.

lackdaz commented 5 years ago

I fixed it, turns out I put the pid.begin in the loop and was constantly redefining the config parameters. For anyone looking to solve this OO style, the solution is above

br3ttb commented 5 years ago

I'll add, for anyone else reading, that my approach in situations like this is to serial.print the values of the internals as much as possible. This will usually point to a value that isn't as it should be, and you can work back from there.

On Sun, Aug 4, 2019, 5:25 AM Seth Loh notifications@github.com wrote:

I fixed it, turns out I put the pid.begin in the loop and was constantly redefining the config parameters. For anyone looking to solve this OO style, the solution is above

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/92?email_source=notifications&email_token=AACYX4XSL52ROTBHJVUWMN3QC2N7RA5CNFSM4HK46ON2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3P5ZOA#issuecomment-517987512, or mute the thread https://github.com/notifications/unsubscribe-auth/AACYX4SSWYAO76M5NEFKCLLQC2N7RANCNFSM4HK46ONQ .