Dimmer flickering

I have a dimmer circuit (ACPhaseControl) running a heater, and when testing with a 60W incadescent light bulb, I get a flicker at most any phase angle. This is probably not an issue for a heater, but I would like to know the reason, and suspect it is in code or the low voltage circuit.

I attached two files showing the drop out of a half cycle, which I suspect is causing the flicker:
Triac_InOut.bmp shows the gate (blue) and load/MT1 (yellow) of the triac;
MOC_InOut shows the gate (blue) of the triac and pin 1 of the MOC triac driver (yellow), which is the turn-on signal from the Arduino after the 220 ohm resistor.

I connected my scope to look at the zero-cross signal to the Arduino, and the MOC digial out to MOC pin 1, and am not able to capture any loss of the Arduino out (even though I can capture as shown in the attachments). I have seen that in the past though, just cannot capture.

My guess is that the MOC is not getting a signal from the Arduino during this drop out. I assume that is due to something in the code. timer interrupt is not working, etc.

If any one has any ideas on why the code would not be sending a steady MOC pin 1 signal, or recommendations for troubleshooting, please advise.

Schematic is attached.
Here is the code:

//Incubator Control
//by Ted Hardwicke
//2016
//temperature sensing, egg turning motor control, heater control, display control


//Libraries
  #include <PID_v1.h>
  #include <avr/io.h>
  #include <avr/interrupt.h>
  #include "DHT.h"
  #include <LiquidCrystal.h>


// Pin assignments

  #define DETECT 2  //zero cross detect
  #define GATE 3    //triac gate
  #define motorPin 4    //Motor on/off    
  #define DHTPIN 5    //DHT sensor input
  #define dayIncrement 6    //DHT sensor input

  #define dEnable 8    //Display enable
  #define dRs 9    //Display register S  
  #define dB7 10    //Display B7
  #define dB6 11    //Display B6  
  #define dB5 12    //Display B5
  #define dB4 13    //Display B4
  
// Specify the LCD
LiquidCrystal lcd(dRs, dEnable, dB4, dB5, dB6, dB7);


// Specify for testing inputs
  #define TEST_INPUT A0  //for test input
  int triacPot = 0;

// Specify MOC/triac pulse and counts in a 1/2 cycle of 60hz for mapping
  int phaseLow = 500;
  int phaseHigh = 40;
  #define PULSE 4

// Specify timing
  unsigned long dayCount =  300000;       // 19 days in milliseconds  =19*24*60*60*1000   1641600000
  unsigned long motorTime = 0; // initialize with 0; the time when the motor was turned on or off
  unsigned long timeOn = 15000; // however long the motor should be on */;
  unsigned long timeOnError =  30000;
  unsigned long timeOff = 60000;// however long the motor should be off */;
  unsigned long timeOffError = 30000;
  unsigned long measureTime = 0; // initialize with 0; the time when the last measurement was made
  unsigned long displayTime = 0; // initialize with 0; the time when the display was last refreshed
  bool motorRunning = false; // start with the motor off
  bool motorError = false; 
  bool heaterError = false; 

// Initialize DHT sensor.
  #define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
  DHT dht(DHTPIN, DHTTYPE);
  float h;
  float t;
  float f;
  
//Specify the PID
  double Setpoint, Input, Output;
  double Kp=18, Ki=1, Kd=1;
  PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


void setup(){

  Serial.begin(9600);

  lcd.begin(20, 4);
  lcd.clear();
  dht.begin();
  
  pinMode(TEST_INPUT, INPUT);   //test purposes potentiometer
  pinMode(DHTPIN, INPUT);   //DHT sensor input
  pinMode(DETECT, INPUT);     //zero cross detect   INPUT_PULLUP
  pinMode(GATE, OUTPUT);      //triac gate control
  pinMode(motorPin, OUTPUT);   //motor control

  
  pinMode(dEnable, OUTPUT);   //display
  pinMode(dRs, OUTPUT);   //display
  pinMode(dB7, OUTPUT);   //display
  pinMode(dB6, OUTPUT);   //display
  pinMode(dB5, OUTPUT);   //display
  pinMode(dB4, OUTPUT);   //display


// set up Timer1    ATMEGA 328 data sheet pg 134)
  OCR1A = 100;      //initialize the comparator
  TIMSK1 = 0x03;    //enable comparator A and overflow interrupts
  TCCR1A = 0x00;    //timer control registers set for
  TCCR1B = 0x00;    //normal operation, timer disabled

// set up zero crossing interrupt
  attachInterrupt(0,zeroCrossingInterrupt, RISING);  //IRQ0 is pin 2. Call on rising signal


//Set up the PID loop
  //initialize the variables we're linked to
    Input = 70;
    Setpoint =100;    // 99 to 101 F is recommended range
    myPID.SetMode(AUTOMATIC);
    
}  

