Help required with delayed countdown timer for relay

Hi everyone.

I'm hoping that someone can help me, please.

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?

Welcome. Unless you post code, we can't sort it out. What have you done so far?

Please edit the subject line of your post, to reflect your actual problem.

If you wish to learn to code and interface the parts, do as member @anon57585045 suggests.

If you want to pay someone to do it all for you, request that a moderator move your post to the Gigs and Collaborations section.

Will send it too you shortly. Just waiting for the lights to come back on.

Here we go...

#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.

Is this and easy thing to sort out?

(mod edit to fix CODE post.)

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use [color = red]code tags[/color] (the </> icon above the compose window) to make it easier to read and copy for examination

I understand.

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?

In the IDE use Ctrl+shift+C to copy the code and then paste it here in a new post. The code tags will have been added by the IDE copy process

Will do, thank you

#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

*/

Thank you

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

1 Like

Yes, much neater indeed.

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.

if(UID == VALID_TAG1 || UID == VALID_TAG2 and timing == false){
   
    countdownTimer = 30;
    digitalWrite(RELAY_PIN, LOW);
    Serial.println("yay");
    Serial.println(countdownTimer);
    timing = true;
  }

  if(countdownTimer < 0){
    digitalWrite(RELAY_PIN, HIGH);
    countdownTimer = 30;
    timing = false;
  }

  countdownTimer--;
  Serial.println(countdownTimer);
1 Like

Arduino is really a learning platform, so you are in luck. Everyone here was once in that position.

1 Like

Thank you for your response cattledog. I do indeed wish to start the countdown from the removal of the tag. How do you suggest I do this, please?

That is what the posted code does... except starts with presence of the tag with

if(UID == VALID_TAG1 || UID == VALID_TAG2 and timing == false){

absence of tag is

if(UID != VALID_TAG1 and UID != VALID_TAG2 and timing == false){
1 Like

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. :wink:

1 Like

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.

1 Like

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.

Welcome back.

Please post the code you ran which gave the errors you reference. Remember to use the code tags.