Стоит термодатчик в серверной, стоит сигнализация на улице в будке у охранников.
Когда отключается кондиционер и температура поднимается, сигнализация включается и работает до тех пор, пока проблема не решится и температура в серверной не опустится до нужного значения.
Попросили сделать устройство, которое будет временно отключать сирену сигнализации на 25 минут, пока устраняется неисправность.

Накидал по-быстрому, собрал. Сегодня поставили) Подключается в разрыв провода сигнализации.
Схема подключения реле такая из-за того, что поначалу реле было автомобильное 4-хконтактное, а потом нашлось другое, но переделывать плату не захотел. В общем, собирал из мусора)

Когда включается сигнализация, открывается транзистор Q1, активируется реле и начинает работать сирена. После нажатия кнопки устройство переходит в режим отсчета обратного времени (25 минут), транзистор закрывается. Светодиоды сигнализируют об оставшемся времени и поочередно гаснут. Каждые 5 минут выключается очередной светодиод (были ноги на контроллере, были светодиоды, зато теперь красиво, админы довольны)))))

От концепта до готового устройства прошло около 4-х часов. Большую часть времени потратил на то, чтобы просверлить отверстия в плате для автомобильного реле (с разводкой чуть промахнулся).

Прикрутили плату болтами к планке, примотали планку изолентой к серверному шкафу, подпаяли внешний выключатель от дверного замка (чтобы большущие руки охранников не промазали), подключили.

Плата 30x75 mm, односторонняя. ЛУТ)

Стоит термодатчик в серверной, стоит сигнализация на улице в будке у охранников.
Когда отключается кондиционер и температура поднимается, сигнализация включается и работает до тех пор, пока проблема не решится и температура в серверной не опустится до нужного значения.
Попросили сделать устройство, которое будет временно отключать сирену сигнализации на 25 минут, пока устраняется неисправность.

Накидал по-быстрому, собрал. Сегодня поставили) Подключается в разрыв провода сигнализации.
Схема подключения реле такая из-за того, что поначалу реле было автомобильное 4-хконтактное, а потом нашлось другое, но переделывать плату не захотел. В общем, собирал из мусора)

Когда включается сигнализация, открывается транзистор Q1, активируется реле и начинает работать сирена. После нажатия кнопки устройство переходит в режим отсчета обратного времени (25 минут), транзистор закрывается. Светодиоды сигнализируют об оставшемся времени и поочередно гаснут. Каждые 5 минут выключается очередной светодиод (были ноги на контроллере, были светодиоды, зато теперь красиво, админы довольны)))))

От концепта до готового устройства прошло около 4-х часов. Большую часть времени потратил на то, чтобы просверлить отверстия в плате для автомобильного реле (с разводкой чуть промахнулся).

Прикрутили плату болтами к планке, примотали планку изолентой к серверному шкафу, подпаяли внешний выключатель от дверного замка (чтобы большущие руки охранников не промазали), подключили.

Плата 30x75 mm, односторонняя. ЛУТ)

Изображения


[​IMG]
[​IMG]
Готовая плата.
[​IMG]

Исходный код

