ATtiny2313а странно работает

Здравствуйте. Живу в частном доме и у нас в деревне довольно часто отключают свет. Электропроводка в доме разделена на силовую и слаботочную. Силовая это чайник, электропечь и холодильники. Слаботочная питает газовый котел, насосы, а так же ТВ, освещение, сигнализацию, роутер и т.п. Она подключена к электросети через ИБП Powerman Online 1000 Plus. Так как ИБП стоит в котельной, в отдельном пристрое, а батареи позволяют ему работать несколько часов, то я не всегда даже знаю, когда отключают электричество. Поэтому решил сделать таймер пропадания электросети на ATtiny2313а с информировании об этом на обычный электронный звонок. Схема получает информацию о наличии напряжения сети с китайского вольтметра по контактам IN+,IN-, а питается 5В от ИБП. В нормальных условиях, когда есть напряжение сети, схема отключена и индикатор не светится. При пропадании сети открывается тиристор MCR100 и подается напряжение на тиньку. Она запускает таймер времени, включает индикатор и отправляет команду на модуль передатчика 433МГц, который транслирует её на звонок. У меня в комнате звонит звонок и я понимаю, что пропала электросеть.


Скетч собрал из разных источников, за основу взял Простые часы.

[code]
/*  Таймер времени при пропадании напряжения сети 
 *  на ATtiny2313 с выводом на дисплей TM1637 с отправкой по 433МГц 
 *  тестового кода  001010110011010101001010<U+202C> / BIN
 ***************************************************  
 *  ATtiny2313a PB0(pin12) == CLK TM1637
 *  ATtiny2313a PB1(pin13) == DIO TM1637
 *  ATtiny2313a PB2(pin14) == пин наличия напряжения сети(0В-сеть есть,+5В-сети нет)
 *  ATtiny2313a PB3(pin15) == идет к пину данных передатчика 
 ***************************************************   
 *   Скетч использует 1236 байт (60%) памяти устройства. Всего доступно 2048 байт.
 *   Глобальные переменные используют 77 байт (60%) динамической памяти, оставляя 51 байт для локальных переменных. Максимум: 128 байт.
 *   оставляя 84 байт для локальных переменных. Максимум: 128 байт.
 *   
 *   test-изменил код передачи
*/
// задаем параметры передатчика
const short  nPulseLength  = 350;
const short  nHighPulses_0 = (nPulseLength * 1);
const short  nLowPulses_0  = (nPulseLength * 3);

