Servo Motor is being temperamental and I dont understand what I am doing wrong.

Hi everybody,

For my project I am attempting to make a cat flap that requires a RFID chip on the outside to open the flap, and a PIR sensor on the other side to open the flap. I am using a servo motor to pull the flap open and both sensors (RF Module and PIR) send signals to the servo to make it turn to a specific angle, wait 8 seconds to allow the cat through, and then turn back to the angle it was at before. I have got this to work with the PIR sensor, however I am having trouble with the RF Module. I am using the RDM630 from SeeedStudio.

For the RDM630 side of it, the servo is resting at 90 degrees, and it should turn to 0 degrees, wait for 8 seconds and then turn back. It does do this when the RFID chip is picked up by the antenna, however after it goes back to the strating position it runs through the whole process again, sometimes 2, often 3 and even more times before stopping. It should only run through once before stopping.

I will attach my code as I believe I have connected everything correctly and it must be a problem within the code.

#include <Servo.h>

#include <LiquidCrystal.h>

#include <SoftwareSerial.h>

LiquidCrystal lcd(12, 11, 5, 4, 10, 8);

unsigned long time; 

int val2;
int ledState = 0;
const int RFrecieve = 2;
const int RFtransmit = 3; 
SoftwareSerial rfidSerial (RFrecieve, RFtransmit);
int incomingByte = 0;

Servo myservo;


int RFID(){ //setting up the RFID function to be used in the void loop

  byte i = 0;
  byte val2 = 0;
  byte code[6];
  byte goodcode[11] = {0x30, 0x30, 0x30, 0x38, 0x39, 0x37, 0x32, 0x35, 0x37, 0x32};
  byte checksum = 0;
  byte bytesread = 0;
  byte tempbyte = 0;
  int result = 0;
  
  if (rfidSerial.available()) {
    result=1;
    if((val2 = rfidSerial.read()) == 0x02) {
      bytesread = 0;
      Serial.println("Read it");
      while(bytesread < 12) { //10 digit code and 2 digit checksum
        if(rfidSerial.available()){
          val2 = rfidSerial.read();
          if((val2 == 0x0D) ||(val2 == 0x0A)||(val2 == 0x03)||(val2 == 0x02)) { //if header or stop bytes 
            break; //stop reading
          }
          //Ascii to hex conversion
          if ((val2>='0') && (val2<='9')) {
            val2 = val2 - '0';
          } else if  ((val2>='A') && (val2<='F')) {
            val2 = 10 + val2 - 'A';
          }
          //Every two hex digits add byte to code:
          if (bytesread & 1 == 1) {
            //make some space for this hex digit by shifting previous hex digit with 4 bits to left
            code[bytesread >> 1] = (val2 | (tempbyte <<4));

            if (bytesread >> 1 !=5){ //if were at checksum byte
              checksum^=code[bytesread >> 1]; //calculate checksum (XOR)
            };
          } else {
            tempbyte = val2 ;//store first hex digit first
          };
          bytesread++; // ready to read next hex digit
        }
      }
      //output to serial

        if (bytesread == 12) { // if 12 digit read is complete
        Serial.print("5-byte code: ");
        for (i=0; i<5; i++) {
          if (code[i] < 16) rfidSerial.print("0");
          Serial.print(code[i], HEX);
          Serial.print(" ");
        }
        Serial.println();
        Serial.print("Checksum: ");
        Serial.print(code[5], HEX);
        Serial.println(code[5] == checksum ? " -- passed." : " -- error.");
        if(code[5] == checksum)
        result=1;
        Serial.println();
      }
      bytesread = 0;;
    }
  }
  return result;

}
 

//int counter = 0;
//int currentState = 0;
//int previousState = 0;

//int counter2 = 0;
//int currentState2 = 0;
//int previousState2 = 0;

//int servoval;
 
const int led = 13; 



int motion = 6; 
int val = 0;
int motionState = LOW;
//int pulse (1500);


//int Sol1State = 0;
//int Sol2State = 0;
//int RFsignal = 0;
//int RFState = LOW; //rest
//int motion = 0;


