Skip to content

Instantly share code, notes, and snippets.

@flowolf
Created November 4, 2016 14:35
Show Gist options
  • Save flowolf/5ae28f3082da9b42bc2958ccae6f2545 to your computer and use it in GitHub Desktop.
Save flowolf/5ae28f3082da9b42bc2958ccae6f2545 to your computer and use it in GitHub Desktop.
/**
* 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