Прерывания ATTiny13

alvor
Offline
Зарегистрирован: 16.10.2014

Здравствуйте друзья!

Пытаюсь собрать диммер на ATTiny13.

Схема рабочая, к контроллеру кроме питания слева ничего не подключено, но мигает как попало:

Затык в программе для МК. Вот код, я уже его упростил до предела, он сейчас ничего не делает, только генерит прерывание и сигнал включения-выключения симистора.  

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

/////////////////////////////////////////////////////
#define ControlSimistor PB4 //выход на симистор
#define AnalogPin PB2  //вход аналогового сигнала
#define ControlZero PB3 //вход контроля перехода через 0
#define steps 5 // количество шагов в 100%, разрядность, ступенчатость
volatile byte Power = 80; //начальное значение мощности в % (можно не задавать)
volatile byte AnalogInput = 0;
 
ISR(PCINT0_vect) // прерывание по вектору PCINT0(ножка РВ0), тоесть по изменению состояния вывода
{
  zero(); // что-то делаем когда меняется состояние порта
}
 
void InitPCINT3() // Инициализация прерываний
{
//  MCUCR =_BV(ISC01) | _BV(ISC00);
  GIMSK = _BV(PCIE);
  PCMSK = _BV(PCINT3);
  sei();
}
 
void setup() {
  InitPCINT3(); // инициалиируем прерывание
  pinMode(ControlZero,INPUT);
  pinMode(ControlSimistor,OUTPUT);
  AnalogInput = 128; 
}
 
void zero() //если словили переход через 0
{
 // int dimtime = (75*AnalogInput);      
  int Zero=LOW;
  Zero=digitalRead(ControlZero);
  if (Zero=HIGH){
 // delayMicroseconds(dimtime);    // Off cycle
  digitalWrite(ControlSimistor, HIGH);   // triac firing
  delayMicroseconds(20);         // triac On propogation delay
  digitalWrite(ControlSimistor, LOW);    // triac Off
   }
}
void loop()
{
 // delay(10);
  //AnalogInput = analogRead(AnalogPin);
  //здесь меняем Power согласно каким то установкам и выполняем другие задачи

  
}

На осцилограмме видна собственно проблема. Детектор нуля работает.

А вот прерывание вызывается не всегда, иногда иногда один, а иногда два раза на одной детекции нуля.

детектор нуля бирюзовый, управление симистором желтый:

А иногда несколько циклов оно не вызывается вообще. (тут поменял щупы, детектор нуля желтый) 

На проверку высокий-низкий уровень у ноги PB3 на которой детектится ноль нет реакции от слова совсем. "if" можно закомментировать, это никак не повлияет на работу программы. Такой мелкий контроллер пытаюсь программировать впервые. Подскажите куда курить?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

