You are on page 1of 8

// Code Reference

// Microphone: https://learn.sparkfun.com/tutorials/electret-mic-breakout-board-hookup-
guide
// Accelerometer: https://www.mepits.com/project/292/Embedded-Projects/How-to-Interface-
ADXL-335-with-Arduino?

#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include <SoftwareSerial.h>
#include <Button.h>

//System variables
Adafruit_LiquidCrystal lcd(0);
Button butt1(5, INPUT_PULLUP); // keypad 1
Button butt2(6, INPUT_PULLUP); // keypad 2
Button butt3(7, INPUT_PULLUP); // keypad 3
Button butt4(8, INPUT_PULLUP); // keypad 4
const int stateLED1 = 9;
const int stateLED2 = 10;
const int alarmLED = 11;
const int speaker = 4;
int protocol;
int systemState;

//Accelerometer variables
const int xout = A0;
const int yout = A1;
const int zout = A2;
const long interval = 1000;
const long interval2 = 300;
const int stdInterval = 22;
long marker = 0;
long marker2 = 0;
int standard;
int out1 = 0;
int sout1 = 0;
int out2 = 0;
int sout2= 0;
int out3 = 0;
int sout3= 0;
int ledState = LOW;

//XBee variables
SoftwareSerial xBee(2, 3); // (TX, RX) : pins on XBee adapter
const String myNodeName = "R";
const byte TAB_CHAR = 0x09;
const byte NEWLINE_CHAR = 0x0A;
const int MAX_FIELDS = 4;
String aNode;
int butter = 0;
int messages = 0;

//Password variables
#define arr_len(x) (sizeof(x) / sizeof(*x))
const int password[5] = {3,2,1,4,3};
const int maxTrial = 3;
int pTrial[5] = {};
int currIndex;
int trialCount;
bool lock1 = true;
bool lock2 = true;
bool alarm = true;
bool warning = false;
bool stolen = false;
int warningCount = 0;

//Voice sensor variable


const int sampleWindow = 250; // Sample window width in mS (250 mS = 4Hz)
const int sigMax = 0;
const int sigMin = 1024;
const int mic = A3;
const int avgKnock = 3.25;
const int maxKnock = 8;
unsigned int knock;
unsigned int peakToPeak = 0; // peak-to-peak level
unsigned int signalMax = 0;
unsigned int signalMin = 1024;
long start;
double knockCheck;
bool firstTime = true;

void setup() {
pinMode(stateLED1, OUTPUT);
pinMode(stateLED2, OUTPUT);
pinMode(alarmLED, OUTPUT);
pinMode(speaker, OUTPUT);

lcd.begin(16, 2);
displayMSG("Food Block");
lcd.setCursor(0,1);
displayPassCount();

Serial.begin(9600);
xBee.begin(9600);
start = millis();

out1 = analogRead(xout);
out2 = analogRead(yout);
out3 = analogRead(zout);
standard = out1 + out2 + out3;
}

