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 и подает питание на схему. Схема запускается, тинька стартует, но код почему то не отправляет. Хотя он стоит в сетапе. Не пойму, почему при резком пропадании тинька из сетапа отправляет код, а при плавном не отправляет?

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

1 лайк

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

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

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

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

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

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

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

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

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

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

2 лайка

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

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

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

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

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

1 лайк

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

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

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

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

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

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