Go Down

Topic: Voltage controlled dimmer with an ATtiny85 (Read 3105 times) previous topic - next topic

ArthurRep

Voltage controlled dimmer with an ATtiny85

I came to this project because the AC phase control as described in http://playground.arduino.cc/main/ACPhaseControl worked well in a simple sketch on an Arduino Nano, but controlling a lot of other things at the same time, the phase control produced irregular output. So I decided to use a stand alone ATtiny85 to handle the dimming and feed it with an analog signal from the Nano. Nevertheless, read this article to understand what you are doing!

I assembled the following circuit:



I used the BTB08-600BW because is has a built-in snubber filter for inductive loads. It can pull 8 amps. I tried resistors from 33 to 68 kOhm to decrease the voltage over the LTV814, which is an optocoupler that detects zero crossings in both directions. At 33k 0.4 W is dissipated each resistor and the zero crossing spike is narrow, at 68k 0.2 W is dissipated, but the zero crossing spike is much wider, which seems to give no problem.

It took a while to convert the original code into something that works on a Tiny85 but finally this is what works:

Code: [Select]

// Voltage controlled dimmer with ATtiny85
//
// This arduino sketch includes a zero
// crossing detect function and an opto-isolated triac.
//
// AC Phase control is accomplished using the internal
// hardware timer1 in the ATtiny85
//
// Timing Sequence
// * timer is set up but disabled
// * zero crossing detected
// * timer starts counting from zero
// * comparator set to "delay to on" value
// * counter reaches comparator value
// * comparator ISR turns on triac gate
// * counter set to overflow - pulse width
// * counter reaches overflow
// * overflow ISR turns off triac gate
// * triac stops conducting at next zero cross

// The hardware timer runs at 8MHz.
// A half period of a 50Hz AC signal takes 10 ms is 80000 counts.
// Prescaler set to 1024 gives 78 counts per half period


#include <avr/io.h>
#include <avr/interrupt.h>

#define DETECT 2      //zero cross detect, interrupt 0, is physical pin 7
#define GATE 3        //triac gate is physical pin 2
#define PULSE 2       //trigger pulse width (counts)
#define INSTELPIN 2   // =A2 (digital pin4) is physical pin 3

