Hello everyone, I am running into an issue where millis() does not update during my long delayed ISRs. I did a bunch of research and all posts seem to tell me to offload the processing to outside of the ISR. I did that and the total timing becomes correct, but the output waveform is slowly becomes off course in relation to the zero crossing wave. So I have two versions of the code: one that performs the AC dimming correctly power-wise but the total time is incorrect, and another that does not perform the AC dimming correctly power-wise but the total time is incorrect. For example, I want the motor to run at .2 for 5s and then 3 for 5s, then 7 for 5s. Version one would change the speed of the motor correctly but would last more than 15s (depending on the delay in the ISR). Version two would not change the speed of the motor correctly but the whole thing would end in 15s (which is what I want). Please assume the hardware is correct, I have a working zero-detection circuit with a triac and optoisolator. Ideally I would like to stick with the second version of the code:
First version:
#include <digitalWriteFast.h>
int timeframes[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
float percent[]{.1,.1,.1,.1,.1,8,8,8,8,8,3,3,3,3,3};
int timeran = 15; //each int is 2 bytes
//dont touch stuff below unless you have to//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define AC_LOAD 7 //Output to Opto Triac pin
//Calculations / variables
const int timePerCycle = 1/60; //time in us
const int timeZeroCrossing = 1/2timePerCycle1000; //~8333us
volatile int timePerStep = timeZeroCrossing/100;
volatile unsigned long curTime = 0;
volatile int ISRcounter = 0;
void setup()
{
pinModeFast(AC_LOAD, OUTPUT);// Set AC Load pin as output
attachInterrupt(digitalPinToInterrupt(2), zero_cross_change, CHANGE);
}
//the interrupt function must take no parameters and return nothing
void zero_cross() //function to be fired at the zero crossing to dim the light
{
/int dimtime = (timePerStepdimming); //dimming = % of max speed
if(once){
delayMicroseconds(8287/2); // Wait till firing the triac
once = 1;
}
else{
delayMicroseconds(500);
}
digitalWriteFast(AC_LOAD, HIGH); // Fire the triac
delayMicroseconds(8287); // Triac on propogation delay
digitalWriteFast(AC_LOAD, LOW); // No longer trigger the triac (the next zero crossing will swith it off)
delayMicroseconds(500);
digitalWriteFast(AC_LOAD, HIGH);
delayMicroseconds(8287/2);
*/
}
void zero_cross_change(){
//if(((curTime > 1501) && (curTime<2501))||((curTime > 3001) && (curTime<4001))||((curTime > 5000) && (curTime<6000))||((curTime > 16001) && (curTime<16500))){
//if(curTime>1000 && curTime <7999){
if((curTime<(timeframes[ISRcounter]1000)) && ISRcounter <=timeran){
int delaytime = 833.33percent[ISRcounter];
digitalWriteFast(AC_LOAD,HIGH);
delayMicroseconds((8333-(delaytime/2))/2);
digitalWriteFast(AC_LOAD, LOW);
delayMicroseconds(delaytime-4); //4us threshold to run this instruction
digitalWriteFast(AC_LOAD, HIGH);
}
// else if(curTime > 8000 && curTime < 16000){
// digitalWriteFast(AC_LOAD, LOW);
// }
else{
ISRcounter++;
digitalWriteFast(AC_LOAD, HIGH);
}
}
void loop() {
curTime = millis();
}
Second version:
#include <digitalWriteFast.h>
int timeframes[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
float percent[]{.1,.1,4,4,4,4,4,4,4,4,.2,.2,.2,.2,.2};
int timeran = 15; //each int is 2 bytes
//dont touch stuff below unless you have to//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define AC_LOAD 7 //Output to Opto Triac pin
//Calculations / variables
const int timePerCycle = 1/60; //time in us
const int timeZeroCrossing = 1/2timePerCycle1000; //~8333us
volatile int timePerStep = timeZeroCrossing/100;
volatile unsigned long curTime = 0;
volatile int ISRcounter = 0;
bool nOPFlag = 0;
bool highFlag = 0;
void setup()
{
pinModeFast(AC_LOAD, OUTPUT);// Set AC Load pin as output
attachInterrupt(digitalPinToInterrupt(2), zero_cross_change, CHANGE);
}
/*void zero_cross() //function to be fired at the zero crossing to dim the light
{
/int dimtime = (timePerStepdimming); //dimming = % of max speed
if(once){
delayMicroseconds(8287/2); // Wait till firing the triac
once = 1;
}
else{
delayMicroseconds(500);
}
digitalWriteFast(AC_LOAD, HIGH); // Fire the triac
delayMicroseconds(8287); // Triac on propogation delay
digitalWriteFast(AC_LOAD, LOW); // No longer trigger the triac (the next zero crossing will swith it off)
delayMicroseconds(500);
digitalWriteFast(AC_LOAD, HIGH);
delayMicroseconds(8287/2);
}*/
//interrupt
void zero_cross_change(){
if((curTime<(timeframes[ISRcounter]*1000000)) && ISRcounter < timeran){
nOPFlag = 1;
}
else if(ISRcounter < timeran){
nOPFlag = 0;
ISRcounter++;
}
}
void normalOP(){
int delaytime = 833.333*percent[ISRcounter];
digitalWriteFast(AC_LOAD,HIGH);
delayMicroseconds((8333.333-(delaytime/2))/2);
digitalWriteFast(AC_LOAD, LOW);
delayMicroseconds(delaytime);
digitalWriteFast(AC_LOAD, HIGH);
}
void ending(){
digitalWriteFast(AC_LOAD, HIGH);
}
void loop() {
curTime = micros();
if(nOPFlag==1){
{
normalOP();
}
}
if(nOPFlag==0){
ending();
}
}