//Interrupt Service Routines

void zeroCrossingInterrupt(){ //zero cross detect   
  TCCR1B=0x04; //start timer with divide by 256 input
  TCNT1 = 0;   //reset timer - count from zero     TCNT1 is the Timer/counter Register for timer 1
}

ISR(TIMER1_COMPA_vect){ //comparator match
  digitalWrite(GATE,HIGH);  //set triac gate to high
  TCNT1 = 65536-PULSE;      //trigger pulse width
}

ISR(TIMER1_OVF_vect){ //timer1 overflow
  digitalWrite(GATE,LOW); //turn off triac gate
  TCCR1B = 0x00;          //disable timer stopd unintended triggers
}

void loop(){

// manage the egg turner
  unsigned long now = millis();
  
    if (millis() <= dayCount)  
    {
      if(motorRunning)
      {
        // The motor is running. 
        // Is it time to turn it off?        
        if(now - motorTime >= timeOn)
        {
          digitalWrite(motorPin, LOW);   // turn off motor
          motorTime = now;
          motorRunning = false;
        }

      }
      else
      {
         // The motor is not running. 
         // Is it time to turn it on?
        if(now - motorTime >= timeOff)
         {
            digitalWrite(motorPin, HIGH);   // turn on motor
            motorTime = now;
            motorRunning = true;
        }
      }
    }


// Reading temperature or humidity takes about 250 milliseconds!
    if(now - measureTime >= 500)
    {
      // It is time to measure temperature
        h = dht.readHumidity();
        //t = dht.readTemperature();
        f = dht.readTemperature(true);  //(isFahrenheit = true)
        // Check if any reads failed and exit early (to try again).
        if (isnan(h) || isnan(t) || isnan(f)) {
          Serial.println("Failed to read from DHT sensor!");
          return;
        }
        measureTime = now;
    }

  Input = f;

  myPID.Compute();

  triacPot = analogRead(TEST_INPUT);

  OCR1A = map(triacPot,0,1023, phaseLow, phaseHigh); //map(Output,0,255, phaseLow, phaseHigh);   //set the compare register brightness desired.

//Send info to LCD display
    if(now - displayTime >= 1000)
      {
//      lcd.clear();
      //Day count
      lcd.setCursor(0, 0);
      lcd.print("Day: ");
      lcd.print("  ");   //print 2 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(5, 0);      //go back to the start of the number  
      lcd.print(millis() / 120000);    //86400000
     
      //temperature
      lcd.setCursor(0, 1);
      lcd.print("Temp: ");
      lcd.print("         ");   //print 9 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(6, 1);      //go back to the start of the number  
      lcd.print(f);
      lcd.print(" ");
      lcd.print((char)223);
      lcd.print("F");    //   \t

      //humidity
      lcd.setCursor(0, 2);
      lcd.print("Hum: ");
      lcd.print("        ");   //print 8 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(5, 2);      //go back to the start of the number  
      lcd.print(h);
      lcd.print(" %");
    
      //humidity/temperature warning
      //lcd.setCursor(0, 0);
    
      //heater percent on
      lcd.setCursor(10, 0);
      lcd.print("Heat: ");
      lcd.print("   ");   //print 3 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(16, 0);      //go back to the start of the number  
      lcd.print(OCR1A); //-phaseLow/(phaseHigh-phaseLow));  OCR1A
      Serial.println(triacPot);
    
      //Motor on/off
      lcd.setCursor(0, 3);
      if(motorRunning)
         {
         lcd.print("Motor: On ");
         }
         else
         {
         lcd.print("Motor: Off");  
         }
      displayTime = now;
      }

}

Schematic20170204.pdf (128 KB)

moc_InOut.pdf (14.4 KB)

triac_InOut.pdf (16.1 KB)

Moving forward in my project. I replaced the breadboard with a custom circuit card.

Still have the flicker.

Went through and turned off all controls but dimmer. no flicker.
Turned on other controls one by one.

The DHT sensor function is causing the flicker. No doubt about it. Not sure why. Will read further into the DHT library.

