Your Name 5 years ago
parent
commit
d254ab7541
2 changed files with 164 additions and 401 deletions
  1. +162
    -388
      ZMHW_Modector/ZMHW_Modector.ino
  2. +2
    -13
      ZMHW_Modector/testsuite/ReadMotionSensor/ReadMotionSensor.ino

+ 162
- 388
ZMHW_Modector/ZMHW_Modector.ino View File

@ -1,233 +1,107 @@
/* /*
* ZMHW Modector
* *
* ZoneMinder Hardware Project
*
* Digital High outputs TCP Packet to ZMTrigger
* Steak Electronics Company 2019
* *
* *
* A sensor on an Arduino UNO communicating
* via ethernet to ZMTrigger daemon for ZoneMinder
* CCTV GNU/Linux software.
*
*
*/
/*
* What it does:
* Works with accompanying shield to act as motion sensor
* for Zoneminder via ZMTrigger. Shield is optional but recommended
* as it's easier to build.
*
* 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
*/ */
/* /*
*
*
*
* 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.
*
*
*
*
*
*/
Same as default library but uses UIPEthernet. Requires UIPEthernet.
Manage Libraries - Download UIP Ethernet library
*/
/*
Web Server
#include <UIPEthernet.h>
//#include <EEPROM.h>
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
//Edit the below values
#include <SPI.h>
#include <UIPEthernet.h>
#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 1 // For a digital High motion sensor. #define NORMALMODECT 1 // For a digital High motion sensor.
#define TWOSERVERS 1
/***************Ethernet ENC28J60***************/
//Mac must be unique for each sensor
byte mac[] = { 0xD3, 0x5D, 0xBE, 0xEF, 0xEE, 0x52 };
//Static IP of Arduino
byte ip[] = { 192, 168, 78, 52 };
//IP of ZM Server
byte server[] = { 192, 168, 78, 123 };
//ZM server IP to put in requests.
String host="192.168.78.123";
char* monnum = "14"; //monitor number
char* LOCATIONOFSENSOR = "Bay 1";
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x50
};
IPAddress ip(192, 168, 1, 50);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
#define LISTENPORT 80
EthernetServer serverHOST(LISTENPORT);
//Client
byte server[] = { 192, 168, 1, 115 };
//byte serverB[] = { 192, 168, 1, 116 }; //can't be server2, as that is already set for ethernetserver below
String host="192.168.1.115";
char* monnum = "32"; //monitor number
char* LOCATIONOFSENSOR = "FtLab";
#define ZMTRIGGERPORT 6802 #define ZMTRIGGERPORT 6802
#define LISTENPORT 80 // (port 80 is default for HTTP)
/***************Pins***************/
//Digital
#define MODECTPIN 4
#define SPEAKERPIN 6
#define LEDPIN 9
//Analog
#define TEMPPIN A0
#define SICKPIN A1
#define MICROPHONEPIN A2
/***************Variables************/
EthernetClient client;
//IO
#define MODECTPIN 8
//GLOBALS
uint8_t AlarmActive = 0; uint8_t AlarmActive = 0;
char* ZMTriggerMessage = "1234567890123456789012345"; //Initialize this with dummy data char* ZMTriggerMessage = "1234567890123456789012345"; //Initialize this with dummy data
uint8_t TEMPERATUREVALUE = 0; uint8_t TEMPERATUREVALUE = 0;
uint8_t TEMPERATUREVALUE2 = 0; uint8_t TEMPERATUREVALUE2 = 0;
uint8_t SOUNDVALUE = 0;
uint16_t MODECTVALUE = 0;
/*
ZMTrigger Command to Send
B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext>
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* onoff = "on"; //command to send to zmtrigger.
char* timealarm = "10"; //time to set monitor to alarm
char* score = "77"; //score to assign
char* source = "ZMHW"; //source. Add details as needed (e.g. Hallway sensor)
//Do not need to edit below
// Initialize the Ethernet server library
EthernetClient client;
EthernetServer server2 = EthernetServer(LISTENPORT);
/*
void chime(int freq){
tone(SPEAKERPIN, freq, 50);
delay(50);
}
void chimefast(int freq, int fast){
tone(SPEAKERPIN, freq, fast);
delay(fast);
}*/
//timer/interrupt
uint16_t timer1;
uint16_t timer1_counter;
uint8_t debouncetime;
uint8_t MODECTVALUE = 0;
char* onoff = "on"; //command to send to zmtrigger.
char* timealarm = "10"; //time to set monitor to alarm
char* score = "77"; //score to assign
char* source = "ZMHW";//source. Add details as needed (e.g. Hallway sensor)
uint8_t ActivateServer2 = 0;
//Interrupt / Timer
uint16_t timer1 = 0;
uint16_t timer1_counter = 0;
uint8_t debouncetime = 0;
uint8_t first_interrupt = 0; uint8_t first_interrupt = 0;
//timer for debounce
//for debounce
ISR(TIMER1_OVF_vect){ ISR(TIMER1_OVF_vect){
timer1++;
timer1++;
if (first_interrupt == 1 ){ if (first_interrupt == 1 ){
debouncetime++; debouncetime++;
} }
if (debouncetime > 2) { if (debouncetime > 2) {
first_interrupt = 0; first_interrupt = 0;
debouncetime = 0; debouncetime = 0;
AlarmActive = 0; AlarmActive = 0;
} }
}
void setup()
{
Serial.begin(9600);
Serial.println(F("ZMHW Project"));
Serial.println(F("Motion Sensor"));
//if sick
pinMode(SICKPIN, INPUT);
//if mic
pinMode(MICROPHONEPIN, INPUT);
//if speaker
pinMode(SPEAKERPIN, OUTPUT);
pinMode(MODECTPIN, INPUT);
pinMode(TEMPPIN, INPUT);
}
//Be careful. This sets Areg to 1.1v!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Used for LM35.
analogReference(INTERNAL);
Ethernet.begin(mac, ip);
server2.begin();
Serial.print(F("server is at "));
Serial.println(Ethernet.localIP());
//timer 1, setup
void TimerInit(void){
//Crystal of Uno is == Mega (16MHz) //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.
//this timer init is flawed, but doesn't matter, as we only
//need two or three counts between alarms. TODO: clean up
//Clear existing registers
TCCR1A = 0;
TCCR1A = 0; //Clear existing registers
TCCR1B = 0; TCCR1B = 0;
// Set timer1_counter to the correct value for our interrupt interval // Set timer1_counter to the correct value for our interrupt interval
@ -238,94 +112,28 @@ void setup()
TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html TCCR1B |= 00000101; // https://web.archive.org/web/20170707164930/http://www.avrbeginners.net:80/architecture/timers/timers.html
// search tccr1b // search tccr1b
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged) TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt (if goes over timer, interrupt flagged)
//end timer1
sei(); //timer needs interrupts, enable (set) interrupts sei(); //timer needs interrupts, enable (set) interrupts
//tone(SPEAKERPIN, 1000, 200);
//delay(100);
//tone(SPEAKERPIN, 2000, 200);
//delay(100);
//tone(SPEAKERPIN, 2200, 200);
//delay(100);
} }
void loop()
{
//delay(50);
/*****************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.
/*
if (SICK){
MotionSensorRead = analogRead(SICKPIN);
Serial.print("Motion Sensor Value: ");
Serial.println(String(MotionSensorRead));
//Serial.println(String(timer1));
delay(30);
}
*/
//todo: only serial.print temp every 10 or so reads
TEMPERATUREVALUE = analogRead(TEMPPIN);
Serial.print(F("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(30);
/*
if (MIC){
SOUNDVALUE = analogRead(MICROPHONEPIN);
Serial.print("Sound Value: ");
Serial.println(String(SOUNDVALUE));
delay(30);
}
*/
if (NORMALMODECT){
void ReadModect(void){
if (NORMALMODECT){
delay(10); delay(10);
MODECTVALUE = digitalRead(MODECTPIN); MODECTVALUE = digitalRead(MODECTPIN);
delay(10); delay(10);
Serial.print(F("Motion Detector Value (normal): "));
//Serial.print(F("Motion Detector Value (normal): "));
//Serial.println(String(MODECTVALUE)); //Serial.println(String(MODECTVALUE));
Serial.println(MODECTVALUE);
delay(30);
//Serial.println(MODECTVALUE);
delay(30);
} }
}
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){
if (MODECTVALUE > 500 && AlarmActive == 0){
Serial.println(F("Motion Detected on Sick"));
void DigiModectChkandSend(void){
//Digital High Motion Sensor
if(NORMALMODECT){
if (MODECTVALUE==HIGH && AlarmActive == 0){
Serial.println(F("Motion Detected on Normal Sensor"));
//firstpacketsend = 0; //firstpacketsend = 0;
cli(); cli();
//some of this may be redundant, need to check //some of this may be redundant, need to check
AlarmActive = 1; AlarmActive = 1;
@ -333,141 +141,102 @@ void loop()
debouncetime = 0; debouncetime = 0;
sei(); 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...");
delay(10);
Serial.println(F("Connecting To Cam Srv"));
if (client.connect(server, ZMTRIGGERPORT)) {
//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(F("the TCP Packet being sent:"));
Serial.println(String(ZMTriggerMessage));
client.println(String(ZMTriggerMessage)); //required
Serial.println(F("TCP packet sent to ZMTrigger"));
client.stop();
if(TWOSERVERS){
ActivateServer2 = 1;
}
}
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(F("Connection to Server failed"));
}
}
}
}
void SendtoServer2(void){
server[0] = 192;
server[1] = 168;
server[2] = 1;
server[3] = 116;
host="192.168.1.116";
delay(10);
Serial.println(F("Connecting To Cam Srv"));
if (client.connect(server, ZMTRIGGERPORT)) {
client.println(String(ZMTriggerMessage)); //required
Serial.println(F("TCP packet sent to Server Two ZMTrigger"));
client.stop();
}
server[0] = 192;
server[1] = 168;
server[2] = 1;
server[3] = 115;
host="192.168.1.115";
ActivateServer2 = 0;
}
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(F("the TCP Packet being sent:"));
//Serial.println(String(ZMTriggerMessage));
client.println(String(ZMTriggerMessage)); //required
Serial.println(F("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(F("Connection to ZM Server failed"));
/*chime(50);
delay(100);
chime(50);
delay(100);
chime(50);
delay(100);
*/
}
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
} }
}//end sick
Serial.println(F("ZMHW Project"));
Serial.println(F("Motion Sensor"));
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
serverHOST.begin();
Serial.print(F("server is at "));
Serial.println(Ethernet.localIP());
//Digital High Motion Sensor
if(NORMALMODECT){
if (MODECTVALUE==HIGH && AlarmActive == 0){
Serial.println(F("Motion Detected on Normal Sensor"));
pinMode(MODECTPIN, INPUT);
//firstpacketsend = 0;
TimerInit();
}
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);
delay(10);
void loop() {
Serial.println(F("Connecting..."));
ReadModect();
DigiModectChkandSend();
if(TWOSERVERS && ActivateServer2){
SendtoServer2();
}
if (client.connect(server, ZMTRIGGERPORT)) {
//chime(13000);
//delay(10);
//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(F("the TCP Packet being sent:"));
Serial.println(String(ZMTriggerMessage));
client.println(String(ZMTriggerMessage)); //required
Serial.println(F("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(F("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()) {
client.stop();
}
/********************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 // listen for incoming clients
EthernetClient client = server2.available();
EthernetClient client = serverHOST.available();
if (client) { if (client) {
Serial.println(F("web visitor"));
Serial.println("new client");
// an http request ends with a blank line // an http request ends with a blank line
boolean currentLineIsBlank = true; boolean currentLineIsBlank = true;
while (client.connected()) { while (client.connected()) {
@ -478,7 +247,7 @@ void loop()
// character) and the line is blank, the http request has ended, // character) and the line is blank, the http request has ended,
// so you can send a reply // so you can send a reply
if (c == '\n' && currentLineIsBlank) { if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
// send a standard http response header
client.println("HTTP/1.1 200 OK"); client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html"); client.println("Content-Type: text/html");
//client.println("Connection: close"); // the connection will be closed after completion of the response //client.println("Connection: close"); // the connection will be closed after completion of the response
@ -487,10 +256,8 @@ void loop()
client.println("<!DOCTYPE HTML>"); client.println("<!DOCTYPE HTML>");
client.println("<html><pre>"); client.println("<html><pre>");
client.println("<b>Steak Electronics</b>"); client.println("<b>Steak Electronics</b>");
client.println("\"Steak it easy... That is, don't overcook steak\"");
client.println("\"Eat Steak, Use Birth Control\"");
client.println(""); client.println("");
//client.println("<b>IP Address:</b>");
//client.println(Ethernet.localIP());
client.print("Sensor Location:"); client.print("Sensor Location:");
client.println(LOCATIONOFSENSOR); client.println(LOCATIONOFSENSOR);
client.print("Type::"); client.print("Type::");
@ -515,19 +282,26 @@ void loop()
delay(1); delay(1);
// close the connection: // close the connection:
client.stop(); client.stop();
Serial.println(F("client disconnected"));
Serial.println("client disconnected");
} }
}
//write to eeprom if connection failed, and try again upon reboot
//EEPROM.write(EEPROM_RETRY, switch_pressed);
/*
ZMTrigger Command to Send
} //end main loop
B<id>|B<action>|B<score>|B<cause>|B<text>|B<showtext>
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.
*/

+ 2
- 13
ZMHW_Modector/testsuite/ReadMotionSensor/ReadMotionSensor.ino View File

@ -1,10 +1,6 @@
/* /*
* NOTE: this test is for HFS-DC06H * NOTE: this test is for HFS-DC06H
* *
* ZMHW Changes:
*
* Using pin 4. This might change depending on PCB revision. Double
* check.
* *
* If the Digital Hi (reads as 1's in serial) doesn't go away, and you are using USB, * If the Digital Hi (reads as 1's in serial) doesn't go away, and you are using USB,
* you might need external power. Some USB is not enough. * you might need external power. Some USB is not enough.
@ -12,15 +8,8 @@
* Ethernet draws power, even if library is not active. * Ethernet draws power, even if library is not active.
*/ */
/*
DigitalReadSerial
Reads a digital input on pin 2, prints the result to the serial monitor
This example code is in the public domain.
*/
// digital pin 2 has a pushbutton attached to it. Give it a name:
int MotionSensor = 4;
int MotionSensor = 8;
// the setup routine runs once when you press reset: // the setup routine runs once when you press reset:
void setup() { void setup() {
@ -36,7 +25,7 @@ void loop() {
int MotionState = digitalRead(MotionSensor); int MotionState = digitalRead(MotionSensor);
// print out the state of the button: // print out the state of the button:
Serial.println(MotionState); Serial.println(MotionState);
delay(100); // delay in between reads for stability
delay(300); // delay in between reads for stability
} }

Loading…
Cancel
Save