По прошествии достаточного количества лет существования замечательного сайта avrproject.ru мной было сделано предложение о расширении его наполнения альтернативными проектами на микроконтроллерах фирм-конкурентов. В частности, в данной статье пойдет речь о применении МК всем известной фирмы Microchip, ну, то есть, как вы уже догадались – PIC контроллерах. Многие true-old программисты начинали свои проекты именно с них, переходя с контроллеров 51 серии, и по своей популярности они ничуть не уступают нашим любимым Atmel’ам. Некоторое время назад мной были куплены по дешевке десяток самых мелких и простых контроллеров PIC10F200 в шестиногом SOT23-6, и периодически туда-сюда я их использовал.
Поскольку мне, в свое изучавшему в альма-матер язык программирования ПЛ/1, Ассемблер, Бейсик и Паскаль, вводя данные на перфокартах, так и не удалось заставить окостеневший разум привыкнуть к синтаксису линейки языков Си, для изучения возможностей Atmel пришлось освоить Bascom, то, соответственно, был произведен выбор в пользу бейсиков и для пикушек. Совершенно случайно я наткнулся на пакет программ от одного физика-теоретика, и это был не Стивен Хокинг и не Шелдон Купер. Итак, знакомьтесь: Владимир Сосо (Vladimir Soso) и его комплекс программных продуктов Oshonsoft. Предлагаемые им среды разработки (IDE) лично мне понравились своим единым интерфейсом, встроенным эмулятором, логическим «осциллографом», и, самое главное, генерацией ассемблерного листинга. Все программы платные с возможностью 30-ти пробных запусков.
В качестве примера давайте рассмотрим сенсорный регулятор освещенности (диммер) на напряжение 220 Вольт. Подвигнуть меня на изготовление данного устройства побудили следующие обстоятельства:
- достаточно частые перегорания ламп;
- отсутствия у домашних чувства «уходя, гаси свет;
- покупка нового светильника без встроенного выключателя;
- наличие необходимых запчастей и собственно готового устройства от Eddy71 – я думаю, многие его знают как разработчика ряда хороших устройств.
Спаянная плата с запрограммированным контроллером показала свою работоспособность согласно заявленному алгоритму, который мне по итогу не подошел – отсутствовал таймер выключения. Исходники отсутствовали, и было принято решение написать свой алгоритм. В процессе написания программы и ее отладки были внесены незначительные изменения в итоговую схему, которая представлена ниже
Принцип работы диммера всем известен, но повторение – мать учения:
Каждую полуволну сети 50 Гц, то есть 100 Гц – 0,01 сек. (10 миллисекунд) микроконтроллер отсчитывает временной интервал времени для включения симистора – реализуется фазовое управление симистором. Т.е. регулируется мощность, подаваемая на лампу накаливания, и, тем самым, излучаемая яркость. Одновременно идет подсчет времени для работы таймера. В случае светодиодных или люминесцентных ламп яркость регулировать не получится – надо замкнуть перемычку на плате – тогда данное устройство работает просто как таймер.
Диммер различает продолжительность касания и защиту от кратковременных помех. При кратковременном касании сенсора (от 0,1 до 0,5 сек) происходит включение лампы. Контроллер обеспечивает плавное зажигание лампы накаливания, тем самым обеспечивая более долговременную ее работу. Касание сенсора длительностью от 0,5 до 1,5 сек. выключает лампу.
В случае применения ламп накаливания по истечении запрограммированного времени яркость лампы снижается, экономя тем самым электроэнергию, и в дальнейшем тухнет окончательно.
Текст программы с построчными комментариями:
Symbol mode_in = GP3 'ножка определяет принцип работы - лампа накаливания или нет
Symbol gate_out = GP0 'выход на симистор
Symbol zero_input = GP1 'вход детектора нуля
'Symbol sens_input = GP2 - вход сенсора, подключенный к транзистору
'Переменные:
Dim zero_cross As Byte 'переменная для детектирования нуля
Dim touch_on As Byte 'длительность касания
Dim touch_off As Byte 'длительность отпускания сенсора
Dim power_on As Byte 'время включения симистора
Dim power_off As Byte 'время выключения симистора
Dim min_power As Byte 'минимальная мощность
Dim counter_decisecond As Byte 'счетчик сотых долей секунд
Dim counter_second As Byte 'счетчик секунд
Dim counter_minute As Byte ' счетчик минут
Dim timer_volume As Byte 'текущее значение таймера микроконтроллера
Const edge_zero = 15 'длительность детектирования нуля
Const gate_on_time = 20 'длительность включения симистора
Const max_count = 75 'максимальное значение цикла подпрограммы
Const count_cycle = 70 'значение таймера, при котором происходит отсчет времени
Const touch_first = 38 'значение таймера, при котором происходит опрос сенсора
Const touch_second = 40 'значение, при котором происходит анализ длительности касания сенсора
'начало программы
TRISIO = %1110 'устанавливаем ножку 1 как выход на ножку симистора
OPTION_REG = %11010110
'Prescaler Rate 1:128 => 1 000 000 : 100 : 128 = Max count TMR0 = 78
gate_out = 0 'гасим симистор
' выбор режима работы
' если ножка mode_in заземлена, то диммер не используется
min_power = 1
If mode_in = 1 Then min_power = 50 'значение минимальной мощности лампы
' старт программы
start:
' детектор перехода с 0 на 1
zero_cross = edge_zero
While zero_cross > 0
If zero_input = 1 Then zero_cross = zero_cross - 1
Wend
Call work_mode() ' вызов подпрограммы
'детектор перехода с 1 на 0
zero_cross = edge_zero
While zero_cross > 0
If zero_input = 0 Then zero_cross = zero_cross - 1
Wend
Call work_mode() ' вызов подпрограммы
Goto start ' возврат на старт программы
End ' конец программы
'тело подпрограммы
Proc work_mode()
TMR0 = 0 'обнуляем таймер микроконтроллера (МК)
timer_volume = 0 'и буферную переменную, куда данное значение копируется
While timer_volume < max_count 'пока значение таймера меньше макс. значения, выполняем цикл
While timer_volume = TMR0 'ждем, когда значение таймера изменится
Wend
timer_volume = TMR0 'присваиваем буферной переменной значение таймера МК
' Проверяем, включен ли свет, если да, то назначаем время выключения симистора
If power_on = 0 Then
power_off = 0
Else
power_off = power_on + 5
Endif
' конец данного условия
' Формируем импульс для симистора
If power_on < timer_volume And timer_volume < power_off Then
High gate_out
WaitUs gate_on_time
Low gate_out
Endif
' конец данного условия
' в зависимости от значения буферной переменной, выполняем разные действия
Select Case timer_volume
' Измеряем длительность касания/отпускания сенсора
Case touch_first 'count length touch to on: 0.2-1s, to off > 1s
zero_cross = GPIO And %00000110
If zero_cross = %00000010 Then touch_on = touch_on + 1
If zero_cross = %00000110 Then touch_off = touch_off + 1
' конец данного условия
' В зависимости от длительности касания/отпускания сенсора, включаем/выключаем лампу
Case touch_second
If touch_off > 20 Then
If touch_on > 50 And touch_on < 151 Then
power_on = 0
Endif
If touch_on > 10 And touch_on < 51 Then
power_on = min_power
Endif
touch_off = 0
touch_on = 0
Endif
' конец данного условия
' В данном случае считаем количество импульсов для таймера
Case count_cycle 'count second & minute
If power_on = 0 Then
counter_decisecond = 0
counter_second = 0
counter_minute = 0
Else
counter_decisecond = counter_decisecond + 1
If counter_decisecond = 250 Then
counter_second = counter_second + 1 '2.5 second
counter_decisecond = 0
If counter_second = 6 Then '15 second - тестовый вариант
'If counter_second = 240 Then '10 minute - рабочий вариант
counter_minute = counter_minute + 1
counter_second = 0
Endif
Endif
If counter_minute > 3 Then power_on = min_power
If counter_minute > 5 Then power_on = 0
Endif
' Плавное зажигание лампы накаливания
If power_on > 1 And counter_minute = 0 Then power_on = power_on - 1
' конец данного условия
Case Else
EndSelect
Wend
' возврат в начало подпрограммы и ожидание следующего значения таймера МК
End Proc
' конец подпрограммы и возврат в основной цикл
Ниже приведен универсальный (работа как с PIC10F200, так и с Attiny13) и усовершенствованный вариант платы диммера - добавлены помехоподавляющие элементы: RC цепочка (3*1,2 кОм и 0,1*275V) и дроссель 220 мкГн. Включение возможно как по трехпроводной схеме – основная разводка, так и по двухпроводной вместо обычного выключателя – добавлено место под перемычку. Данные элементы выделены красным цветом. Размер платы и расположение элементов выбирались исходя из корпуса – верхней части блока питания от старой Nokia, малогабаритный трансформатор от которой ушел на другие проекты. В качестве сенсора используется советский транзистор КТ605 с никелированной крышечкой – получилось достаточно эстетично. Плата выполнена на одной стороне, прикручена 3 шурупчиками к существующим стойкам и корпус в сборе посажен на двухсторонний скотч. Тиристор припаян к плате и вокруг него напаяно несколько ребер из жести для охлаждения. Видимое на фотографии отверстие служит для конвекции воздуха.
ВАЖНО: не забываем про работу с 220 Вольт. Диммер чувствителен к включению в розетку – при неправильной фазировке просто переверните вилку.
Перевести данный алгоритм в Bascom для Attiny13 не составит труда – главное правильно настроить порты и таймер, но эту задачу я оставлю желающим.
Пример настройки таймера на частоту 1,2 МГц приведен ниже.
TCCR0A = %00000000
TCCR0B = %00000011
OCR0B = 187
'Prescaler Rate 1:64 => 1 200 000 : 100 : 64 = Max count TMR0 = 187
'WDTCR = %00000100 'Prescaler Rate 1:32K = 0.25 sec
автор: Pchela5