Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Arduino AC phase control

Status
Not open for further replies.

123mmm

Member
Hi, I have uploaded on my Arduino Uno the attached code, and I am facing the following issue: If the temperature is set to max (about 18mV on the Thermocouple) then if I rotate the pot to minimum temperature, the voltage on the TC starts to reduce, until it reach about 17mV. Then it goes very fast to about 22-23mV, and if I try to rotate the pot again to maximum and then to minimum, then it does nothing, on the scope I see only the image from the second screenshot. Then I need to unplug the 24Vac/100VA transformer from the wall socket to protect the heater of the soldering iron.
Screenshot at max temperature (with the probe on the heater): DS0168.jpg
Screenshot when it reach about 17mV on the TC (with the probe on the heater): DS0169.jpg

The schematic of the circuit: schematic_v2.png

I made the following checks: I verified the pot - it is ok, I verified the OpAmp - this also is ok, I verified the zero cross circuit - this also is ok, I verified the output pin which goes to the triac - it is ok. I also checked those parts of the schematic in serial monitor and they are acting as normal.
Arduino, optocoupler, LM358, optotriac and the pot are powered from USB 5V, and the part of the schematic with LM317 is not yet built, it will be build on the final circuit.

Please have a look at the code, and help me what should I do in order to repair this issue ?

The code of Arduino Uno:
C:
//Inputs and outputs
int firing_pin = 5;
int zero_cross = 2;

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

//////////////////////////////////////////////////////
int maximum_firing_delay = 7400;
/*Later in the code you will se that the maximum delay after the zero detection
* is 7400. Why? Well, we know that the 220V AC voltage has a frequency of around 50-60HZ so
* the period is between 20ms and 16ms, depending on the country. We control the firing
* delay each half period so each 10ms or 8 ms. To amke sure we wont pass thsoe 10ms, I've made tests
* and the 7400us or 7.4ms was a good value. Measure your frequency and chande that value later */
//////////////////////////////////////////////////////

unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
int temp_read_Delay = 500;
int real_temperature = 0;
int setpoint = 0;

//PID variables
float PID_error = 0;
float previous_error = 0;
float elapsedTime, Time, timePrev;
int PID_value = 0;
//PID constants
int kp = 20;   int ki= 5;   int kd = 10;
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);
  PCICR |= (1 << PCIE2);    //enable scan                                          
  PCMSK2 |= (1 << PCINT18);  //Set pin D2 (zero cross input) trigger an interrupt on state change.
}


void loop() {
  currentMillis = millis();           //Save the value of time before the loop
  if(currentMillis - previousMillis >= temp_read_Delay){
    previousMillis += temp_read_Delay;              //Increase the previous time for next loop
    //get the real temperature in Celsius degrees
    real_temperature = map(real_temperature, 0, 550, 25, 400);
    // added by Mike_Mike
    for(int i=0;i<50;i++)
    real_temperature += analogRead(A0);
    real_temperature /= 50;
    real_temperature = map(real_temperature, 0, 550, 25, 400);
    // end added by Mike_Mike
    setpoint = analogRead(A1);
    setpoint = map(setpoint, 0, 1023, 150, 400);
    PID_error = setpoint - real_temperature;        //Calculate the pid ERROR

    if(PID_error > 30)                              //integral constant will only affect errors below 30ºC      
    {PID_i = 0;}

    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

    //We define firing delay range between 0 and 7400. Read above why 7400!!!!!!!
    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)
    {
      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;
    }
}

//This is the interruption routine (pind D2(zero cross))
//----------------------------------------------

ISR(PCINT2_vect){
  //Input from optocoupler
  if(PIND & B00000010){            //We make an AND with the state register, We verify if pin D2 is HIGH???
    if(last_CH1_state == 0){       //If the last state was 0, then we have a state change...
      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 2 is LOW and the last state was HIGH then we have a state change
    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
    }
}
 
Last edited:
1. It doesn't look like you understand thermocouples. if you do linearization yourself, you need the temperature of the local isothermal junction, look-up tables and reverse look-up tables.

1a Grounded vs Isolated thermocouples

2. You need to convert your firing time proportional to V^2.

3. If the load is inductive, you need to keep firing the triac.
 
Status
Not open for further replies.

Latest threads

Back
Top