Thanks for that,
I have another sketch which I have modified to suit, it gives 0V = OFF & 255 is full ON. I noted the special cases you mentioned for these values.
I have a potentiometer connected so adjustment is 0v to 5V which will be good for the PID setup - I think.
There is a small glitch somewhere that I can't find as yet.
With the pot turned to 0V output there is 0V output from the Triac circuit, basically flat lined, then intermittently there is a very small spike, not enough to flash the Lamp but on the scope you can see one Zero Cross Pulse & it's just enough to trigger the Gate of the Triac causing a small spike.
It very intermittent but still it is an issue I guess.
See below for sketch, credit is given for the original sketch.
Cheers
/*
*****************************************************************************
Thanks to
Ryan McLaughlin <
ryanjmclaughlin@gmail.com>
Mark Chester <
mark@chesterfamily.org>
James Orland <
ptd@caff.cx>
**broken link removed**
for the original sketch ideas.
*****************************************************************************
Modified Sketch
Willeng
22/7/2014
Pin A0 -- Potentiometer 0V to 5V Input---Potentiometer
Pin 2 -- Zero Cross Interupt (Interupt 0)
Pin 3 -- Trigger Pulse to Triac Single pulse at this stage.
0 = 0V 255 = 5V from Arduino
0V AC output from circuit -- True Zero---HEY!!!!
*/
#include <TimerOne.h>
// General
boolean debug = false;
unsigned long int ZeroXTime[4] = {0,0,0,0}; // Timestamp in micros() of the zero crossing interrupts
unsigned long int PowerStep; // How many micros() in each step of power output
unsigned long int AvgPeriod; // The average line voltage period in micros()
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 PowerRes = 256; // How many steps of power resolution
volatile unsigned long int PowerStepCounter; // For counting Timer1 interrupts
volatile unsigned long int FireTriac = 0; // When it's OK to fire the triacs, in counts of PowerRes
volatile boolean zero_cross = 0; // Tels us we've crossed the zero line
byte TriacPin = 3; // Which digital IO pins to use
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
};
void setup() { // Begin setup
Serial.begin(9600);
Timer1.initialize(PowerStep); // Start up the Timer1 timer
attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
pinMode(TriacPin, OUTPUT); // Set the Triac pin as output
measure_half_period(); // Initially measure the half period
} // End setup
void measure_half_period() {
zero_cross = 0; // Clearing this here increases the accuracy of the measurement
byte F = 0; // Frequency counter counter
while ( F < 4 ) { // This loop takes 4 zero cross samples
if ( zero_cross ) { // Only run if a zero cross is detected
ZeroXTime[F] = micros(); // Set the new current zero cross time in micros()
zero_cross = 0; // Reset zero_cross
F++; // Bump the counter for the next sample
}
} // Now we calc the length of each PowerStep
PowerStep = (((ZeroXTime[1]-ZeroXTime[0]) + (ZeroXTime[2]-ZeroXTime[1]) + (ZeroXTime[3]-ZeroXTime[2])) / 3) / PowerRes;
Timer1.attachInterrupt(fire_triacs, PowerStep); // (Re)Associate fire_triacs() with the Timer1 interrupt and the latest PowerStep period
ResetPeriod = ResetPeriod + PeriodResync; // Set the next time when we'll measure the half period again
}
void zero_cross_detect() { // function to be fired at the zero crossing
zero_cross = 1; // set a variable that's picked up later
PowerStepCounter = 0; // Reset the step counter for the next round of triac firings
}
void fire_triacs() { // improved version with full OFF and ON
if ( FireTriac == PowerStepCounter ) { // Is it time to fire?
if(FireTriac !=(PowerRes-1)) // When the power output is 0% never turn the triac on
digitalWrite(TriacPin, HIGH); // Fire the Triac mid-phase
if(FireTriac != (PowerRes-1) && FireTriac != 0) //Only bother to add a timing delay when both digitalWrites are active
delayMicroseconds(2);
if(FireTriac != 0) // When the power output is 100% never turn the triac off
digitalWrite(TriacPin, LOW); // Turn off the Triac gate (Triac will not turn off until next zero cross)
}
PowerStepCounter++;
}
void loop() { // Main Loop
if ( millis() >= ResetPeriod ) { // Measure the half period every PeriodResync milliseconds to prevent drift
measure_half_period();
}
FireTriac = PowerMap[(PowerRes * analogRead(0)) / 1024]; // Read input and calc the next triac fire time
if (debug) Serial.println( PowerStep );
if (debug) Serial.println(" " );
if (debug) Serial.println( FireTriac );
delay(100);
}