AC heater temperature control

i ask anyone to help me in this project of mine because the current is not detected when the firing pin is triggering the gate of triac to powered the heater

#include "max6675.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

//Inputs and outputs
int firing_pin = 3;
const int increase_pin = 11;
const int decrease_pin = 12;
int start_pin = 9;
int estop_pin = 10;
int zero_cross = 8;
int so1Pin = 4;
int cs1Pin = 5;
int sck1Pin = 6;
MAX6675 thermocouple(sck1Pin, cs1Pin, so1Pin);

//Variables
int last_CH1_state = 0;
bool zero_cross_detected = false;
int firing_delay = 7400;

int maximum_firing_delay = 7400;
/*We know that the 240V AC voltage has a frequency of around 50-60HZ so the period is between 20ms and 16ms,
  which is standard for housing in Malaysia. We control the firing delay each half period so each 10ms or 8 ms.
  To make sure we wont pass those 10ms, I selected the 7400us or 7.4ms as the value. */

unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
int temp_read_Delay = 500;
int real_temperature = 0;
int setpoint = 100;
bool heating_active = false;     // Flag for heating status
bool estop_active = false;       // Emergency stop flag
bool timer_started = false;      // Flag to track if the countdown has started
unsigned long heating_start_time = 0; // Store heating start time
unsigned long heating_duration = 5400000;  // 90 minutes (in milliseconds)
unsigned long time_remaining = 0; // Time remaining for the countdown
int buttonPushCounter = 0;    // counter for the number of button presses
int up_buttonState = 0;       // current state of the up button
int up_lastButtonState = 0;   // previous state of the up button
int down_buttonState = 0;         // current state of the down button
int down_lastButtonState = 0;     // previous state of the down button
bool bPress = false;

//PID variables
float PID_error = 0;
float previous_error = 0;
float elapsedTime, Time, timePrev;
int PID_value = 0;
//PID constants
int kp = 203;   int ki = 7.2;   int kd = 1.04;
int PID_p = 0;    int PID_i = 0;    int PID_d = 0;


void setup() {
  //Define the pins
  pinMode (firing_pin, OUTPUT);
  pinMode (zero_cross, INPUT);
  pinMode (increase_pin, INPUT_PULLUP);
  pinMode (decrease_pin, INPUT_PULLUP);
  pinMode (start_pin, INPUT);
  pinMode (estop_pin, INPUT);

  lcd.init();       //Start the LC communication
  lcd.backlight();  //Turn on backlight for LCD
}

void loop()
{
  zeroCross();
  checkUp();
  checkDown();
  currentMillis = millis();           //Save the value of time before the loop
  lcd.clear();

  real_temperature = thermocouple.readCelsius();  //get the real temperature in Celsius degrees
  lcd.setCursor(0, 0);
  lcd.print("ST: ");
  lcd.setCursor(4, 0);
  lcd.print(setpoint);
  lcd.setCursor(8, 0);
  lcd.print("RT: ");
  lcd.setCursor(12, 0);
  lcd.print(real_temperature);
  delay(500);

  // Push the start button to activate heating but NOT start the timer yet
  if (digitalRead(start_pin) == HIGH && digitalRead(estop_pin) == LOW)
  {
    heating_active = true;    // Activate heating
    timer_started = false;    // Ensure the timer doesn't start until setpoint is reached

    // Heating is active and estop is not active
    if (heating_active == true && estop_active == false)
    {
      if (currentMillis - previousMillis >= temp_read_Delay)
      {
        previousMillis += temp_read_Delay;              //Increase the previous time for next loop

        PID_error = setpoint - real_temperature;        //Calculate the pid ERROR
        PID_p = kp * PID_error;                         //Calculate the P value
        PID_i = PID_i + (ki * PID_error);               //Calculate the I value
        timePrev = Time;                    // the previous time is stored before the actual time read
        Time = millis();                    // actual time read
        elapsedTime = (Time - timePrev) / 1000;
        PID_d = kd * ((PID_error - previous_error) / elapsedTime); //Calculate the D value
        PID_value = PID_p + PID_i + PID_d;                      //Calculate total PID value


        if (PID_value <= 0)
        {
          PID_value = 0;
        }
        if (PID_value >= 7400)
        {
          PID_value = 7400;
        }

        previous_error = PID_error; //Remember to store the previous error.
      }

      //If the zero cross interruption was detected we create the 100us firing pulse
      if (zero_cross_detected == true)
      {
        delayMicroseconds(maximum_firing_delay - PID_value); //This delay controls the power
        digitalWrite(firing_pin, HIGH);
        delayMicroseconds(100);
        digitalWrite(firing_pin, LOW);
        zero_cross_detected = false;
      }

      // If the heater reaches the setpoint for the first time, start the 90-minute countdown
      if (timer_started == false && real_temperature >= setpoint)
      {
        heating_start_time = millis();  // Store the time when the setpoint is reached
        timer_started = true;           // Flag to indicate the timer has started
      }

      // If the 90-minute countdown has started, update the remaining time
      if (timer_started == true)
      {
        time_remaining = heating_duration - (millis() - heating_start_time);

        // Calculate minutes and seconds
        int m = time_remaining / 60000;
        int s = (time_remaining % 60000) / 1000;

        // Display the countdown on the LCD
        lcd.setCursor(0, 1);
        lcd.print("TL: ");
        if (m < 10)
        {
          lcd.print("0");  // Leading zero for minutes
          lcd.print(m);
          lcd.print(":");
        }

        if (s < 10)
        {
          lcd.print("0");  // Leading zero for seconds
          lcd.print(s);
        }

        // If the countdown has reached 0, stop the heating
        if (time_remaining <= 0)
        {
          heating_active = false;   // Stop heating after 90 minutes
          digitalWrite(firing_pin, LOW);  // Turn off the heater
        }
      }
    }
  }

  // Push the estop button to immediately stop the heating
  else if (digitalRead(estop_pin) == HIGH && digitalRead(start_pin) == LOW)
  {
    estop_active = true;   // Activate emergency stop
    heating_active = false;  // Turn off heating
    timer_started = false;   // Stop the timer
    digitalWrite(firing_pin, LOW);  // Ensure the heater is off
  }
}
//End of void loop

