AC phase manipulated PID temperature controller via Arduino and Labview

If you like or get help from this project, you can support me. ( my paypal account: arduinofunding at gmail.com ); So I can share more Arduino applications in future. Or just let me know how you enjoy or think of this project. Thank you.

The things, which I want to improve in future, are upgrading my arduino board, building wireless (xbee) network between arduinos and iOS device, and developing a graphic user interface (GUI) on iOS devices. So you can control and monitor the system with a compact and smart phone, not a bulky computer with Labview!!!.

This is a project of using Arduino with/without Labview to realize PID control through manipulating AC phase for power supply. To demonstrate the effects, three videos will be provided first. Detailed introduction about this project, circuits and code information are given after that.

It needs to be noted that you may find other work also providing AC phase control. But my work emphasizes the PID control through incorporating AC phase control. Details can be found in section 3 for code.

0. Demonstration Videos

Three videos were recorded for demonstrating effects from my work:

•Breathing light – using Arduino for AC phase control without working with Labview (Standalone version; used Code 1) Watch the video here Breathing light - using Arduino board - YouTube

•Light dimmer and Breathing light – using Arduino and Labview for AC phase control (External system version; used Code 2) Watch the video here Light dimmer and breathing light - using Arduino board and Labview - YouTube

•PID controller with automatic AC phase control for an application requiring constant temperature (working with and recording through Labview; used Code 3) Watch the video here Arduino and Labview for a constant temperature application - YouTube

[
Table 0.1 Codes comparison[/center]

1. Introduction

I have built an in house automated optical fiber manufacturing system with accurate temperature and product quality control using four Arduino boards. This system comes with notable accuracy in temperature control (±1 ? error at 900 ?) and reliability in quality control (±5 µm error in relation to 125 µm outside diameter of optical fiber) for specialty optical fiber fabrication. A 2,400 watts customized radiation furnace is operated automatically through a proportional–integral–derivative (PID) controller to maintain a constant high temperature during optical fiber fabrication. It has the ability of either working as a standalone system or with a Labview user interface for specialty optical fiber fabrications. With the use of Arduino boards, this system is also programmable for other tasks. I would like to share part of my work to help those who need a PID controller through automatic AC phase control in their applications.

[
Figure 1.1 High power radiation furnace[/center]

!!!Safety first. An isolation transformer is highly recommended.!!!

2. Circuit scheme - zero cross circuit and trigger circuit

As shown in the system layout (Figure 2.1), there are two circuits used for control. One is zero cross circuit. The other is trigger circuit. A multi-meter is used to display real time furnace temperature measured from temperature detection circuit. The two control circuits were built referring application notes [1-2]. If the control circuit needs to be adjusted for other applications such as motor speed control, these references can help you redesign the circuit.

[
Figure 2.1 Control circuit[/center]

2.1 Zero cross circuit

Zero cross points are the points where AC phase crosses through x axis (see below Figure 2.2). This circuit detects the starting point of an AC phase.

[
Figure 2.2 Zero cross points[/center]

2.1.1 Scheme

[
Figure 2.3 Zero cross circuit[/center]

2.1.2 Parts list of zero cross circuit

• Resistor
R1,R2, R3, R4: 100k ohm
R5: 470 ohm
R6: 10k ohm
R7: 5.6k ohm

Note: All resistors are 1/4 watt. The resistors in the circuit scheme are paralleled. I used such an arrangement because these are what I have at hand. If you have power resistors, these paralleled resistors can be replaced.

• Diode
D1, D2, D3, D4: 1N4002
(Or you can use a bridge to replace them.)

• Transistor
Q1: 2N3904

• Optoisolator
U1: H11A1

2.2 Trigger circuit

Trigger circuit works for triggering triac to turn on the power. Because of the high current (over 10A) in my application, a CPU heat sink is used to cool down the triac (see Figure 2.1).

2.2.1 Scheme

[
Figure 2.4 Trigger circuit[/center]

2.2.2 Parts list of trigger circuit

• Resistor
R1, R2: 1k ohm
R3: 5.6k ohm
R4,R5,R6,R7: 720 ohm
R8,R9,R10,R11: 9.6k ohm

• Optoisolator
O1: MOC3063

• Capacitor
C1: 1nF

• Triac
T1: MAC15DG
](Trigger circuit | laiforum | Flickr)](Zero cross circuit | laiforum | Flickr)](Zero cross points of AC Phase | laiforum | Flickr)](AC phase control circuit | laiforum | Flickr)](Furance ON | OLYMPUS DIGITAL CAMERA | laiforum | Flickr)](Codes comparison | laiforum | Flickr)