HEX Файл
  1. /*
  2. * alarm_timer.c
  3. *
  4. * Created: 22.02.2015 19:24:30
  5. * Author: .ctor
  6. */
  7.  
  8.  
  9. #include <avr/io.h>
  10. #include <avr/interrupt.h>
  11. //---------------------------------------------------------------------------------------------------------
  12. #define SET_B(x) |= (1<<x)
  13. #define CLR_B(x) &amp;=~(1<<x)
  14. #define INV_B(x) ^=(1<<x)
  15. #define GET_B(x,y) (x >> y ) &amp; 0x01
  16. //---------------------------------------------------------------------------------------------------------
  17. volatile uint16_t __time_ms;
  18. volatile uint16_t __time_s;
  19.  
  20. #define TIME 25
  21. void Reset();
  22. //---------------------------------------------------------------------------------------------------------
  23. // External Interrupt 0 service routine
  24. ISR (INT0_vect)
  25. {
  26. Reset();
  27. }
  28. //---------------------------------------------------------------------------------------------------------
  29. // Timer 0 overflow interrupt service routine
  30. ISR(TIM0_OVF_vect)
  31. {
  32. TCNT0=0x83;
  33. if (__time_s)
  34. {
  35. for (uint8_t i=0;i<5;i++)
  36. {
  37. const uint16_t t = TIME*60/(5);
  38.  
  39. if (__time_s>t*(i))
  40. PORTA SET_B(i);
  41. else
  42. PORTA CLR_B(i);
  43. }
  44. PORTA CLR_B(5);
  45. if (__time_ms == 999)
  46. {
  47. __time_s--;
  48. __time_ms = 0;
  49. }
  50. else
  51. __time_ms ++;
  52. }
  53. else
  54. {
  55. PORTA = PORTA &amp; 0b011100000;
  56. PORTA SET_B(5);
  57. }
  58. }
  59. //---------------------------------------------------------------------------------------------------------
  60. void Reset()
  61. {
  62. __time_ms = 0;
  63. __time_s = TIME * 60; //25 min
  64. PORTA SET_B(5);
  65. }
  66. //---------------------------------------------------------------------------------------------------------
  67. void main(void)
  68. {
  69. // Declare your local variables here
  70.  
  71. // Crystal Oscillator division factor: 1
  72. #pragma optsize-
  73. CLKPR=0x80;
  74. CLKPR=0x00;
  75. #ifdef _OPTIMIZE_SIZE_
  76. #pragma optsize+
  77. #endif
  78.  
  79. // Input/Output Ports initialization
  80. // Port A initialization
  81. // Func7=In Func6=In Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
  82. // State7=T State6=T State5=1 State4=0 State3=0 State2=0 State1=0 State0=0
  83. PORTA=0x20;
  84. DDRA=0x3F;
  85.  
  86. // Port B initialization
  87. // Func3=In Func2=In Func1=In Func0=In
  88. // State3=T State2=P State1=T State0=T
  89. PORTB=0x04;
  90. DDRB=0x00;
  91.  
  92. // Timer/Counter 0 initialization
  93. // Clock source: System Clock
  94. // Clock value: 125,000 kHz
  95. // Mode: Normal top=0xFF
  96. // OC0A output: Disconnected
  97. // OC0B output: Disconnected
  98. TCCR0A=0x00;
  99. TCCR0B=0x03;
  100. TCNT0=0x00;
  101. OCR0A=0x00;
  102. OCR0B=0x00;
  103.  
  104. // Timer/Counter 1 initialization
  105. // Clock source: System Clock
  106. // Clock value: Timer1 Stopped
  107. // Mode: Normal top=0xFFFF
  108. // OC1A output: Discon.
  109. // OC1B output: Discon.
  110. // Noise Canceler: Off
  111. // Input Capture on Falling Edge
  112. // Timer1 Overflow Interrupt: Off
  113. // Input Capture Interrupt: Off
  114. // Compare A Match Interrupt: Off
  115. // Compare B Match Interrupt: Off
  116. TCCR1A=0x00;
  117. TCCR1B=0x00;
  118. TCNT1H=0x00;
  119. TCNT1L=0x00;
  120. ICR1H=0x00;
  121. ICR1L=0x00;
  122. OCR1AH=0x00;
  123. OCR1AL=0x00;
  124. OCR1BH=0x00;
  125. OCR1BL=0x00;
  126.  
  127. // External Interrupt(s) initialization
  128. // INT0: On
  129. // INT0 Mode: Falling Edge
  130. // Interrupt on any change on pins PCINT0-7: Off
  131. // Interrupt on any change on pins PCINT8-11: Off
  132. MCUCR=0x02;
  133. GIMSK=0x40;
  134. GIFR=0x40;
  135. // Timer/Counter 0 Interrupt(s) initialization
  136. TIMSK0=0x01;
  137.  
  138. // Timer/Counter 1 Interrupt(s) initialization
  139. TIMSK1=0x00;
  140.  
  141. // Universal Serial Interface initialization
  142. // Mode: Disabled
  143. // Clock source: Register &amp; Counter=no clk.
  144. // USI Counter Overflow Interrupt: Off
  145. USICR=0x00;
  146.  
  147. // Analog Comparator initialization
  148. // Analog Comparator: Off
  149. // Analog Comparator Input Capture by Timer/Counter 1: Off
  150. ACSR=0x80;
  151. ADCSRB=0x00;
  152. DIDR0=0x00;
  153.  
  154. // ADC initialization
  155. // ADC disabled
  156. ADCSRA=0x00;
  157.  
  158. // Global enable interrupts
  159. sei();
  160.  
  161. while (1)
  162. {
  163. // Place your code here
  164.  
  165. }
  166. }