SD and or RTC stops servo from working

Hi, I am new to Arduino and programming etc but I am trying to develop an RFID system to lock and unlock tool cabinets at work. I am using an Elegoo Uno R3 and a data logger shield with DS1307 and an RC522 RFID reader.

I have managed to piece together code from various sources along with some of my own alterations.

This uses a master card to add or remove other cards to an array that is stored in the eeprom. I also want to store the date, time and UID of each access event to an SD card.

I have got the code working for the master card access and eeprom storage working, and I have also got the SD logging working separately but when I combine the two pieces of code everything works as it should except that the servo stops working. I have noted the part that, when incorporated, causes the issue.

Can anyone help me to understand if there is some conflict in my code that is doing this or if there is another issue?

As I am writing this it has occurred to me that maybe it's a power issue, I am only powering this from the USB port. Is it possible that this can't support both the servo and the SD together? Also if I try powering with a 9v battery nothing works, my red LED on my breadboard just flashes slowly, no idea why.

I would really appreciate any help you guys can give. Thanks.

//RFID Based Solenoid Door lock using Arduino
//The IoT Projects https://www.youtube.com/c/TheIoTProjects
//website:https://iotprojectsideas.com/
//RFID RC522 Master Card, Add and Remove multiple Cards 




#include <SPI.h>
#include <Wire.h>
#include <MFRC522.h>
#include <Servo.h>
#include <SD.h>
#include <EEPROM.h>
#include <I2C_RTC.h>

#define RST_PIN 9
#define SS_PIN  2
#define SERVO_PIN A5

#define STATE_STARTUP       0
#define STATE_STARTING      1
#define STATE_WAITING       2
#define STATE_SCAN_INVALID  3
#define STATE_SCAN_VALID    4
#define STATE_SCAN_MASTER   5
#define STATE_ADDED_CARD    6
#define STATE_REMOVED_CARD  7

#define REDPIN 4
#define GREENPIN 5
#define BUZZER 7

File dataFile;

Servo servo;
int angle = 0; //current angle of servo motor
const int chipSelect = 10; // SD card CS pin connected to pin 10 of Arduino
const int cardArrSize = 6; // Number of stored card UID's allowed??
const int cardSize    = 4; // Number of no. sections
byte cardArr[cardArrSize][cardSize];
byte masterCard[cardSize] = {41,33,216,90};   //Change Master Card ID
byte readCard[cardSize];
byte cardsStored = 0;

static DS1307 RTC;

// Create MFRC522 instance
MFRC522 mfrc522(SS_PIN, RST_PIN);
// Set the LCD I2C address

byte currentState = STATE_STARTUP;
unsigned long LastStateChangeTime;
unsigned long StateWaitTime;



//------------------------------------------------------------------------------------
int readCardState()
{
  int index;

  Serial.print("Card Data - ");
  for(index = 0; index < 4; index++)
  {
    readCard[index] = mfrc522.uid.uidByte[index];

    // Print a comma after the first three uid numbers
    Serial.print(readCard[index]);
    if (index < 3)
    {
      Serial.print(",");
    }
  }
  Serial.println(" ");

  //Check Master Card
  if ((memcmp(readCard, masterCard, 4)) == 0)
  {
    return STATE_SCAN_MASTER;
  }

  if (cardsStored == 0)
  {
    return STATE_SCAN_INVALID;
  }

  for(index = 0; index < cardsStored; index++)
  {
    if ((memcmp(readCard, cardArr[index], 4)) == 0)
    {
      return STATE_SCAN_VALID;
    }
  }

 return STATE_SCAN_INVALID;
}


//------------------------------------------------------------------------------------
void addReadCard()
{
  int cardIndex;
  int index;
  if (cardsStored <= 20)
  {
    cardsStored++;
    cardIndex = cardsStored;
    cardIndex--;
  }
  for (index = 0; index < 4; index++)
  {
    cardArr[cardIndex][index] = readCard[index];
  }
  // Write the updated card list to EEPROM
  EEPROM.write(0, cardsStored);
  for (int i = 0; i < cardsStored; i++)
  {
    for (int j = 0; j < 4; j++)
    {
      EEPROM.write((i * 4) + j + 1, cardArr[i][j]);
    }
  }
  //EEPROM.commit();
}