void setup() {
  Serial.begin(9600);//serial comms between arduino and computer
  rfidSerial.begin(9600);//softwareserial allows for one than one serial i/o
  //Serial.println("RFID TEST");
//  pinMode(Motor, OUTPUT);
  pinMode (led, OUTPUT);
  pinMode (motion, INPUT);
  pinMode (RFrecieve, INPUT);
  pinMode (RFtransmit, OUTPUT);
//  digitalWrite(Motor, LOW);
  digitalWrite(led, LOW);
  lcd.begin(16, 2);
  myservo.attach(9); //attaches the servo to pin 9 in setup rather than declaring as const int
  myservo.write(90);
  delay(2000);
  
}

void loop()
{
  {
  delay(140);
  if (RFID()==1)
  {
  //servoval = digitalRead(RFID);
  //servoval = map(servoval, 0, 1023, 0, 180);
  myservo.write(0);
  delay(8000);
  myservo.write(90);
  delay(1500);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("Cat inside");
  delay(140);
  }
  }
  //THIS LOOP IS FOR THE RF MODULE RDM630. ANY CODE WHICH IS // OUT IS NO LONGER NEEDED AND SHOULD BE IGNORED, HOWEVER I NEVER DELETE CODE UNTIL I HAVE THE FINAL PRODUCT WORKING I JUST // IT OUT
  
  //else
  //{
//    digitalWrite(Motor, LOW);
//myservo.write(0);
  //}
//} //FOR RF READER

                  
{ 
  val = digitalRead (motion);
  if (val == HIGH)
  {  
  myservo.write(180);
  delay(8000);
  myservo.write(90);
  delay(1500);
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("Cat outside");
  } //THIS LOOP IS FOR THE PIR SENSOR. ANY CODE WHICH IS // OUT IS NO LONGER NEEDED AND SHOULD BE IGNORED, HOWEVER I NEVER DELETE CODE UNTIL I HAVE THE FINAL PRODUCT WORKING I JUST // IT OUT.
  }
  //else
  //{
   // digitalWrite (led, LOW);
    //if (motionState == LOW)//PIR sensor (inside to outside) part
    //Serial.println("PIR off");
    //motionState = LOW;
  }


//    currentState2 = 0;
  
  //if(currentState2 != previousState2)
//{
  //if (currentState2 == 1)
  //{
    //counter2 = counter2 + 1;
    //lcd.setCursor(0, 8);
    //lcd.print(counter2);
  //}
//}
//previousState2 = currentState2;
//delay(250);
    //{
  //  Serial.print("Time: ");
    //time = millis();
    //lcd.setCursor(1, 0);
    //lcd.print(time);
  //  delay(1000);
  //}
//}
//}

I understand it is a lot of code to look through, but the loop is very simple there is just a lot before.
I would appreciate it if someone could have a look through this and help me out.

Thanks :slight_smile:

You probably need a variable to record the fact that the flap has opened and closed and that variable can be checked to prevent the door opening when you don't want it to. Maybe call it doorActivated and then your code could be something like this

 if (RFID()==1 && doorActivated == false)   // <-----------
  {
     //servoval = digitalRead(RFID);
     //servoval = map(servoval, 0, 1023, 0, 180);
     myservo.write(0);
     delay(8000);
     myservo.write(90);
     doorActivated = true;  //  <-------
     delay(1500);
     lcd.clear();
     lcd.setCursor(0, 1);
     lcd.print("Cat inside");
     delay(140);
  }

I don't know the circumstances in which doorActivated should be set back to false - perhaps when the cat goes out?

...R

Robin,

Just had a try at the solution you suggested, however the problem is still there :confused:

You mean hobby servo? Not a servomotor surely?
Anyway are you providing adequate power for the servo, they need a lot of current?

joe_wilson99:
Just had a try at the solution you suggested, however the problem is still there :confused:

You need to post the exact program that you tried - otherwise I have no idea what might be the problem.

And please post it after this Reply and do not over-write your earlier code.

...R

Robin2, here is the code I tried.

void loop()
{
  {
  delay(140);
  if (RFID()==1 && doorActivated == false) 
  {
    myservo.attach(9);
  //servoval = digitalRead(RFID);
  //servoval = map(servoval, 0, 1023, 0, 180);
  myservo.write(0);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("Cat inside");
  delay(8000);
  myservo.write(90);
  doorActivated = true;
  delay(1500);
  myservo.detach();
   
  delay(1500);
  doorActivated = false;
  //int off = false;
  //myservo.attach(9);
  }
  }

And in response to MarkT, sorry your correct I meant hobby servo, and yes it is I checked before building the circuit and have tested it with a multimeter.

joe_wilson99:
Robin2, here is the code I tried.

You need to post the complete program.

...R