Go Down

Topic: Arduino AC Power Shield! (Read 60577 times) previous topic - next topic


Oct 14, 2009, 07:00 pm Last Edit: Oct 14, 2009, 07:06 pm by bluefish Reason: 1
Hi my friends,

After I tried and tested, I can control AC output very accurate and stable by using phase and PID control, which can be found on the arduino library. The max AC power output for my system is about 1000 watt. The error of the temperature inside my furnace is lower than 1 degree C.

I found why I randomly lost phase control before. Codes from koyaanisqatsi and caff are not big different. To koyannisqatsi, your original code is work well. But your newest code is not work well for me. The trouble comes from my AC triac circuit design. I missed the limitation of dv/dt before. If AC triac circuit doesn't follow this limitation, you may get phase control at first like me. But the system could lose control later depending on your using. For me, my system lost phase control; the high power output (over 2800 watt) damaged everything.

Unfortunately, different triaces have different limitation for dv/dt. Different AC voltage also infects your AC triac circuit design because dv depends on your using voltage. For example, there are needed different AC triac circuit designs for 120 and 220 Vac. On the other hand, static dv/dt is for resistor only system, like heat coil furnace. Commutating dv/dt is for RCL (resistor, capacitor and inductor) mixed system, like AC motor speed control. Static dv/dt has more range than commutating dv/dt. That is why window fan has only 3 or 4 control speeds.

Therefore, the conclusion is for different applications and AC voltages, different AC triac circuits are needed.

Before do arduino phase control, something which you need to knows.

-      triac which you will use
-      AC voltage which your system will work at
-      The limitation for triac: (dv/dt)s or (dv/dt)c;  for several applications: di/dt
-      Basic circuit knowledge

If someone is still interested in this AC power phase control circuit and can make several PCB for me (3-6; I will pay what I get), I am happy to share my circuit, which can be designed a shield to mount on the arduino, without AC triac part.

AC triac part is needed to design for different systems. It is not a good ideal to mount on the arduino due to high current and voltage. I don't want to become a thanksgiving turkey. The AC triac part is needed to put on a separated metal box.

Cheer  ;D


Hi Bluefish,
I do appreciate that English is not your first language but what you say makes no sense. dv/dt is an other way of saying the rate of change of voltage with time.

Therefore, the conclusion is for different applications and AC voltages, different AC triac circuits are needed.

I would also disagree with this.
Different loads will affect the phase angle between voltage and current and for some loads you might have to apply phase angle correction but this is not part of the design of the AC dimmer.

What circuit designed changes do you think are needed. Have you any schematics we can look at so we can see where you are misunderstanding things.


Mike and BlueFish,

I think what's being discussed is the slew rate of the AC sine, considering the voltage, frequency and any distortion caused by the type of load.  It sounds like the slew rate made a difference in how reliably the triacs would fire.  But I think that by increasing the time of the trigger pulse, you could overcome any slew rate issues in the triacs.  It's currently somewhere around 2-6 us, but could easily be increased into the ms range to be sure the pulse was still there when the triac finally detected the AC voltage rise.  Your limiting factor will be that the trigger pulse must end on or before the next zero-crossing.

I discussed in a previous post the idea of making the trigger pulse last all the way through to the next zero cross.  That would assure triac firing under weird circumstances.


What blue-fish is talking about is that a Triac can latch into a permanent on state under certain conditions when it should turn off at the end of a half cycle. It is all explained here:
in a link that I'm not allowed to post!


so her it goes


Excellent thread about AC control. I wanted to add this resource to the great info here:


This is a reference design using a freescale micro + capacitive touch sensor to implement a light dimmer. It also has wireless control via RF (802.15.4). In the documentation, they have detailed schematics of the AC circuits.


Hi Bluefish,

Finally what version of code do you suggest to use. I am also interested in Furnace control. I am using simplified version of code and it is not working for me @ 100% output. I get the same wattage at both 70% output and 100% output. Can anybody suggest whats wrong with this code

