diff --git a/ZMHW_Project_InfraredDiodeSensor.ino b/ZMHW_Project_InfraredDiodeSensor.ino index 29058ba..51277a3 100644 --- a/ZMHW_Project_InfraredDiodeSensor.ino +++ b/ZMHW_Project_InfraredDiodeSensor.ino @@ -1,19 +1,32 @@ /* * * ZoneMinder Hardware Project - * Laser Sensor + * * * - * A sensor communicating - * via ENC28J60 to ZMTrigger daemon + * A sensor on an Arduino UNO communicating + * via ethernet to ZMTrigger daemon for ZoneMinder + * CCTV GNU/Linux software. * * */ /* - * What it does: + * What it does: + * Works with accompanying shield to act as motion sensor + * for Zoneminder via ZMTrigger. Shield is optional if you + * want to bother with a perf board and components instead. * + * Components: + * ENC28J60 + * Motion Sensor (Either PIR, or microwave HFS-DC06H) + * Microphone for Loud Noise alarms + * LM35 Temperature Sensor + * RGB Status LED + * Speaker + * + * Power from External 12V supply, not USB!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * */ @@ -21,18 +34,15 @@ * * * - * Directions: - * - * Use Arduino Uno - * Connect Pin 3 to Reset pin (may not be needed) - * Connect ENC28J60 using these instructions: - * https://github.com/ntruchsess/arduino_uip - * http://web.archive.org/save/https://create.arduino.cc/projecthub/Sourcery/how-to-connect-the-enc28j60-to-an-arduino-efd0dd - * CS for ENC and UIP library is 10 by default on UNO. Not 8, like that link says. + * Directions: + * Use Arduino Uno + * See https://git.steakelectronics.com/adminguy/ZMHW_Project_InfraredDiodeSensor + * + * Connect ENC28J60 using these instructions: + * https://github.com/ntruchsess/arduino_uip + * http://web.archive.org/save/https://create.arduino.cc/projecthub/Sourcery/how-to-connect-the-enc28j60-to-an-arduino-efd0dd + * CS for ENC and UIP library is 10 by default on UNO. Not 8, like that link says. * - * Connect microwave motion sensor such as HB100, or laser diode to A1 - * Add a speaker for audible debugging - * LED can also be added * * * @@ -50,74 +60,64 @@ //Edit the below values -#define DEBUGMODE 1 // 1 == on. 0 == off. - +#define DEBUGMODE 0 // 1 == on. 0 == off. +#define MIC 0 // 1 == on. 0 == off. +#define SICK 0 // set to 1 if using sick sensor (on analog pin) + // sick sensor is a transistor activated photoelectric + // sensor. More details below. +#define NORMALMODECT 0 // For a digital High motion sensor. /***************Ethernet ENC28J60***************/ -//Mac must be unique +//Mac must be unique for each sensor byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xEA, 0x15 }; -//IP of Arduino +//Static IP of Arduino byte ip[] = { 192, 168, 1, 177 }; -//IP of zm server +//IP of ZM Server byte server[] = { 192, 168, 1, 178 }; - -//ZM server ip to put in requests. -//maybe you can use hostname, not sure. TODO: test hostnames +//ZM server IP to put in requests. String host="192.168.1.178"; -//username and password to login to Zoneminder Server. -//If you don't have authentication, you will need to edit the -//script. -//NOTE: not needed for ZMTrigger. Only API. DO NOT USE -//String username="username"; -//String password="password"; -EthernetClient client; #define ZMTRIGGERPORT 6802 +#define LISTENPORT 80 // (port 80 is default for HTTP) -//set to 1 if using sick sensor (on analog pin) -#define SICK 0 /***************Pins***************/ -#define SPEAKER_PIN 6 -#define LED_PIN 9 -//#define RESETPIN 2 //may not be needed here -#define SENSORPIN A1 -#define TEMPPIN A0 +//Digital +#define MODECTPIN 2 +#define SPEAKERPIN 6 +#define LEDPIN 9 -/***************Variables************/ +//Analog +#define TEMPPIN A0 +#define SICKPIN A1 +#define MICROPHONEPIN A2 -int MotionSensorRead = 0; -uint8_t AlarmActive = 0; -char* ZMTriggerMessage = "1234567890123456789012345678901234"; //Initialize this with dummy data -int TEMPERATUREVALUE = 0; -int TEMPERATUREVALUE2 = 0; -// Upper and lower limit for ADC to register motion -// The HB100 outputs a wave that chaotically moves up and down. If the wave reaches a -// high or low point, we register an alarm. - -// These should be tuned depending on your setup and how sensitive you want motion detected -// without getting false alarms. Easiest to test with Serial output - -#define UPPERLIMIT 900 -#define LOWERLIMIT 100 +char* LOCATIONOFSENSOR = "Bay Four - Tool Room"; +/***************Variables************/ +uint16_t MotionSensorRead = 0; +uint8_t AlarmActive = 0; +char* ZMTriggerMessage = "1234567890123456789012345678901234"; //Initialize this with dummy data +uint8_t TEMPERATUREVALUE = 0; +uint8_t TEMPERATUREVALUE2 = 0; +uint8_t SOUNDVALUE = 0; +uint8_t MODECTVALUE = 0; /* - ZMTrigger Command to Send B|B|B|B|B|B @@ -137,37 +137,31 @@ char* monnum = "25"; //monitor number char* onoff = "on"; //command to send to zmtrigger. char* timealarm = "10"; //time to set monitor to alarm char* score = "100"; //score to assign -char* source = "ZMHW MotionSensor"; //source - - - - - -// Initialize the Ethernet server library - -#define LISTENPORT 80// (port 80 is default for HTTP): -EthernetServer server2 = EthernetServer(LISTENPORT); +char* source = "ZMHW MotionSensor"; //source. Add details as needed (e.g. Hallway sensor) +//Do not need to edit below -//Do not need to edit below +// Initialize the Ethernet server library +EthernetClient client; +EthernetServer server2 = EthernetServer(LISTENPORT); void chime(int freq){ - tone(SPEAKER_PIN, freq, 50); + tone(SPEAKERPIN, freq, 50); delay(50); } void chimefast(int freq, int fast){ - tone(SPEAKER_PIN, freq, fast); + tone(SPEAKERPIN, freq, fast); delay(fast); } @@ -202,11 +196,12 @@ void setup() Serial.println("ZMHW Project"); Serial.println("Motion Sensor"); - pinMode(SENSORPIN, INPUT); - pinMode(SPEAKER_PIN, OUTPUT); - //pinMode(RESETPIN, OUTPUT); + pinMode(SICKPIN, INPUT); + pinMode(MICROPHONEPIN, INPUT); + pinMode(SPEAKERPIN, OUTPUT); + pinMode(MODECTPIN, INPUT); - //Be careful. Areg is 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //Be careful. This sets Areg to 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! analogReference(INTERNAL); @@ -234,21 +229,21 @@ void setup() //timer1_counter = 10000; // 62500 for one second if using 256 prescaler. can't be over 16 bit value (timer1 is 16bit limited) //timer1_counter = 10; //TCNT1 = timer1_counter; // TCNT1 is what we are overflowing on - TCCR1B |= (1 << CS12); // 256 prescaler (divide 16mhz/256 = 62500) - TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html - // search tccr1b - TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged) - //end timer1 + TCCR1B |= (1 << CS12); // 256 prescaler (divide 16mhz/256 = 62500) + TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html + // search tccr1b + TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged) + //end timer1 - sei(); //timer needs interrupts, enable interrupts + sei(); //timer needs interrupts, enable (set) interrupts - tone(SPEAKER_PIN, 1000, 200); + tone(SPEAKERPIN, 1000, 200); delay(100); - tone(SPEAKER_PIN, 2000, 200); + tone(SPEAKERPIN, 2000, 200); delay(100); - tone(SPEAKER_PIN, 2200, 200); + tone(SPEAKERPIN, 2200, 200); delay(100); } @@ -258,17 +253,23 @@ void loop() { + + +/*****************ANALOG SECTION******************/ + //The SICK infrared laser requires a transistor to output //high or low, but we will cheat and instead, put it through //a serial diode, and then use the ADC instead of a digital pin //saves a few seconds to put a diode on the end instead of transistor + //when soldering by hand. Works equally as well. Requires ADC pin. - - MotionSensorRead = analogRead(SENSORPIN); + if (SICK){ + MotionSensorRead = analogRead(SICKPIN); Serial.print("Motion Sensor Value: "); Serial.println(String(MotionSensorRead)); //Serial.println(String(timer1)); delay(10); + } TEMPERATUREVALUE = analogRead(TEMPPIN); Serial.print("Temperature Value: "); @@ -276,17 +277,38 @@ void loop() TEMPERATUREVALUE2 = (TEMPERATUREVALUE / 9.31)* 2 + 30; Serial.println(String(TEMPERATUREVALUE2)); delay(10); + + if (MIC){ + SOUNDVALUE = analogRead(MICROPHONEPIN); + Serial.print("Sound Value: "); + Serial.println(String(SOUNDVALUE)); + delay(10); + } + + //if (NORMALMODECT){ + MODECTVALUE = digitalRead(MODECTPIN); + Serial.print("Motion Detector Value (normal): "); + Serial.println(String(MODECTVALUE)); + //} + if(DEBUGMODE){ delay(10); } + + +/****************MOTION SENSING****************/ + + + + //SICK //Motion sensing for Sick Photoelectric sensor only //upon boot, values are around 400 sometimes, so only alert at higher - if(SICK == 1){ + if(SICK){ if (MotionSensorRead > 500 && AlarmActive == 0){ - Serial.println("Motion Detected"); + Serial.println("Motion Detected on Sick"); //firstpacketsend = 0; @@ -299,6 +321,7 @@ void loop() //Want the chime to be only noticeable if you know what to listen //for. Make it a high freq. sound that is easy to miss. + //Resistors to speaker should be high chime(13000); @@ -315,11 +338,7 @@ void loop() snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source); Serial.print("the TCP Packet being sent:"); Serial.println(String(ZMTriggerMessage)); - - client.println(String(ZMTriggerMessage)); //required - - Serial.println("TCP packet sent to ZMTrigger"); client.stop(); } @@ -344,6 +363,66 @@ void loop() + + + //Digital High Motion Sensor + if(NORMALMODECT){ + + if (MODECTVALUE==HIGH){ + Serial.println("Motion Detected on Normal Sensor"); + + //firstpacketsend = 0; + + cli(); + //some of this may be redundant, need to check + AlarmActive = 1; + first_interrupt = 1; + debouncetime = 0; + sei(); + + //Want the chime to be only noticeable if you know what to listen + //for. Make it a high freq. sound that is easy to miss. + //Resistors to speaker should be high + chime(13000); + + + Serial.println("Connecting..."); + + + if (client.connect(server, ZMTRIGGERPORT)) { + + chime(13000); + + + + //beware that the buffer in snprintf is big enough to hold everything + snprintf(ZMTriggerMessage, 56, "%s|%s+%s|%s|%s||", monnum, onoff, timealarm, score, source); + Serial.print("the TCP Packet being sent:"); + Serial.println(String(ZMTriggerMessage)); + client.println(String(ZMTriggerMessage)); //required + Serial.println("TCP packet sent to ZMTrigger"); + client.stop(); + } + else { + //NOTE: If you are not connected to the network + //the device will currently freeze up, and not timeout. + //Need to implement a watchdog. + //If you ARE connected to the network, and server is not available + //then it will timeout. + + Serial.println("Connection to ZM Server failed"); + + chime(40); + delay(100); + chime(60); + delay(100); + chime(60); + delay(100); + } + } + MODECTVALUE=LOW; + }//end normal Motion Sensor + //disconnect if (!client.connected()) { @@ -353,6 +432,19 @@ void loop() + + + +/********************SERVER STATUS PAGE*********************/ +/* + * With this, you can logon to the Sensor from your LAN to find + * out just what device this IP address is, in case you happen to + * forget. We can also pull the temperature from this page, and + * populate it to the camera feed, via ZMTrigger, from a server + * side wget. + */ + + //Serve Status Page // listen for incoming clients EthernetClient client = server2.available(); @@ -382,7 +474,7 @@ void loop() //client.println("IP Address:"); //client.println(Ethernet.localIP()); client.println("Sensor Location:"); - client.println("Bay Four - Tool Room"); + client.println(LOCATIONOFSENSOR); client.println("Type of Sensor:"); client.println("Microwave - HFS-DC06H"); client.println("Temperature Sensor Value:");