Здравствуйте. Живу в частном доме и у нас в деревне довольно часто отключают свет. Электропроводка в доме разделена на силовую и слаботочную. Силовая это чайник, электропечь и холодильники. Слаботочная питает газовый котел, насосы, а так же ТВ, освещение, сигнализацию, роутер и т.п. Она подключена к электросети через ИБП 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 и подает питание на схему. Схема запускается, тинька стартует, но код почему то не отправляет. Хотя он стоит в сетапе. Не пойму, почему при резком пропадании тинька из сетапа отправляет код, а при плавном не отправляет?