Hey everyone!
I'm not sure if this is the correct category, so I appologize if I've made a mistake.
I'm trying to build an AC dimmer circuit that works on 220V 50Hz as per these 2 tutorials:
The problem with these tutorials (and all other examples, libraries and other information I found online) is that it is controlled by phase cut percentage and not by the actual voltage percentage. For example (assuming we have 220V AC): 50% does not mean 110V. Instead, both in simulation (Proteus) and in a real circuit I get 157V.
Here's the current code I'm using for testing purposes:
#define TRIAC 3
void zero_crossing()
{
delayMicroseconds(map(analogRead(A0), 0, 1024, 0, 10000));
digitalWrite(TRIAC, HIGH);
delayMicroseconds(10);
digitalWrite(TRIAC, LOW);
}
void setup()
{
pinMode(A0, INPUT);
pinMode(TRIAC, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), zero_crossing, CHANGE);
}
void loop() {}
And here's the circuit:
Yes, I know the code is not optimal and I should do as little as possible in an interrupt routine, but this is just for testing purposes. I'll replace the delay functions with actual timer interrupts in the future.
You might've noticed that I use a value of 1024 in the map function, and that's because of the following article, but it should make much of a difference:
Another thing I want to mention is the attachInterrupt
function. I use an "on CHANGE" mode because I'm using LM393 for the zero crossing detection. If I replace it with 4N25 (and of course, a bridge rectifier) I should use a RISING mode pin interrupt. I've tried both LM393 and 4N25 zero crossing detectore, but the results are the same.
Finally, I should also mention that when testing in real life, I use BT139 triac instead of the one shown on the image above.
So now, my question is:
Can I somehow calculate the amount of delay needed to achieve a given voltage?
Here's an example, just to make things extra clear:
#define TRIAC 3
uint16_t triacDelay = 0;
// The parameter voltage has a range of 0 to 220
uint16_t get_delay_from_voltage(uint8_t voltage)
{
// Calculate the delay according to a given voltage
uint16_t delayAmount = 0;
// Perform the actual calculations here
// ...
// ...
// ...
return delayAmount;
}
void zero_crossing()
{
delayMicroseconds(triacDelay);
digitalWrite(TRIAC, HIGH);
delayMicroseconds(10);
digitalWrite(TRIAC, LOW);
}
void setup()
{
pinMode(TRIAC, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), zero_crossing, CHANGE);
}
void loop()
{
// The code in the loop function alternates between 100v and 200v each 5 seconds.
// This means that we should have an output voltage of 100 volts
triacDelay = get_delay_from_voltage(100);
delay(5000);
// This means that we should have an output voltage of 200 volts
triacDelay = get_delay_from_voltage(200);
delay(5000);
}
Making a lookup table has crossed my mind, but I don't think it's the most optimal solution, because of the need to test 220 values and create the table according to the them.
I'd gladly provide any additional information needed and I'd greatly appreciate any help.
Thanks in advance!