Одно- и двух- канальный диммер.

Эти устройства разрабатывалось для управления лампами освещения по сети RS-485 в составе системы «Умный дом». В устройствах реализован «мягкий старт» (для обычных ламп накаливания) и быстрое включение (для управления энергосберегающими лампами). Время включения и выключения в режиме «мягкого старта» фиксировано, и от нудя до полной яркости, составляет 2 сек.

Схема электрическая принципиальная.

Устройства собраны на микроконтроллере ATtiny2313. Тактируется он от внешнего кварцевого резонатора частотой 14,7456 МГц. Частота выбрана исходя из наименьшего процента ошибки при работе USART на различных скоростях.

Для подключения к сети RS-485 используется драйвер DA5, подключенный к выводам USART микроконтроллера. Управляется драйвер с ножки 6 микроконтроллера, настроенного по умолчанию как выход с низким уровнем, переключающий драйвер сети на прием данных.

Для определения момента перехода сетевого напряжения через 0, используется детектор нуля, собранный на транзисторах VT1, VT2 и описанный здесь. Нагрузкой детектора нуля служит оптопара DA1, выполняющая роль опторазвязки микроконтроллера от напряжения сети. Выход оптопары подключен к ножке 7 микроконтроллера, которая является входом внешнего прерывания INT1.

Управление нагрузкой осуществляется тиристорами VS1, VS2 через оптопары DA2, DA3. Для управления яркостью ламп и для «мягкого старта» эти оптопары должны быть без встроенного детектора перехода через ноль.

Элементы VD4, R17, C9 служат для формирования сигнала сброса микроконтроллера, при включении напряжения питания.

Напряжение питания +12В подается на устройства по сетевому кабелю, через разъем XS1. Питается устройство от встроенного стабилизатора напряжения +5В, собранного на микросхеме DA4.

Описание программы микроконтроллера.

Протокол работы сходен с описным здесь, с небольшими изменениями. Данные устройства поддерживают две команды, команду передачи данных от устройства к ведущему контроллеру – RD (h3C) и команду записи данных от ведущего контроллера в устройства – WD (h3E).

При запросе на передачу данных ведущий контроллер посылает запрос в общем виде:

Адреса устройств определяются в файле define.inc, контрольная сумма в ведущем контроллере должна вычисляться программно, при формировании запроса. Контрольная сумма при приеме данных вычисляется программно, табличным методом. Подпрограмма вычисления контрольной суммы находится в файле subr.inc (метка Wire_CRC8), а таблица для расчета контрольной суммы находится в файле tables.inc.

После получения данной команды устройства передают в шину данные состояния внутренних регистров. Для обмена по сети, в области RAM микроконтроллера, определен буфер обмена. Длинна буфера различается для одноканальных и двухканальных димеров:

Addr_data – адрес ведомого контроллера (h01);

Type_data – тип димера (hD2 – для двухканального и hD1 – для одноканального димера);

Mng_Dim1 – байт заданной яркости канала 1;

Dim1_data – байт текущей яркости канала 1;

Mng_Dim2 – байт заданной яркости канала 2 (только для двухканального димера);

Dim2_data – байт текущей яркости канала 2 (только для двухканального димера);

Ask_data – байт подтверждения приема;

CRC_data – байт контрольной суммы.

Поскольку USART микроконтроллеров работает в режиме мультипроцессорного обмена и передает 9 байт данных, в начале посылки передается адрес ведущего контроллера. Тип димера нужен для определения ведомым контроллером общей длинны посылки (для одноканального димера – 6 байтов, для двухканального – 8 байтов). Заданная яркость в каналах записывается при приеме данных от ведущего контроллера, об этом будет сказано ниже. Текущая яркость каналов может отличатся от заданной при работе режима «мягкий старт». Байт подтверждения показывает, правильно ли была принята предыдущая команда от ведущего контроллера. Если данные были приняты без ошибок, байт подтверждения будет равен h21 ("!"), при ошибках в приеме байт подтверждения будет равен h3F?»). Контрольная сумма вычисляется для всех байтов посылки в подпрограмме Calc_CRC8_RAM которая находится в файле subr.inc.

Для управления яркостью каналов димеров ведущий контроллер передает в шину команду записи данных. Если нужно, зажечь лампы канала 1 на 50% яркости, а лампы канала 2 на 30% яркости (для двухканального димера), посылка будет выглядеть следующим образом:

* только для двухканального димера

Кроме того, димеры поддерживают команду пропуска регулировки яркости канала IGN (hFF). Этой командой удобно пользоваться, если нужно изменить яркость только одного канала в двухканальном димере. То есть команда h0B h3E hFF h1E hBD – изменит яркость только второго канала, при этом яркость первого останется неизменной.