const short nHighPulses_1   = (nPulseLength * 3);
const short nLowPulses_1    = (nPulseLength * 1);
const short nLowPulses_sync = (nPulseLength * 31);
//---------------------------------------------------
#define PIN_CLK   (1<<PB0)    // вывод PB0(pin12), пин CLK TM1637
#define PIN_DIO   (1<<PB1)    // вывод PB1(pin13), пин DIO TM1637
#define PIN_IN    (1<<PB2)    // вывод PB2(pin14), пин наличия напряжения сети
#define PIN_TX    (1<<PB3)    // вывод PB3(pin15), идет к пину данных передатчика
//---------------------------------------------------
int i;                        // такт 0,1сек
byte i1;                      // такт 0,1сек для двоеточия
byte hh,mm;                   // часы и минуты
byte bb;                      // двоеточия
byte detect;                  // сигнал наличия напряжения сети(1-сеть есть, 0-сети нет)
bool sending;                 // когда произошла передача - true
//---------------------------------------------------
void setup(){
    DDRB = 0b00000000; 
    PORTB |= PIN_IN;                    // устанавливаем 1 на выводе PIN_IN 
     cli();  
    TCCR1A = 0;   
    TCCR1B = 0;   
    OCR1A = 12499;                        // 0.1 s
    TCCR1B |= (1 << WGM12); 
    TCCR1B |= (1 << CS11) | (1 << CS10);  // делитель 64  
    TIMSK |= (1 << OCIE1A);  
     sei(); 
// передаем сигнал    
    DDRB |= PIN_TX;                      // Установить направление вывода на PIN_TX
    for(byte i = 0; i<5; ++i){send("001010110011010101001010");} 
}
//---------------------------------------------------
void loop(){
  if(detect == 0){print_time(hh * 100 + mm, bb, 7);   // int число выводимое на индикатор, двоеточие, яркость от 0 до 7
                 if(i1 <= 5){bb = 1;} else {bb = 0;}
  }
  else           {if(i1 <= 5){print_time(hh * 100 + mm, 1, 7);} // мигаем индикатором
                  else       {print_time(hh * 100 + mm, 0, -1 );}
  }
// если сеть появилась, отправляем сигнал  
  if(!(PINB & PIN_IN)){detect = 1;   // Чтение состояния(лог. 0) на порту PIN_IN
                       if(!sending){
                       for(byte i = 0; i<5; ++i){send("001010110011010101001010<U+202C><U+202C>");} 
                       sending = true;}
  }                      
}
//---------------------------------------------------
void tm_dec(byte dig){
    for(int i = 0; i < 8; i++){
      DDRB |= PIN_CLK;      // устанавливаем вывод PB0 как выход
      del();                 // ждем 100мксек.
      if(dig & 0x01){DDRB &= ~PIN_DIO;}
      else
         DDRB |= PIN_DIO;   // устанавливаем вывод PB1 как выход
         del();              // ждем 100мксек.
         DDRB &= ~PIN_CLK;  // устанавливаем вывод PB0 как вход
         del();              // ждем 100мксек.
         dig = dig >> 1;
    }
    
    DDRB |= PIN_CLK;        // устанавливаем вывод PB0 как выход
    DDRB &= ~PIN_DIO;       // устанавливаем вывод PB1 как вход
    del();                   // ждем 100мксек.
    DDRB &= ~PIN_CLK;       // устанавливаем вывод PB0 как вход
    del();                   // ждем 100мксек.
     
  if(!(PINB & PIN_DIO))     // Чтение состояния(лог. 0) на порту PIN_DIO:
    DDRB |= PIN_DIO;        // устанавливаем вывод PB1 как выход
    del();                   // ждем 100мксек.
    DDRB |= PIN_CLK;        // устанавливаем вывод PB0 как выход
    del();                   // ждем 100мксек.
}  
//---------------------------------------------------
void tm_stop(){
     DDRB |= PIN_DIO;      // устанавливаем вывод PB1 как выход
     del();                 // ждем 100мксек.
     DDRB &= ~PIN_CLK;     // устанавливаем вывод PB0 как вход
     del();                 // ждем 100мксек.
     DDRB &= ~PIN_DIO;     // устанавливаем вывод PB1 как вход
     del();                 // ждем 100мксек.
}  
//---------------------------------------------------
void tm_start(){
    DDRB |= PIN_DIO;      // устанавливаем вывод PB1 как выход
    del();                 // ждем 100мксек.
}
//---------------------------------------------------
void print_time(int t, bool pd_t, int br){
    tm_start(); tm_dec(0b10001000 + br);
    tm_dec(0x40); tm_stop(); tm_start();
        
    int data0 = t / 1000;
    int data1 = t / 100 % 10;
    int data2 = t / 10 % 10;
    int data3 = t % 10;
        
    for(byte n = 0; n < 4; n++){
       int data;
       switch(n){
         case 0: data = data0; break;
         case 1: data = data1; break;
         case 2: data = data2; break;
         case 3: data = data3; break;
       }
              
       switch(data){  // XGFEDCBA
         case 0:  data = 0b00111111; break;     // 0
         case 1:  data = 0b00000110; break;     // 1
         case 2:  data = 0b01011011; break;     // 2
         case 3:  data = 0b01001111; break;     // 3
         case 4:  data = 0b01100110; break;     // 4
         case 5:  data = 0b01101101; break;     // 5
         case 6:  data = 0b01111101; break;     // 6
         case 7:  data = 0b00000111; break;     // 7
         case 8:  data = 0b01111111; break;     // 8
         case 9:  data = 0b01101111; break;     // 9
       }
              
       if(n == 0){data0 = data;}
       if(n == 1){data1 = data;}
       if(n == 2){data2 = data;}
       if(n == 3){data3 = data;}
    }
    if(pd_t == 1){data1+= 0b10000000;}
    tm_dec(0xC0); tm_dec(data0); tm_dec(data1); tm_dec(data2); tm_dec(data3); tm_stop();
}  
//---------------------------------------------------
void del(){
    delayMicroseconds(100); // ждем 100мксек.
}
//---------------------------------------------------
ISR(TIMER1_COMPA_vect){
     i1++;
     if(detect == 0){i++;} 
     if(i1 > 9) {i1 = 0;}
     if(i > 599){mm++; i = 0;}
     if(mm > 59){hh++; mm = 0;}
     if(hh > 23){hh = 0;}
}
//---------------------------------------------------
void send(char* sCodeWord){
  while(*sCodeWord != '\0'){PORTB |= PIN_TX; // то же, что и digitalWrite high
      if(*sCodeWord == '0'){delayMicroseconds(nHighPulses_0);
                            PORTB &= ~PIN_TX; // то же, что и digitalWrite low
                            delayMicroseconds(nLowPulses_0);
                           }
      else                 {delayMicroseconds(nHighPulses_1);
                            PORTB &= ~PIN_TX;
                            delayMicroseconds(nLowPulses_1);
                           } 

      ++sCodeWord;
  }
    PORTB |= PIN_TX;
    delayMicroseconds(nHighPulses_0);

    PORTB &= ~PIN_TX;
    delayMicroseconds(nLowPulses_sync);
}
//END------------------------------------------------
[/code]