3. Code

There are three sets of code in this project for AC phase manipulated PID controls. The functions they realize and the methods they used are different. Details about them are provided as a table below.

[
Table 3.1 Codes comparison[/center]

Note: There are two versions of AC phase trigger code in this forum [3-4]. My code is different to incorporate the functions of AC phase triggering, PID control, and the communication between Arduino boards and a computer. If you interested in the AC phase trigger code I used, you can find the code development in [5].

3.1 The concept of AC phase control for Arduino

[
Figure 3.1 Concept of AC phase control[/center]

The earlier that power is triggered on in a half period of an AC phase, the more power will be obtained. For example, 50% output can be obtained at N/2th step. With the circuit design in my project, control for obtaining output over 85% is not recommended. This is because AC phase could be mis-triggered in that situation. If a control of over 85% output power is needed, you can redesign the control circuit using application notes [1-2]. The best performance of this control in my application happened when the desired output power range is between 0% and 80% of total power output. For reference, Figure 3.2 and 3.3 show AC phase waveforms of different power outputs in ideal and practical situations.

[
Figure 3.2 Different power outputs[/center]

[
Figure 3.3 Different outputs from an oscilloscope[/center]

3.2 Code 1 - AC phase control - Breathing light (Standalone version)

Program used: Arduino v0022 or v1.0.1
Library used: TimeOne

 /* 
Breathing light – using Arduino for AC phase control without working with Labview
(Standalone version; used Code 1)

digital pin 02 (interupt 0)is used to detect AC phase interupt
digital pin 04 and 05 is used to trigger triac
        Pin 04 is for breath light
        Pin 05 is for test(fixed phase)
   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <TimerOne.h>                                  // TimeOne Library; http://arduino.cc/playground/Code/Timer1     

// For AC phase
unsigned long int ZeroXTime[4] = {0,0,0,0};            // Timestamp in micros() of the zero crossing interrupts
unsigned long int Steptime;                            // How many microseconds in each step 
unsigned long int AvgPeriod;                           // The average half phase period in microseconds
// unsigned long int PeriodResync = 3000;                 // Number of milliseconds between line freq measurements
// unsigned long int ResetPeriod = PeriodResync;          // The timestamp in millis() when we will measure the period again
unsigned long int AC_step = 100;                       // How many steps in an half AC phase
volatile unsigned long int SteptimeCounter;            // For counting Timer1 interrupts
volatile unsigned long int FireTriac[2] = {0,0};       // Set for multiple firetriac outputs
volatile boolean zero_cross = 0;                       // Tels us we've crossed the zero line
byte TriacPin[2] = {4,5};                              // Digital pins are used for firetriac
byte PowerMap[100] = {
                       99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,
                       63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,
                       27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
                     };                                //Powermap for speeding up the phase control

// For breath light
int x=0;                                               // initial variable for breath light loop
byte breathMap[31]= {
                      99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,85,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99
                    };                               //Breath map
                                          
void setup() {                                         // Initial setup
  Timer1.initialize(Steptime);                         // Start up Timer1 timer
  attachInterrupt(0, zero_cross_detect, FALLING);      // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  pinMode(TriacPin[0], OUTPUT);                        // Set the Triac pin as output (Digital Pin 4 is used.)
  pinMode(TriacPin[1], OUTPUT);                        // Set the Triac pin as output (Digital Pin 5 is used.)
  measure_half_period();                               // Initially measure the average half phase period
}                                                      // End setup

void measure_half_period() {
  zero_cross = 0;                                      // Set zero_cross
  byte F = 0;                                          // Set a variable for the loop count
  while ( F < 4 ) {                                    // This loop takes 4 zero cross samples (F from 0 to 3)
    if ( zero_cross ) {                                // When a zero cross is detected
      ZeroXTime[F] = micros();                         // Record the current zeor cross time in microsecond
      zero_cross = 0;                                  // Reset zero_cross
      F++;                                             // 
    }
  }                                                    // Calculate the time of each Steptime
  Steptime = (((ZeroXTime[1]-ZeroXTime[0]) + (ZeroXTime[2]-ZeroXTime[1]) + (ZeroXTime[3]-ZeroXTime[2])) / 3) / AC_step;
  Timer1.attachInterrupt(fire_triacs, Steptime);       // Associate fire_triacs() with the Timerone interrupt and the Steptime period
  //ResetPeriod = ResetPeriod + PeriodResync;          // Set the next time when we'll measure the half period again
}
  
void zero_cross_detect() {                             // function for detectind zero cross
  zero_cross = 1;                                      // set a variable that's picked up later
  SteptimeCounter = 0;                                 // Reset the step counter for the next round of triac firings
}

void fire_triacs() {
  if ( FireTriac[0] == SteptimeCounter ) {             // Is it time to fire triac?
      digitalWrite(TriacPin[0], HIGH);                 // Fire the Triac
      delayMicroseconds(2); 
      digitalWrite(TriacPin[0], LOW);                  // Turn off the Triac gate (Triac will not turn off until next zero cross)
  }
  
  if ( FireTriac[1] == SteptimeCounter ) {             // Is it time to fire triac?
      digitalWrite(TriacPin[1], HIGH);                 // Fire the Triac
      delayMicroseconds(2); 
      digitalWrite(TriacPin[1], LOW);                  // Turn off the Triac gate (Triac will not turn off until next zero cross)
  }
  SteptimeCounter++;                                   // This counter increments every time fire_triacs runs
}

void loop() { 	
  // Breath Light Control
     for(x=0; x< 31; x++){                             // Set a loop for breath control
     FireTriac[0] = breathMap[x];                      // Fire triac
     delay(200);                                       // delay 50 milliseconds
     }
     
  // Fire Triac at a fixed power output
     FireTriac[1] = PowerMap[5];                       // Fixed phase value for test
 }

](Practical output power results | laiforum | Flickr)](Ideal output power results | laiforum | Flickr)](The concept of AC Phase control | laiforum | Flickr)](Codes comparison | laiforum | Flickr)

3.3 Code 2 - AC phase control - Light dimmer and Breathing light (External system version)

Programs used: Arduino v0022 and Labview 8.5
Library used: TimeOne, Messenger (version: 1.3)

This code only works with Arduino program v0022. Messenger library is not compatible with Arduino v1.0.1.

 /* 
Light dimmer and Breathing light – using Arduino and Labview for AC phase control 
(External system version; used Code 2)

digital pin 02 (interupt 0)is used to detect AC phase interupt
digital pin 04 and 05 is used to trigger triac
        Pin 04 is for breath light via Labview
        Pin 05 is for test(fixed phase)
        
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <TimerOne.h>                                  // TimeOne Library; http://arduino.cc/playground/Code/Timer1
#include <Messenger.h>                                 // Messenger Library(version: 1.3); http://www.arduino.cc/playground/Code/Messenger

// For Messenger Define function
Messenger message = Messenger();

// For AC phase
unsigned long int ZeroXTime[4] = {0,0,0,0};            // Timestamp in micros() of the zero crossing interrupts
unsigned long int Steptime;                            // How many microseconds in each step 
unsigned long int AvgPeriod;                           // The average half phase period in microseconds
// unsigned long int PeriodResync = 3000;                 // Number of milliseconds between line freq measurements
// unsigned long int ResetPeriod = PeriodResync;          // The timestamp in millis() when we will measure the period again
unsigned long int AC_step = 100;                       // How many steps in an half AC phase
volatile unsigned long int SteptimeCounter;            // For counting Timer1 interrupts
volatile unsigned long int FireTriac[2] = {0,0};       // Set for multiple firetriac outputs
volatile boolean zero_cross = 0;                       // Tels us we've crossed the zero line
byte TriacPin[2] = {4,5};                              // Digital pins are used for firetriac
byte PowerMap[100] = {
                       99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,
                       63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,
                       27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
                     };                                //Powermap for speeding up the phase control

// Inital value for computer control
unsigned long val = 90;                                // Set a variable for Computer Control
                                          
void setup() {                                         // Initial setup
  Timer1.initialize(Steptime);                         // Start up Timer1 timer
  attachInterrupt(0, zero_cross_detect, FALLING);      // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  pinMode(TriacPin[0], OUTPUT);                        // Set the Triac pin as output (Digital Pin 4 is used.)
  pinMode(TriacPin[1], OUTPUT);                        // Set the Triac pin as output (Digital Pin 5 is used.)
  measure_half_period();                               // Initially measure the average half phase period
  Serial.begin(9600);                                  // open the serial port at 9600 bps for computer control 
}                                                      // End setup

void measure_half_period() {
  zero_cross = 0;                                      // Set zero_cross
  byte F = 0;                                          // Set a variable for the loop count
  while ( F < 4 ) {                                    // This loop takes 4 zero cross samples (F from 0 to 3)
    if ( zero_cross ) {                                // When a zero cross is detected
      ZeroXTime[F] = micros();                         // Record the current zeor cross time in microsecond
      zero_cross = 0;                                  // Reset zero_cross
      F++;                                             // 
    }
  }                                                    // Calculate the time of each Steptime
  Steptime = (((ZeroXTime[1]-ZeroXTime[0]) + (ZeroXTime[2]-ZeroXTime[1]) + (ZeroXTime[3]-ZeroXTime[2])) / 3) / AC_step;
  Timer1.attachInterrupt(fire_triacs, Steptime);       // Associate fire_triacs() with the Timerone interrupt and the Steptime period
  //ResetPeriod = ResetPeriod + PeriodResync;          // Set the next time when we'll measure the half period again
}
  
void zero_cross_detect() {                             // function for detectind zero cross
  zero_cross = 1;                                      // set a variable that's picked up later
  SteptimeCounter = 0;                                 // Reset the step counter for the next round of triac firings
}

void fire_triacs() {
  if ( FireTriac[0] == SteptimeCounter ) {             // Is it time to fire triac?
      digitalWrite(TriacPin[0], HIGH);                 // Fire the Triac
      delayMicroseconds(2); 
      digitalWrite(TriacPin[0], LOW);                  // Turn off the Triac gate (Triac will not turn off until next zero cross)
  }
  
  if ( FireTriac[1] == SteptimeCounter ) {             // Is it time to fire triac?
      digitalWrite(TriacPin[1], HIGH);                 // Fire the Triac
      delayMicroseconds(2); 
      digitalWrite(TriacPin[1], LOW);                  // Turn off the Triac gate (Triac will not turn off until next zero cross)
  }
  SteptimeCounter++;                                   // This counter increments every time fire_triacs runs
}

void loop() {
  // Read data                                         // Read triac timing form a computer
     while ( Serial.available() ) {                    // Check if there is Serial data
     if ( message.process(Serial.read() ) ){           // Process the Serial data and continue if there is a message
         val = message.readInt();                      // Set the phase value
     }}
 
  // Fire Triac
     FireTriac[0] = PowerMap[val];                     // Fire Triac via computer control
     FireTriac[1] = PowerMap[5];                       // Fixed phase value for test
 }

Labview setting for sending commands to an Arduino board

[
Figure 3.4 Labview setting for sending commands to an Arduino board- Termination character[/center]


Figure 3.5 Labview setting for sending commands to an Arduino board- Data type[/center]
](Labview setting for sending commands 01 | laiforum | Flickr)

3.4 Code 3 - PID controller with automatic AC phase control (Standalone and external system version)

Programs used: Arduino v0022 and Labview 8.5
Library used: TimeOne, Messenger (version: 1.3), PID (version: Beta6)
This code is not compatible with Arduino v1.0.1, too.

 /*
PID controller with automatic AC phase control for an application requiring constant temperature
(working with and recording through Labview; used Code 3)

digital pin 02 (interupt 0)is used to detect AC phase interupt
digital pin 04 and 05 is used to trigger triac
        Pin 04 is for PID temperature control
        Pin 05 is for test (fixed phase)
Analogh Pin 00 for temperature sensor

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <TimerOne.h>                                  // TimeOne Library; http://arduino.cc/playground/Code/Timer1
#include <Messenger.h>                                 // Messenger Library(version: 1.3); http://www.arduino.cc/playground/Code/Messenger
#include <PID_Beta6.h>                                 // PID Control Library (version: Beta6); http://www.arduino.cc/playground/Code/PIDLibrary

// For Messenger Define function
Messenger message = Messenger();

// For PID Control Define Variables
double Set_temp, Input, Output;                        // variables for PID Control
unsigned long Volt,Temp;                               // variables for reading real-time temperature 
int PID_Out;                                           // variable for PID output
PID pid(&Input, &Output, &Set_temp,3,4,1);             // Specify initial PID parameters

// For AC phase
unsigned long int ZeroXTime[4] = {0,0,0,0};            // Timestamp in micros() of the zero crossing interrupts
unsigned long int Steptime;                            // How many microseconds in each step 
unsigned long int AvgPeriod;                           // The average half phase period in microseconds
// unsigned long int PeriodResync = 3000;                 // Number of milliseconds between line freq measurements
// unsigned long int ResetPeriod = PeriodResync;          // The timestamp in millis() when we will measure the period again
unsigned long int AC_step = 256;                       // How many steps in an half AC phase
volatile unsigned long int SteptimeCounter;            // For counting Timer1 interrupts
volatile unsigned long int FireTriac[2] = {0,0};       // Set two outputs for triggering Triac
volatile boolean zero_cross = 0;                       // Tels us we've crossed the zero line
byte TriacPin[2] = {4,5};                              // Define digital pins for triggering Triac
byte PowerMap[256] = {255,245,241,237,235,232,230,228,226,224,223,221,220,218,217,215,214,213,211,210,209,208,207,205,204,203,202,201,200,199,198,197,
                      196,195,194,193,192,192,191,190,189,188,187,186,185,185,184,183,182,181,181,180,179,178,177,177,176,175,174,174,173,172,171,171,
                      170,169,168,168,167,166,165,165,164,163,163,162,161,161,160,159,158,158,157,156,156,155,154,154,153,152,152,151,150,150,149,148,
                      148,147,146,146,145,144,144,143,143,142,141,141,140,139,139,138,137,137,136,135,135,134,134,133,132,132,131,130,130,129,128,128,
                      127,127,126,125,125,124,123,123,122,121,121,120,120,119,118,118,117,116,116,115,114,114,113,112,112,111,111,110,109,109,108,107,
                      107,106,105,105,104,103,103,102,101,101,100,99,99,98,97,97,96,95,94,94,93,92,92,91,90,90,89,88,87,87,86,85,84,84,83,82,81,81,80,
                      79,78,78,77,76,75,74,74,73,72,71,70,70,69,68,67,66,65,64,63,63,62,61,60,59,58,57,56,55,54,53,52,51,50,48,47,46,45,44,42,41,40,38,
                      37,35,34,32,31,29,27,25,23,20,18,14,10,0
                     };                                //Steps from 0% to 100% output
                                          
void setup() {                                         // Initial setup
  Timer1.initialize(Steptime);                         // Start up Timer1 timer
  attachInterrupt(0, zero_cross_detect, FALLING);      // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  pinMode(TriacPin[0], OUTPUT);                        // Set the Triac pin as output (Digital Pin 4 is used.)
  pinMode(TriacPin[1], OUTPUT);                        // Set the Triac pin as output (Digital Pin 5 is used.)
  measure_half_period();                               // Measure the average half phase period
  Serial.begin(9600);                                  // open serial port at 9600 bps for computer communication
  pid.SetOutputLimits(2,230);                          // Define the level range of PID control(Ex: 5 means 95 and 80 means 20 at powermap)
  Output = 2;                                          // Set inital PID output (O: 99 at powermap)
  Set_temp = 20;                                       // Set target temperature for standalone or initial temperature for computer control
                                                       // Celsius degree in this program (depending on temperatuer sensor and circuit design)
  pid.SetMode(AUTO);                                   // Turn on the PID Control
}                                                      // End setup


void measure_half_period() {
  zero_cross = 0;                                      // Set zero_cross
  byte F = 0;                                          // Set a variable for the loop count
  while ( F < 4 ) {                                    // This loop takes 4 zero cross samples (F from 0 to 3)
    if ( zero_cross ) {                                // When a zero cross is detected
      ZeroXTime[F] = micros();                         // Record the current zeor cross time in microseconds
      zero_cross = 0;                                  // Reset zero_cross
      F++;                                              
    }
  }                                                    // Calculate the time of each Steptime
  Steptime = (((ZeroXTime[1]-ZeroXTime[0]) + (ZeroXTime[2]-ZeroXTime[1]) + (ZeroXTime[3]-ZeroXTime[2])) / 3) / AC_step;
  Timer1.attachInterrupt(fire_triacs, Steptime);       // Associate fire_triacs() with the Timerone interrupt and the Steptime period
  //ResetPeriod = ResetPeriod + PeriodResync;          // Set the next time when we'll measure the half period again
}
  
void zero_cross_detect() {                             // function for detectind zero cross
  zero_cross = 1;                                      // set a variable that's picked up later
  SteptimeCounter = 0;                                 // Reset the step counter for the next round of triac firings
}

void fire_triacs() {
  if ( FireTriac[0] == SteptimeCounter ) {             // Is it time to fire triac?
      digitalWrite(TriacPin[0], HIGH);                 // Fire the Triac
      delayMicroseconds(2); 
      digitalWrite(TriacPin[0], LOW);                  // Turn off the Triac gate (Triac will not turn off until next zero cross)
  }
  
  if ( FireTriac[1] == SteptimeCounter ) {             // Is it time to fire triac?
      digitalWrite(TriacPin[1], HIGH);                 // Fire the Triac
      delayMicroseconds(2); 
      digitalWrite(TriacPin[1], LOW);                  // Turn off the Triac gate (Triac will not turn off until next zero cross)
  }
  SteptimeCounter++;                                   // This counter increments every time fire_triacs runs
}

void loop() {
   // Read data                                         // Read target temperature from a computer (Ex: Labview)
      while ( Serial.available() ) {                    // Check if there is Serial data
      if ( message.process(Serial.read() ) ){           // Process the Serial data and continue if there is a message
         Set_temp = message.readInt();                  // Read the target temperature from computer
     }}
 /*
   // Recheck AC Period
    if ( millis() >= ResetPeriod ) {          // Measure the half period every PeriodResync milliseconds to prevent drift
         measure_half_period();
    }
 */
   // Read Temperature from Furnace and control by PID control
      Volt = analogRead(0);                             // Read voltage from a temperature sensor
      Temp = Volt*500/1023;                             // Convert voltage to real-time temperature
      Input = Temp;                                     // Send temperature data to PID program
      //Serial.println(Temp);
      pid.Compute();                                    // PID control
      PID_Out = int(Output);                            // Convert Output from double type to int type
      
   // Fire Triac
      FireTriac[0] = PowerMap[PID_Out];                 // Fire Triac via PID control
      FireTriac[1] = PowerMap[128];                     // Fixed phase value for test
 }

Labview setting for receiving data from an Arduino board

[
Figure 3.6 Labview setting for receiving data from an Arduino board - Termination character[/center]

[
Figure 3.7 Labview setting for receiving data from an Arduino board - Type[/center]

4. Conclusions

This Arduino based PID controller with a control circuit can be used for constant temperature applications, motor speed control applications, and AC phase control applications. On the other hand, when working with various sensors and circuits, it can also be used for applications such as DC motor control, pulse-width modulation (PWM) applications, Laser power control, and optical fiber alignment, etc.

5. Reference

[1] Applications of Zero Voltage Crossing Optically Isolated Triac Drivers
www.fairchildsemi.com/an/AN/AN-3004.pdf
[2] Optically Isolated Phase Controlling Circuit Solution
www.fairchildsemi.com/an/AN/AN-3006.pdf
[3] Arduino Playground - ACPhaseControl
[4] Arduino Playground - ACPhaseControl
[5] http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236998971
](Labview setting for receiving data 02 | laiforum | Flickr)](Labview setting for receiving data 01 | laiforum | Flickr)

Note that the diode bridge rectifier in figure 2.3 'Zero cross circuit' is drawn in error. Diode D2 needs to be reversed.

Lefty

I corrected it.
Thank you for your message. :slight_smile:

This is very nice.

Im trying somthing very similar. My Arduino code for the phase control is rather simple tho. but it gets the job done.
I want to try and read the phase controlled wave back into labview ? Have you tried this ? any ideas ?

Hi maltrap,

There are two methods I can think of for this purpose. First, you can use an oscilloscope that comes with a GPIB or USB output port. With its Labview driver, you should be able to monitor or record AC voltage phase waveform. If you want to monitor current waveform, you need a current probe that works with the oscilloscope.

The other way you can try is to redesign a P3 kill a watt monitor (See the links below). It is a good and inexpensive alternative (about $25). Once you redesign it, you can write your own Arduino code to make it into a three-in-one monitor (voltage, current, and power). I built one and recorded real-time voltage, current, and power waveforms via Labview for my project.

For your reference, AC voltage and current waveforms which you can watch is here:
http://www.ladyada.net/make/tweetawatt/software.html

The full guide of Tweet-a-watt is here:
http://www.ladyada.net/make/tweetawatt/index.html

I hope this is helpful.

Hi bluefish

I checked out those links. that seems very nifty !
Will look into one of those. (or I can even find somthing similar here in South Africa)

Thanks for the advice

Can someone please provide the labview code for code 2? :slight_smile:

please send me screen shot lab view block diagram. I am 1st year student in hnd electronic i don't no how to build block diagram
my email chathuranga032@gmail.com my project is smart A/C power controller please help me

Hi. Im trying to make a dimmer controlled by labview using arduino controller. For this I used this tutorial http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/
I have the simmer working fine only with arduino. Now the problem is that I dont know how to do the vi on labview or program on labview. Can you help me by sending me the vi of labiview you used, or images please or something that could help me in this purpose. erick06_10@hotmail.com

Hey,

I'm working on Biodiesel reactor for which a PID controller with automatic AC phase control for a set constant temperature (around 240°C) is required. There are 3 heaters, each of 1400W, for a total of 4200W. I would like to know how the design would need to be upgraded to hold 25A current. I'm only starting to discover the world of electronics and arduino, there is a professor around my location who already uses arduino and can assist me further. This design seems to correspond to my application, the only different thing I notice is the higher current of 25A instead of 10A. Let me know your suggestions.

Sincerely,
Lucas O'Phoenix

One thing I noticed in the zero-cross circuit - you have 4 100k resistors in parallel at mains
voltage. That's increasing the risk of short-circuit failure by 4.

Using 4 6k8 resistors in series would give the same effect and reduce the failure risk by a
factor of 4, as well as not requiring mains-voltage rated resistors.

Also the bridge rectifier isn't needed if you use an AC optocoupler (which has two IR
emitters back-to-back). Again fewer components to fail...

Hyperlight:
how the design would need to be upgraded to hold 25A current.

A more potent output triac...

Bluefish thank you for this desighn