alvor, как выдумаете, в каком случае в строке   if (Zero=HIGH){  38Zero будет не HIGH?

alvor
Offline
Зарегистрирован: 16.10.2014

dimax пишет:

alvor, как выдумаете, в каком случае в строке   if (Zero=HIGH){  38Zero будет не HIGH?

Эта строка ничего не меняет. Если её убрать всё тоже самое происходит.

Прерывания на ногах PB1-PB5 согласно даташиту вызываются по любому изменению уровня. Этим я пытался отбросить вариант изменения с  HIGH на LOW.

alvor
Offline
Зарегистрирован: 16.10.2014

dimax пишет:

alvor, как выдумаете, в каком случае в строке   if (Zero=HIGH){  38Zero будет не HIGH?

Грех над убогими смеятся )) 

nik182
Offline
Зарегистрирован: 04.05.2015

Попробуй в 35 строке вставить пустой цикл for с волотильной переменной где то до 100 итераций. Будешь удивлён результатом. Либо 37 строку раз 20 прочитай и используй только последний результат. 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

alvor пишет:

dimax пишет:
alvor, как выдумаете, в каком случае в строке   if (Zero=HIGH){  Zero будет не HIGH?

Эта строка ничего не меняет. Если её убрать всё тоже самое происходит.

Конечно ничего не меняет, потому что результать операции присвоения

Zero=HIGH

Всегда TRUE. Если вы хотите делать проверку, то надо писать

 

if (Zero==HIGH){

 

alvor
Offline
Зарегистрирован: 16.10.2014

Не ловит стабильно прерывание, уже на насколько раз код переписал. Сейчас выглядит вот так. Сигнал на входе PB3 просто шикарный. Чёткий пик 5 вольт. А прерывания ловит через раз по непонятному принципу. Притом переход 0->1 ловит в несколько раз чаще чем 1->0 (Если выключить проверку стр 31) В целом сигналы точно такие-же как на картинках в топике.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
/////////////////////////////////////////////////////
#define ControlSimistor PB4 //выход на симистор
#define AnalogPin PB2  //вход аналогового сигнала
#define ControlZero PB3 //вход контроля перехода через 0
volatile int ZeroFound; //начальное значение мощности в % (можно не задавать)
int AnalogInput = 0;

ISR(PCINT0_vect) // прерывание по вектору PCINT0(ножка РВ0), тоесть по изменению состояния вывода
{
  zero(); // что-то делаем когда меняется состояние порта
}

void InitPCINT3() // Инициализация прерываний
{
  GIMSK |= (1<<PCIE);
  PCMSK |= (1<<PB3);
  SREG |= (1<<SREG_I);
}

void setup() {
  InitPCINT3(); // инициалиируем прерывание
  pinMode(ControlZero, INPUT);
  pinMode(ControlSimistor, OUTPUT);
 }

void zero() //если словили переход через 0
{
  if (digitalRead(PB3)==HIGH)
  ZeroFound = 1;
}

void loop()
{
  if (ZeroFound == 1) {
    digitalWrite(ControlSimistor, HIGH);   // triac firing
    delayMicroseconds(20);         // triac On propogation delay
    digitalWrite(ControlSimistor, LOW);    // triac Off
    ZeroFound = 0;
  }
}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

alvor, ну видимо что-то аппаратное. Посмотрите осциллом что на питании творится во время работы. И кстати, ресет у вас в воздухе висит что ли?

alvor
Offline
Зарегистрирован: 16.10.2014

dimax пишет:

alvor, ну видимо что-то аппаратное. Посмотрите осциллом что на питании творится во время работы. И кстати, ресет у вас в воздухе висит что ли?

Да, висит в воздухе.... Но он же подтянут внутри, не? На нём осцилом 5В видно.

alvor
Offline
Зарегистрирован: 16.10.2014

Подтянул, ничего не изменилось. ATtiny13-ки разные пробовал...

Заодно все остальные ноги подтянул. Тоже безрезультатно.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

alvor, Применять PCINT в данном случае не стоит из-за дребезга. Для начала перекиньте вход на INT0 (PB1) и загрузите нормальный скетч. Убедитесь что фузы выставлены без делителей частоты, т.е. на 9МГц.

// PB4 выход на симистор
// PB1 вход контроля перехода через 0

void setup() {
DDRB=1<<4;
MCUCR|=(1<<ISC00) | (1<<ISC01); //The rising edge of INT0 generates an interrupt request.
GIMSK=1<<INT0;
}


ISR(INT0_vect){
    PORTB|=1<<4;  
    delayMicroseconds(20);   
    PORTB&=~(1<<4);  
}
 void loop(){}

С этим скетчем точно должно работать правильно. Если глюки продолжаются, то разбирайтесь, с пайкой, с питанием итп итд.

 

alvor
Offline
Зарегистрирован: 16.10.2014

Частоты пробовал все, бп тоже три разных, заведомо рабочих. Чипы разные из разных партий. INT0, да ещё не пробовал. Попробую. Кондюки ещё попробую завтра на питание разные.

Просто так симистор нагрузкой управляет, лампочка накаливания даже "регулируется", только процентов а 50 тусклее чем надо за счет пропусков прерывания. Но у меня мощный светодиод в нагрузке должен работать, а он совсем плохо работает. Ну вернее на полностью включеном периоде, мигает с частотой ~10 Гц, аж звенит. Пропуски идут волнами, вот так и плавают на эти ~10 Гц.

SergeiL
SergeiL аватар
Offline
Зарегистрирован: 05.11.2018

Если не принципиально, то несколько двухканальных диммеров  работают по  i2C подключенные к ESP8266 на AtTiny25.

Описал все здесь.

Ванная и туалет с галогенками, так как более естественный свет :-) .

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

Попробуйте объявить ZeroFound как byte:

volatile byte ZeroFound;