Activating servo's with RFID (im clueless at this point, my code doesn't work)

Hello fellow coders and builders,

i'm trying to control 2 servo's with 2 RFID tags, and a reader in between. So far i've had the reader activate 2 LED's in the right way, The 2 servo's work perfectly fine in the code i wrote for them.
and then the mayhem begins, when combining these 2 codes the servo's wont move an inch, they are active, that i can tell from the constant shivering when they stay in "0" position, but when i hold a tag for the reader nothing happens, and im clueless why.
So plz help!

the 1st code for the RFID reader, controlling LED's:

int RFIDResetPin = 13;

//Register your RFID tags here
char tag1[13] = "060097889A83";
char tag2[13] = "060097889F86";


void setup(){
  Serial.begin(9600);

  pinMode(RFIDResetPin, OUTPUT);
  digitalWrite(RFIDResetPin, HIGH);

  //ONLY NEEDED IF CONTROLING THESE PINS - EG. LEDs
  pinMode(12, OUTPUT);
  pinMode(8, OUTPUT);
  
}

void loop(){

  char tagString[13];
  int index = 0;
  boolean reading = false;

  while(Serial.available()){

    int readByte = Serial.read(); //read next available byte

    if(readByte == 2) reading = true; //begining of tag
    if(readByte == 3) reading = false; //end of tag

    if(reading && readByte != 2 && readByte != 10 && readByte != 13){
      //store the tag
      tagString[index] = readByte;
      index ++;
    }
  }

  checkTag(tagString); //Check if it is a match
  clearTag(tagString); //Clear the char of all value
  resetReader(); //eset the RFID reader
}

void checkTag(char tag[]){
///////////////////////////////////
//Check the read tag against known tags
///////////////////////////////////

  if(strlen(tag) == 0) return; //empty, no need to contunue

  if(compareTag(tag, tag1)){ // if matched tag1, do this
    lightLED(12);

  }else if(compareTag(tag, tag2)){ //if matched tag2, do this
    lightLED(8);
    
  }else{
    Serial.println(tag); //read out any unknown tag
  }

}

void lightLED(int pin){
///////////////////////////////////
//Turn on LED on pin "pin" for 250ms
///////////////////////////////////
  Serial.println(pin);

  digitalWrite(pin, HIGH);
  delay(250);
  digitalWrite(pin, LOW);
}

void resetReader(){
///////////////////////////////////
//Reset the RFID reader to read again.
///////////////////////////////////
  digitalWrite(RFIDResetPin, LOW);
  digitalWrite(RFIDResetPin, HIGH);
  delay(500);
}

void clearTag(char one[]){
///////////////////////////////////
//clear the char array by filling with null - ASCII 0
//Will think same tag has been read otherwise
///////////////////////////////////
  for(int i = 0; i < strlen(one); i++){
    one[i] = 0;
  }
}

boolean compareTag(char one[], char two[]){
///////////////////////////////////
//compare two value to see if same,
//strcmp not working 100% so we do this
///////////////////////////////////

  if(strlen(one) == 0) return false; //empty

  for(int i = 0; i < 12; i++){
    if(one[i] != two[i]) return false;
  }

  return true; //no mismatches
}

the above works like a charm.

then i wrote this, to control the servo's :

#include <Servo.h>
Servo myservo;
Servo myservo1;
int pos = 0;

void setup(){
  myservo.attach(10);
  myservo1.attach(9);
}

void loop(){

  myservo.write(90);
  delay(200);
  myservo.write(0);
  delay(800);
  
  myservo1.write(90);
  delay(200);
  myservo1.write(0);
  delay(800);
}

nothing to special, but it works like a charm.

then I combined the 2:

int RFIDResetPin = 13;

char tag1[13] = "060097889A83";
char tag2[13] = "060097889F86";

#include <Servo.h>
Servo myservo;
Servo myservo1;
int pos = 0;


void setup(){
  Serial.begin(9600);

  pinMode(RFIDResetPin, OUTPUT);
  digitalWrite(RFIDResetPin, HIGH);

  myservo.attach(10);
  myservo1.attach(9);


}

