ATtiny85 AC Phase Control для регулировки яркости лампочки
Я пытаюсь затемнить лампочку через ATtiny85, который принимает команды, отправленные по I2C. Моя проблема в том, что лампочка едва тускнеет и довольно сильно мерцает.
Мою схему можно увидеть здесь:
Оптоизолятор (и, следовательно, симистор) управляется через контакт 2 (AKA PB3, AKA PCINT3), а обнаружение перехода через ноль переменного тока осуществляется через контакт 3 (AKA PB4, AKA PCINT4) на ATtiny85.
В коде используется разрешение прерывания изменения контакта, а не одно разрешение внешнего прерывания, поскольку контактом внешнего прерывания является контакт 7 (он же PB2), который используется в качестве SCL для связи I2C.
Используется внутренняя тактовая частота 8 МГц, а прескалер таймера/счетчика равен 1024, что означает, что у меня эффективный входной диапазон (см. переменную level
в коде) примерно от 0 до 65. Мой источник переменного тока — США (60 Гц).
#include <avr/interrupt.h>
#include <avr/io.h>
#include <TinyWireS.h>
#define PULSE 4 // ширина импульса запуска (отсчетов)
#define I2C_SLAVE_ADDR 0x4 // 7-битный адрес (не забудьте изменить его при адаптации этого примера)
byte trigger = 3;
byte detector = 4;
byte level = 50;
byte maxLevel = 65;
byte minLevel = 0;
void setup() {
TinyWireS.begin(I2C_SLAVE_ADDR); // присоединяемся к сети i2c
TinyWireS.onRequest(requestEvent); //настраиваем реквестер i2c
digitalWrite(detector, HIGH); //включаем подтягивающий резистор
pinMode(trigger, OUTPUT);//Устанавливаем вывод нагрузки переменного тока в качестве выхода
TCCR1 = 0; //остановим таймер
OCR1A = level; //инициализируем компаратор
TIMSK = _BV(OCIE1A) | _BV(TOIE1); //прерывание при сравнении совпадения A и включение прерывания переполнения таймера
GIMSK = 0b00100000; //Включаем прерывание смены контакта
PCMSK = 0b00010000; //PB4, физический контакт 3 PCINT4
TCCR1 = B00001011; //Предварительно масштабируем таймер
sei(); // Включаем прерывания
}
ISR(PCINT0_vect) {
//прерываем поиск пересечения нуля
TCNT1 = 0; //сбрасываем таймер - отсчитываем с нуля
OCR1A = level;
TCCR1 = B00001011;// прескалер на 1024, см. таблицу 12-5 таблицы данных tiny85
}
ISR(TIMER1_COMPA_vect) {
//соответствие компаратора
digitalWrite(trigger,HIGH); //устанавливаем высокий уровень симисторного вентиля
TCNT1 = 255-PULSE;
// ширина импульса запуска на несколько циклов для фиксации симистора. 255 г. до н. э. счетчик может считать только до 255.
}
ISR(TIMER1_OVF_vect) {
//переполнение таймера1
digitalWrite(trigger, LOW); //выключаем симистор
TCCR1 = 0; //отключаем таймер, останавливаем непреднамеренные триггеры
}
void loop() {}
void requestEvent() {
if (TinyWireS.available()) {
level = TinyWireS.receive();
if (level > maxLevel) {
level = maxLevel;
else if (level < minLevel){
level = minLevel;
}
}
TinyWireS.send(OCR1A);
}
Я пробовал разные лампы (лампы накаливания и светодиоды с регулируемой яркостью), но ни одна не работала лучше другой.
Вот видео, показывающее обнаружение пересечения нуля (желтый) и триггер ATtiny85 (синий) на осциллографе, когда я отправляю на него различные уровни затемнения Плохое видео с телефона
Я подумал о демпфере, просто у меня сейчас нет под рукой запчастей. Я думаю, что это поможет, но не думаю, что это исправит мою большую проблему.
Буду признателен всем и за любую помощь. Спасибо.
(Примечание: я также разместил это здесь. Приносим извинения, если кросспостинг не одобряется).
@thread9000, 👍0
Обсуждение1 ответ
Лучший ответ:
Поэтому я думаю, что было (было?) две проблемы.
1) Прерывания по изменению вывода на Attiny85 срабатывают по нарастающим и падающим фронтам, что, как я думаю, и вызывает мерцание.
Я изменил код, чтобы он срабатывал только по переднему фронту:
ISR(PCINT0_vect){ //прерывание в поисках пересечения нуля
if (digitalRead(4) == HIGH){
TCNT1 = 0; //сброс таймера - отсчет с нуля
OCR1A = level;
TCCR1 = B00001011;// предделитель на 1024, см. таблицу 12-5 в техническом описании tiny85
}
}
2) Attiny85 #reset pin. Подтянул этого парня резистором.
В любом случае, вот видео с осциллографом и светодиодом с регулировкой яркости: youtube
Кроме того, я перешел на BTB08-600BWRG для симистора, который помогает с индуктивностью (пока у меня пять (эквивалент 65 Вт) светодиодных лампочек работают отлично). (Заметьте, это на самом деле ничего не сделало для решения исходной проблемы), @thread9000
- Прерывать каждую секунду на ATTiny84 (и спать все остальное)
- Attiny85 Таймер 1 компаратор B не работает должным образом (в то время как A работает)
- Как указать имя таймера в зависимости от чипа, в который он будет компилироваться?
- Использование millis() и micros() внутри процедуры прерывания
- Получение BPM из данного кода
- Программа arduino выдаёт ошибку expected //primary-expression before ')' token error: //expected ';' before '}' token E
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Использование TIMER0_COMPB_vect
Умеете ли вы выключать лампочку? Возможно, сигнал необходимо инвертировать. Схема симистора мне кажется очень простой, но я не особо люблю симисторы., @Gerben
Отправка максимального уровня отключает его... Но я не знаю, действительно ли он делает это так, как я хочу. Хм, что значит, что сигнал нужно инвертировать? Меня вдохновило [это](http://playground.arduino.cc/Main/ACPhaseControl), @thread9000
Я имел в виду нормально высокий сигнал с коротким НИЗКИМ импульсом. Итак, синий след перевернут. Но я здесь только предполагаю., @Gerben
Вы уверены насчет "47к" "R1" к оптотриаку? Ток триггера составляет «15 мА» для «MOC3021», а у вас меньше «0,1 мА» (с источником питания «5 В»)., @KIIV
Это 0,47К. Плохое качество изображения. И использование 330 Ом ничего не исправляет., @thread9000
@thread9000, ну, это должно быть около 220R на 5В. Лучше померить., @KIIV
Спасибо @KIIV, но результат все равно не меняется. Есть еще мысли?, @thread9000
На самом деле это вопрос электроники, а не Arduino, тем более, что вы настраиваете оборудование ATtiny напрямую, а не используете структуру Arduino в более чем тривиальном смысле. Ситуацию с демпфером действительно нельзя игнорировать. В конечном итоге вам нужно увидеть поведение симистора, но попытка измерить его с помощью осциллографа сопряжена со слишком многими опасными ошибками, чтобы рекомендовать их. Вы уверены, что вам нужно построить это самостоятельно? Это можно сделать, но с этим нельзя играть, если вы действительно не понимаете, что происходит и как это сделать безопасно., @Chris Stratton
@Gerben, похоже, схема управляет анодом оптосимисторного устройства, поэтому для включения симистора будет активный высокий импульс. Типичный диммер, подобный этому, обеспечивает ШИМ за счет задержки на некоторое время после перехода через ноль перед включением симистора, который затем будет оставаться включенным (независимо от входного сигнала), пока не отключится при следующем пересечении нуля., @Chris Stratton
Привет @ChrisStratton. Причина, по которой я публикую это здесь, заключалась в проверке моего кода, который в значительной степени использует API Arduino. Любая помощь и проверка электрооборудования являются бонусом, поэтому я ценю ваш вклад. Сейчас жду поставки симистора со встроенным демпфером. Я согласен, было бы неплохо увидеть выход симистора. Я свяжусь с инженером-электриком, с которым работаю., @thread9000