I bought an Arduino UNO with an rfid reader and a relay which I want to use as added security on my laptop (because the battery is cooked). The relay is used to intercept the power cable to the laptop and is in a normally open state, unless the reader detects the tag, in which case it closes the relay and maintains that until the tag is removed. Once the tag is removed, there needs to be a 30 second countdown before the relay is opened thus breaking the circuit.
The biggest challenge that I face is this: I am a chef and know absolutely nothing about coding. If you say garlic, I say aioli. If you say serial.println, I'm completely clueless.
I've looked at tutorials but it just doesn't make sense to me.
Can someone please help me sort the code out for this?
#include <arduino.h> // this is an include, this is how you add stuff to a project.
#include <SPI.h> // this is the SPI bus libary. how you talk to the reader over the wires
#include <MFRC522.h> // this is the card readers lib.. takes the hassle out of having to roll your own.
#define SS_PIN 10 // that SS pin on the card? a #define is a macro.. a easy representation in english as to what you are up to.
#define RST_PIN 9 // strictly not necessary, but tell it where and what.
#define RELAY_PIN 3
#define DEBUG true
#define VALID_TAG1 "_43_7b_e2_9a"
#define VALID_TAG2 "43 7B E2 9A"
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance. // you have now made a MRFC object.. this is your gateway to the device.
/**
* this is global space. anything declared here can be accessed by the everything inside this file
*
*/
/**
* @brief setup().. this code runs once at startup. put setup code in here.. -_-
*/
int countdownTimer = 30;
void setup() {
Serial.begin(9600); // a way to read what the hell the arduino is up to.
SPI.begin(); // starts up the SPI bus
mfrc522.PCD_Init(); // starts up the card reader
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, HIGH);
Serial.println("Approximate your card to the reader..."); // Serial.print("bla bla"); is how you send text out to the PC
Serial.println();
}
void loop() {
delay(1000); // chill for 1 second
String UID = "";
if(!mfrc522.PICC_IsNewCardPresent()){ // this is a convenience function. if you hover over the test, it will show you its return type. in this case a bool.... a true/false, yes/no 1/0
// this is a if(){} as name implies. if( this is true){ do the stuff in here if condition is true} else {do the stuff in here if condition is false} ... simple?
Serial.println("WHERE IS MY CARD?");
return;
}
if(!mfrc522.PICC_ReadCardSerial()){ // this actually reads the serial of the tag
Serial.println("get me a valid tag you muppet");
return;
}
#if DEBUG
mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); // will spit all the info to the serial port
#endif
for(byte i = 0;i < mfrc522.uid.size; i++){
UID.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? "_0" : "_"));
UID.concat(String(mfrc522.uid.uidByte[i], HEX));
}
Serial.print("my ID is:");
Serial.println(UID);
if(UID == VALID_TAG1 || UID == VALID_TAG2){
countdownTimer = 30;
digitalWrite(RELAY_PIN, LOW);
Serial.println("yay");
Serial.println(countdownTimer);
}
if(countdownTimer < 0){
digitalWrite(RELAY_PIN, HIGH);
countdownTimer = 30;
}
countdownTimer--;
Serial.print(countdownTimer);
}
This was done in vs code as instructed, however I'd rather do it in Arduino IDE which I downloaded two days ago.
At this point, the receiver reads the tag and the relay closes, but when I remove the tag from the receiver, after 30 seconds nothing happens to the relay and it remains closed.
If I've crossed any lines, please accept my apologies, it is not my intention. I literally don't know how to write code and doing all the above is virtually impossible for me. Iots like trying to learn an alien language with no background. Is there any way that I can send someone a message with the code in it so that I don't cause any waves on the forum?
#include <arduino.h> // this is an include, this is how you add stuff to a project.
#include <SPI.h> // this is the SPI bus libary. how you talk to the reader over the wires
#include <MFRC522.h> // this is the card readers lib.. takes the hassle out of having to roll your own.
#define SS_PIN 10 // that SS pin on the card? a #define is a macro.. a easy representation in english as to what you are up to.
#define RST_PIN 9 // strictly not necessary, but tell it where and what.
#define RELAY_PIN 3
#define DEBUG true
#define VALID_TAG1 "_43_7b_e2_9a"
#define VALID_TAG2 "43 7B E2 9A"
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance. // you have now made a MRFC object.. this is your gateway to the device.
/**
* this is global space. anything declared here can be accessed by the everything inside this file
*
*/
/**
* @brief setup().. this code runs once at startup. put setup code in here.. -_-
*/
int countdownTimer = 30;
void setup() {
Serial.begin(9600); // a way to read what the hell the arduino is up to.
SPI.begin(); // starts up the SPI bus
mfrc522.PCD_Init(); // starts up the card reader
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, HIGH);
Serial.println("Approximate your card to the reader..."); // Serial.print("bla bla"); is how you send text out to the PC
Serial.println();
}
void loop() {
delay(1000); // chill for 1 second
String UID = "";
if(!mfrc522.PICC_IsNewCardPresent()){ // this is a convenience function. if you hover over the test, it will show you its return type. in this case a bool.... a true/false, yes/no 1/0
// this is a if(){} as name implies. if( this is true){ do the stuff in here if condition is true} else {do the stuff in here if condition is false} ... simple?
Serial.println("WHERE IS MY CARD?");
return;
}
if(!mfrc522.PICC_ReadCardSerial()){ // this actually reads the serial of the tag
Serial.println("get me a valid tag you muppet");
return;
}
#if DEBUG
mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); // will spit all the info to the serial port
#endif
for(byte i = 0;i < mfrc522.uid.size; i++){
UID.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? "_0" : "_"));
UID.concat(String(mfrc522.uid.uidByte[i], HEX));
}
Serial.print("my ID is:");
Serial.println(UID);
if(UID == VALID_TAG1 || UID == VALID_TAG2){
countdownTimer = 30;
digitalWrite(RELAY_PIN, LOW);
Serial.println("yay");
Serial.println(countdownTimer);
}
if(countdownTimer < 0){
digitalWrite(RELAY_PIN, HIGH);
countdownTimer = 30;
}
countdownTimer--;
Serial.print(countdownTimer);
}
/* this is a comment block
// to comment a line use // in front of it.
* Typical pin layout used:
* -----------------------------------------------------------------------------------------
* MFRC522 Arduino Arduino Arduino Arduino Arduino
* Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
* Signal Pin Pin Pin Pin Pin Pin
* -----------------------------------------------------------------------------------------
* RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
* SPI SS SDA(SS) 10 53 D10 10 10
* SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
* SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
* SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
*/
I hope that you can see how much nicer the presentation of the code is when you use code tags. It will not fix your problem, of course, but will make it easier to provide help
In the current code, you reset the countdownTimer to a starting value of 30 each pass of the loop. You need to start the timer only once.
There are several ways to achieve what you want, and one of the most simple is to use a boolean control variable. The variable will enable countdown when true and stop countdown when false.
With this scheme, the countdown will start from the point of reading a valid tag. If you indeed want the countdown to start from the removal of a valid tag, you will need to revise the code to detect a valid tag and then the change to no tag.
Declare a new global variable
boolean timing = false;
Then the countdown portion of the code will look like this.
I believe this will require complete recrafting or your program as you will need to track the transitions from either no card or a not valid reading to a valid reading and then back to a no card state in order to start the relay delay timing.
This will likely require a coding configuration called a "state machine".
Perhaps some other helper may be willing to write the complete code for you, but I do not have any card reader hardware so I can't really test. Perhaps the card reader can be simulated in Wokwi but I am not a user.
For now I have weather issues to deal with and sitting at my computer is not what I need to be doing.
Good luck taking this forward. You may decide you want to code as well as cook.
I suggest, break the project down into manageable parts, like "detect a card", "start a timer", "operate a relay". Make them all work separately and then put it together. Use surrogate components or inputs to simulate the missing parts, for example you could take inputs from the serial monitor instead of the card reader, to set up the rest of the logic.
This is not Star Wars, there is "try".
Regarding the state machine, it is a design pattern that you can use. Honestly, if you are a very, very beginner that is not for you. But if you first write and play with a few simple projects you will be ready.
Basically, the reason you're stumped, you haven't followed the path to get where you need to go. We can't provide a complete learning environment here, it won't fit in forum posts. We can only answer specific questions or help with certain problems.
Merry Christmas everyone. My apologies for disappearing during the conversation, I am only allowed to send 20 messages per day. Life has been hectic the past 3 days and I only managed to get to my PC and look at this code after lunch today.
Ok, so I copied and pasted the above code and upon uploading it, got 2 errors with squiggles on both of the words 'timing' in this new code.
The first error states, and I quote, 'identifier "timing" is undefinedC/C++(20)
'timing' was not declared in this scope'.
The second error states ' 'timing' was not declared in this scope'.
I also tried engaging the relay with another tag using the unedited code. The outcome is that when the reader picks up the tag, it starts a 30-second countdown. So the countdown works when an incorrect tag is read but this is wrong. The countdown needs to start once the correct tag is no longer in proximity to the reader and after 30 seconds, the relay needs to open.
I appreciate your input. So close to getting this right.