void loop(){
  char tagString[13];
  int index = 0;
  boolean reading = false;
  
  myservo.write(0);
  myservo1.write(0);
  
  while(Serial.available()){

    int readByte = Serial.read(); //read next available byte

    if(readByte == 2) reading = true; //begining of tag
    if(readByte == 3) reading = false; //end of tag

    if(reading && readByte != 2 && readByte != 10 && readByte != 13){
      //store the tag
      tagString[index] = readByte;
      index ++;
    }
  }

  checkTag(tagString); //Check if it is a match
  clearTag(tagString); //Clear the char of all value
  resetReader(); //eset the RFID reader
}

void checkTag(char tag[]){
  ///////////////////////////////////
  //Check the read tag against known tags
  ///////////////////////////////////

  if(strlen(tag) == 0) return; //empty, no need to contunue

  if(compareTag(tag, tag1)){ // if matched tag1, do this
    Drop1(10);

  }
  else if(compareTag(tag, tag2)){ //if matched tag2, do this
    Drop2(9);

  }
  else{
    Serial.println(tag); //read out any unknown tag
  }

}

void Drop1(int pin){
  Serial.println(pin);
  
  myservo.write(90);
  delay(200);
  myservo.write(0);
  delay(800);
 }
 
void Drop2(int pin){
  
  myservo1.write(90);
  delay(200);
  myservo1.write(0);
  delay(800);
}

void resetReader(){
  ///////////////////////////////////
  //Reset the RFID reader to read again.
  ///////////////////////////////////
  digitalWrite(RFIDResetPin, LOW);
  digitalWrite(RFIDResetPin, HIGH);
  delay(500);
}

void clearTag(char one[]){
  ///////////////////////////////////
  //clear the char array by filling with null - ASCII 0
  //Will think same tag has been read otherwise
  ///////////////////////////////////
  for(int i = 0; i < strlen(one); i++){
    one[i] = 0;
  }
}

boolean compareTag(char one[], char two[]){
  ///////////////////////////////////
  //compare two value to see if same,
  //strcmp not working 100% so we do this
  ///////////////////////////////////

  if(strlen(one) == 0) return false; //empty

  for(int i = 0; i < 12; i++){
    if(one[i] != two[i]) return false;
  }

  return true; //no mismatches
}

And nothing happens, this is the 3rd try on combining the first 2 codes, and none works properly.
I added myservo.write(0) in setup because i notices that the servo's weren't turned on at first, and when i kept a tag near the reader they went "on", after witch nothing happens...
Im sorry for not explaining every bit of code, but most of it is plain simple, im not that good with arduino yet :slight_smile:
If any of you got some suggestions on improving this code, and making it work, don't hesitate and respond please.
btw, the idea behind this is: when a tag comes near the reader, the servo's remove a pin, so a golf-ball rolls down a pipe.

Thanx in advance

Koen de Knegt

Hi dr_happy_feet,

I don't have any servos or a RFID reader to test your code but I would suggest you insert some well placed Serial.print commands to help debug. First place I would insert them is at the Drop1 & Drop2 calls or subroutines to see if they get called correctly and then work your way back from there.
The main loop resets the servos to zero so are the delays in Drop1 & 2 long enough to allow servo to do it's movement before being asked to return to zero.
You don't use the pos variable anywhere in your code apert from where it's initialized so either something is missing or it can be removed.

Thanks for the reply,

indeed the pos can be removed, its a remainder of previous try's
I never tough of the debugging by serial print, thanks a lot for this insight.

more feedback is always welcome, ill keep this topic updated.

You don't do any checks in your code. For example there is no check if the reader is giving you more then the 12 characters you expect. If there is a problem on the serial line (interference or the like) you might not get the end character and write to index 12, 13, 14 and so on which corrupts your memory with unforeseeable consequences.
The you read the reader from the serial line but also write debugging information to the serial connection. Did you make the wiring correct for this double usage of the serial interface?

Another problem. You set index to 0, then see if there are characters in the serial buffer. If, at this exact moment, the reader only sent 4 digits yet, you will compare only these characters to the stored values. In the next round you get the rest of the transmission (or again part of it). You should change that behaviour to look for the start character and then read till the end character is read or the buffer overflows, no matter in which call of the loop() routine you are. clearTag() should reset index to 0.

You should also get rid of the delays in the servo code. Use state variables and check against the current time (see the BlinkWithoutDelay example and compare against the simple Blink example).

oke, so im back at school now and i tested the signals by serial.print commands...
and, drop1&2 dont activate....

