Reflow Oven PID

Progress
Wow, it has been a busy week but not without something to show for it. I have working on the reflow oven project on two major fronts. The first was to create a python plotting interface such that I could plot out the PID varibles over time. The second was tuning the PID for the reflow oven. I had pretty good success on both accounts. This post will just be talking about the success of the PID and some of the non conventional stuff put in place to make it that way.

PID
The PID algorithm didn’t depart too much from the classic model.The PID now is in the main loop() of the Arduino code. It will be in it’s own subroutine later. Here is the heart of the code:

```int error, pid, diff, ingr, prop;
...
//calculate PID
time = millis();
reference = SnPbProfilePoint(time);
//reference =500;

for (i=0;i<4;i++){
temperature /= 2;
}
```

In order to keep the calculations for SnPbProfilePoint(time) and the PID variables in integer math (avoiding floating point math) temperature is left in its native scale of 1/4 degC per count. I added a method called readQtrCelsius() to the MAX6675 class to read back this raw data. Time is left in milliseconds to keep as much accurracy as possible. I averaged the temperature with four readings to help with noise. I tried up to eight but anything over four didn’t seem to make a difference.

```	error = reference-temperature;
prop = 32*error;
diff = 128*(temperature-temp_last)-256*(reference - ref_last);

ingr = error/24+ingr_last;
if (error>0){ingr+=1;}
if (error<0) {ingr-=10;	}

ingr = constrain(ingr,0,1000);

pid = prop + ingr - diff;
```

P
The prop was scaled to a non oscillation value once I thought the diff scalers were good.
D
The differential variable is generated with a couple of twists. Instead of basing it off of the difference in error it is calculated with a change in temperature reading and the change in reference. Doing it this way helped it keep up with the changing reference. It is also weighted heavily when compared to the P and the I variables.

I
The ingr was the wimp of the three. I found that turning the scaler down so low most of the time resulted in a 0 contribution. So to keep some in there I added or subtracted some based on the sign of the error. For a constant reference, this will still zero out error over time. Since the oven is quick on the rise in temperature but slow on the fall (no active cooling) it was give a faster integration in the negative direction. Finally it was constrained between 0 and 100% duty cycle because beyond these extremes would add response delay.

```
pid = constrain(pid,1,1000);
// turn on pwm
digitalWrite(pwmOut, HIGH);
delay(pid);
if (pid<1000) {digitalWrite(pwmOut, LOW);}
delay(1000-pid);
ingr_last = ingr;
temp_last = temperature;
ref_last = reference;

//update Plot then loop again
```

PWM
The duty cycle is proportional to pid. pid =1000 is 100% pwm. pid was constrained between 1 and 1000. The minimum of 1 was because delay(0) turns out to be a very looooong delay.

Results

I am quite pleased with the results! Next I will tackle the LCD and the menu system and then start putting all these pieces together into a complete system.