Servo library and speed controllers showing strange behavior

Greetings,
I was wondering if anyone has any advice on 2 major issues I am seeing with my current project.

Summary: I have an Arduino Micro attached to 2 speed controllers whose rpm's are determined by a simple hall effect throttle. The design uses an RFID reader that acts as a security gate such that the speed controllers are shut down when not authenticated.

Problems:

  1. I am getting slight jolting movements on the engines attached to my speed controllers. when the user of this device is not authorized or throttle is off I am sending a 1 ms pulse to the speed controllers. As documented in the device's pdf this is the correct "off" setting. This jolting movement is intermittent but occurs when the throttle is off. It seems like it might be some sort of electronic echo but I am not a electrical engineer.

  2. when running the engines using the hall effect throttle to control rpm's occasionally one engine will just shut down and the other keeps running. then if i power down and start up again the engines will run well for awhile but the issue is frequent enough that it has to get fixed. I am using 2 Servo instances to send messages to the speed controllers.

here is my code. :

#include <Servo.h>
#include <SoftwareSerial.h>

//Virtual Serial Port RX,TX
SoftwareSerial rfidPort(10,11);

//RFID variables
char davidHoff[13] = "7C00563B9988";
String testID;
char tagID[12];
char tagRead;
int loopIndex = 0;
int readIndex = 0;
int ignoreIndex = 0;
int awayCount = 0;
int RFIDResetPin = 12;
boolean userAuthorized = false;
boolean completeTagRead = true;
unsigned long startTime;
unsigned long currentTime;
boolean startFound = false;


//Throttle Variables and Servo objects
Servo jetLeft;
Servo jetRight;
int hallLow = 22;
int hallHigh = 894;
int throttleHigh = 872;
int pulseBase = 1000;
int pulseInterval = 20000;
int calibrated = 1;
int jetPinLeft = 4;
int jetPinRight = 9;

//LED variables
int led = 7;

void setup() 
{
 Serial.begin(9600);
 
 pinMode(led, OUTPUT);
 pinMode(RFIDResetPin, OUTPUT);
 digitalWrite(RFIDResetPin, HIGH);
 rfidPort.begin(9600);
 jetLeft.attach(jetPinLeft);
 jetRight.attach(jetPinRight);
 
}

void loop() 
{   
   if(loopIndex == 0) {
     resetRfidReader();
   }
   if (!rfidPort.available()) {
     digitalWrite(led, LOW);
     userAuthorized = false;
   }
   
   //wait for RFID Reset to occur
   if(loopIndex > 15 ) {
     if (rfidPort.available()) {        
       tagRead = rfidPort.read(); 
       if(ignoreIndex > 4) {
         if (tagRead == davidHoff[0]) {      
           startFound = true;
           readIndex++;
           loopIndex = 16; 
         } else {
           if(startFound == true) {
             if (tagRead != davidHoff[readIndex]){
               completeTagRead = false; 
             }              
             readIndex++;
           }  
         }
       }
       ignoreIndex++;       
     } else {
       digitalWrite(led, LOW);
       userAuthorized = false; 
       
     }
   } 
     
   int pulseLength = readThrottle();

   delay(10);
   if (userAuthorized == true) {
     digitalWrite(led, HIGH);
     jetLeft.writeMicroseconds(pulseLength + pulseBase);
     jetRight.writeMicroseconds(pulseLength + pulseBase);
     delayMicroseconds(pulseInterval - pulseLength); 
   } else {
     digitalWrite(led, LOW);
     jetLeft.writeMicroseconds(1000);
     jetRight.writeMicroseconds(1000);
     delayMicroseconds(1900);   
   }

   loopIndex++;
  
   if (readIndex == 12 && completeTagRead == true) {      
     userAuthorized = true;
     awayCount = 0;      
   }
   if (completeTagRead == false) {
     userAuthorized = false;    
   }
   if (awayCount > 1) {
     userAuthorized = false;    
   }  
     
   if (readIndex >= 12 || loopIndex >= 32) {      
     loopIndex = 0; 
     readIndex = 0;
     ignoreIndex = 0;
     startFound = false;
     completeTagRead = true;
     awayCount++;           
   } 
}