//------------------------------------------------------------------------------------
void removeReadCard() 
{     
  int cardIndex;
  int index;
  boolean found = false;
  if (cardsStored == 0)
  {
    return;
  }
  for (index = 0; index < cardsStored; index++)
  {
    if ((memcmp(readCard, cardArr[index], 4)) == 0)
    {
      found = true;
      cardIndex = index;
    }
  }
  if (found == true)
  {
    // Remove the card from the array
    for (index = cardIndex; index < (cardsStored - 1); index++)
    {
      for (int j = 0; j < 4; j++)
      {
        cardArr[index][j] = cardArr[index + 1][j];
      }
    }
    cardsStored--;
    // Write the updated card list to EEPROM
    EEPROM.write(0, cardsStored);
    for (int i = 0; i < cardsStored; i++)
    {
      for (int j = 0; j < 4; j++)
      {
        EEPROM.write((i * 4) + j + 1, cardArr[i][j]);
      }
    }
    //EEPROM.commit();
  }
}

//------------------------------------------------------------------------------------
void updateState(byte aState)
{
  if (aState == currentState)
  {
    return;
  }

  // do state change
  switch (aState)
  {
    case STATE_STARTING:
      StateWaitTime = 1000;
      //digitalWrite(REDPIN, HIGH);
      //digitalWrite(GREENPIN, LOW);
      break;
    case STATE_WAITING:
      StateWaitTime = 0;
      //digitalWrite(REDPIN, LOW);
      //digitalWrite(GREENPIN, LOW);
      break;
    case STATE_SCAN_INVALID:
      if (currentState == STATE_SCAN_MASTER)
      {
        addReadCard();
        aState = STATE_ADDED_CARD;
        StateWaitTime = 2000;
        tone (BUZZER, 3000);
        delay (200);
        noTone (BUZZER);
        addedLed();
        //digitalWrite(REDPIN, LOW);
        //digitalWrite(GREENPIN, HIGH);
      }
      else if (currentState == STATE_REMOVED_CARD)
      {
        return;
      }
      else
      {
        StateWaitTime = 2000;
        //digitalWrite(REDPIN, HIGH);
        //digitalWrite(GREENPIN, LOW);
        tone (BUZZER, 3000);
        delay (200);
        noTone (BUZZER);
        deniedLed();
      }
      break;
    case STATE_SCAN_VALID:
      if (currentState == STATE_SCAN_MASTER)
      {
        removeReadCard();
        aState = STATE_REMOVED_CARD;
        StateWaitTime = 2000;
        tone (BUZZER, 3000);
        delay (200);
        noTone (BUZZER);
        //digitalWrite(REDPIN, LOW);
        //digitalWrite(GREENPIN, HIGH);
      }
      else if (currentState == STATE_ADDED_CARD)
      {
        return;
      }
      else
      {
        StateWaitTime = 2000;
        //digitalWrite(REDPIN, LOW);
        //digitalWrite(GREENPIN, HIGH);
        changeServo(); 
        timeStamp();
      }
      break;
    case STATE_SCAN_MASTER:
      StateWaitTime = 5000;
      tone (BUZZER, 3000);
        delay (200);
        noTone (BUZZER);
        delay (100);
        tone (BUZZER, 3000);
        delay (200);
        noTone (BUZZER);

      //digitalWrite(REDPIN, LOW);
      //digitalWrite(GREENPIN, HIGH);
      break;
  }

  currentState = aState;
  LastStateChangeTime = millis();
}
void changeServo() {
  // change angle of servo motor
  if (angle == 0){
    angle = 180;
    digitalWrite(REDPIN, LOW);
    digitalWrite(GREENPIN, HIGH);
  }
  else {//if(angle == 180)
    angle = 0;
    digitalWrite(REDPIN, HIGH);
    digitalWrite(GREENPIN, LOW);
  }
  // control servo motor arccoding to the angle
  servo.write(angle);
  Serial.print("Rotate Servo Motor to ");
  Serial.print(angle);
Serial.println("°");
}