Собрал схему на макетке, всё отлично работает. Поставил в щиток, оказалось, что индикатор работает, а код не отправляется. Получилась такая ситуация. Когда просто выдергиваешь разьем IN+,IN-, программа отрабатывает как надо, и индикатор загорается и начинает считать время и код оправляется. А когда входы IN+,IN- подключены к блоку питания китайского вольтметра, в котором стоит электролит 1000 на 16В, то при пропадании сети электролит плавно разряжается через оптрон. Транзистор оптрона плавно закрывается и когда напряжение достигнет необходимого уровня для открывания тиристора MCR100, он открывается и открывает транзистор ВС327 и подает питание на схему. Схема запускается, тинька стартует, но код почему то не отправляет. Хотя он стоит в сетапе. Не пойму, почему при резком пропадании тинька из сетапа отправляет код, а при плавном не отправляет?

Попробуйте в сетап добавить задержку -
чтобы Тинька стартовала уже после разряда конденсатора

А куда, в самом начале сетапа или перед передачей кода? Что самое интересное, тинька же стартует, запускает отсчет и выводит индикацию, а код не передает.

В самое начало, или
до разрешения настроенного прерывания

И BOD ставил 4,3V. И задержку в самом начале сетапа поставил 5 сек. Код не отправляется. Чудеса.

Не измеряли мультиметром, может 5 сек мало?

Измерял, там порядка 3 сек. Для верности поставил задержку 5 сек. Код не передается.

Через мультиметр тоже немного разряжается. Что-бы отбросить уже эту версию, я бы ещё время задержки добавил

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

Я измерял питание тиньки. Оно с 0 до 4,6В вырастает за 3 сек. Прошил BOD 4,3V что бы она запускалась при этом напряжении. По сути, та же задержка. Плюс delay(5000) в сетапе. Неужели мало?

Кстати, еще вариант - возможно чип передатчика при плавном нарастании напряжения просто не стартует. (пытается стартовать на недостаточном питании и виснет)

Вам нужно организовать некий аналог супервизора питания, который будет подавать питание на всю схему только когда внешнее напряжение вырастет до 4.6в

Очень здравая мысль. Может действительно так. Буду думать как сделать.
И действительно при самостоятельном питании передатчика всё работает.

Получается, что именно так.

Нужно, что то типа триггера шмидта, который при переходе через порог, включал питание.

Для проверки можно и 10000мс сделать задержку.
Хотя версия b707 тоже очень может быть.

Можно Тиньку запускать просто по BOD, затем после задержки в сетапе, просто открыть ключ питания на передатчик свободным пином. Затем ещё одна задержка.

Так и сделаю. Спасибо всем за помощь.

Кстати, вдогонку спрошу ещё, если можно? У меня передатчик wl102-341 имеет pin EN, который по умолчанию, перемычкой соединен с плюсом питания. И пишут, если убрать перемычку от питания, то типа можно через этот пин, включать и отключать передатчик. Попробовал, но пин тиньки его не тянет. Может есть у кого опыт использования пина EN передатчика wl102-341, для этих целей.

Так изначальная проблема-то решилась?

Это очень странно.Если я не ошибаюсь, общий ток потребления модуля -17мА. Ток одного пина не может быть больше. Смотрите по схеме, может ещё есть перемычки
P.S. Измерьте сопротивление между EN и VDD и EN и GND. Может конденсатор пробит или что-то ещё есть , что мешает
P.P.S. И, кстати, при использовании EN нужно ставить делитель, чтобы согласовать уровни. Возможно потому и “не тянет”, что уже “убит”

Проблема с тинькой решилась. Сейчас решаю проблему с передатчиком.

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