so i went back and uploaded an earlier sketch to see if what is the big difference,
the sketch where i used LED's to check if the signal was there and was processed works like a charm, and i don't see the big difference...
and that's what i don't get, although im relatively new to arduino and coding, the steps i took seem logic to me, all i did was replacing the "void lichtled" by "void drop", using the same structure...

he you read the reader from the serial line but also write debugging information to the serial connection. Did you make the wiring correct for this double usage of the serial interface?

please clarify yourself, I wired the sensor like shown on the datasheet (im using an ID-20: http://www.sparkfun.com/datasheets/Sensors/ID-12-Datasheet.pdf) so i have 2 ground wires, a reset wire (wired to +5v, this way it will sense a tag only once if its in range, in stead of every ~ 20 milliseconds or so) I wired the D0 (data0) to pin 0->RX and that is wiring the sensor.

Another problem. You set index to 0, then see if there are characters in the serial buffer. If, at this exact moment, the reader only sent 4 digits yet, you will compare only these characters to the stored values. In the next round you get the rest of the transmission (or again part of it). You should change that behaviour to look for the start character and then read till the end character is read or the buffer overflows, no matter in which call of the loop() routine you are. clearTag() should reset index to 0.

this seems oh so true, but i have no clue how to implement it in code, like mentioned before, im rather new to arduino... if you could also clarify some of this, and how you would implement this in code, i would be gratefull :slight_smile:

thanks for the feedback, and please keep it coming.

oke, so after a couple of Serial.println commands, i can confirm that the code mess up is indeed happening, although I also had the first successful results!

this is the code witch got me the first success:

int RFIDResetPin = 13;

char tag1[13] = "060097889A83";
char tag2[13] = "060097889F86";

#include <Servo.h>
Servo myservo;
Servo myservo1;



void setup(){
  Serial.begin(9600);

  pinMode(RFIDResetPin, OUTPUT);
  digitalWrite(RFIDResetPin, HIGH);

  myservo.attach(10);
  myservo1.attach(9);


}

void loop(){
  char tagString[13];
  int index = 0;
  boolean reading = false;
  
  myservo.write(0);
  myservo1.write(0);
  
  while(Serial.available()){

    int readByte = Serial.read(); //read next available byte

    if(readByte == 2) reading = true; //begining of tag
    if(readByte == 3) reading = false; //end of tag

    if(reading && readByte != 2 && readByte != 10 && readByte != 13){
      //store the tag
      tagString[index] = readByte;
      index ++;
      Serial.println(tagString);
    }
  }

  checkTag(tagString); //Check if it is a match
  clearTag(tagString); //Clear the char of all value
  resetReader(); //eset the RFID reader
}

void checkTag(char tag[]){
  ///////////////////////////////////
  //Check the read tag against known tags
  ///////////////////////////////////

  if(strlen(tag) == 0) return; //empty, no need to contunue

  if(compareTag(tag, tag1)){ // if matched tag1, do this
    Drop1(10);

  }else if(compareTag(tag, tag2)){ //if matched tag2, do this
    Drop2(9);

  }else{
    Serial.println(tag); //read out any unknown tag
  }

}

void Drop1(int pin){
  Serial.println(pin);
  
  myservo.write(90);
  delay(200);
  myservo.write(0);
  delay(800);
 }
 
void Drop2(int pin){
  Serial.println(pin);
  
  myservo1.write(90);
  delay(200);
  myservo1.write(0);
  delay(800);
}

void resetReader(){
  ///////////////////////////////////
  //Reset the RFID reader to read again.
  ///////////////////////////////////
  digitalWrite(RFIDResetPin, LOW);
  digitalWrite(RFIDResetPin, HIGH);
  delay(500);
}

void clearTag(char one[]){
  ///////////////////////////////////
  //clear the char array by filling with null - ASCII 0
  //Will think same tag has been read otherwise
  ///////////////////////////////////
  for(int i = 0; i < strlen(one); i++){
    one[i] = 0;
  }
}

boolean compareTag(char one[], char two[]){
  ///////////////////////////////////
  //compare two value to see if same,
  //strcmp not working 100% so we do this
  ///////////////////////////////////

  if(strlen(one) == 0) return false; //empty

  for(int i = 0; i < 12; i++){
    if(one[i] != two[i]) return false;
  }

  return true; //no mismatches
}

nothing to different from the original code posted above, but hey, it worked :slight_smile:

this is what serial monitor showed me:

06009æ·
06009æ·
06009æ·
06009æ·
06009æ·
060097æ·
0600978·
06009788·
060097889
060097889FÂ
060097889F8
060097889F86
9
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
9
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889F86
060097889A86
060097889A86
060097889A83
10
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
060097889A83
10

the first few tries, resulting in a happy moving servo

but after a while:

060097889A83
060097889A83
060097889A83
10
160097889A83
190097889A83
197097889A83
197897889A83
197887889A83
19788B889A83
19788BF89A83
19788BF09A83
19788BF0CA83
19788BF0C083
19788BF0C0D3
19788BF0C0DA
19788BF0C0DA
09788æ·
06788æ·
06188æ·
06108æ·
06109æ·
061097æ·
0610978·
06109788·
061097889
061097889FÂ
061097889F9
061097889F96
061097889F96
061097889F96
061097889F96
061097889F96
061897889F96
061887889F96
061889889F96
061889F89F96
061889FF9F96
061889FF0F96
061889FF0196
061889FF0166
061889FF0169
061889FF0169
161889FF0169
191889FF0169
197889FF0169
197889FF0169
197889FF0169
19788BFF0169
19788BFF0169
19788BF00169
19788BF0C169
19788BF0C069
19788BF0C0D9
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA
19788BF0C0DA

it just messes up real good.

Pylon, you said this could be a problem, and indeed it is, do you also have a solution? i would be realy gratefull if you could help me with this, for this seems to be the main problem with this setup+code.

Thanks in advance

Koen de Knegt

Try this:

int RFIDResetPin = 13;

char tag1[] = "060097889A83";
char tag2[] = "060097889F86";

#include <Servo.h>
Servo myservo;
Servo myservo1;
int pos = 0;


void setup(){
  Serial.begin(9600);

  pinMode(RFIDResetPin, OUTPUT);
  digitalWrite(RFIDResetPin, HIGH);

  myservo.attach(10);
  myservo1.attach(9);


}

void loop(){
  char tagString[13];
  static int index = 0;
  static boolean reading = false;
  
  myservo.write(0);
  myservo1.write(0);
  
  while(Serial.available()){

    int readByte = Serial.read(); //read next available byte

    if(readByte == 2) {
      reading = true; //begining of tag
    } else if(readByte == 3) {
      reading = false; //end of tag
      tagString[index] = 0;
      index = 0;
      checkTag(tagString); //Check if it is a match
      resetReader(); //reset the RFID reader (is this really necessary?)
    } else if(reading && index < 12 && ((readByte >= '0' && readByte <='9') || (readByte >= 'A' && readByte <= 'F')){
      //store the tag
      tagString[index++] = readByte;
    }
  }
}

void checkTag(char tag[]){
  ///////////////////////////////////
  //Check the read tag against known tags
  ///////////////////////////////////

  if(strlen(tag) != 12) return; //not complete, no need to continue

  if(strncmp(tag, tag1, 12) == 0){ // if matched tag1, do this
    Drop(10);

  } else if(strncmp(tag, tag2, 12) == 0){ //if matched tag2, do this
    Drop(9);
  } else{
    Serial.println(tag); //read out any unknown tag
  }

}

void Drop(int pin){
  Serial.println(pin);
  
  myservo.write(90);
  delay(500); // give the servo half a second to reach position
  myservo.write(0);
 }

void resetReader(){
  ///////////////////////////////////
  //Reset the RFID reader to read again.
  ///////////////////////////////////
  digitalWrite(RFIDResetPin, LOW);
  digitalWrite(RFIDResetPin, HIGH);
}

Pylon, thanks for the quick reply.

I loaded your code, added a Serial.println(tagString) command after the read part you modded, and did some tests.

and im sorry to tell you, the code you set up does not work properly... it has more problems with reading the tag's, and it seems to only activate 1 servo.

I will do some more tests, and im really thankful that you took the time to help me out.

The original code works rather well at the moment, it does need a user manual, dont spam tags in front of the reader and stuff, but it works :slight_smile:

thanks again for the help,

Koen de Knegt

and im sorry to tell you, the code you set up does not work properly... it has more problems with reading the tag's

Remember that more often than not, other people don't have your exact hardware and, more importantly, don't have your eyes and ears.
It's no good complaining when some non-trivial code doesn't do exactly what you want it to do; it's up to you to examine it and fix it, or provide the person who posted sufficient accurate observations to allow thm to hlp you to fix.