int readThrottle()
{
   int rawHE = analogRead(A5);
   rawHE = rawHE - 22;
   if (rawHE < 0 ) {
     rawHE = 0;
   }
   int invert = throttleHigh - rawHE;
   float ratio = invert/872.0;
   int pulseLength = int(ratio * 1000.0);
   
   return pulseLength;
}

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

}

any thoughts would be greatly appreciates.

Thanks!

SoftwareSerial and the Servo libraries interfere with each other.

You could try the ServoTimer2 library or maybe my yet another software serial

And please edit your Post and put your code in code tags using the code button '</>'

...R

One of the ESCs shutting down means it has detected an error condition and it shuts down
for safety - perhaps undervoltage, overcurrent, drop-out of servo signal for too long, or
over-heating.

Robin2: quick question about your "yet another Software Serial" code. I am working on a Arduino Micro, will that cause a problem?

r737lundgren:
Robin2: quick question about your "yet another Software Serial" code. I am working on a Arduino Micro, will that cause a problem?

Sorry - I don't know. If it uses the same hardware as the Atmega 328 there may not be a problem, but you will just have to try it.

I wrote the code so that people could study it and modfy it to suit their needs.
Look at the appropriate Atmel datasheets.

...R

i feel like a total idiot. can't i use the Micro's RX/TX pins or do those interfere with the Servo Library as well?

else {
     digitalWrite(led, LOW);
     jetLeft.writeMicroseconds(1000);
     jetRight.writeMicroseconds(1000);
     delayMicroseconds(1900);  
   }

Shouldn't this delay be 19000? I don't think it will help anything, just saying. Pulse interval is not anywhere near as critical as pulse width of the high portion when dealing with only servos (try it yourself, see how high you can get the pulse interval before your servo starts to go lax in between pulses or set it really low and see if anything bad happens).

As an alternate experiment since you are dealing with ESCs try commenting out all of your pulse interval delays, if your pulse interval gets too long then the ESC will likely error out, since you are hand setting delays to be equal to 20ms and have additional processing going on then the pulse interval is most certainly greater than the 20ms specification.

Additionally since you are basically doing all of the work by hand already you do not really need to use the servo library, the following code..

  digitalWrite(led, LOW);

  digitalWrite(jetLeft, HIGH);
  delayMicroseconds(1000);
  digitalWrite(jetLeft, LOW);

  digitalWrite(jetRight, HIGH);
  delayMicroseconds(1000);
  digitalWrite(jetRight, LOW);

  delayMicroseconds(18000); //I set this to 18000 because we already used 2ms setting left and right

Should accomplish the exact same thing as the piece of code above without using the servo library, of course without the servo library you do not have the other associated functions but it does not appear that you are using them anyway (except attach() which is basically a setup function for the servo library).

I honestly do not know what it is between the Software serial library and Servo library that causes them to not play well together (I believe it has something to do with interrupts being disabled), so I truly do not know if you would see any benefit implementing this method.

BH72:
it does not appear that you are using them anyway (except attach() which is basically a setup function for the servo library).

Although don't forget that an attach() does send a positioning pulse to the servo. That pulse is dictated by the value of DEFAULT_PULSE_WIDTH in servo.h (1500us unless you edited it), or the value of write() you gave just before the attach(), or the value it was using before a detach().

#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached

r737lundgren:
i feel like a total idiot. can't i use the Micro's RX/TX pins or do those interfere with the Servo Library as well?

If the HardwareSerial RxTx is available that won't interfere with the Servo library.

...R

solved it. thx for all of your help. using the RX/TX pins cleaned up the Servo signals and its all working flawlessly. thx again