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.

529 lines
13 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 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 1 // For a digital High motion sensor.
  57. /***************Ethernet ENC28J60***************/
  58. //Mac must be unique for each sensor
  59. byte mac[] = { 0xD3, 0x5D, 0xBE, 0xEF, 0xEE, 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. uint8_t AlarmActive = 0;
  80. char* ZMTriggerMessage = "1234567890123456789012345"; //Initialize this with dummy data
  81. uint8_t TEMPERATUREVALUE = 0;
  82. uint8_t TEMPERATUREVALUE2 = 0;
  83. uint8_t SOUNDVALUE = 0;
  84. uint16_t MODECTVALUE = 0;
  85. /*
  86. ZMTrigger Command to Send
  87. B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext>
  88. which in this code is:
  89. monnum | onoff + timealarm | score | source
  90. e.g.
  91. 2|on+5|100|ZoneAVR||
  92. This will send a command to ZMTrigger.pl to turn monitor #2 ON (alarm state) for five seconds, with a score of 100
  93. and the source of ZoneAVR. The text field, and show text are not setup here.
  94. */
  95. char* monnum = "25"; //monitor number
  96. char* onoff = "on"; //command to send to zmtrigger.
  97. char* timealarm = "10"; //time to set monitor to alarm
  98. char* score = "100"; //score to assign
  99. char* source = "ZMHW"; //source. Add details as needed (e.g. Hallway sensor)
  100. //Do not need to edit below
  101. // Initialize the Ethernet server library
  102. EthernetClient client;
  103. EthernetServer server2 = EthernetServer(LISTENPORT);
  104. /*
  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(F("ZMHW Project"));
  134. Serial.println(F("Motion Sensor"));
  135. //if sick
  136. pinMode(SICKPIN, INPUT);
  137. //if mic
  138. pinMode(MICROPHONEPIN, INPUT);
  139. //if speaker
  140. pinMode(SPEAKERPIN, OUTPUT);
  141. pinMode(MODECTPIN, INPUT);
  142. pinMode(TEMPPIN, INPUT);
  143. //Be careful. This sets Areg to 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  144. analogReference(INTERNAL);
  145. Ethernet.begin(mac, ip);
  146. server2.begin();
  147. Serial.print(F("server is at "));
  148. Serial.println(Ethernet.localIP());
  149. //timer 1, setup
  150. //Crystal of Uno is == Mega (16MHz)
  151. //this timer is all bodged up, but doesn't matter, as we only
  152. //need two or three counts between alarms. Not going to fix atm.
  153. //and it works.
  154. //Clear existing registers
  155. TCCR1A = 0;
  156. TCCR1B = 0;
  157. // Set timer1_counter to the correct value for our interrupt interval
  158. //timer1_counter = 10000; // 62500 for one second if using 256 prescaler. can't be over 16 bit value (timer1 is 16bit limited)
  159. //timer1_counter = 10;
  160. //TCNT1 = timer1_counter; // TCNT1 is what we are overflowing on
  161. TCCR1B |= (1 << CS12); // 256 prescaler (divide 16mhz/256 = 62500)
  162. TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html
  163. // search tccr1b
  164. TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged)
  165. //end timer1
  166. sei(); //timer needs interrupts, enable (set) interrupts
  167. //tone(SPEAKERPIN, 1000, 200);
  168. //delay(100);
  169. //tone(SPEAKERPIN, 2000, 200);
  170. //delay(100);
  171. //tone(SPEAKERPIN, 2200, 200);
  172. //delay(100);
  173. }
  174. void loop()
  175. {
  176. //delay(50);
  177. /*****************ANALOG SECTION******************/
  178. //The SICK infrared laser requires a transistor to output
  179. //high or low, but we will cheat and instead, put it through
  180. //a serial diode, and then use the ADC instead of a digital pin
  181. //saves a few seconds to put a diode on the end instead of transistor
  182. //when soldering by hand. Works equally as well. Requires ADC pin.
  183. /*
  184. if (SICK){
  185. MotionSensorRead = analogRead(SICKPIN);
  186. Serial.print("Motion Sensor Value: ");
  187. Serial.println(String(MotionSensorRead));
  188. //Serial.println(String(timer1));
  189. delay(30);
  190. }
  191. */
  192. TEMPERATUREVALUE = analogRead(TEMPPIN);
  193. Serial.print(F("Temperature Value: "));
  194. // See resources. uses 1.1 aref, converts to celcius, then to Fareinheit.
  195. TEMPERATUREVALUE2 = (TEMPERATUREVALUE / 9.31)* 2 + 30;
  196. Serial.println(String(TEMPERATUREVALUE2));
  197. delay(30);
  198. /*
  199. if (MIC){
  200. SOUNDVALUE = analogRead(MICROPHONEPIN);
  201. Serial.print("Sound Value: ");
  202. Serial.println(String(SOUNDVALUE));
  203. delay(30);
  204. }
  205. */
  206. if (NORMALMODECT){
  207. delay(10);
  208. MODECTVALUE = digitalRead(MODECTPIN);
  209. delay(10);
  210. Serial.print(F("Motion Detector Value (normal): "));
  211. //Serial.println(String(MODECTVALUE));
  212. Serial.println(MODECTVALUE);
  213. delay(30);
  214. }
  215. if(DEBUGMODE){
  216. delay(10);
  217. }
  218. /****************MOTION SENSING****************/
  219. //SICK
  220. //Motion sensing for Sick Photoelectric sensor only
  221. //upon boot, values are around 400 sometimes, so only alert at higher
  222. if(SICK){
  223. if (MODECTVALUE > 500 && AlarmActive == 0){
  224. Serial.println(F("Motion Detected on Sick"));
  225. //firstpacketsend = 0;
  226. cli();
  227. //some of this may be redundant, need to check
  228. AlarmActive = 1;
  229. first_interrupt = 1;
  230. debouncetime = 0;
  231. sei();
  232. //Want the chime to be only noticeable if you know what to listen
  233. //for. Make it a high freq. sound that is easy to miss.
  234. //Resistors to speaker should be high
  235. //chime(13000);
  236. Serial.println("Connecting...");
  237. if (client.connect(server, ZMTRIGGERPORT)) {
  238. //chime(13000);
  239. //beware that the buffer in snprintf is big enough to hold everything
  240. snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source);
  241. Serial.print(F("the TCP Packet being sent:"));
  242. Serial.println(String(ZMTriggerMessage));
  243. client.println(String(ZMTriggerMessage)); //required
  244. Serial.println(F("TCP packet sent to ZMTrigger"));
  245. client.stop();
  246. }
  247. else {
  248. //NOTE: If you are not connected to the network
  249. //the device will currently freeze up, and not timeout.
  250. //Need to implement a watchdog.
  251. //If you ARE connected to the network, and server is not available
  252. //then it will timeout.
  253. Serial.println(F("Connection to ZM Server failed"));
  254. /*chime(50);
  255. delay(100);
  256. chime(50);
  257. delay(100);
  258. chime(50);
  259. delay(100);
  260. */
  261. }
  262. }
  263. }//end sick
  264. //Digital High Motion Sensor
  265. if(NORMALMODECT){
  266. if (MODECTVALUE==HIGH && AlarmActive == 0){
  267. Serial.println(F("Motion Detected on Normal Sensor"));
  268. //firstpacketsend = 0;
  269. cli();
  270. //some of this may be redundant, need to check
  271. AlarmActive = 1;
  272. first_interrupt = 1;
  273. debouncetime = 0;
  274. sei();
  275. //Want the chime to be only noticeable if you know what to listen
  276. //for. Make it a high freq. sound that is easy to miss.
  277. //Resistors to speaker should be high
  278. //chime(13000);
  279. delay(10);
  280. Serial.println(F("Connecting..."));
  281. if (client.connect(server, ZMTRIGGERPORT)) {
  282. //chime(13000);
  283. //delay(10);
  284. //beware that the buffer in snprintf is big enough to hold everything
  285. snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source);
  286. Serial.print(F("the TCP Packet being sent:"));
  287. Serial.println(String(ZMTriggerMessage));
  288. client.println(String(ZMTriggerMessage)); //required
  289. Serial.println(F("TCP packet sent to ZMTrigger"));
  290. client.stop();
  291. }
  292. else {
  293. //NOTE: If you are not connected to the network
  294. //the device will currently freeze up, and not timeout.
  295. //Need to implement a watchdog.
  296. //If you ARE connected to the network, and server is not available
  297. //then it will timeout.
  298. Serial.println(F("Connection to ZM Server failed"));
  299. /* chime(40);
  300. delay(100);
  301. chime(60);
  302. delay(100);
  303. chime(60);
  304. delay(100);
  305. */
  306. }
  307. }
  308. MODECTVALUE=LOW;
  309. }//end normal Motion Sensor
  310. //disconnect
  311. if (!client.connected()) {
  312. client.stop();
  313. }
  314. /********************SERVER STATUS PAGE*********************/
  315. /*
  316. * With this, you can logon to the Sensor from your LAN to find
  317. * out just what device this IP address is, in case you happen to
  318. * forget. We can also pull the temperature from this page, and
  319. * populate it to the camera feed, via ZMTrigger, from a server
  320. * side wget.
  321. */
  322. //Serve Status Page
  323. // listen for incoming clients
  324. EthernetClient client = server2.available();
  325. if (client) {
  326. Serial.println(F("web visitor"));
  327. // an http request ends with a blank line
  328. boolean currentLineIsBlank = true;
  329. while (client.connected()) {
  330. if (client.available()) {
  331. char c = client.read();
  332. Serial.write(c);
  333. // if you've gotten to the end of the line (received a newline
  334. // character) and the line is blank, the http request has ended,
  335. // so you can send a reply
  336. if (c == '\n' && currentLineIsBlank) {
  337. // send a standard http response header
  338. client.println("HTTP/1.1 200 OK");
  339. client.println("Content-Type: text/html");
  340. //client.println("Connection: close"); // the connection will be closed after completion of the response
  341. //client.println("Refresh: 5"); // refresh the page automatically every 5 sec
  342. client.println();
  343. client.println("<!DOCTYPE HTML>");
  344. client.println("<html><pre>");
  345. client.println("<b>Steak Electronics</b>");
  346. client.println("\"Steak it easy... That is, don't overcook steak\"");
  347. client.println("");
  348. //client.println("<b>IP Address:</b>");
  349. //client.println(Ethernet.localIP());
  350. client.println("<b>Sensor Location:</b>");
  351. //client.println("Bay Four - Tool Room");
  352. client.println(LOCATIONOFSENSOR);
  353. client.println("<b>Type of Sensor</b>:");
  354. client.println("Microwave - HFS-DC06H");
  355. client.println("<b>Temperature Sensor Value:</b>");
  356. client.println(TEMPERATUREVALUE2);
  357. client.println("</pre></html>");
  358. break;
  359. }
  360. if (c == '\n') {
  361. // you're starting a new line
  362. currentLineIsBlank = true;
  363. } else if (c != '\r') {
  364. // you've gotten a character on the current line
  365. currentLineIsBlank = false;
  366. }
  367. }
  368. }
  369. // give the web browser time to receive the data
  370. delay(1);
  371. // close the connection:
  372. client.stop();
  373. Serial.println(F("client disconnected"));
  374. }
  375. //write to eeprom if connection failed, and try again upon reboot
  376. //EEPROM.write(EEPROM_RETRY, switch_pressed);
  377. } //end main loop