AC-PWM + PID controll

Hi, so I am building an apparatus which consists of a ceramic AC heater which will heat up a solid surface. Reading the temperature will be a IR temperature sensor which takes reading at an accuracy of 0.01 Celcuis.

Till now I succeeded in controlling a AC desk lamp with a circuit I bought from Ebay using a TRIAC and a MOSFET, also I am not using the ACPWM from the Arduino library but I am using another from GITHUB using interrupts to sync the zero-crossing.

The objective will be as I said to control an AC Heater (which I assume will not differ from controlling a desk lamp) but, the heater will increase or decrease its output according to the IR sensor which will keep the surface temperature to the target temperature.

So my questions are,

  • How can I integrate PID in an AC-PWM situation?

  • Can I use any mathematical formula or logic expression to a least narrow down the values for my PID tuning ?

How can I integrate PID in an AC-PWM situation?

Have a look at the PID library. Use its error output to adjust the PWM value depending on the target and current temperatures.

Sorry for taking so long to reply.

I am sorry but I can’t quite comprehend what’s going on and how does the logic for ACPWM and PID work.

This is the code I have for the ACPWM which controls an AC LOAD with a LDR and it works.

int AC_LOAD = 2;    // Output to Opto Triac pin
int dimming = 1024;  // Dimming level (0-1024)  0 = ON, 1024 = OFF

void setup()
{
  Serial.begin(9600);
  pinMode(AC_LOAD, OUTPUT);        // Set the AC Load as output
  attachInterrupt(1, zero_crosss_int, RISING);  // Choose the zero cross interrupt # from the table above
}

void zero_crosss_int()  // function to be fired at the zero crossing to dim the light
{
  // Firing angle calculation :: 50Hz-> 10ms (1/2 Cycle)
  // (10000us - 10us) / 1024 = 10 (Approx)
  int dimtime = (10*dimming);      
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(AC_LOAD, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay
  digitalWrite(AC_LOAD, LOW);    // triac Off
}

void loop()
{
  int sens = analogRead(5);
  if (sens > 899 )
  {
    sens = 900;
    digitalWrite(AC_LOAD, LOW);
  }
  if (sens < 11)
  {
    sens = 10; 
    digitalWrite(AC_LOAD, HIGH); 
  }
  else
  {
    dimming = sens;
  } 

  Serial.print("Input Value: ");
  Serial.println(sens);
  Serial.print("Output Value: ");
  Serial.println(dimming);
}

On the other hand this is the PID Example code from Arduino

#include <PID_v1.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Input = analogRead(0);
  Setpoint = 100;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
  Input = analogRead(0);
  myPID.Compute();
  analogWrite(3,Output);
}

How can I amalgamate these two together ?? Were the objective will be to have a preset LDR value where the AC LOAD will vary its output when an external light source is added on the LDR. Therefore to keep the LDR value as close as possible to a predefined PRESET value the AC LOAD will increase or decrease the output.

AC output load is a Desk Lamp for now as it is more safe to experiment with than a heat source

double Setpoint, Input, Output;These are the key to how the PID works

Setpoint is the value you are trying to reach
Input is how far you are from the target value
Output is a value returned by the PID that, when applied to the system, will reduce the difference between Setpoint and the Input

In the case of your lamp you will have a voltage as Setpoint, either fixed or variable by meant of a potentiometer, a voltage from an LDR as Input and will use Output to adjust the PWM value applied to the lamp.

All I needed to hear I guess lol I got it to work :smiley: :smiley:

Although not quite happy as it takes a while to settle for the setpoint and it deviates a little even when reached.

#include <PID_v1.h>

int AC_LOAD = 2;    // Output to Opto Triac pin
double High_Value = 240; // Lamp Fully Off
double Low_Value = 2;    // Lamp Fully On
double set_value = 200;
double input = 0;
double output = 0;

PID test_PID(&input, &output, &set_value, 4.0, 0.2, 1.0, DIRECT);

void setup()
{
  Serial.begin(9600);
  
  input = analogRead(5);
  input = map(input, 0, 1023, 0, 255);
  test_PID.SetMode(AUTOMATIC);
  test_PID.SetOutputLimits(Low_Value,High_Value);
  
  pinMode(AC_LOAD, OUTPUT);        // Set the AC Load as output
  attachInterrupt(1, zero_crosss_int, RISING);  // Choose the zero cross interrupt # from the table above
}

void zero_crosss_int()  // function to be fired at the zero crossing to dim the light
{
  input = analogRead(5);
  input = map(input, 0, 1023, 0, 255);
  // Firing angle calculation :: 50Hz-> 10ms (1/2 Cycle)
  // (10000us - 10us) / 255 = 40 (Approx)
  int dimtime = (40*output);      
  delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(AC_LOAD, HIGH);   // triac firing
  delayMicroseconds(10);         // triac On propogation delay
  digitalWrite(AC_LOAD, LOW);    // triac Off
}

void loop()
{

  test_PID.Compute();
 
  Serial.print("Input Value: ");
  Serial.println(input);
  Serial.print("Output Value: ");
  Serial.println(output);
  //delay(1000);
}

Although not quite happy as it takes a while to settle for the setpoint and it deviates a little even when reached

It sounds like you need to tune the PID parameters.