Регулировка яркости каналов, «мягкий старт», быстрое включение \ выключение.

В димерах предусмотрена регулировка яркости каналов в 100 градаций с шагом в 1%. Для регулировки яркости каналов используется фазо-импульсное управление нагрузкой синхронизированным ШИМ. Как это работает…

Управление яркостью ламп в каналах осуществляется временем открывания симистора после перехода напряжения через ноль.

В микроконтроллере ATtiny2313 есть замечательный 16-ти разрядный таймер–счетчик, позволяющий с высокой точностью формировать временные интервалы и имеющий два независимых модуля совпадения с прерываниями OCF1A и OCF1B. Их и будем использовать для отсчета времени открывания симисторов.

Синхронизируется таймер по срабатыванию детектора перехода через ноль. Детектор вырабатывает импульс при каждом переходе напряжения сети через 0, вызывая обработчик прерывание INT1. В обработчике прерывания сбрасывается счетный регистр таймера, и однозначно выключаются оба канала.

За 1 сек, прерывание INT1 будет вызвано 100 раз. Время между прерываниями Т=1/100=0,01 сек. При выбранной частоте кварцевого резонатора 14,7456 МГц и делителе таймера-счетчика = 8, за 0,01 сек, таймер отсчитает 14745600/8/100=18432 такта (переменная TFull в файле define.inc). Для большей надежности возьмем немного большее значение и занесем его в регистры совпадения OCR1A и OCR1B. Пока эти значения неизменны, таймер не успеет досчитать до момента совпадения, и будет сброшен при обработке прерывания INT1 от детектора нуля. Если значение в регистрах OCR1A или OCR1B уменьшить, то совпадение значений в счетном регистре TCNT1 и регистре совпадения произойдет до окончания полупериода напряжения. При этом в регистре TIFR будет установлен соответствующий флаг (OCF1A или OCF1B) и произойдет вызов обработчика прерывания. В этом обработчике нужно просто включить соответствующий канал. Таким образом, можно регулировать яркость ламп в обоих каналах. Для изменения яркости на 1% нужно уменьшить или увеличить значение в счетном регистре на 18432/100=184 (переменная TNul в файле define.inc).

Таким образом, если значение в регистре совпадения = 184 – лампы канала будут гореть с максимальной яркостью, при значении 184*50=9200 лампы канала будут гореть с яркостью 50%, а при значении 18432 лампы канала полностью выключатся.

Для защиты ламп накаливания во время включения/выключения в программе предусмотрена функция «мягкого старта». При включении ламп канала, значение от 0% (18432) до заданного уровня происходит не сразу, а с плавным нарастанием яркости. Время включения ламп на полную яркость выбрано равным 2 секунды. То есть, от 0% до 100% яркости лампа включится за 2 секунды, от 0% до 50% яркости за 1 секунду, и от 0% до 75% за 1,5 секунды.

За 2 секунды прерывание от детектора нуля будет вызвано 2*100=200 раз, то есть если при обработке прерывания INT1 увеличивать яркость на 0,5% (уменьшая значение в регистрах совпадения) то ровно через 2 секунды яркость ламп изменится от 0% до максимальной. Но, чтобы не заниматься обработкой чисел с запятой, можно изменять яркость ламп (значение в регистрах совпадения) каждый второй полупериод. Для этого введен дополнительный регистр – счетчик тактов step_count. В режиме изменения яркости, значение этого регистра увеличивается при вызове прерывания INT1. Если значение регистра равно времени полного переключения (2), значение в регистрах совпадения OCF1A или OCF1B изменяется, а сам регистр – счетчик сбрасывается. Это удобно еще и тем, что время полного включения можно легко изменить, не внося изменений в программу, достаточно изменить только значение переменной TSwitch в файле define.inc. Замечу, что плавная регулировка яркости происходит как при включении, так и при выключении ламп в каналах.

Для управления энергосберегающими лампами этот режим не приемлем, поэтому предусмотрена возможность быстрого включения/выключения ламп в каналах. При этом для включения ламп в регистры совпадения OCF1A или OCF1B сразу заносится значение максимальной яркости (184), а для выключения значение = 18432.

На уровне управления по сети это происходит достаточно просто. Для плавного изменения яркости в регистры заданной яркости Mng_Dim1 или Mng_Dim2 заносится число от 0% (h00) до 100% (h32). Для быстрого включения заносится любое значение большее 100% (например h40). При этом помните, что значение hFF – это зарезервированная команда пропуска изменения яркости IGN. Программа корректирует значение, записываемое в регистры совпадения OCF1A и OCF1B на уровне 100%.