void loop() {
protocol = 0;
if (alarm) {
if(!lock1) {
keyCheck();
}

//Mic code
knock = analogRead(mic);
if (millis() - start < sampleWindow) {
if (knock < 1024) { //This is the max of the 10-bit ADC so this loop will include all
readings
if (knock > signalMax) {
signalMax = knock; // save just the max levels
} else if (knock < signalMin) {
signalMin = knock; // save just the min levels
}
}
} else {
peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude
double volts = (peakToPeak * 3.3) / 1024; // convert to volts
firstTime = !firstTime;
knockCheck += volts;
signalMax = sigMax;
signalMin = sigMin;
start = millis();
}
if (firstTime && lock1) {
if (knockCheck >= avgKnock*2 && knockCheck < maxKnock) {
lock1 = false;
protocol = 5;
Serial.println("Knock Knock");
}
knockCheck = 0;
}

//Password code
if(currIndex == 5) {
lock2 = passwordCheck();
if(!lock2) {
alarm = false;
displayMSG(" ");
displayMSG("Disarmed");
protocol = 8;
systemState = 8;
stolen = false;
trialCount = 0;
tone(speaker, 1600, 500);
Serial.println("*****UNLOCKED*****");
} else {
trialCount++;
displayMSG(" ");
displayMSG("Incorrect");
Serial.println("*****INCORRECT*****");
}
memset(pTrial, 0, sizeof(pTrial));
currIndex = 0;
displayPassCount();
if (trialCount == maxTrial) {
lock1 = true;
displayMSG("Food Block");
trialCount = 0;
tone(speaker, 800, 200);
}
}
if (!warning) {
int moveValue = out1 + out2 + out3;
if (standard - stdInterval > moveValue || standard + stdInterval < moveValue) {
warning = true;
Serial.println("*****MOVED*****");
protocol = 7;
}
}
} else {
setAlarm();
}
LEDControl();

//XBee code
xBeeCommand();

//Accelerometer code
if(millis() - marker >= interval) {
marker = millis();
out1 = analogRead(xout);
sout1 = map(out1, 0, 1023, 0, 255);
out2 = analogRead(yout);
sout2 = map(out2, 0, 1023, 0, 255);

out3 = analogRead(zout);
sout3 = map(out3, 0, 1023, 0, 255);
}
}

//--------------------Extra Functions--------------------
void xBeeCommand() {
if (protocol != 0) {
String msg = myNodeName + "\t" + protocol + "\n";
Serial.println(msg);
xBee.print(msg);
}

// check to see if any complete incoming messages are ready


String msg = checkMessageReceived();

if (msg.length() > 0) {
// if the result is a null string, then there is not a complete message ready
// otherwise we have received a complete message and can process it
String msgFields[MAX_FIELDS];

for (int i = 0; i < MAX_FIELDS; i++) {


msgFields[i] = "";
}

int fieldsFound = 0;
String buf = "";

for (int i = 0; i < msg.length(); i++) {


if (((msg.charAt(i) == TAB_CHAR) ||
(msg.charAt(i) == NEWLINE_CHAR)) &&
(fieldsFound < MAX_FIELDS)) {
msgFields[fieldsFound] = buf;
buf = "";
fieldsFound++;
}
else {
buf += msg.charAt(i);
}
}

if (msgFields[0].equals("R")){
aNode = "Remote";
} else if (msgFields[0].equals("B")){
aNode = "Food Box";
} else {
aNode = "Unknown";
}
Serial.print("Site = ");
Serial.println(aNode);

int aNumber = msgFields[1].toInt();


Serial.print("Code = ");
Serial.println(aNumber);

switch (aNumber) {
case 1:
// message code = 1 action
//Serial.println("code 1");
break;
case 2:
// message code = 2 action
//Serial.println("code 2");
break;
case 3:
// message code = 3 action
//Serial.println("code 3");
break;
case 4:
// message code = 4 action
//Serial.println("cose 4");
break;
case 5:
// message code = 5 action
//Serial.println("code 5");
break;
case 6:
// message code = 6 action
//Serial.println("code 6");
break;
case 7:
// message code = 7 action
//Serial.println("code 7");
break;
case 8:
// message code = 8 action
//Serial.println("code 8");
displayMSG(" ");
displayMSG("Disarmed");
systemState = 8;
break;
case 9:
// message code = 9 action
//Serial.println("code 9");
systemState = 9;
warning = true;
stolen = false;
displayMSG(" ");
displayMSG("Warning!");
break;
case 10:
// message code = 10 action
//Serial.println("code 10");
displayMSG(" ");
displayMSG("Food Block");
systemState = 10;
stolen = false;
break;
case 11:
// message code = 11 action
//Serial.println("code 11");
break;
case 12:
// message code = 12 action
//Serial.println("code 12");
systemState = 12;
warning = true;
stolen = true;
displayMSG(" ");
displayMSG("Stolen!");
Serial.println("stolen");
break;
default:
// if nothing else matches, do the default
Serial.println("code unknown");
break;
}
}
}

// check if Xbee has received message or not


String checkMessageReceived () {
static String msgBuffer = ""; // buffer to collect incoming message: static instead of
global !
String returnMsg = ""; // the result to return to the caller

if (xBee.available()) {

// there is at least one character in the input queue of the XBee,


// so fetch it. to prevent blocking the main loop, only one byte
// is fetched on each call. add it to the nsg buffer accumulating the byutes
byte ch = xBee.read();
msgBuffer += char(ch);

// now check to see if this is the message terminator


if (ch == NEWLINE_CHAR) {
// if so, then return the completed message
returnMsg = msgBuffer;
// and clear out the buffer for the next message
msgBuffer = "";
}
else {
// the message isn't complete yet, so just return a null string to the caller
}
}
else {
// nothing has been received, so
// return a null string to the caller
}
return returnMsg;
}

// check password
bool passwordCheck() {
int i;
for(i = 0; i < arr_len(password); i++) {
if (password[i] != pTrial[i]) {
return true;
}
}
return false;
}

// check pressed key


void keyCheck() {
int key1 = butt1.checkButtonAction();
int key2 = butt2.checkButtonAction();
int key3 = butt3.checkButtonAction();
int key4 = butt4.checkButtonAction();

if (key1 == Button::CLICKED) {
tone(speaker, 600, 100);
pTrial[currIndex] = 1;
currIndex++;
displayPassCount();
} else if (key2 == Button::CLICKED) {
tone(speaker, 600, 100);
pTrial[currIndex] = 2;
currIndex++;
displayPassCount();
} else if (key3 == Button::CLICKED) {
tone(speaker, 600, 100);
pTrial[currIndex] = 3;
currIndex++;
displayPassCount();
} else if (key4 == Button::CLICKED) {
tone(speaker, 600, 100);
pTrial[currIndex] = 4;
currIndex++;
displayPassCount();
} else if (key1 == Button::HELD_CLICKED || key2 == Button::HELD_CLICKED || key3 ==
Button::HELD_CLICKED || key4 == Button::HELD_CLICKED) {
lock1 = true;
lock2 = true;
alarm = true;
displayMSG("Food Block");
protocol = 10;
}
}

// chnage LED & alarm states


void LEDControl() {
if (lock1) {
digitalWrite(stateLED1, HIGH);
} else {
digitalWrite(stateLED1, LOW);
}
if (lock2) {
digitalWrite(stateLED2, HIGH);
} else {
digitalWrite(stateLED2, LOW);
}

if (warning) {
if(millis() - marker2 >= interval2) {
marker2 = millis();
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
if (stolen) {
tone(speaker, 1000, 500);
} else {
noTone(speaker);
}
digitalWrite(alarmLED, ledState);
warningCount++;
}
if (systemState != 12 && systemState != 9) {
if (warningCount > 8) {
warningCount = 0;
warning = false;
}
}
} else {
if (alarm) {
digitalWrite(alarmLED, HIGH);
} else {
digitalWrite(alarmLED, LOW);
}
}
}

// reset alarm
void setAlarm() {
int key1 = butt1.checkButtonAction();
int key2 = butt2.checkButtonAction();
int key3 = butt3.checkButtonAction();
int key4 = butt4.checkButtonAction();

if (key1 == Button::HELD_CLICKED || key2 == Button::HELD_CLICKED || key3 ==


Button::HELD_CLICKED || key4 == Button::HELD_CLICKED) {
lock1 = true;
lock2 = true;
alarm = true;
displayMSG("Food Block");
protocol = 10;
}
}

// check & display a number of pressed passwords


void displayPassCount() {
int startIndex = (16 - arr_len(password)) / 2;
lcd.setCursor(startIndex, 1);
int i;
String msg;
for (i = 0; i < arr_len(password); i++) {
if(i < currIndex) {
msg += "*";
} else {
msg += "_";
}
}
lcd.print(msg);
}

// display msg at the center of the LCD


void displayMSG(String msg) {
int startIndex = (16 - msg.length()) / 2;
lcd.setCursor(startIndex, 0);
lcd.print(msg);
}