void checkUp()
{
  up_buttonState = digitalRead(increase_pin);
  if (up_buttonState != up_lastButtonState)    // compare the buttonState to its previous state
  {
    if (up_buttonState == LOW)   // if the state has changed, increment the counter
    {
      bPress = true;  // if the current state is HIGH then the button went from off to on:
      setpoint += 5;
      delay(50);  // Delay a little bit to avoid bouncing
    }
  }
  up_lastButtonState = up_buttonState;   // save the current state as the last state, for next time through the loop
}

void checkDown()
{
  down_buttonState = digitalRead(decrease_pin);
  if (down_buttonState != down_lastButtonState)  // compare the buttonState to its previous state
  {
    if (down_buttonState == LOW)   // if the state has changed, increment the counter
    {
      bPress = true;
      setpoint -= 5;
      delay(50);            // Delay a little bit to avoid bouncing
    }
  }
  down_lastButtonState = down_buttonState;  // save the current state as the last state, for next time through the loop
}

void zeroCross()
{
  if (zero_cross == HIGH) {          //We make an AND with the state register, We verify if pin D8 is HIGH???
    if (last_CH1_state == 0) {     //If the last state was 0, then we have a state change...
      delay(50);
      zero_cross_detected = true;  //We have detected a state change! We need both falling and rising edges
    }
  }
  else if (last_CH1_state == 1) {  //If pin 8 is LOW and the last state was HIGH then we have a state change
    delay(50);
    zero_cross_detected = true;    //We haev detected a state change!  We need both falling and rising edges.
    last_CH1_state = 0;            //Store the current state into the last state for the next loop
  }
}
//End of interruption vector for pins on port 8

Your topic has been moved. Please do not post in "Uncategorized"; see the sticky topics in Uncategorized - Arduino Forum.

Your other topic on the same subject deleted.

Please do not duplicate your questions as doing so wastes the time and effort of the volunteers trying to help you as they are then answering the same thing in different places.

Please create one topic only for your question and choose the forum category carefully. If you have multiple questions about the same project then please ask your questions in the one topic as the answers to one question provide useful context for the others, and also you won’t have to keep explaining your project repeatedly.

Repeated duplicate posting could result in a temporary or permanent ban from the forum.

Could you take a few moments to Learn How To Use The Forum

It will help you get the best out of the forum in the future.

Thank you.

why a Triac? just turn it on until the temperature is reached and then turn it off.

Because I want to create an oven that can bake for 90 minutes and triac to control how much time current can enter the heater

just turn it on and off based on the temperature.
Triac is used if we want to consume solar production surplus exactly. it doesn't make sense to control a heater with Triac to control the temperature.

You need to show a schematic of your TRIAC circuit
Do you have an optocoupler to trigger the TRIAC?
Include datasheets for all major parts.

There are quite a few errors in your program.
This statement would require you to hold the start button down in order for the code to run. You need to detect a state change like you do with the increase/decrease buttons.

  if (digitalRead(start_pin) == HIGH && digitalRead(estop_pin) == LOW)

Long ago I had to use a triac for temperature control using a lightbulb for an incubator. I don't think that there is much difference with OP's approach :wink: And for me it makes sense, but that is something else.

If you need 0.1 degC accuracy, triac control may very well be the way to go.
Otherwise you can usually get away with 1 degC hysteresis and simple on/off control. And that can also be done with a triac... so it may be it overdone, but it should work...

Why not a triac...?

I am not understanding the issue and question here. How are you expecting to see the current? Do you have a current sensor? Or perhaps a current shunt resistor?

Of course, the more information you provide will allow you to receive better responses more quickly.

As for the triac and AC heater, it will definitely allow you to run an oven for 90 minutes and control the timing of the AC heater element. More details on how you intend to control the triac will help us understand your project more thoroughly.

I see your sketch has a zero-cross function defined, but that function is called during the main loop. This means that the function may not be active during the zero-crossing event and will usually not see the event. This type of AC control requires the detection function to operate as an interrupt type function and significantly increases the program difficulty. Is this precision control necessary for your oven?

I don't see any reason to control an oven using phase cutting. You could do it just on/off or if for some reason that is too "granular", you could use "pulse train" modulating integral cycles. Much cleaner.
I agree with @Juraj, phase angle control is only needed if you need to control power to match your excess solar production or some other particular cases.

sorry Triac is OK as a switch. I meant phase cutting wit zero crossing detector is not needed.


this is the circuit diagram in proteus

Also, when i am using it in hardware the button is not working thus making the setting temp not working

see post #7

I just saw it but i still don't understand?
Plz help me

Do like you did in ckeckup routine for the increment button but do it for the start button
Only execute the code when the button state changes not when the button is held down.

Good schematic!
Clear.
Next time: minimize turns (move start button a bit higher, improve connections to heater), put input left and output right...
100 ohm to opto diac is a bit on the low side...

Can you pls update the new cosing?
I in need of emergency now becauss i need to demonstrate the oven in 10 days

Are you asking me to write the code for you?
I will help you to write the code.