void setup() 
{
  SPI.begin();         // Init SPI Bus
  mfrc522.PCD_Init();  // Init MFRC522
  servo.attach(SERVO_PIN);
  servo.write(angle); // rotate servo to 0°

    // Initialize the EEPROM
  //EEPROM.begin(512);
  // Read the stored card list from EEPROM
  cardsStored = EEPROM.read(0);
  if (cardsStored > cardArrSize)
  {
    cardsStored = 0;
  }
  for (int i = 0; i < cardsStored; i++)
  {
    for (int j = 0; j < 4; j++)
    {
      cardArr[i][j] = EEPROM.read((i * 4) + j + 1);
    }
  }

  LastStateChangeTime = millis();
  updateState(STATE_STARTING);

  pinMode(REDPIN, OUTPUT);
  pinMode(GREENPIN, OUTPUT);
  pinMode(BUZZER, OUTPUT);

  Serial.begin(9600);
 
 /* RTC.begin();                                              
  RTC.setHourMode(CLOCK_H24);
  RTC.setDate(31,8,24);
  RTC.setTime(21,30,00);

  SPI.begin(); // Init SPI bus

  mfrc522.PCD_Init(); // Init MFRC522

  // Setup for the SD card
  Serial.print("Initialising SD card...");                   // This section stops the servo from working

  if(!SD.begin(chipSelect)) {
    Serial.println("initialisation failed!");
    return;
  }
  Serial.println("initialisation done.");
*/

  dataFile = SD.open("LOGDATA.txt", FILE_WRITE); // Open file
                                                               
// If file opened ok write to it:
  if (dataFile){
    Serial.println("File opened ok");
    // Print headings for data
    dataFile.println("Date, Time, UID");
  }
  dataFile.close(); // FIND OUT WHAT THESE ARE FOR!!
    //Serial.println("CLEARDATA"); // Clears up any data left from previous projects
    //Serial.println("LABEL, Date, Time, UID"); // Always write LABEL, to indicate it as first line
    //Serial.println("RESETTIMER");
  Serial.println("Tap RFID/NFC Tag on reader");

}

void loop() 
{
  byte cardState;

  if ((currentState != STATE_WAITING) &&
      (StateWaitTime > 0) &&
      (LastStateChangeTime + StateWaitTime < millis()))
  {
    updateState(STATE_WAITING);
  }

  // Look for new cards 
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  { 
    return; 
  } 
  
  // Select one of the cards 
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  { 
    return; 
  }

  cardState = readCardState();
  updateState(cardState);


}
void timeStamp() {
  
  dataFile = SD.open("LOGDATA.txt", FILE_WRITE);

  // IF THE FILE IS AVAILABLE, WRITE TO IT:
  if (dataFile) {
    dataFile.print(RTC.getDay()); 
    dataFile.print("/"); // Move to next column using a ","

    dataFile.print(RTC.getMonth()); 
    dataFile.print("/"); // Move to next column using a ","

    dataFile.print(RTC.getYear()); 
    dataFile.print(","); // Move to next column using a ","

    dataFile.print(RTC.getHours()); 
    dataFile.print(":"); // Move to next column using a ","

    dataFile.print(RTC.getMinutes()); 
    dataFile.print(","); // Move to next column using a ","

// Prints cards UID to dataFile
for (int i = 0; i < mfrc522.uid.size; i++) {
          dataFile.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
          dataFile.print(mfrc522.uid.uidByte[i], HEX);
        }
  
    dataFile.println();
  }
  dataFile.close();

 
}

void deniedLed(){
  if (angle == 180){
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  }
  else {
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  digitalWrite (REDPIN, LOW);
  delay (200);
  digitalWrite (REDPIN, HIGH);
  delay (200);
  }

}

void addedLed(){
  if (angle == 0){
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  }
  else {
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  digitalWrite (GREENPIN, LOW);
  delay (200);
  digitalWrite (GREENPIN, HIGH);
  delay (200);
  }

}

You may be on the right track. A simple test is to use another wall wart to power the servo, I doubt the SD card puts much of a load on anything. Can't hurt to try.

#define SERVO_PIN A5

A5 is SCL on the I2C bus, you can't use A4 or A5 when using the I2C bus.

1 Like

Thanks so much @david_2018 that's exactly the problem, changed servo to A1 and works perfectly.

I'm annoyed I didn't figure that out myself.

Thanks again.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.