/* * * ZoneMinder Hardware Project * Laser Sensor * * * A sensor communicating * via ENC28J60 to ZMTrigger daemon * * */ /* * What it does: * * */ /* * * * * 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. * * Connect microwave motion sensor such as HB100, or laser diode to A1 * Add a speaker for audible debugging * LED can also be added * * * * */ #include #include //Edit the below values #define DEBUGMODE 1 // 1 == on. 0 == off. /***************Ethernet ENC28J60***************/ //Mac must be unique byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xEA, 0x15 }; //IP of Arduino byte ip[] = { 192, 168, 1, 177 }; //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 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 //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 /***************Variables************/ 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 /* ZMTrigger Command to Send B|B|B|B|B|B which in this code is: monnum | onoff + timealarm | score | source e.g. 2|on+5|100|ZoneAVR|| This will send a command to ZMTrigger.pl to turn monitor #2 ON (alarm state) for five seconds, with a score of 100 and the source of ZoneAVR. The text field, and show text are not setup here. */ 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); //Do not need to edit below void chime(int freq){ tone(SPEAKER_PIN, freq, 50); delay(50); } void chimefast(int freq, int fast){ tone(SPEAKER_PIN, freq, fast); delay(fast); } //timer/interrupt uint16_t timer1; uint16_t timer1_counter; uint8_t debouncetime; uint8_t first_interrupt = 0; //timer for debounce ISR(TIMER1_OVF_vect){ timer1++; if (first_interrupt == 1 ){ debouncetime++; } if (debouncetime > 2) { first_interrupt = 0; debouncetime = 0; AlarmActive = 0; } } void setup() { Serial.begin(9600); Serial.println("ZMHW Project"); Serial.println("Motion Sensor"); pinMode(SENSORPIN, INPUT); pinMode(SPEAKER_PIN, OUTPUT); //pinMode(RESETPIN, OUTPUT); //Be careful. Areg is 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! analogReference(INTERNAL); Ethernet.begin(mac, ip); server2.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); //timer 1, setup //Crystal of Uno is == Mega (16MHz) //this timer is all bodged up, but doesn't matter, as we only //need two or three counts between alarms. Not going to fix atm. //and it works. //Clear existing registers TCCR1A = 0; TCCR1B = 0; // Set timer1_counter to the correct value for our interrupt interval //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 sei(); //timer needs interrupts, enable interrupts tone(SPEAKER_PIN, 1000, 200); delay(100); tone(SPEAKER_PIN, 2000, 200); delay(100); tone(SPEAKER_PIN, 2200, 200); delay(100); } void loop() { //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 MotionSensorRead = analogRead(SENSORPIN); Serial.print("Motion Sensor Value: "); Serial.println(String(MotionSensorRead)); //Serial.println(String(timer1)); delay(10); TEMPERATUREVALUE = analogRead(TEMPPIN); Serial.print("Temperature Value: "); // See resources. uses 1.1 aref, converts to celcius, then to Fareinheit. TEMPERATUREVALUE2 = (TEMPERATUREVALUE / 9.31)* 2 + 30; Serial.println(String(TEMPERATUREVALUE2)); delay(10); if(DEBUGMODE){ delay(10); } //Motion sensing for Sick Photoelectric sensor only //upon boot, values are around 400 sometimes, so only alert at higher if(SICK == 1){ if (MotionSensorRead > 500 && AlarmActive == 0){ Serial.println("Motion Detected"); //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. 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(50); delay(100); chime(50); delay(100); chime(50); delay(100); } } }//end sick //disconnect if (!client.connected()) { client.stop(); } //Serve Status Page // listen for incoming clients EthernetClient client = server2.available(); if (client) { Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println("Refresh: 5"); // refresh the page automatically every 5 sec client.println(); client.println(""); client.println("
");
          client.println("Steak Electronics");
          client.println("\"Steak it easy... That is, don't overcook steak\"");
          client.println("");
          //client.println("IP Address:");
          //client.println(Ethernet.localIP());
          client.println("Sensor Location:");
          client.println("Bay Four - Tool Room");
          client.println("Type of Sensor:");
          client.println("Microwave - HFS-DC06H");
          client.println("Temperature Sensor Value:");
          client.println(TEMPERATUREVALUE2);
          client.println("
"); break; } if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); Serial.println("client disconnected"); } //write to eeprom if connection failed, and try again upon reboot //EEPROM.write(EEPROM_RETRY, switch_pressed); } //end main loop