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.

421 lines
10 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
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
  1. /*
  2. *
  3. * ZoneMinder Hardware Project
  4. * Laser Sensor
  5. *
  6. *
  7. * A sensor communicating
  8. * via ENC28J60 to ZMTrigger daemon
  9. *
  10. *
  11. */
  12. /*
  13. * What it does:
  14. *
  15. *
  16. */
  17. /*
  18. *
  19. *
  20. *
  21. * Directions:
  22. *
  23. * Use Arduino Uno
  24. * Connect Pin 3 to Reset pin (may not be needed)
  25. * Connect ENC28J60 using these instructions:
  26. * https://github.com/ntruchsess/arduino_uip
  27. * http://web.archive.org/save/https://create.arduino.cc/projecthub/Sourcery/how-to-connect-the-enc28j60-to-an-arduino-efd0dd
  28. * CS for ENC and UIP library is 10 by default on UNO. Not 8, like that link says.
  29. *
  30. * Connect microwave motion sensor such as HB100, or laser diode to A1
  31. * Add a speaker for audible debugging
  32. * LED can also be added
  33. *
  34. *
  35. *
  36. *
  37. */
  38. #include <UIPEthernet.h>
  39. #include <EEPROM.h>
  40. //Edit the below values
  41. #define DEBUGMODE 1 // 1 == on. 0 == off.
  42. /***************Ethernet ENC28J60***************/
  43. //Mac must be unique
  44. byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xEA, 0x15 };
  45. //IP of Arduino
  46. byte ip[] = { 192, 168, 1, 177 };
  47. //IP of zm server
  48. byte server[] = { 192, 168, 1, 178 };
  49. //ZM server ip to put in requests.
  50. //maybe you can use hostname, not sure. TODO: test hostnames
  51. String host="192.168.1.178";
  52. //username and password to login to Zoneminder Server.
  53. //If you don't have authentication, you will need to edit the
  54. //script.
  55. //NOTE: not needed for ZMTrigger. Only API. DO NOT USE
  56. //String username="username";
  57. //String password="password";
  58. EthernetClient client;
  59. #define ZMTRIGGERPORT 6802
  60. //set to 1 if using sick sensor (on analog pin)
  61. #define SICK 0
  62. /***************Pins***************/
  63. #define SPEAKER_PIN 6
  64. #define LED_PIN 9
  65. //#define RESETPIN 2 //may not be needed here
  66. #define SENSORPIN A1
  67. #define TEMPPIN A0
  68. /***************Variables************/
  69. int MotionSensorRead = 0;
  70. uint8_t AlarmActive = 0;
  71. char* ZMTriggerMessage = "1234567890123456789012345678901234"; //Initialize this with dummy data
  72. int TEMPERATUREVALUE = 0;
  73. int TEMPERATUREVALUE2 = 0;
  74. // Upper and lower limit for ADC to register motion
  75. // The HB100 outputs a wave that chaotically moves up and down. If the wave reaches a
  76. // high or low point, we register an alarm.
  77. // These should be tuned depending on your setup and how sensitive you want motion detected
  78. // without getting false alarms. Easiest to test with Serial output
  79. #define UPPERLIMIT 900
  80. #define LOWERLIMIT 100
  81. /*
  82. ZMTrigger Command to Send
  83. B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext>
  84. which in this code is:
  85. monnum | onoff + timealarm | score | source
  86. e.g.
  87. 2|on+5|100|ZoneAVR||
  88. This will send a command to ZMTrigger.pl to turn monitor #2 ON (alarm state) for five seconds, with a score of 100
  89. and the source of ZoneAVR. The text field, and show text are not setup here.
  90. */
  91. char* monnum = "25"; //monitor number
  92. char* onoff = "on"; //command to send to zmtrigger.
  93. char* timealarm = "10"; //time to set monitor to alarm
  94. char* score = "100"; //score to assign
  95. char* source = "ZMHW MotionSensor"; //source
  96. // Initialize the Ethernet server library
  97. #define LISTENPORT 80// (port 80 is default for HTTP):
  98. EthernetServer server2 = EthernetServer(LISTENPORT);
  99. //Do not need to edit below
  100. void chime(int freq){
  101. tone(SPEAKER_PIN, freq, 50);
  102. delay(50);
  103. }
  104. void chimefast(int freq, int fast){
  105. tone(SPEAKER_PIN, freq, fast);
  106. delay(fast);
  107. }
  108. //timer/interrupt
  109. uint16_t timer1;
  110. uint16_t timer1_counter;
  111. uint8_t debouncetime;
  112. uint8_t first_interrupt = 0;
  113. //timer for debounce
  114. ISR(TIMER1_OVF_vect){
  115. timer1++;
  116. if (first_interrupt == 1 ){
  117. debouncetime++;
  118. }
  119. if (debouncetime > 2) {
  120. first_interrupt = 0;
  121. debouncetime = 0;
  122. AlarmActive = 0;
  123. }
  124. }
  125. void setup()
  126. {
  127. Serial.begin(9600);
  128. Serial.println("ZMHW Project");
  129. Serial.println("Motion Sensor");
  130. pinMode(SENSORPIN, INPUT);
  131. pinMode(SPEAKER_PIN, OUTPUT);
  132. //pinMode(RESETPIN, OUTPUT);
  133. //Be careful. Areg is 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  134. analogReference(INTERNAL);
  135. Ethernet.begin(mac, ip);
  136. server2.begin();
  137. Serial.print("server is at ");
  138. Serial.println(Ethernet.localIP());
  139. //timer 1, setup
  140. //Crystal of Uno is == Mega (16MHz)
  141. //this timer is all bodged up, but doesn't matter, as we only
  142. //need two or three counts between alarms. Not going to fix atm.
  143. //and it works.
  144. //Clear existing registers
  145. TCCR1A = 0;
  146. TCCR1B = 0;
  147. // Set timer1_counter to the correct value for our interrupt interval
  148. //timer1_counter = 10000; // 62500 for one second if using 256 prescaler. can't be over 16 bit value (timer1 is 16bit limited)
  149. //timer1_counter = 10;
  150. //TCNT1 = timer1_counter; // TCNT1 is what we are overflowing on
  151. TCCR1B |= (1 << CS12); // 256 prescaler (divide 16mhz/256 = 62500)
  152. TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html
  153. // search tccr1b
  154. TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged)
  155. //end timer1
  156. sei(); //timer needs interrupts, enable interrupts
  157. tone(SPEAKER_PIN, 1000, 200);
  158. delay(100);
  159. tone(SPEAKER_PIN, 2000, 200);
  160. delay(100);
  161. tone(SPEAKER_PIN, 2200, 200);
  162. delay(100);
  163. }
  164. void loop()
  165. {
  166. //The SICK infrared laser requires a transistor to output
  167. //high or low, but we will cheat and instead, put it through
  168. //a serial diode, and then use the ADC instead of a digital pin
  169. //saves a few seconds to put a diode on the end instead of transistor
  170. MotionSensorRead = analogRead(SENSORPIN);
  171. Serial.print("Motion Sensor Value: ");
  172. Serial.println(String(MotionSensorRead));
  173. //Serial.println(String(timer1));
  174. delay(10);
  175. TEMPERATUREVALUE = analogRead(TEMPPIN);
  176. Serial.print("Temperature Value: ");
  177. // See resources. uses 1.1 aref, converts to celcius, then to Fareinheit.
  178. TEMPERATUREVALUE2 = (TEMPERATUREVALUE / 9.31)* 2 + 30;
  179. Serial.println(String(TEMPERATUREVALUE2));
  180. delay(10);
  181. if(DEBUGMODE){
  182. delay(10);
  183. }
  184. //Motion sensing for Sick Photoelectric sensor only
  185. //upon boot, values are around 400 sometimes, so only alert at higher
  186. if(SICK == 1){
  187. if (MotionSensorRead > 500 && AlarmActive == 0){
  188. Serial.println("Motion Detected");
  189. //firstpacketsend = 0;
  190. cli();
  191. //some of this may be redundant, need to check
  192. AlarmActive = 1;
  193. first_interrupt = 1;
  194. debouncetime = 0;
  195. sei();
  196. //Want the chime to be only noticeable if you know what to listen
  197. //for. Make it a high freq. sound that is easy to miss.
  198. chime(13000);
  199. Serial.println("Connecting...");
  200. if (client.connect(server, ZMTRIGGERPORT)) {
  201. chime(13000);
  202. //beware that the buffer in snprintf is big enough to hold everything
  203. snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source);
  204. Serial.print("the TCP Packet being sent:");
  205. Serial.println(String(ZMTriggerMessage));
  206. client.println(String(ZMTriggerMessage)); //required
  207. Serial.println("TCP packet sent to ZMTrigger");
  208. client.stop();
  209. }
  210. else {
  211. //NOTE: If you are not connected to the network
  212. //the device will currently freeze up, and not timeout.
  213. //Need to implement a watchdog.
  214. //If you ARE connected to the network, and server is not available
  215. //then it will timeout.
  216. Serial.println("Connection to ZM Server failed");
  217. chime(50);
  218. delay(100);
  219. chime(50);
  220. delay(100);
  221. chime(50);
  222. delay(100);
  223. }
  224. }
  225. }//end sick
  226. //disconnect
  227. if (!client.connected()) {
  228. client.stop();
  229. }
  230. //Serve Status Page
  231. // listen for incoming clients
  232. EthernetClient client = server2.available();
  233. if (client) {
  234. Serial.println("new client");
  235. // an http request ends with a blank line
  236. boolean currentLineIsBlank = true;
  237. while (client.connected()) {
  238. if (client.available()) {
  239. char c = client.read();
  240. Serial.write(c);
  241. // if you've gotten to the end of the line (received a newline
  242. // character) and the line is blank, the http request has ended,
  243. // so you can send a reply
  244. if (c == '\n' && currentLineIsBlank) {
  245. // send a standard http response header
  246. client.println("HTTP/1.1 200 OK");
  247. client.println("Content-Type: text/html");
  248. client.println("Connection: close"); // the connection will be closed after completion of the response
  249. client.println("Refresh: 5"); // refresh the page automatically every 5 sec
  250. client.println();
  251. client.println("<!DOCTYPE HTML>");
  252. client.println("<html><pre>");
  253. client.println("<b>Steak Electronics</b>");
  254. client.println("\"Steak it easy... That is, don't overcook steak\"");
  255. client.println("");
  256. //client.println("<b>IP Address:</b>");
  257. //client.println(Ethernet.localIP());
  258. client.println("<b>Sensor Location:</b>");
  259. client.println("Bay Four - Tool Room");
  260. client.println("<b>Type of Sensor</b>:");
  261. client.println("Microwave - HFS-DC06H");
  262. client.println("<b>Temperature Sensor Value:</b>");
  263. client.println(TEMPERATUREVALUE2);
  264. client.println("</pre></html>");
  265. break;
  266. }
  267. if (c == '\n') {
  268. // you're starting a new line
  269. currentLineIsBlank = true;
  270. } else if (c != '\r') {
  271. // you've gotten a character on the current line
  272. currentLineIsBlank = false;
  273. }
  274. }
  275. }
  276. // give the web browser time to receive the data
  277. delay(1);
  278. // close the connection:
  279. client.stop();
  280. Serial.println("client disconnected");
  281. }
  282. //write to eeprom if connection failed, and try again upon reboot
  283. //EEPROM.write(EEPROM_RETRY, switch_pressed);
  284. } //end main loop