void setup(){
  // set up pins
  pinMode(DETECT, INPUT);      //zero cross detect
  digitalWrite(DETECT, HIGH);  //enable pull-up resistor
  pinMode(GATE, OUTPUT);       //triac gate control

  // set up Timer1
  TCCR1 = 0;     // stop timer
  OCR1A = 50;    //initialize the comparator
  TIMSK = _BV(OCIE1A) | _BV(TOIE1);  //interrupt on Compare Match A | enable timer overflow interrupt
  sei();  // enable interrupts
  // set up zero crossing interrupt
  attachInterrupt(0,zeroCrossingInterrupt, FALLING);   


//Interrupt Service Routines
void zeroCrossingInterrupt(){   
  TCNT1 = 0;   //reset timer - count from zero
  TCCR1 = B00001011;        // prescaler on 1024, see table 12.5 of the tiny85 datasheet
}

ISR(TIMER1_COMPA_vect){    //comparator match
  digitalWrite(GATE,HIGH); //set triac gate to high
  TCNT1 = 255-PULSE;       //trigger pulse width, when TCNT1=255 timer1 overflows
}
 
ISR(TIMER1_OVF_vect){       //timer1 overflow
  digitalWrite(GATE,LOW);   //turn off triac gate
  TCCR1 = 0;                //disable timer stop unintended triggers
}

void loop(){     // use analog input to set the dimmer
int instelwaarde = analogRead(INSTELPIN);
OCR1A = map(instelwaarde, 0, 1023, 65, 2);
}


OCR1A sets the delay between zero crossing and firing the triac. In the sketch an analog input of 0V will cause maximum dimming. You can change this, of course.


Coding Badly


Do you have a question?

Or should this thread be moved to Exhibition?



ArthurRep

No questions left... You can move it to any place where people might enjoy my project.

Coding Badly


Declan

Looking at the circuit in the first post, is it possible to have the BTB08/600BW "remote".
By this I mean, can I feed AC Live / Neutral into the LTV814 so that the ATTiny can detect the Zero-Crossing.
Have the same AC Live fed into pin 4 of the MOC3052.
Pin 6 of the MOC3052 would then be on a header that would be wired to the Gate of the BTB08.
The AC Live would then be connected to the A2 of the BTB08 and the AC Neutral to the A1 of the BTB08.
What I want to achieve is to have a separate "switch" PCB that would have the ATTiny, LTV814 and the MOC3052. The BTB08 would then be on a heatsink that is mounted on the cabinet.

Is there an example of the final working sketch that was accomplished by ArthurRep?

mcvl

hi,
Very nice schematic and code Arthur..
I have use  it for derivating solar energy surplus to electric boiler.I have reduced attiny clock to 1mhz for lowest consumption (2-2.5ma instead 8mA).I use EL814 and two 47K resistors for zero crossing.I have included also a ZERO volt ac output (no pulse) for low input voltage.
i have reduced the input range for me to 0v_180v ac output.
find enclose code:

code:
// Voltage controlled dimmer with ATtiny85
//
// This arduino sketch includes a zero
// crossing detect function and an opto-isolated triac.
//
// AC Phase control is accomplished using the internal
// hardware timer1 in the ATtiny85
//
// Timing Sequence
// * timer is set up but disabled
// * zero crossing detected
// * timer starts counting from zero
// * comparator set to "delay to on" value
// * counter reaches comparator value
// * comparator ISR turns on triac gate
// * counter set to overflow - pulse width
// * counter reaches overflow
// * overflow ISR turns off triac gate
// * triac stops conducting at next zero cross

// The hardware timer runs at 1MHz (3mA).
// A half period of a 50Hz AC signal takes 10 ms is 10000 counts.
// @ 1MHZ (3ma)prescaler (1000) 128 78 counts per half period

#include <avr/io.h>
#include <avr/interrupt.h>

#define DETECT 2      //zero cross detect, interrupt 0, is physical pin 7
#define GATE 3        //triac gate is physical pin 2 pourrait etre 0 (pin5)
#define PULSE 2       //trigger pulse width 4 if 512 (counts)
#define INSTELPIN 2   // =A2 (digital pin4) is physical pin 3

void setup(){
  // set up pins
  pinMode(DETECT, INPUT);      //zero cross detect
  digitalWrite(DETECT, HIGH);  //enable pull-up resistor
  pinMode(GATE, OUTPUT);       //triac gate control

  // set up Timer1
  TCCR1 = 0;     // stop timer
  OCR1A = 50;    //initialize the comparator
  TIMSK = _BV(OCIE1A) | _BV(TOIE1);  //interrupt on Compare Match A | enable timer overflow interrupt
  sei();  // enable interrupts
  // set up zero crossing interrupt
  attachInterrupt(0,zeroCrossingInterrupt, FALLING);   //


//Interrupt Service Routines
void zeroCrossingInterrupt(){   
  TCNT1 = 0;   //reset timer - count from zero
  TCCR1 = B00001000;        // 1000 for 64 see table 12.5 of the tiny85 datasheet
}

ISR(TIMER1_COMPA_vect){    //comparator match
  if(OCR1A>65){            //send no pulse to triac for low input voltage for 0v output
    return;
  }
  digitalWrite(GATE,HIGH); //set triac gate to high
  TCNT1 = 255-PULSE;       //trigger pulse width, when TCNT1=255 timer1 overflows
}
 
ISR(TIMER1_OVF_vect){ //timer1 overflow
  digitalWrite(GATE,LOW);   //turn off triac gate
  TCCR1 = 0;                //disable timer stop unintended triggers
}

void loop(){     // use analog input to set the dimmer
int instelwaarde = analogRead(INSTELPIN);
OCR1A = map(instelwaarde, 0, 1023, 70, 25);// 0v to 180v (220v input)
}



thanks again

Declan

#6
Jan 18, 2016, 02:50 pm Last Edit: Jan 18, 2016, 02:58 pm by Declan
I am using the above sketch code by ArthurRep as edited by mcvl as a "soft-starter" for a heating element.
This code limits the voltage output to 180V.
How would I change the code below to get a full 220V output:
Code: [Select]
void loop(){     // use analog input to set the dimmer
int instelwaarde = analogRead(INSTELPIN);
OCR1A = map(instelwaarde, 0, 1023, 70, 25);// 0v to 180v (220v input)
}

I would also like to change the functionality from reading an Analog input so that once power is applied, the TRIAC will switch:
Code: [Select]

//int instelwaarde = 1023;  // Output is 108V
int instelwaarde = 1020;  // Output is 127V
OCR1A = map(instelwaarde, 0, 1023, 70, 25);// 0v to 180v (220v input)

What value for "int instelwaarde =" would give me a full 220V output?

What exactly is: OCR1A = map(instelwaarde, 0, 1023, 70, 25);
Where:
instelwaarde = input value
0 = ?
1023 = ?
70 = ?
25 = ?


Your assistance is greatly appreciated.

mcvl

hi,
For a soft start i suppose you increase Vin from 0v to 5v-->0 to 1023 (DAC conversion)
For 0v you need the max delay pulse :60-70 (need to be adjust because that cause flicking if you are over 10ms period)
for 5v you need the minimum delay for 220v :2
the final code is:

OCR1A = map(instelwaarde, 0, 1023, 70, 2);

regards

mcvl


another precision:

the line in my code vs arthur

  if(OCR1A>65){            //send no pulse to triac for low input voltage for 0v output
    return;
  }
is also to avoid the flicking and can be adjust up to 69  according to value of OCR1A (70 in this case)

instelwaarde=input value (0 to 1023)
regards

GPshanky

Hie;

I am bit new to this arduino family.... can anyone explain the entire code to me??

I am trying to code the same in proteus using c code. (AVRGCC)

The interrupt service routines for comparing and overflow are partially understood. I am not getting how

the following TWO code will be initiated? as a subroutine for interrupt ? and if yes then how?



void zeroCrossingInterrupt()

{   
  TCNT1 = 0;   //reset timer - count from zero
  TCCR1 = B00001011;        // prescaler on 1024, see table 12.5 of the tiny85 datasheet
}


void loop()

{     // use analog input to set the dimmer
int instelwaarde = analogRead(INSTELPIN);
OCR1A = map(instelwaarde, 0, 1023, 65, 2);
}


I have read the map function. But for AVRGCC what will be equivalent code that can be used for reading

analog input and mapping ?


Also how

attachInterrupt(0,zeroCrossingInterrupt, FALLING);

can be used in C code?


Thank you in advance.

Um-ka

#10
May 24, 2016, 06:40 am Last Edit: May 24, 2016, 06:46 am by Um-ka
{archive_file_path}(wiring.c.o): In function `__vector_4':
C:\Users\Roma\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/wiring.c:93: multiple definition of `__vector_4'
sketch_may24b.cpp.o:C:\Program Files (x86)\Arduino/sketch_may24b.ino:62: first defined here
collect2.exe: error: ld returned 1 exit status

Board - digispark.
IDE - 1.6.5

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy