Created
November 4, 2016 14:35
-
-
Save flowolf/5ae28f3082da9b42bc2958ccae6f2545 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* door lock application (c) 2011 Florian Klien | |
* some code parts are borrowed from different authors ;) thx | |
*/ | |
#include <NewSoftSerial.h> | |
#define rxPin 2 | |
#define txPin 3 | |
// door defs | |
#define DOOR_SENS 3 // analog | |
#define DRIVER_SWITCH 6 | |
#define DOOR_SW 2 // analog | |
// motor defs | |
#define DIR_PIN 7 | |
#define STEP_PIN 8 | |
#define ledIN 5 | |
#define ledOUT 11 | |
NewSoftSerial rfid = NewSoftSerial( rxPin, txPin ); | |
// The tag database consists of two parts. The first part is an array of | |
// tag values with each tag taking up 5 bytes. The second is a list of | |
// names with one name for each tag (ie: group of 5 bytes). | |
char* allowedTags[] = { | |
"AABBCCDDEE", // Tag 1 | |
"AABBCCDDEE", // Tag 2 | |
}; | |
// List of names to associate with the matching tag IDs | |
char* tagName[] = { | |
"User1", // Tag 1 | |
"User2", // Tag 2 | |
}; | |
// software version number: | |
char* software_version = "1.1"; | |
// Check the number of tags defined | |
int numberOfTags = sizeof(allowedTags)/sizeof(allowedTags[0]); | |
int incomingByte = 0; // To store incoming serial data | |
boolean locked = true; | |
int door_open = 0; // pseudo digital | |
boolean prev_status = false; | |
boolean auto_lock = true; | |
//unsigned long auto_lock_time = 0; | |
int auto_lock_delay = 5; // in seconds | |
int auto_lock_switch_time = 2; // in seconds | |
int status_led = 0; | |
unsigned long status_led_time = millis(); | |
boolean status_led_on = false; | |
unsigned long status_breathe_time = millis(); | |
int breathe_delay = 10; | |
boolean breathe_up = true; | |
int breathe_i = 15; | |
unsigned long last_successful_rfid_read = 0; | |
int rfid_success_timeout = 5000; // millis | |
float lock_speed = 1; | |
/** | |
* Setup | |
*/ | |
unsigned long time_door = millis(); | |
unsigned long time_switch = millis(); | |
long debounce = 500; | |
void setup() { | |
pinMode(ledIN, OUTPUT); | |
pinMode(ledOUT, OUTPUT); | |
digitalWrite(ledIN, HIGH); | |
digitalWrite(ledOUT, HIGH); | |
delay(300); | |
digitalWrite(ledIN, LOW); | |
digitalWrite(ledOUT, LOW); | |
pinMode(DRIVER_SWITCH, OUTPUT); | |
digitalWrite(DRIVER_SWITCH, LOW); | |
pinMode(DIR_PIN, OUTPUT); | |
digitalWrite(DIR_PIN, LOW); | |
pinMode(STEP_PIN, OUTPUT); | |
digitalWrite(STEP_PIN, LOW); | |
pinMode(DOOR_SENS,INPUT); | |
pinMode(DOOR_SW,INPUT); | |
Serial.begin(9600); // Serial port for connection to host | |
rfid.begin(9600); // Serial port for connection to RFID module | |
Serial.println("RFID reader starting up"); | |
delay(1000); | |
Serial.println("done"); | |
Serial.print("Software Version no: "); | |
Serial.println(software_version); | |
Serial.print("door locked: "); | |
Serial.print(locked, DEC); | |
Serial.print("\n"); | |
Serial.print("door closed: "); | |
Serial.print(!door_open, DEC); | |
Serial.print("\n"); | |
} | |
/** | |
* Loop | |
* non-blocking version of each function! | |
*/ | |
void loop() { | |
readRFID(); | |
doorSensor(); | |
doorSwitch(); | |
statusLed(); | |
} | |
void doorSensor(){ | |
// pseudo digital | |
door_open = analogRead(DOOR_SENS); | |
if(millis() - time_door > debounce){ | |
if (door_open <= 500 && prev_status == false){ | |
Serial.println("Door: opened"); | |
prev_status = true; | |
locked = false; | |
}else if(door_open > 500 && prev_status == true){ | |
Serial.println("Door: closed"); | |
prev_status = false; | |
if(auto_lock){ | |
Serial.println("locking door automatically..."); | |
delay(auto_lock_delay*1000); | |
lock(); | |
locked = true; | |
} | |
} | |
time_door = millis(); | |
} | |
} | |
void doorSwitch(){ | |
int dstimer = 0; | |
int door_switch = analogRead(DOOR_SW); // pseudo digital | |
if(millis() - time_switch > debounce && door_switch >= 300){ | |
while (analogRead(DOOR_SW) >= 300) { | |
delay(100); | |
dstimer++; | |
} | |
Serial.println(door_switch,DEC); | |
Serial.println(dstimer,DEC); | |
if (dstimer < auto_lock_switch_time*10) { //button has been pressed less than 2 seconds = 1000/100 | |
if (locked == false){ | |
Serial.println("door locked"); | |
locked = true; | |
lock(); | |
}else if(locked == true){ | |
Serial.println("door unlocked"); | |
locked = false; | |
unlock(); | |
} | |
}else { | |
// auto_unlock off/on | |
if(auto_lock == true){ | |
Serial.println("auto_lock off"); | |
auto_lock = false; | |
}else{ | |
Serial.println("auto_lock on"); | |
auto_lock = true; | |
} | |
analogWrite(ledIN, 0); // resetting output | |
} | |
time_switch = millis(); | |
} | |
} | |
// breathing status led on the inside | |
void statusBreathe(){ | |
if( (status_breathe_time + breathe_delay) < millis() ){ | |
analogWrite(ledIN, breathe_i/1.5); | |
status_breathe_time = millis(); | |
if (breathe_up == true){ | |
if (breathe_i > 150) { | |
breathe_delay = 4; | |
} | |
if ((breathe_i > 125) && (breathe_i < 151)) { | |
breathe_delay = 5; | |
} | |
if (( breathe_i > 100) && (breathe_i < 126)) { | |
breathe_delay = 7; | |
} | |
if (( breathe_i > 75) && (breathe_i < 101)) { | |
breathe_delay = 10; | |
} | |
if (( breathe_i > 50) && (breathe_i < 76)) { | |
breathe_delay = 14; | |
} | |
if (( breathe_i > 25) && (breathe_i < 51)) { | |
breathe_delay = 18; | |
} | |
if (( breathe_i > 1) && (breathe_i < 26)) { | |
breathe_delay = 19; | |
} | |
breathe_i += 1; | |
if( breathe_i >= 255 ){ | |
breathe_up = false; | |
} | |
}else{ | |
if (breathe_i > 150) { | |
breathe_delay = 4; | |
} | |
if ((breathe_i > 125) && (breathe_i < 151)) { | |
breathe_delay = 5; | |
} | |
if (( breathe_i > 100) && (breathe_i < 126)) { | |
breathe_delay = 7; | |
} | |
if (( breathe_i > 75) && (breathe_i < 101)) { | |
breathe_delay = 10; | |
} | |
if (( breathe_i > 50) && (breathe_i < 76)) { | |
breathe_delay = 14; | |
} | |
if (( breathe_i > 25) && (breathe_i < 51)) { | |
breathe_delay = 18; | |
} | |
if (( breathe_i > 1) && (breathe_i < 26)) { | |
breathe_delay = 19; | |
} | |
breathe_i -= 1; | |
if( breathe_i <= 15 ){ | |
breathe_up = true; | |
breathe_delay = 970/2; | |
} | |
} | |
} | |
} | |
void statusLed(){ | |
if(auto_lock == false){ | |
status_led = 150; | |
}else{ | |
// set this to > 0 if you want the status led to blink in default mode | |
status_led = 0; | |
if(status_led == 0){ | |
statusBreathe(); | |
} | |
} | |
if(millis() - status_led_time >= status_led && status_led != 0){ | |
status_led_on = !status_led_on; | |
digitalWrite(ledIN,status_led_on); | |
status_led_time = millis(); | |
} | |
} | |
void readRFID(){ | |
byte i = 0; | |
byte val = 0; | |
byte checksum = 0; | |
byte bytesRead = 0; | |
byte tempByte = 0; | |
byte tagBytes[6]; // "Unique" tags are only 5 bytes but we need an extra byte for the checksum | |
char tagValue[10]; | |
if(rfid.available()>0){ | |
if((val = rfid.read()) == 2) { // Check for header | |
bytesRead = 0; | |
while (bytesRead < 12) { // Read 10 digit code + 2 digit checksum | |
val = rfid.read(); | |
Serial.print(val,BYTE); | |
// Append the first 10 bytes (0 to 9) to the raw tag value | |
if (bytesRead < 10) | |
{ | |
tagValue[bytesRead] = val; | |
} | |
// Check if this is a header or stop byte before the 10 digit reading is complete | |
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { | |
break; // Stop reading | |
} | |
// Ascii/Hex conversion: | |
if ((val >= '0') && (val <= '9')) { | |
val = val - '0'; | |
} | |
else if ((val >= 'A') && (val <= 'F')) { | |
val = 10 + val - 'A'; | |
} | |
// Every two hex-digits, add a byte to the code: | |
if (bytesRead & 1 == 1) { | |
// Make space for this hex-digit by shifting the previous digit 4 bits to the left | |
tagBytes[bytesRead >> 1] = (val | (tempByte << 4)); | |
if (bytesRead >> 1 == 5) { // If we're at the checksum byte, | |
checksum ^= tagBytes[bytesRead >> 1]; // Calculate the checksum... (XOR) | |
}; | |
} else { | |
tempByte = val; // Store the first hex digit first | |
}; | |
bytesRead++; // Ready to read next digit | |
} | |
// Send the result to the host connected via USB | |
if (bytesRead == 12) { // 12 digit read is complete | |
tagValue[10] = '\0'; // Null-terminate the string | |
Serial.print("Tag read: "); | |
for (i=0; i<5; i++) { | |
// Add a leading 0 to pad out values below 16 | |
if (tagBytes[i] < 16) { | |
Serial.print("0"); | |
} | |
Serial.print(tagBytes[i], HEX); | |
} | |
Serial.println(); | |
Serial.print("Checksum: "); | |
Serial.print(tagBytes[5], HEX); | |
Serial.println(tagBytes[5] == checksum ? " -- passed." : " -- error."); | |
// Show the raw tag value | |
//Serial.print("VALUE: "); | |
//Serial.println(tagValue); | |
Serial.print("door_open: "); | |
Serial.println(door_open,DEC); | |
// Search the tag database for this particular tag | |
int tagId = findTag( tagValue ); | |
// Only fire the strike plate if this tag was found in the database | |
if( tagId > 0 ) | |
{ | |
Serial.print("Authorized tag ID "); | |
Serial.print(tagId); | |
if(door_open > 500 && (last_successful_rfid_read + rfid_success_timeout) < millis() ){ | |
Serial.print(": unlocking for "); | |
Serial.println(tagName[tagId - 1]); // Get the name for this tag from the database | |
unlock(); | |
last_successful_rfid_read = millis(); | |
delay(2000); | |
} | |
} else { | |
Serial.println("Tag not authorized"); | |
//failSound(); | |
for (int i=0;i<7;i++){ // FIXXME nonblocking version? | |
digitalWrite(ledOUT, HIGH); | |
digitalWrite(ledIN, HIGH); | |
delay(100); | |
digitalWrite(ledOUT, LOW); | |
digitalWrite(ledIN, LOW); | |
delay(80); | |
} | |
} | |
Serial.println(); // Blank separator line in output | |
} | |
bytesRead = 0; | |
} | |
} | |
} | |
/** | |
* Fire the relay to activate the strike plate for the configured | |
* number of seconds. | |
*/ | |
void unlock() { | |
digitalWrite(ledOUT, HIGH); | |
digitalWrite(ledIN, HIGH); | |
delay(100); | |
// if your stepper is powerful enough you can use full speed | |
rotateDeg(-800, 0.6); | |
digitalWrite(ledIN, LOW); | |
digitalWrite(ledOUT, LOW); | |
locked = false; | |
} | |
void lock(){ | |
digitalWrite(ledOUT, HIGH); | |
digitalWrite(ledIN, HIGH); | |
delay(100); | |
rotateDeg(800, 1); | |
digitalWrite(ledIN, LOW); | |
digitalWrite(ledOUT, LOW); | |
locked = true; | |
} | |
void rotate(int steps, float speed){ | |
// power driver | |
digitalWrite(DRIVER_SWITCH,HIGH); | |
delay(200); | |
//rotate a specific number of microsteps (8 microsteps per step) - (negitive for reverse movement) | |
//speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger | |
int dir = (steps > 0)? HIGH:LOW; | |
steps = abs(steps); | |
digitalWrite(DIR_PIN,dir); | |
float usDelay = (1/speed) * 250; | |
for(int i=0; i < steps; i++){ | |
digitalWrite(STEP_PIN, HIGH); | |
delayMicroseconds(usDelay); | |
digitalWrite(STEP_PIN, LOW); | |
delayMicroseconds(usDelay); | |
} | |
// unpower driver | |
delay(200); | |
digitalWrite(DRIVER_SWITCH,LOW); | |
} | |
void rotateDeg(float deg, float speed){ | |
// power driver | |
digitalWrite(DRIVER_SWITCH,HIGH); | |
delay(200); | |
//rotate a specific number of degrees (negative for reverse movement) | |
//speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger | |
int dir = (deg > 0)? HIGH:LOW; | |
digitalWrite(DIR_PIN,dir); | |
int steps = abs(deg)*(1/0.225); | |
float usDelay = (1/speed) * 250; | |
for(int i=0; i < steps; i++){ | |
digitalWrite(STEP_PIN, HIGH); | |
delayMicroseconds(usDelay); | |
digitalWrite(STEP_PIN, LOW); | |
delayMicroseconds(usDelay); | |
} | |
// unpower driver | |
delay(200); | |
digitalWrite(DRIVER_SWITCH,LOW); | |
} | |
/** | |
* Search for a specific tag in the database | |
*/ | |
int findTag( char tagValue[10] ) { | |
for (int thisCard = 0; thisCard < numberOfTags; thisCard++) { | |
// Check if the tag value matches this row in the tag database | |
if(strcmp(tagValue, allowedTags[thisCard]) == 0) | |
{ | |
// The row in the database starts at 0, so add 1 to the result so | |
// that the card ID starts from 1 instead (0 represents "no match") | |
return(thisCard + 1); | |
} | |
} | |
// If we don't find the tag return a tag ID of 0 to show there was no match | |
return(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment