Time between interrupt "flickering"

Hello

I'm trying to control two back to back SCRs with the phase-angle "principle", but I'm having problem with inconsistent values, ie. the light flickers every so slightly now and then, it's not a constant flicker.

I've checked with oscilloscope on zero-cross signal and "fire"-signal and the ZC-signal is consistent but the fire-signal jitters approximately +/- 300µs around the point where the signal is stationary. As I said this isnt a constant flicker, just now and then. However this jitter is enough to experience a slight dim in the light bulbs.

Is this possible related to code-issues?

For now I'm only testing on one phase, but I'll add another two when testing is done.
I'm using an Arduino Micro, so I have tree interrupt-pins available for zero-cross triggering.

/* ------------*/
/* INPUTS PINS */
/* ------------*/
const byte L1_ZC_Pin  = 2;
const byte L1_SCR_Pin = 4;
const byte pot_Pin    = 5;

/* ----------*/
/* CONSTANTS */
/* ----------*/
const long iDelay         = 10000;  // Sampling delay/interval [µs]
const int SCR_Pulse_Width = 100;    // SCR Pulse-width [µs]
const int minimumDelay    = 300;    // Minimum firing-delay at max power [µs]
const float smoothFactor  = 0.95;   // Smoothing value for fire delay [0-1].

/* ----------*/
/* VARIABLES */
/* ----------*/
int potValue;             // Raw value of the potentiometer
volatile byte L1_ZC_Trg;  // Variable triggered by ISR for Zero Cross

float delayValAvg;        // Smoothed fire delay from measured samples
int rawFireDelay;         // Fire delay mapped from potmeter value and delta time for ZC

unsigned long dT_ZC_INT;  // time between zero crosses
unsigned long pDelay;     // Previous time a sample happened
unsigned long pL1_ZC;     // Previous time zero cross phase L1
unsigned long pL1_SCR;    // Previous time L1 SCR was fired
unsigned long microsNow;  // Time now


void setup() {
  // Initialize IO-Pins
  pinMode(L1_ZC_Pin, INPUT);
  pinMode(L1_SCR_Pin, OUTPUT);

  // Activate interrupt routines
  attachInterrupt(digitalPinToInterrupt(L1_ZC_Pin), L1_ZC, RISING);
}

void loop() {
  microsNow = micros(); // Save current time

  // Sample potmeter and time for zero-cross
  if ( microsNow - pDelay >= iDelay ) {
    pDelay = microsNow;
  
    potValue = analogRead(pot_Pin);
    
    // Map the delay time from the potentiometer
    // from "minimumDelay" to "zero-cross delta time"
    // Unit: µseconds
    rawFireDelay = map(potValue, 1023, 0, minimumDelay, dT_ZC_INT);

    // Low Pass filtering of raw values
    delayValAvg = delayValAvg * smoothFactor + rawFireDelay * (1-smoothFactor);
  }

  // Firing L1 SCR if trig'd
  if ( L1_ZC_Trg && (microsNow - pL1_ZC) >= (int)delayValAvg ) {
    L1_ZC_Trg = 0; // Disable bit for L1 Trigger
  
    PORTD |= B00010000; // Set pin 4 to 1
    delayMicroseconds(SCR_Pulse_Width);
    PORTD &= B11101111; // Set pin 4 to 0
  }
}

// ISR for Phase L1
void L1_ZC () {
  L1_ZC_Trg = 1;                    // Enable bit for L1 Trigger
  dT_ZC_INT = microsNow - pL1_ZC;   // Calculate current zero cross delta time
  pL1_ZC = microsNow;               // Set previous zero cross to "now"
}

Variables used by ISRs and other functions should be volatile. Your ISR uses microsNow, L1_ZC_Trg, dT_ZC_INT, and pL1_ZC. Only L1_ZC_Trg is volatile.

Make them all volatile, and see if the problem persists.

Hmm. Tried that but it didnt fix the issue. It might have improved it slightly tho.

Any other suggestions?

Any other suggestions?

Often in critical timing situations, You can see jitter from the effect of the Timer0 overflow interrupt used for micros()/millis(). You need to disable the Timer0 interrupts, to test this out.

Unfortunately your program is using micros(), but I'm not sure it needs to do so. The potentiometer readings do not need to be on a timer, and if you have fixed frequency for your AC , you do not need to record the actual time since the last zero cross interrupt, but can use the timing of the wave frequency.

I’ll check those things out, but I quite dont understand what you mean. Isnt Timer0 used by micros/millis and if I disable it…?

Why is it unfortunate that my program is using micros? I figured when the half period of the AC is 10ms the resolution would be too low with millis?

Unfortunately the frequency isnt fixed as I’m using the system on marine generators and hence the frequency will droop as the load increases.

I’ll check those things out, but I quite dont understand what you mean. Isnt Timer0 used by micros/millis and if I disable it…?

That’s the problem. If you disable Timer 0 you cant use the standard millis() or micros() in the sketch. Take a look at the AC phase control examples which shows how to get the scr trigger delay using a hardware timer. https://playground.arduino.cc/Main/ACPhaseControl

The lack of a fixed frequency is a different problem? Doesn’t the generator have independent speed control to help maintain the frequency under varying load?

Flicker may not be due to the Timer 0 interrupt, but if you want to do a quick test to see if it is, then you will have to work with an assumed fixed frequency.

If you are deriving zero-crossing points from the 50-Hz /60-Hz line frequency, then place 0.1 uF (104) capacitor to the input of the ZCD (zero-crossing detector).

cattledog:
That's the problem. If you disable Timer 0 you cant use the standard millis() or micros() in the sketch. Take a look at the AC phase control examples which shows how to get the scr trigger delay using a hardware timer. Arduino Playground - ACPhaseControl

Flicker may not be due to the Timer 0 interrupt, but if you want to do a quick test to see if it is, then you will have to work with an assumed fixed frequency.

Alright, I'll do a test with fixed frequency "on shore" and report back later.

cattledog:
The lack of a fixed frequency is a different problem? Doesn't the generator have independent speed control to help maintain the frequency under varying load?

That's how most generator systems works (except those running with isosynchronous speed control). When the load increases they reduce their speed governor, if they dont they'll "fight" eachother (when in parallell) and hence the frequency will droop in a non-stiff AC-grid such as in island operation/ships. Connected to the "global" AC-grid there is "infinite" amount of inertia making the grid so stiff that the frequency wont droop.

GolamMostafa:
If you are deriving zero-crossing points from the 50-Hz /60-Hz line frequency, then place 0.1 uF (104) capacitor to the input of the ZCD (zero-crossing detector).

What's the reason behind this?

My schematic by the way: https://i.imgur.com/jZiDAca.jpg