NerdKits - electronics education for a digital generation

You are not logged in. [log in]

Library > Switch 115v AC using ATtiny85 and Triac


This was first implemented on the Nerdkits ATmega168 but it seemed way overpowered since only a couple pins were to be used. The ATtiny85 is a much better match for the application. The plan is to use the ATtiny85 to switch on a 115v air pump five seconds after the power comes back on. I wanted to do this to prevent the pump motor cycling until the power became stable. The pump runs 24 x 7 unless there is a power outage so there is no need to do anything more once the triac is turned on.

The software is pretty simple, start a timer and after five seconds turn on the triac. Removing unused libraries from the compile and link results in a program that is 182 bytes in size which easily fits on any of the ATtiny's. You will need an ISP programmer to load the ATtiny85. If you don't already have one you may want to try the one I use, the Nerdkit ISP Programmer. This is the command I use to compile the program.

avr-gcc -g -Os -fno-jump-tables -Wall -mmcu=attiny85 -mcall-prologues \
        Triac_Delay_Start.c -o Triac_Delay_Start.o 

The ATtiny85 comes from the factory with fuses set for the internal 1mhz clock. In this program, the timer is set up for an 8mhz clock so don't forget to change the factory default fuse settings for an 8mhz clock. The fuse values I used are: LOW 0xE2, HIGH 0xDF, EXT 0xFF.

The circuit side is a bit more challenging. Although not much current is needed, the ATtiny85 must be powered from the line voltage. I'm using a capacitive transformerless AC to DC power supply with a 447 ohm resistor and .5 uf capacitor. The ATtiny, optoisolator, and TRIAC draws at most about 7.5 ma but the power supply can provide about 11 ma according to the calculator (bottom of the web page on transformerless power supplies) so there is a little room for expansion. Maybe a temperature sensor could be used without exceeding the power available.

schematic

//
// Triac_Delay_Start.c for Tiny85
//
// v1.0 - Use triac to switch on circuit after short delay on reset
//

#include <avr/io.h> 
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// preprocessor macros for port/pin manulipulation
//
#define INPUT2(port,pin) DDR ## port &= ~_BV(pin) 
#define OUTPUT2(port,pin) DDR ## port |= _BV(pin) 
#define CLEAR2(port,pin) PORT ## port &= ~_BV(pin) 
#define SET2(port,pin) PORT ## port |= _BV(pin) 
#define TOGGLE2(port,pin) PORT ## port ^= _BV(pin) 
#define READ2(port,pin) ((PIN ## port & _BV(pin))?1:0)
//
#define INPUT(x) INPUT2(x) 
#define OUTPUT(x) OUTPUT2(x)
#define CLEAR(x) CLEAR2(x)
#define SET(x) SET2(x)
#define TOGGLE(x) TOGGLE2(x)
#define READ(x) READ2(x)
#define PULLUP_ON(x) INPUT2(x); SET2(x)
#define PULLUP_OFF(x) INPUT2(x); CLEAR2(x)

// define ports, pins
#define UNUSED_B0       B,0
#define UNUSED_B1       B,1
#define UNUSED_B2       B,2
#define UNUSED_B3       B,3
#define TRIAC_CONTROL   B,4
#define UNUSED_B5       B,5

volatile uint16_t time;
volatile uint16_t ms;

// --------------------------------------------------------------------------------------------------------
int main() {
    // set unused pins to known state
    PULLUP_ON(UNUSED_B0);
    PULLUP_ON(UNUSED_B1);
    PULLUP_ON(UNUSED_B2);
    PULLUP_ON(UNUSED_B3);
    PULLUP_ON(UNUSED_B5);

    // setup I/O pins
    SET(TRIAC_CONTROL);
    OUTPUT(TRIAC_CONTROL);

    // setup timer for interrupts
    #define Timer1_div_32       6
    TCCR1 = Timer1_div_32;      // 8mhz clock / 32 gives 250000 tics/sec 
    OCR1A = 250;                // match 1ms
    TIMSK = _BV(OCIE1A);        // interrupt on OCR0A match

    // enable interrupts
    sei();

    // initialize variables
    time=0;     // total time in ms

    // run
    while(true){
        if(time>=5000){
            // turn on the triac
            TCCR1=0;                // disable timer
            CLEAR(TRIAC_CONTROL);   // pull to GND to turn on triac
            while(true);            // we're done, stick here forever
        }
    }
}

// handle timer interrupt
ISR(TIMER1_COMPA_vect, ISR_NOBLOCK){
    time++;
}

Last edited by Noter on 07/07/2011 at 4:51 p.m. PDT
Did you know that many systems in nature can be described by a first order response? Learn more...