Кроме того, при изменении яркости, программа корректирует значение регистров состояния яркости каналов Dim1_data и Dim2_data, которые находятся в буфере приема-передачи. Таким образом, можно в любое время отслеживать состояние каналов димера.

Программная реализация.

При инициализации периферии микроконтроллера в файле init.inc, в оба канала совпадения записывается значение переменной TFull, для выключения ламп каналов, и разрешаются прерывания по совпадению в каналах А и В.

; === Таймер 1 ===================================================================

; Таймер используется для отсчета времени включения симисторов

out16 OCR1A,TFull ; записываем начальные установки времени

out16 OCR1B,TFull ; в оба канала ТС1

sbrp TIMSK,(3<<OCIE1B) ; разрешаем прерывания по совпадению каналов А и В

Также настраивается срабатывание внешнего прерывания INT1 по спаду.

; === Инициализация внешних прерываний ==================================================

sbrp MCUCR,(1<<ISC11) ; прерывания INT1 (ZCD) по спаду

Перед запуском главного цикла в файле Dimmer.asm разрешается срабатывание этого прерывания и запускается таймер–счетчик 1 с предделителем = 8.

rcall Calc_CRC8_RAM ; исправляем CRC

sbrp GIMSK,(1<<INT1) ; разрешаем прерывание INT1

outi TCCR1B,(1<<CS11) ; запускаем ТС1 с предделителем 8

sei ; разрешаем прерывания глобально

Далее программа переходит в бесконечный замкнутый цикл. Все процедуры регулировки производятся в прерываниях.

При срабатывании детектора нуля происходит вызов прерывания Detect_zero. В нем, прежде всего, сбрасывается счетный регистр таймера 1 и выключаются оба канала ламп.

clr16 TCNT1 ; сбросить ТС1

OffChen ; выключить оба канала

Далее увеличивается значение регистра – счетчик тактов step_count и проверяется его переполнение. Если значение регистра не равно времени полного переключения (TSwitch), программа выходит из обработчика прерывания, не выполняя никаких действий. Если данные в регистре совпадает с перемен-ной TSwitch, счетчик обновляется и происходит обработка каналов.

inc step_count ; увеличить счетчик

cpi step_count,TSwitch ; если переполнение

breq PC+2 ; продолжить

rjmp Exit_DZ ; иначе - выйти

clr step_count ; сбросить счетчик

При обработке канала в первую очередь происходит сравнение заданной яркости (Mng_Dim1) с текущей (Dim1_data).

Если яркость обоих ячеек равна (нет задания на изменение яркости) программа переходит к проверке канала 2 (для двухканального диммера) или к выходу из прерывания (для одноканального димера). Если заданная яркость больше текущей, программа переходит по метке MinusLum1. Если заданная яркость меньше текущей, программа продолжает работу по метке PlusLum1.

lds temp1,Mng_Dim1 ; читаем из RAM заданную и

lds temp2,Dim1_data ; текущую яркость канала 1

cp temp1,temp2 ; сравниваем

breq Check_Chen_2 ; если равны - перейти к проверке канала 2

brlo MinusLum1 ; если больше – перейти

; иначе

PlusLum1: ; увеличиваем значение яркости

В следующей процедуре происходит увеличение яркости ламп канала. Прежде всего, проверяется, в каком режиме работает канал. Если заданная яркость больше 100% (управление энергосберегающими лампами), в ячейку текущей яркости Dim1_data переписывается значение заданной яркости, а в регистр совпадения таймера заносится значение максимальной яркости ламп, после чего происходит переход к проверке канала 2 (для двухканального димера) или к выходу из прерывания (для одноканального димера). Если заданная яркость меньше или равна 100% (режим «мягкий старт») программа переходит по метке PL1.

PlusLum1:

cpi temp1,101 ; если заданная яркость меньше или равна 100

brlo PL1 ; перейти дальше

; иначе

sts Dim1_data,temp1 ; корректировать текущую яркость

out16 OCR1A,TNul ;

rjmp Check_Chen_2 ; перейти к проверке канала 2

В этой процедуре происходит увеличение текущей яркости канала на 1%. В 16- ти разрядный регистр Z копируются данные регистра совпадения OCR1A, затем вычитается значение 184 (TStep) и данные переписываются обратно в регистр совпадения. После чего увеличивается значение текущей яркости и записывается в ячейку Dim1_data.

PL1:

in ZL,OCR1AL ; читаем настоящую яркость канала в регистр Z

in ZH,OCR1AH ;

subi ZL,TStep ; вычитаем из данных один шаг яркости

sbci ZH,0 ;

