Стоит термодатчик в серверной, стоит сигнализация на улице в будке у охранников.
Когда отключается кондиционер и температура поднимается, сигнализация включается и работает до тех пор, пока проблема не решится и температура в серверной не опустится до нужного значения.
Попросили сделать устройство, которое будет временно отключать сирену сигнализации на 25 минут, пока устраняется неисправность.
Накидал по-быстрому, собрал. Сегодня поставили) Подключается в разрыв провода сигнализации.
Схема подключения реле такая из-за того, что поначалу реле было автомобильное 4-хконтактное, а потом нашлось другое, но переделывать плату не захотел. В общем, собирал из мусора)
Когда включается сигнализация, открывается транзистор Q1, активируется реле и начинает работать сирена. После нажатия кнопки устройство переходит в режим отсчета обратного времени (25 минут), транзистор закрывается. Светодиоды сигнализируют об оставшемся времени и поочередно гаснут. Каждые 5 минут выключается очередной светодиод (были ноги на контроллере, были светодиоды, зато теперь красиво, админы довольны)))))
От концепта до готового устройства прошло около 4-х часов. Большую часть времени потратил на то, чтобы просверлить отверстия в плате для автомобильного реле (с разводкой чуть промахнулся).
Прикрутили плату болтами к планке, примотали планку изолентой к серверному шкафу, подпаяли внешний выключатель от дверного замка (чтобы большущие руки охранников не промазали), подключили.
Плата 30x75 mm, односторонняя. ЛУТ)
Изображения
-
Готовая плата.
Исходный код
- HEX Файл
- /*
- * alarm_timer.c
- *
- * Created: 22.02.2015 19:24:30
- * Author: .ctor
- */
- #include <avr/io.h>
- #include <avr/interrupt.h>
- //---------------------------------------------------------------------------------------------------------
- #define SET_B(x) |= (1<<x)
- #define CLR_B(x) &=~(1<<x)
- #define INV_B(x) ^=(1<<x)
- #define GET_B(x,y) (x >> y ) & 0x01
- //---------------------------------------------------------------------------------------------------------
- volatile uint16_t __time_ms;
- volatile uint16_t __time_s;
- #define TIME 25
- void Reset();
- //---------------------------------------------------------------------------------------------------------
- // External Interrupt 0 service routine
- ISR (INT0_vect)
- {
- Reset();
- }
- //---------------------------------------------------------------------------------------------------------
- // Timer 0 overflow interrupt service routine
- ISR(TIM0_OVF_vect)
- {
- TCNT0=0x83;
- if (__time_s)
- {
- for (uint8_t i=0;i<5;i++)
- {
- const uint16_t t = TIME*60/(5);
- if (__time_s>t*(i))
- PORTA SET_B(i);
- else
- PORTA CLR_B(i);
- }
- PORTA CLR_B(5);
- if (__time_ms == 999)
- {
- __time_s--;
- __time_ms = 0;
- }
- else
- __time_ms ++;
- }
- else
- {
- PORTA = PORTA & 0b011100000;
- PORTA SET_B(5);
- }
- }
- //---------------------------------------------------------------------------------------------------------
- void Reset()
- {
- __time_ms = 0;
- __time_s = TIME * 60; //25 min
- PORTA SET_B(5);
- }
- //---------------------------------------------------------------------------------------------------------
- void main(void)
- {
- // Declare your local variables here
- // Crystal Oscillator division factor: 1
- #pragma optsize-
- CLKPR=0x80;
- CLKPR=0x00;
- #ifdef _OPTIMIZE_SIZE_
- #pragma optsize+
- #endif
- // Input/Output Ports initialization
- // Port A initialization
- // Func7=In Func6=In Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
- // State7=T State6=T State5=1 State4=0 State3=0 State2=0 State1=0 State0=0
- PORTA=0x20;
- DDRA=0x3F;
- // Port B initialization
- // Func3=In Func2=In Func1=In Func0=In
- // State3=T State2=P State1=T State0=T
- PORTB=0x04;
- DDRB=0x00;
- // Timer/Counter 0 initialization
- // Clock source: System Clock
- // Clock value: 125,000 kHz
- // Mode: Normal top=0xFF
- // OC0A output: Disconnected
- // OC0B output: Disconnected
- TCCR0A=0x00;
- TCCR0B=0x03;
- TCNT0=0x00;
- OCR0A=0x00;
- OCR0B=0x00;
- // Timer/Counter 1 initialization
- // Clock source: System Clock
- // Clock value: Timer1 Stopped
- // Mode: Normal top=0xFFFF
- // OC1A output: Discon.
- // OC1B output: Discon.
- // Noise Canceler: Off
- // Input Capture on Falling Edge
- // Timer1 Overflow Interrupt: Off
- // Input Capture Interrupt: Off
- // Compare A Match Interrupt: Off
- // Compare B Match Interrupt: Off
- TCCR1A=0x00;
- TCCR1B=0x00;
- TCNT1H=0x00;
- TCNT1L=0x00;
- ICR1H=0x00;
- ICR1L=0x00;
- OCR1AH=0x00;
- OCR1AL=0x00;
- OCR1BH=0x00;
- OCR1BL=0x00;
- // External Interrupt(s) initialization
- // INT0: On
- // INT0 Mode: Falling Edge
- // Interrupt on any change on pins PCINT0-7: Off
- // Interrupt on any change on pins PCINT8-11: Off
- MCUCR=0x02;
- GIMSK=0x40;
- GIFR=0x40;
- // Timer/Counter 0 Interrupt(s) initialization
- TIMSK0=0x01;
- // Timer/Counter 1 Interrupt(s) initialization
- TIMSK1=0x00;
- // Universal Serial Interface initialization
- // Mode: Disabled
- // Clock source: Register & Counter=no clk.
- // USI Counter Overflow Interrupt: Off
- USICR=0x00;
- // Analog Comparator initialization
- // Analog Comparator: Off
- // Analog Comparator Input Capture by Timer/Counter 1: Off
- ACSR=0x80;
- ADCSRB=0x00;
- DIDR0=0x00;
- // ADC initialization
- // ADC disabled
- ADCSRA=0x00;
- // Global enable interrupts
- sei();
- while (1)
- {
- // Place your code here
- }
- }