Processing reading serial affecting servo control?

Hi All,

I have an arduino using an ID-20 for reading rfid tags. I also have a single servo hooked up to the arduino that turns based on whether a rfid tag is present or not.
The arduino then sends the tag via the serial to processing listening down the line.

Everything works until I start using processing. When I read from the serial port the servo no longer moves.

On the arduino I have tested the servo.h library but this seems to cause more problems when using with the ID-12.

Would there be a reason these two components could not like working together? Could it be related to sharing the 5V? Is the serial library and the servo library related in anyway?

Thanks.

-Matt

Would there be a reason these two components could not like working together?

There are lots of reasons why they might not be working together (depending on your code). There is no reason why they can not work together.

Could it be related to sharing the 5V?

You aren't powering the servo from the Arduino, are you?

On the arduino I have tested the servo.h library but this seems to cause more problems when using with the ID-12.

What kinds of problems?

Is the serial library and the servo library related in anyway?

Close cousins. They both work with the Arduino. Does this cause a problem? No.

What kinds of problems?

The problem is when I read an RFID tag (still not sure If I am doing this correctly) the servo is to rotate by an arbitrary angle and when a tag is not being read again the servo rotates by an arbitrary angle. This works until I start either the serial monitor or processing, which is reading the tags that are sent via the serial link. This will cause the servo to intermittently stop rotating, or not rotate at all. This problem is most common when I fire up processing.
I have tried to isolate the issue by testing the reader on its own and the servo. Both work independently.

You aren't powering the servo from the Arduino, are you?

Yes I am, is this problem?

Below is my arduino code. I have tested several methods to rotate the servo. Using servo.h will not allow me to rotate the servo while using the ID-20.

////////////////////////////////
//
// Arduino RFID reader
// 

#include <Servo.h>

#define DEBUG 0
#define READ_RFID 1

#define SERVO_OPENED 90
#define SERVO_CLOSED 0

// Servo system
Servo servo1;
bool zoomState = true; // True is zoomed, false is not
int servoPin = 6; // Servo pin
int RFIDResetPin = 12;
int initReader = 1;

int boardLED = 13;
 
const int tagLength = 13; //  13 = 0-12
char tagString[tagLength] = {};
char curTag[tagLength] = {};

int sendTag = true;
int buttonPin = 3; // Button pin

void setup() {
  // Setup test button
  #ifndef DEBUG
    pinMode(buttonPin, OUTPUT);
  #endif
  
  Serial.begin(9600);

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

  //servo1.attach(servoPin);
  //servo1.write(0);
  // Required by moveServo function 
  pinMode(servoPin, OUTPUT);

}

void moveServo(Servo servo, int sStart, int sEnd) {
    if (sStart < sEnd) {
      for(int pos = sStart; pos < sEnd; pos += 1)  // goes from 0 degrees to 180 degrees 
      {                                      // in steps of 1 degree 
          servoPulse(servoPin, sEnd);  
      }
    } else {
      for(int pos = sEnd; pos < sStart; pos -= 1)  // goes from 0 degrees to 180 degrees 
      {                                      // in steps of 1 degree 
          servoPulse(servoPin, sStart);
      }
    }
}

void servoPulse (int servo, int myAngle1) {
  int pulseWidth1 = (myAngle1 * 11) + 500; // Converts angle to microseconds
  digitalWrite(servo, HIGH); // Set servo high (turns it on)
  delayMicroseconds(pulseWidth1); // Wait a very very small amount
  digitalWrite(servo, LOW); // Set servo low (turns it off)
  delay(20); // Typical Refresh cycle of servo (20 ms)
}

void zoomLensOut() {
    moveServo(servo1, 0, 90);
}


void zoomLensIn() {
    moveServo(servo1, 90, 180);
}

void readRFIDTag() {
  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 != tagLength) {
      //store the tag
      tagString[index] = readByte;
      index ++;
    }  
  }
}

void loop() {
  
  #ifdef READ_RFID
    readRFIDTag();
  #else
    // read the state of the pushbutton value:
    buttonState = digitalRead(buttonPin);

    // check if the pushbutton is pressed.
    // if it is, the buttonState is HIGH:
    if (buttonState == LOW) {
      // turn LED on:    
      if (debugTag < 3) {
        debugTag++;
      } else {
        debugTag = 0;
      }
      delay(500);
    }
    tagString = tagArray[debugTag];
  #endif
  
  
  #ifdef DEBUG
  if(tagString != "" && !sendTag)
    Serial.println(tagString);
  #endif
  
  
  strcpy(curTag, tagString);
  // Check if the current tag is the same.
  if (!compareTag(curTag, tagString) && tagString[0] != NULL) {
    // New tag read -- ZOOM IN
    strcpy(curTag, tagString);
    Serial.print(tagString);
    if (!zoomState) {
      moveServo(servo1, 0, 90);
      zoomState = true;
      //Serial.println("ZOOM IN NEW");
    }
  } else if (compareTag(curTag, tagString) && tagString[0] != NULL) {
    // Same tag read -- ZOOM IN
    Serial.print(tagString);
    if (!zoomState) {
      moveServo(servo1, 0, 90);
      //servo1.write(90);
      //delay(50);
      zoomState = true;
      //Serial.println("ZOOM IN SAME");
    }
  } else {
    // No tag read -- ZOOM OUT
    if (zoomState) {
      moveServo(servo1, 90, 140);
      //servo1.write(0);
      //delay(50);
      zoomState = false;
      //Serial.println("ZOOM OUT");
    }
  }

  clearTag(tagString); //Clear the char of all value
  resetReader(); //eset the RFID reader
}


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

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
}

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;
  }
}

Thanks.

-Matt

Yes I am, is this problem?

Most likely. The source of power when the USB cable is connected is not the same source of power as when the USB cable is not connected.

The current required to move the servo may be marginally safe when the Arduino is powered by batteries/wall-wart, or it may not.

The current required to move the servo simply may not be available when the Arduino is USB powered.

In any case, running all the current that the servo needs through the Arduino is not a good idea.

The servo should be powered independently of the Arduino (with the grounds connected), and simply commanded by the Arduino.

const int tagLength = 13; //  13 = 0-12

I think your math is wrong. 0 minus 12 is -12, not 13. :slight_smile:

Cool I will do some testing with a wall-wart (never heard that before! Awesome). This could likely be my problem as the ID-20 (RFID reader) and the servo were both powered by the arduino.

I think your math is wrong. 0 minus 12 is -12, not 13.

Depends which way you look at it. Counting from 0 to 12 is 13 numbers. I just used it to remind me what I was doing. Probably not very descriptive though.

Thanks.

-Matt

I just used it to remind me what I was doing. Probably not very descriptive though.

I was just teasing. I'd have used "13: 0 -> 12" or "13: 0 to 12", instead of "13 = 0 - 12".