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)