#include <TimerOne.h>                                
byte oput=0;
byte cntr=0;
unsigned long int DimStep=1000000/102/256;
long int starttime;
volatile unsigned long int DimStepCounter;            
volatile unsigned long int FireTriac = 0;  
volatile boolean zero_cross = 0;                      
byte TriacPin = 14;                          
byte PowerMap[256] = {

void setup()
 attachInterrupt(0, zero_cross_detect, FALLING);      
 pinMode(TriacPin, OUTPUT);                        
 Timer1.attachInterrupt(fire_triacs, DimStep);
 FireTriac = PowerMap[oput];
void zero_cross_detect()
 DimStepCounter = 0;

void fire_triacs()
 if ( FireTriac == DimStepCounter )                  
   digitalWrite(TriacPin, HIGH);                  
   digitalWrite(TriacPin, LOW);    

void loop()



Can you explain these bits of code?

Code: [Select]
byte oput=0;
unsigned long int DimStep=1000000/102/256;

Code: [Select]
FireTriac = PowerMap[oput];

The oput variable is an integer type variable. The only place it gets assigned a value is in setup. Do you have any idea what value is being stored in oput?

DimStep ends up with a value of 38. Why not just assign it that directly? Do those magic numbers mean something?

The only place PowerMap is referenced is in setup. FireTriac is getting assigned a value here, and nowhere else. Why not just hardcode the value for FireTriac? That would be faster, and require a much smaller memory footprint than this way.
The art of getting good answers lies in asking good questions.


Hi Paul,

I actually intended to do use the code with combination of PID code to control the furnace temperature. I have started with complex version of code and ended up with the code above as I started debugging. Eventually '100' in 'oput' would get the value of percentage output from PID code and then PowerMap will give me the time step at which triac should fire.

2.56 is multiplied to percentage to convert it into one of 256 levels of Powermap array and to find out the time in micro seconds after which triac should fire.

I was trying to change the values of oput manually and observing the wattage of load(100W bulb). when I give 100% (i.e 100*2.56 = 256 level),I expected the bulb would glow with full brightness, but is not glowing at all.I tried with even 95% also, it also didnot worked.

And about DimStep magic numbers, frequency of AC voltage which we use here is 51Hz, and I want to divide the time between two zero-crossings into 256 levels. so 1e6microseconds/102zerocrossings/256 levels. Instead I could have used 38 as you said.I was not convinced about the idea of using the time required for previous zero-crossings to determine the current DimStep. So I chose to go for constant DimStep. I donot know if it would create problems.

What could be wrong with this code, as it is not working when I give 100*2.56 in oput, Powermap would give me value of 0. So as soon as zero crossing happens, triac should fire. Which I didnot observed. Is it becuase of some time synchronization problem between two interrupts?


First, about the "magic" numbers. Use something like this:

Code: [Select]
#define FREQ 51
#define STEPS 256
unsigned long int DimStep=1000000/(FREQ*2)/STEPS;

The result will be the same, but the intent is much clearer.

I question that 51, though. If it's AC power you are talking about, the frequency should be either 50 or 60, depending on where you are. 51 seems non-standard.

The oput variable is an integer type. The 2.56 value is not. I was asking if you know what value is actually stored in oput when you assign it a value of 100*2.56. Is it 256, or is it 200?

Since you use oput as an index into the array, the difference is important.

If the value is 256, that is not a valid index into the array. Valid indices are from 0 to 255.

What value is being stored in FireTriac?

Use the Serial.print and Serial.println functions, along with Serial.begin, to write data to the serial port, and open the serial monitor (using the rightmost button in the IDE). You can get answers to all of the questions I am asking, and, perhaps, see for yourself what is happening.
The art of getting good answers lies in asking good questions.


first post!

Couldn't you have at least posted that in Bar Sport or something rather than in the middle of an unrelated thread?  ::)


Couldn't you have at least posted that in Bar Sport or something rather than in the middle of an unrelated thread?

That would have been too easy!



It is not good......

Can we get you reported cos you have done nothing but post hardly related posts on random topics...

Go Up