If anyone knows of any conflicts between the DHT library I am using and external interrupts or other function of turning on pin 3 which drives a triac, (assuming the problem is in one of these areas) please let me know.

Here is my code.

//Incubator Control
//by Ted Hardwicke
//2016
//temperature sensing, egg turning motor control, heater control, display control


//Libraries
  #include <PID_v1.h>
  #include <avr/io.h>
  #include <avr/interrupt.h>
  #include "DHT.h"
  #include <LiquidCrystal.h>


// Pin assignments

  #define DETECT 2  //zero cross detect
  #define GATE 3    //triac gate
  #define motorPin 4    //Motor on/off    
  #define DHTPIN 5    //DHT sensor input
  #define dayIncrement 6    //DHT sensor input

  #define dRs 8    //Display register S  
  #define dEnable 9    //Display enable
  #define dB4 10    //Display B7
  #define dB5 11    //Display B6  
  #define dB6 12    //Display B5
  #define dB7 13    //Display B4
  
// Specify the LCD
LiquidCrystal lcd(dRs, dEnable, dB4, dB5, dB6, dB7);


// Specify for testing inputs
  #define TEST_INPUT A0  //for test input
  int triacPot = 0;    // initialize to an off condition, test only

// Specify MOC/triac pulse and counts in a 1/2 cycle of 60hz for mapping
  int phaseLow = 500;
  int phaseHigh = 40;
  #define PULSE 4

// Specify timing
  unsigned long turnDays = 420000;       // 19 days in milliseconds  =19*24*60*60*1000   1641600000
  unsigned long dayCount =  0;
  unsigned long oneDay = 108000;    //86400000
  unsigned long motorTime = 0; // initialize with 0; the time when the motor was turned on or off
  unsigned long timeOn = 3000; // however long the motor should be on */;   15000
  unsigned long timeOnError =  30000;
  unsigned long timeOff = 6000;// however long the motor should be off */;  3585000
  unsigned long timeOffError = 30000;
  unsigned long measureTime = 0; // initialize with 0; the time when the last measurement was made
  unsigned long displayTime = 0; // initialize with 0; the time when the display was last refreshed
  unsigned long testTime = 0;
  bool motorRunning = false; // start with the motor off
  bool motorError = false; 
  bool heaterError = false; 
  bool DHTerror = false;

// Initialize DHT sensor.
  #define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
  DHT dht(DHTPIN, DHTTYPE);
  float h;
  float t;
  float f;
  
//Specify the PID
  double Setpoint, Input, Output;
  double Kp=18, Ki=1, Kd=1;
  PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


void setup(){

  Serial.begin(9600);

  lcd.begin(20, 4);
  lcd.clear();
  dht.begin();
  
  pinMode(TEST_INPUT, INPUT);   //test purposes potentiometer
  pinMode(DHTPIN, INPUT);   //DHT sensor input
  pinMode(DETECT, INPUT);     //zero cross detect   INPUT_PULLUP
  pinMode(GATE, OUTPUT);      //triac gate control
  pinMode(motorPin, OUTPUT);   //motor control

  
  pinMode(dEnable, OUTPUT);   //display
  pinMode(dRs, OUTPUT);   //display
  pinMode(dB7, OUTPUT);   //display
  pinMode(dB6, OUTPUT);   //display
  pinMode(dB5, OUTPUT);   //display
  pinMode(dB4, OUTPUT);   //display


// set up Timer1    ATMEGA 328 data sheet pg 134)
  OCR1A = 510;      //initialize the comparator to an off/low condition
  TIMSK1 = 0x03;    //enable comparator A and overflow interrupts
  TCCR1A = 0x00;    //timer control registers set for
  TCCR1B = 0x00;    //normal operation, timer disabled

// set up zero crossing interrupt
  attachInterrupt(digitalPinToInterrupt(DETECT),zeroCrossingInterrupt, RISING);  //IRQ0 is pin 2. Call on rising signal


//Set up the PID loop
  //initialize the variables we're linked to
    Input = 70;
    Setpoint =100;    // 99 to 101 F is recommended range
    myPID.SetMode(AUTOMATIC);
    
}  

//Interrupt Service Routines

void zeroCrossingInterrupt(){ //zero cross detect   
  TCCR1B=0x04; //start timer with divide by 256 input
  TCNT1 = 0;   //reset timer - count from zero     TCNT1 is the Timer/counter Register for timer 1
}

