Диммеры – это простые электронные устройства, которые используются для управления уровнем яркости освещения или интенсивностью подачи напряжения на нагрузку. Многие домовладельцы устанавливают диммеры для управления освещением, экономии на счетах за электричество или в качестве дополнительной функции своей системы умного дома.
Диммеры сегодня широко представлены на рынке, но стоимость некоторых может быть не для всех приемлемой. Впрочем, это несложное устройство можно сделать и самому, при этом для данной цели потребуется не так много компонентов, и все они будут недорогими.
Данный проект диммера основан на микроконтроллере ATtiny13, который очень компактен и стоит дешево. Управление диммером осуществляется с помощью трех кнопок: для повышения, понижения и включения/выключения нагрузки. Также имеются 8 светодиодов для индикации процента мощности.
Микроконтроллер сохраняет значения в EEPROM для восстановления значений после сброса. Из-за малого количества выводов ATtiny13 светодиоды подключаются с помощью сдвигового регистра 74HC164. Эта модель не имеет буферного регистра, поэтому для управления ей нужны два контакта. на один вывод меньше, чем у популярного 74HC595.
Обратите внимание, этот модуль не изолирован от сети. Он должен содержаться в подходящем пластиковом корпусе.
Схемы диммера на основе микроконтроллера ATtiny представлены далее.
Код программы диммера состоит из нескольких файлов. Main.c:
#define KEY_DN 0
#define KEY_UP 1
#define KEY_SET 2
#define KEY_NO 3
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include "aux_source.h"
#include "shiftreg.h"
uint8_t dim_data;
bool deviceOn = true;
const uint16_t Dimmers[8] = { 0, 253, 369, 468, 531, 631, 850, 1000 };
int main()
{
init_IO();
dim_data = eeprom_read_byte(0);
if (dim_data > 7) dim_data = 7;
tsr_shiftOut((1 << (dim_data + 1)) - 1);
_delay_ms(250);
while(1)
{
uint8_t key = ReadKeys();
if (deviceOn)
{
if (key != KEY_NO && key != KEY_SET)
{
if (key == KEY_DN)
{
if (dim_data > 0) dim_data--;
}
else if (key == KEY_UP)
{
if (dim_data < 7) dim_data++;
}
tsr_shiftOut((1 << (dim_data + 1)) - 1);
eeprom_write_byte(0, dim_data);
_delay_ms(100);
}
}
if (key == KEY_SET)
{
deviceOn = !deviceOn;
if (deviceOn) tsr_shiftOut((1 << (dim_data + 1)) - 1);
else tsr_shiftOut(0);
_delay_ms(800);
}
}
}
void sup_delay(uint16_t del)
{
while (del--)
{
_delay_us(10);
}
}
ISR(INT0_vect)
{
if (deviceOn)
{
if (dim_data != 7)
{
sup_delay(Dimmers[dim_data]);
PORTB |= (1 << PORTB0);
_delay_us(30);
PORTB &= ~(1 << PORTB0);
}
else
{
PORTB |= (1 << PORTB0);
_delay_us(30);
PORTB &= ~(1 << PORTB0);
}
}
}
Файл инициализации периферии:
#include "aux_source.h"
void init_IO()
{
DDRB = (1 << DDB0) | (1 << DDB3) | (1 << DDB4);
PORTB |= (1 << PORTB2);
ADMUX = (1 << ADLAR) | 1;
DIDR0 = (1 << ADC1D);
ADCSRA = (1 << ADEN) | (1 << ADSC) | 5;
while (!(ADCSRA & (1 << ADIF))) ;
ADCSRA |= (1 << ADIF);
MCUCR = 1;
GIMSK = (1 << INT0);
sei();
}
uint8_t ReadKeys()
{
ADCSRA |= (1 << ADSC);
while (!(ADCSRA & (1 << ADIF))) ;
ADCSRA |= (1 << ADIF);
return ((ADCH * 3 + 80) / 256) ;
}
Библиотека сдвигового регистра:
#include "shiftReg.h"
uint8_t tsr_buff[DAT_SZ_BYTE] = { 0 };
void tsr_initIO(void)
{
CLK_DAT_LATCH_OUT_INIT;
CLK_OUT_LO;
DAT_OUT_LO;
LATCH_OUT_LO;
}
void tsr_shiftBuffer(void)
{
uint8_t j = 0;
while (j < DAT_SZ_BYTE)
{
tsr_shiftOut(tsr_buff[j]);
j++;
}
}
void tsr_shiftOut(uint8_t tsr_var)
{
uint8_t i = 0b10000000;
LATCH_OUT_LO;
while (i != 0)
{
if (tsr_var & i) DAT_OUT_HI;
else DAT_OUT_LO;
CLK_DELAY;
CLK_OUT_HI;
CLK_DELAY;
CLK_OUT_LO;
CLK_DELAY;
i = i >> 1;
}
}
void tsr_latchOut(void)
{
LATCH_OUT_HI;
}
void sr_setBit(uint32_t srBuffBit, bool srBuffVal)
{
uint8_t q = srBuffBit/8;
uint8_t r = srBuffBit%8;
if(srBuffVal) tsr_buff[q] |= (1<<r);
else tsr_buff[q] &=~(1<<r);
}
Заголовочный файл библиотеки сдвигового регистра:
#ifndef __SHIFTREG_H__
#define __SHIFTREG_H__
#include <avr/io.h>
#include <util/delay.h>
#define CLK_DAT_LATCH_OUT_INIT DDRB |= (1 << DDB3) | (1 << DDB4)
#define CLK_OUT_HI PORTB |= (1<<PORTB3)
#define CLK_OUT_LO PORTB &=~(1<<PORTB3)
#define CLK_OUT_TOG PINB |= (1<<PINB3)
#define DAT_OUT_HI PORTB |= (1<<PORTB4)
#define DAT_OUT_LO PORTB &=~(1<<PORTB4)
#define LATCH_OUT_HI
#define LATCH_OUT_LO
#define DAT_SZ_BYTE 1
#define CLK_DELAY
#define DAT_SZ_BYTE 1
extern uint8_t tsr_buff[DAT_SZ_BYTE];
void tsr_initIO(void);
void tsr_shiftOut(uint8_t tsr_var);
void tsr_latchOut(void);
void tsr_setBit(uint32_t srBuffBit, bool srBuffVal);
void tsr_shiftBuffer(void);
#endif
Заголовочный файл инициализации периферии:
#pragma once
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "shiftreg.h"
void init_IO();
uint8_t ReadKeys();