out OCR1AH,ZH ; переписываем обратно

out OCR1AL,ZL ; в счетчик

inc temp2 ; увеличиваем значение текущей яркости

sts Dim1_data,temp2 ; записываем в RAM

rjmp Check_Chen_2 ; перейти к проверке канала 2

Если заданная яркость больше текущей, программа переходит к уменьшению яркости по метке MinusLum1. В этой процедуре происходит уменьшение яркости ламп канала. Прежде всего, проверяется, в каком режиме работает канал.

MinusLum1: ; уменьшаем значение яркости

cpi temp2,101 ; если текущая яркость меньше 101

brlo ML12 ; перейти

tst temp1 ; заданная яркость = 0?

brne ML11 ; нет - перейти

sts Dim1_data,temp1 ; корректировать текущую яркость

out16 OCR1A,TFull ; время = 0%

rjmp Check_Chen_2 ; выйти

Если текущая яркость больше 100% (управление энергосберегающими лампами), проверяется значение заданной яркости, и если она равна 0% (команда на выключение ламп канала) программа записывает в ячейку текущей яркости значение h00, а в регистры совпадения таймера 1 значение 18432 (TFull).

Если текущая яркость меньше 100% (режим «мягкий старт»), программа переходит к увеличению яркости по метке ML12. В этой части программы происходит уменьшение текущей яркости канала на 1%. В 16- ти разрядный регистр Z копируются данные регистра совпадения OCR1A, затем к нему прибавляется значение 184 (TStep) и данные переписываются обратно в регистр совпадения. После чего уменьшается значение текущей яркости и записывается в ячейку Dim1_data.

ML12:

in ZL,OCR1AL ; читаем настоящую яркость канала в регистр Z

in ZH,OCR1AH ;

subi ZL,-TStep ; прибавляем один шаг яркости

sbci ZH,-1 ;

out OCR1AH,ZH ; переписываем обратно

out OCR1AL,ZL ; в счетчик

dec temp2 ; уменьшаем значение настоящей яркости

sts Dim1_data,temp2 ; записываем в RAM

Если текущая яркость больше 100% (управление энергосберегающими лампами), а заданная яр-кость больше нуля (команда на плавное уменьшение яркости) программа переходит по метке ML11, где происходит корректировка значения текущей яркости до 100%, после чего по метке ML12 яркость плавно уменьшается.

ML11:

ldi temp1,100 ; корректировать текущую яркость *

Корректировка значения текущей яркости необходима, так как она связана со значением в регистре совпадения. Димер принимает любое значение заданной яркости (Mng_Dim1) от 101(h65) до 254 (hFE) как команду на быстрое включение ламп канала, и сохраняет его в ячейке текущей яркости Dim1_data. При уменьшении яркости начинает увеличивать значение в регистре совпадения, и соответственно уменьшать значение ячейки Dim1_data. Если не скорректировать это значение, произойдет глюк вселенских масштабов…

При выходе из обработчика прерывания по метке Exit_DZ программа сбрасывает флаги и разрешает прерывания при совпадении каналов А и В таймера 1.

Exit_DZ: ; выход

sbrp TIFR,(3<<OCF1B) ; сбрасываем флаги

sbrp TIMSK,(3<<OCIE1B) ; разрешаем прерывания по совпадению каналов А и В

reti ; выходим

При совпадении значения счетного регистра TCNT1 со значением, записанным в регистре OCR1A, устанавливается флаг OCF1A, и вызывается обработчик прерывания Timer1A_Ok. В этом обработчике включается выход управления каналом 1 и запрещается срабатывание прерывания по совпадению этого канала. То есть лампа канала включается, и горит до момента перехода напряжения через 0, и вызова прерывания Detect_zero.

Timer1A_Ok: ; обработка включения канала 1

OnChen2 ; включаем канал 1

cbrp TIMSK,(1<<OCIE1A) ; запретить прерывание канала А

reti ; выходим

Печатная плата.

Печатная плата разрабатывалась только для двухканального димера. Для сборки одноканального варианта нужно собрать только один канал управления. На печатной плате не установлены светодиоды, они нужны были только при проектировании и отладке.

Все файлы проекта находятся в одном архиве.

В папке Dimmer_1Ch находится исходник программы одноканального димера и .hex файл прошивки.

В папке Dimmer_2Ch находится исходник программы двухканального димера и .hex файл прошивки.

В папке Proteus Failes находится проект в Proteus.

Печатная плата в формате .lay.

Схема в формате .spl7.

Кроме того в файле алгоритм.vsd находится блок-схема описанного выше процесса регулировки яркости ламп. Этот файл создан в программе MS Visio.