ISR(TIMER1_COMPA_vect){ //comparator match
  digitalWrite(GATE,HIGH);  //set triac gate to high
  TCNT1 = 65536-PULSE;      //trigger pulse width
}

ISR(TIMER1_OVF_vect){ //timer1 overflow
  digitalWrite(GATE,LOW); //turn off triac gate
  TCCR1B = 0x00;          //disable timer stopd unintended triggers
}

void loop(){

// manage the egg turner
  unsigned long now = millis();

    dayCount = millis() / oneDay;
  
    if (millis() <= turnDays || motorRunning ==true)  //enter this block only if time is less than 19 days or the motor is running 
    {
      if(motorRunning)
      {
        // The motor is running. 
        // Is it time to turn it off?        
        if(now - motorTime >= timeOn)
        {
          digitalWrite(motorPin, LOW);   // turn off motor
          motorTime = now;
          motorRunning = false;
        }

      }
      else
      {
         // The motor is not running. 
         // Is it time to turn it on?
        if(now - motorTime >= timeOff)
         {
            digitalWrite(motorPin, HIGH);   // turn on motor
            motorTime = now;
            motorRunning = true;
        }
      }
    }


// Reading temperature or humidity takes about 250 milliseconds!
    if(now - measureTime >= 500)
    {
      // It is time to measure temperature
        h = dht.readHumidity();
        //t = dht.readTemperature();
        f = dht.readTemperature(true);  //(isFahrenheit = true)
        // Check if any reads failed and exit early (to try again).
        if (isnan(h) || isnan(t) || isnan(f)) {
          DHTerror = true; 
          //Serial.println("Failed to read from DHT sensor!");
          return;
        }
        measureTime = now;
    }

  Input = f;

  myPID.Compute();

 if(now - testTime >= 20000)    ///-------------------------------------------
    {
        triacPot =  triacPot + 100;   //  analogRead(TEST_INPUT);
        if(OCR1A > 499)
        {
          triacPot = 0;
        }
        OCR1A = map(triacPot,0,1023, phaseLow, phaseHigh); //map(Output,0,255, phaseLow, phaseHigh);   //set the compare register brightness desired.
        testTime = now;
    }





//Send info to LCD display
    if(now - displayTime >= 1000)
      {
//      lcd.clear();
      //Day count
      lcd.setCursor(0, 0);
      lcd.print("Day: ");
      lcd.print("  ");   //print 2 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(5, 0);      //go back to the start of the number  
      lcd.print(dayCount);
     
      //temperature
      lcd.setCursor(0, 1);
      lcd.print("Temp: ");
      lcd.print("         ");   //print 9 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(6, 1);      //go back to the start of the number  
      lcd.print(f);
      lcd.print(" ");
      lcd.print((char)223);
      lcd.print("F");    //   \t

      //humidity
      lcd.setCursor(0, 2);
      lcd.print("Hum: ");
      lcd.print("        ");   //print 8 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(5, 2);      //go back to the start of the number  
      lcd.print(h);
      lcd.print(" %");
    
      //humidity/temperature warning
      //lcd.setCursor(0, 0);
    
      //heater percent on
      lcd.setCursor(10, 0);
      lcd.print("Heat: ");
      lcd.print("    ");   //print 3 blanks in case the number changes from 3 to 2 digits
      lcd.setCursor(16, 0);      //go back to the start of the number  
      lcd.print(OCR1A); //-phaseLow/(phaseHigh-phaseLow));  OCR1A
      //Serial.println(triacPot);
    
      //Motor on/off
      lcd.setCursor(0, 3);
      if(motorRunning)
         {
         lcd.print("Motor: On ");
         }
         else
         {
         lcd.print("Motor: Off");  
         }

      //Display Millis()
      lcd.setCursor(11, 3);
      lcd.print(millis());
      
         
      displayTime = now;
      }

}

The DHT sensor function is causing the flicker. No doubt about it. Not sure why. Will read further into the DHT library. If anyone knows of any conflicts between the DHT library I am using and external interrupts or other function of turning on pin 3 which drives a triac, (assuming the problem is in one of these areas) please let me know.

There is a period of time of several milliseconds where interrupts are disabled by the DHT library during a reading of the sensor.

There is a period of time of several milliseconds where interrupts are disabled by the DHT library during a reading of the sensor.

Any ideas on work-arounds?

I could pole the DHT sensor fewer times.

There is a very simple DHT11 library which does not disable the interrupts.