have recently finished up on an Arduino powered garage door opener. I wrote the code, assembled the parts on a custom-designed PCB, and created a box to encase the project. The basic idea is that I have an RFID reader on the outside of my garage door and the Arduino on the inside. The Arduino has a list of acceptable codes and if the card that was read is on the list, it connects the garage door opener circuit with the relay. There are two buttons and two LEDs on the box that allow you to add and remove cards from that list.
The project works exactly how I want it … for a little while. After an arbitrary amount of time, cards are no longer read. The buttons on the box still work but cards just don’t. The problem can be fixed by restarting the Arduino. The amount of time that it takes for this to happen can vary from a couple of hours to a couple of days. I assume that the problem is the SPI communication between the Arduino and the RFID reader stops but I don't know why and how to fix it. Right now I have a temporary solution where the Arduino resets itself every couple minutes but I've found that this sometimes doesn't even work.
Hardware
Arduino Nano Atmega 328 (Old boot-loader)
RFID Reader(RC522)
5v Relay
2 Push Buttons
2 LEDs
PCB
Software
Here is the code for my project:
#include <EEPROM.h>
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);
char rcv[16] = "";
char list[20][14] = {};
int cardnum = 0;
int lengthv = 0;
bool snext = false;
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
pinMode(5, INPUT);
pinMode(8, INPUT);
pinMode(3, OUTPUT);
pinMode(7, OUTPUT);
pinMode(6, OUTPUT);
bool reading = false;
int point = 0;
//Reading EEPROM ( 89 is the start of a new card, 90 is the end of a card, 255 is empty value)
for (unsigned int i = 0; i < EEPROM.length(); i++) {
int j = EEPROM.read(i);
Serial.println(char(j));
if (j == 255) {
break;
}
lengthv ++;
if (j == 89) {
reading = true;
}
if (j == 90) {
reading = false;
point = 0;
cardnum ++;
}
if (reading == true && j != 89) {
list[cardnum][point] = char(j);
point ++;
}
}
}
void(* resetFunc) (void) = 0;
bool programming = false;
bool add = false;
int reset = 0;
int over = 0;
void loop() {
delay(100);
//buttons
int value = digitalRead(8);
int value2 = digitalRead(5);
if (programming == true) {
reset = reset + 1;
}
//turns off programming mode if no card is read:
if (reset == 30) {
reset = 0;
programming = false;
digitalWrite(7, LOW);
digitalWrite(3, LOW);
}
//turns on adding:
if (value == 1) {
reset = 0;
programming = true;
digitalWrite(7, HIGH);
digitalWrite(3, LOW);
add = true;
}
//turns on subtracing:
if (value2 == 1) {
reset = 0;
digitalWrite(3, HIGH);
digitalWrite(7, LOW);
add = false;
programming = true;
}
//If cards are not being programmed:
if (programming == false) {
over ++;
}
if (over > 6000) {
resetFunc();
}
//If no cards are present, returns
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
//content holds card's UIDs
String content = "";
//Reads UID
for (byte i = 0; i < mfrc522.uid.size; i++)
{
content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
content.concat(String(mfrc522.uid.uidByte[i], HEX));
}
//formats content
content.toUpperCase();
content.replace(" ", "");
for (unsigned int i = 0; i < content.length(); i++) {
rcv[i] = content[i];
}
Serial.println(rcv);
//adds or removes card if programming is enabled
if (programming == true) {
if (add == true) {
Add();
} else {
Sub();
}
delay(1000);
snext = true;
return;
} else if (snext == false) {
for (int i = 0; i < 15; i++) {
if ( strcmp(rcv, list[i]) == 0) {
digitalWrite(6, HIGH);
delay(1000);
digitalWrite(6, LOW);
}
}
} else {
snext = false;
}
}
void Add() {
bool match = false;
//checks to see if card is already in list
for (int i = 0; i < 15; i++) {
if ( strcmp(rcv, list[i]) == 0) {
match = true;
}
}
//if it isn't:
if (match == false) {
int rlen = 0;
//gets length of recieved card
for (unsigned int i = 0; i < sizeof(rcv); i ++) {
if (rcv[i] != 0) {
rlen ++;
}
}
//Adds 'Y' to the start and 'Z' to the End for reading
char placeholder[rlen + 2] = "Y";
strcat(placeholder, rcv);
strcat(placeholder, "Z");
for (int i = 0; i < rlen; i++) {
list[cardnum][i] = rcv[i];
}
//Increases number of recorded cards
cardnum++;
//Writes to EEPROM
for (unsigned int i = 0; i < sizeof(placeholder); i++) {
EEPROM.write(i + lengthv, placeholder[i]);
}
lengthv += sizeof(placeholder);
//flickers LED to show that we are done
flicker(7);
}
}
//flickers led when programming is done
void flicker(int pin) {
programming = false;
digitalWrite(pin, LOW);
delay(150);
digitalWrite(pin, HIGH);
delay(150);
digitalWrite(pin, LOW);
delay(150);
digitalWrite(pin, HIGH);
delay(150);
digitalWrite(pin, LOW);
}
//removes card
void Sub() {
bool match = false;
int rcard = 0;
//checks to see if the recieved card matches any card in the list
for (int i = 0; i < 15; i++) {
if ( strcmp(rcv, list[i]) == 0) {
match = true;
rcard = i;
}
}
if (match == true) {
int posn = 0;
char megastring[350] = "";
for (int i = 0; i < 15; i++) {
if (i != rcard && list[i][0] != 0) {
megastring[posn] = 89;
posn ++;
for (unsigned int s = 0; s < sizeof(list[i]); s++) {
if (list[i][s] != 0) {
megastring[posn] = list[i][s] ;
posn ++;
}
}
megastring[posn] = 90;
posn++;
}
}
//clears removed card form list
memset(list[rcard], 0, sizeof(list[rcard]));
//clears EEPROM
for (unsigned int i = 0; i < EEPROM.length(); i++) {
EEPROM.write(i, 255);
}
//reset lengthv
lengthv = 0;
//Rewrites EEPROM with new list
for (unsigned int i = 0; i < sizeof(megastring); i++) {
if (megastring[i] != 0) {
EEPROM.write(i, megastring[i]);
lengthv ++;
}
}
//flicker LED to show that we are done
flicker(3);
}
}
When it loads, it reports back:
Sketch uses 8748 bytes (28%) of program storage space. Maximum is 30720 bytes.
Global variables use 543 bytes (26%) of dynamic memory, leaving 1505 bytes for local variables. Maximum is 2048 bytes.
Is there any way to fix this without upgrading my hardware?
Is it possible to reset the SPI line periodically or when it disconnects?
Is my code the problem?
If anyone can help me, it would mean so much. Let me know if there is any more information that you need.