Using a Sick WS15-D1130 Infrared Diode pair to act as a hardware motion detection sensor for Zoneminder. Also testing out an Omrom photo electric sensor, the E3F2-R2C4. This is a tripwire alarm sensor. When the beam is blocked, the alarm is activated.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

513 lines
13 KiB

6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
  1. /*
  2. *
  3. * ZoneMinder Hardware Project
  4. *
  5. *
  6. *
  7. * A sensor on an Arduino UNO communicating
  8. * via ethernet to ZMTrigger daemon for ZoneMinder
  9. * CCTV GNU/Linux software.
  10. *
  11. *
  12. */
  13. /*
  14. * What it does:
  15. * Works with accompanying shield to act as motion sensor
  16. * for Zoneminder via ZMTrigger. Shield is optional if you
  17. * want to bother with a perf board and components instead.
  18. *
  19. * Components:
  20. * ENC28J60
  21. * Motion Sensor (Either PIR, or microwave HFS-DC06H)
  22. * Microphone for Loud Noise alarms
  23. * LM35 Temperature Sensor
  24. * RGB Status LED
  25. * Speaker
  26. *
  27. * Power from External 12V supply, not USB!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  28. *
  29. */
  30. /*
  31. *
  32. *
  33. *
  34. * Directions:
  35. * Use Arduino Uno
  36. * See https://git.steakelectronics.com/adminguy/ZMHW_Project_InfraredDiodeSensor
  37. *
  38. * Connect ENC28J60 using these instructions:
  39. * https://github.com/ntruchsess/arduino_uip
  40. * http://web.archive.org/save/https://create.arduino.cc/projecthub/Sourcery/how-to-connect-the-enc28j60-to-an-arduino-efd0dd
  41. * CS for ENC and UIP library is 10 by default on UNO. Not 8, like that link says.
  42. *
  43. *
  44. *
  45. *
  46. *
  47. */
  48. #include <UIPEthernet.h>
  49. #include <EEPROM.h>
  50. //Edit the below values
  51. #define DEBUGMODE 0 // 1 == on. 0 == off.
  52. #define MIC 0 // 1 == on. 0 == off.
  53. #define SICK 0 // set to 1 if using sick sensor (on analog pin)
  54. // sick sensor is a transistor activated photoelectric
  55. // sensor. More details below.
  56. #define NORMALMODECT 0 // For a digital High motion sensor.
  57. /***************Ethernet ENC28J60***************/
  58. //Mac must be unique for each sensor
  59. byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xEA, 0x15 };
  60. //Static IP of Arduino
  61. byte ip[] = { 192, 168, 1, 177 };
  62. //IP of ZM Server
  63. byte server[] = { 192, 168, 1, 178 };
  64. //ZM server IP to put in requests.
  65. String host="192.168.1.178";
  66. #define ZMTRIGGERPORT 6802
  67. #define LISTENPORT 80 // (port 80 is default for HTTP)
  68. /***************Pins***************/
  69. //Digital
  70. #define MODECTPIN 2
  71. #define SPEAKERPIN 6
  72. #define LEDPIN 9
  73. //Analog
  74. #define TEMPPIN A0
  75. #define SICKPIN A1
  76. #define MICROPHONEPIN A2
  77. char* LOCATIONOFSENSOR = "Bay Four - Tool Room";
  78. /***************Variables************/
  79. uint16_t MotionSensorRead = 0;
  80. uint8_t AlarmActive = 0;
  81. char* ZMTriggerMessage = "1234567890123456789012345678901234"; //Initialize this with dummy data
  82. uint8_t TEMPERATUREVALUE = 0;
  83. uint8_t TEMPERATUREVALUE2 = 0;
  84. uint8_t SOUNDVALUE = 0;
  85. uint8_t MODECTVALUE = 0;
  86. /*
  87. ZMTrigger Command to Send
  88. B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext>
  89. which in this code is:
  90. monnum | onoff + timealarm | score | source
  91. e.g.
  92. 2|on+5|100|ZoneAVR||
  93. This will send a command to ZMTrigger.pl to turn monitor #2 ON (alarm state) for five seconds, with a score of 100
  94. and the source of ZoneAVR. The text field, and show text are not setup here.
  95. */
  96. char* monnum = "25"; //monitor number
  97. char* onoff = "on"; //command to send to zmtrigger.
  98. char* timealarm = "10"; //time to set monitor to alarm
  99. char* score = "100"; //score to assign
  100. char* source = "ZMHW MotionSensor"; //source. Add details as needed (e.g. Hallway sensor)
  101. //Do not need to edit below
  102. // Initialize the Ethernet server library
  103. EthernetClient client;
  104. EthernetServer server2 = EthernetServer(LISTENPORT);
  105. void chime(int freq){
  106. tone(SPEAKERPIN, freq, 50);
  107. delay(50);
  108. }
  109. void chimefast(int freq, int fast){
  110. tone(SPEAKERPIN, freq, fast);
  111. delay(fast);
  112. }
  113. //timer/interrupt
  114. uint16_t timer1;
  115. uint16_t timer1_counter;
  116. uint8_t debouncetime;
  117. uint8_t first_interrupt = 0;
  118. //timer for debounce
  119. ISR(TIMER1_OVF_vect){
  120. timer1++;
  121. if (first_interrupt == 1 ){
  122. debouncetime++;
  123. }
  124. if (debouncetime > 2) {
  125. first_interrupt = 0;
  126. debouncetime = 0;
  127. AlarmActive = 0;
  128. }
  129. }
  130. void setup()
  131. {
  132. Serial.begin(9600);
  133. Serial.println("ZMHW Project");
  134. Serial.println("Motion Sensor");
  135. pinMode(SICKPIN, INPUT);
  136. pinMode(MICROPHONEPIN, INPUT);
  137. pinMode(SPEAKERPIN, OUTPUT);
  138. pinMode(MODECTPIN, INPUT);
  139. //Be careful. This sets Areg to 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  140. analogReference(INTERNAL);
  141. Ethernet.begin(mac, ip);
  142. server2.begin();
  143. Serial.print("server is at ");
  144. Serial.println(Ethernet.localIP());
  145. //timer 1, setup
  146. //Crystal of Uno is == Mega (16MHz)
  147. //this timer is all bodged up, but doesn't matter, as we only
  148. //need two or three counts between alarms. Not going to fix atm.
  149. //and it works.
  150. //Clear existing registers
  151. TCCR1A = 0;
  152. TCCR1B = 0;
  153. // Set timer1_counter to the correct value for our interrupt interval
  154. //timer1_counter = 10000; // 62500 for one second if using 256 prescaler. can't be over 16 bit value (timer1 is 16bit limited)
  155. //timer1_counter = 10;
  156. //TCNT1 = timer1_counter; // TCNT1 is what we are overflowing on
  157. TCCR1B |= (1 << CS12); // 256 prescaler (divide 16mhz/256 = 62500)
  158. TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html
  159. // search tccr1b
  160. TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged)
  161. //end timer1
  162. sei(); //timer needs interrupts, enable (set) interrupts
  163. tone(SPEAKERPIN, 1000, 200);
  164. delay(100);
  165. tone(SPEAKERPIN, 2000, 200);
  166. delay(100);
  167. tone(SPEAKERPIN, 2200, 200);
  168. delay(100);
  169. }
  170. void loop()
  171. {
  172. /*****************ANALOG SECTION******************/
  173. //The SICK infrared laser requires a transistor to output
  174. //high or low, but we will cheat and instead, put it through
  175. //a serial diode, and then use the ADC instead of a digital pin
  176. //saves a few seconds to put a diode on the end instead of transistor
  177. //when soldering by hand. Works equally as well. Requires ADC pin.
  178. if (SICK){
  179. MotionSensorRead = analogRead(SICKPIN);
  180. Serial.print("Motion Sensor Value: ");
  181. Serial.println(String(MotionSensorRead));
  182. //Serial.println(String(timer1));
  183. delay(10);
  184. }
  185. TEMPERATUREVALUE = analogRead(TEMPPIN);
  186. Serial.print("Temperature Value: ");
  187. // See resources. uses 1.1 aref, converts to celcius, then to Fareinheit.
  188. TEMPERATUREVALUE2 = (TEMPERATUREVALUE / 9.31)* 2 + 30;
  189. Serial.println(String(TEMPERATUREVALUE2));
  190. delay(10);
  191. if (MIC){
  192. SOUNDVALUE = analogRead(MICROPHONEPIN);
  193. Serial.print("Sound Value: ");
  194. Serial.println(String(SOUNDVALUE));
  195. delay(10);
  196. }
  197. //if (NORMALMODECT){
  198. MODECTVALUE = digitalRead(MODECTPIN);
  199. Serial.print("Motion Detector Value (normal): ");
  200. Serial.println(String(MODECTVALUE));
  201. //}
  202. if(DEBUGMODE){
  203. delay(10);
  204. }
  205. /****************MOTION SENSING****************/
  206. //SICK
  207. //Motion sensing for Sick Photoelectric sensor only
  208. //upon boot, values are around 400 sometimes, so only alert at higher
  209. if(SICK){
  210. if (MotionSensorRead > 500 && AlarmActive == 0){
  211. Serial.println("Motion Detected on Sick");
  212. //firstpacketsend = 0;
  213. cli();
  214. //some of this may be redundant, need to check
  215. AlarmActive = 1;
  216. first_interrupt = 1;
  217. debouncetime = 0;
  218. sei();
  219. //Want the chime to be only noticeable if you know what to listen
  220. //for. Make it a high freq. sound that is easy to miss.
  221. //Resistors to speaker should be high
  222. chime(13000);
  223. Serial.println("Connecting...");
  224. if (client.connect(server, ZMTRIGGERPORT)) {
  225. chime(13000);
  226. //beware that the buffer in snprintf is big enough to hold everything
  227. snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source);
  228. Serial.print("the TCP Packet being sent:");
  229. Serial.println(String(ZMTriggerMessage));
  230. client.println(String(ZMTriggerMessage)); //required
  231. Serial.println("TCP packet sent to ZMTrigger");
  232. client.stop();
  233. }
  234. else {
  235. //NOTE: If you are not connected to the network
  236. //the device will currently freeze up, and not timeout.
  237. //Need to implement a watchdog.
  238. //If you ARE connected to the network, and server is not available
  239. //then it will timeout.
  240. Serial.println("Connection to ZM Server failed");
  241. chime(50);
  242. delay(100);
  243. chime(50);
  244. delay(100);
  245. chime(50);
  246. delay(100);
  247. }
  248. }
  249. }//end sick
  250. //Digital High Motion Sensor
  251. if(NORMALMODECT){
  252. if (MODECTVALUE==HIGH){
  253. Serial.println("Motion Detected on Normal Sensor");
  254. //firstpacketsend = 0;
  255. cli();
  256. //some of this may be redundant, need to check
  257. AlarmActive = 1;
  258. first_interrupt = 1;
  259. debouncetime = 0;
  260. sei();
  261. //Want the chime to be only noticeable if you know what to listen
  262. //for. Make it a high freq. sound that is easy to miss.
  263. //Resistors to speaker should be high
  264. chime(13000);
  265. Serial.println("Connecting...");
  266. if (client.connect(server, ZMTRIGGERPORT)) {
  267. chime(13000);
  268. //beware that the buffer in snprintf is big enough to hold everything
  269. snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source);
  270. Serial.print("the TCP Packet being sent:");
  271. Serial.println(String(ZMTriggerMessage));
  272. client.println(String(ZMTriggerMessage)); //required
  273. Serial.println("TCP packet sent to ZMTrigger");
  274. client.stop();
  275. }
  276. else {
  277. //NOTE: If you are not connected to the network
  278. //the device will currently freeze up, and not timeout.
  279. //Need to implement a watchdog.
  280. //If you ARE connected to the network, and server is not available
  281. //then it will timeout.
  282. Serial.println("Connection to ZM Server failed");
  283. chime(40);
  284. delay(100);
  285. chime(60);
  286. delay(100);
  287. chime(60);
  288. delay(100);
  289. }
  290. }
  291. MODECTVALUE=LOW;
  292. }//end normal Motion Sensor
  293. //disconnect
  294. if (!client.connected()) {
  295. client.stop();
  296. }
  297. /********************SERVER STATUS PAGE*********************/
  298. /*
  299. * With this, you can logon to the Sensor from your LAN to find
  300. * out just what device this IP address is, in case you happen to
  301. * forget. We can also pull the temperature from this page, and
  302. * populate it to the camera feed, via ZMTrigger, from a server
  303. * side wget.
  304. */
  305. //Serve Status Page
  306. // listen for incoming clients
  307. EthernetClient client = server2.available();
  308. if (client) {
  309. Serial.println("new client");
  310. // an http request ends with a blank line
  311. boolean currentLineIsBlank = true;
  312. while (client.connected()) {
  313. if (client.available()) {
  314. char c = client.read();
  315. Serial.write(c);
  316. // if you've gotten to the end of the line (received a newline
  317. // character) and the line is blank, the http request has ended,
  318. // so you can send a reply
  319. if (c == '\n' && currentLineIsBlank) {
  320. // send a standard http response header
  321. client.println("HTTP/1.1 200 OK");
  322. client.println("Content-Type: text/html");
  323. client.println("Connection: close"); // the connection will be closed after completion of the response
  324. client.println("Refresh: 5"); // refresh the page automatically every 5 sec
  325. client.println();
  326. client.println("<!DOCTYPE HTML>");
  327. client.println("<html><pre>");
  328. client.println("<b>Steak Electronics</b>");
  329. client.println("\"Steak it easy... That is, don't overcook steak\"");
  330. client.println("");
  331. //client.println("<b>IP Address:</b>");
  332. //client.println(Ethernet.localIP());
  333. client.println("<b>Sensor Location:</b>");
  334. client.println(LOCATIONOFSENSOR);
  335. client.println("<b>Type of Sensor</b>:");
  336. client.println("Microwave - HFS-DC06H");
  337. client.println("<b>Temperature Sensor Value:</b>");
  338. client.println(TEMPERATUREVALUE2);
  339. client.println("</pre></html>");
  340. break;
  341. }
  342. if (c == '\n') {
  343. // you're starting a new line
  344. currentLineIsBlank = true;
  345. } else if (c != '\r') {
  346. // you've gotten a character on the current line
  347. currentLineIsBlank = false;
  348. }
  349. }
  350. }
  351. // give the web browser time to receive the data
  352. delay(1);
  353. // close the connection:
  354. client.stop();
  355. Serial.println("client disconnected");
  356. }
  357. //write to eeprom if connection failed, and try again upon reboot
  358. //EEPROM.write(EEPROM_RETRY, switch_pressed);
  359. } //end main loop