I've read a dozen or so requests for help with servos, and I think this problem is a bit different. But someone made the comment on one of those threads that calls to Serial will cause problems, and I wonder if that's part of what I'm seeing. I've attached a Sparkfun TFMini to the horns of a Futaba S3003 servo. I'm only using one motor. I'm trying to make a poor-man's LIDAR system, with a +50º to -50º, slow, smooth sweep. What I'm getting is a smooth sweep about 80% of the time, and jerky, twitchy behavior 20% of the time.
Code is:
/*
* Testbed for integrating servo sweep with TFMini
*/
#include <Servo.h>
#include <SoftwareSerial.h>
#include "TFMini.h"
// Setup software serial port
SoftwareSerial mySerial(2, 3); // Uno RX (TFMINI TX), Uno TX (TFMINI RX)
TFMini tfmini;
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup()
{
Serial.begin(19200) ;
myservo.attach(9); // attaches the servo on pin 9 to the servo object
while (!Serial){
}
mySerial.begin(TFMINI_BAUDRATE);
// Step 3: Initialize the TF Mini sensor
tfmini.begin(&mySerial);
}
void loop()
{
int val = 0 ;
uint16_t dist ;
uint16_t strength ;
// Set at neutral, around 95 with this servo,
// but jump to 80 and move slowly to center
Serial.println("Centering") ;
for (pos = 80; pos < 95; pos += 3)
{
myservo.write(pos) ;
delay(200);
}
delay(1000) ;
// transition from 'neutral' to -50
Serial.println("Positioning") ;
for (pos = 95; pos > 45; pos -= 3)
{
myservo.write(pos) ;
delay(200) ;
}
// transition from -50 to +50
Serial.println("Sweeping") ;
// ten sweeps, then recenter
for (int j = 0; j < 10; j++)
{
for (pos = 45; pos < 130; pos += 3)
{
Serial.print(pos) ;
Serial.print("\t") ;
dist = tfmini.getDistance();
strength = tfmini.getRecentSignalStrength();
// Display the measurement
Serial.print(dist);
Serial.print(" cm\tsigstr: ");
Serial.print(strength);
// Make a pseudo bar chart of distances
if (dist < 1200)
{
Serial.print("\t") ;
for (int i = 0; i < dist; i += 10)
{
Serial.print("|") ;
}
}
Serial.println() ;
// move servo to next postion
myservo.write(pos) ;
delay(200); // waits for the servo to reach the position
}
Serial.println() ;
// transition from +50 to -50
//Serial.println("Sweeping other direction") ;
for (pos = 130; pos > 45; pos -= 3) // goes from +50 to -50
{
Serial.print(pos) ;
Serial.print("\t") ;
dist = tfmini.getDistance();
strength = tfmini.getRecentSignalStrength();
// Display the measurement
Serial.print(dist);
Serial.print(" cm\tsigstr: ");
Serial.print(strength);
if (dist < 1200)
{
Serial.print("\t") ;
for (int i = 0; i < dist; i += 10)
{
Serial.print("|") ;
}
}
Serial.println() ;
// Move to next position
myservo.write(pos) ;
delay(200); // wait for the servo to reach the position
}
Serial.println() ;
}
// transition back from -50 to neutral
Serial.println("Centering") ;
for (pos = 45; pos < 95; pos += 3)
{
myservo.write(pos) ;
delay(200); // waits 15ms for the servo to reach the position
}
}
[Wiring picture attached]
So, center the servo, reposition to -50, sweep back and forth from -50 to +50 ten times, repeat. Along the way, take readings with the TFMini.
Based on other recommendations, I have the servo on its own +5.3V 8A (measured) max power supply with grounds connected (actually, the motion is smoother with just my Ruggeduino, but the power drops too much, of course.) I have a 470µf capacitor right before the leads for the motor. I've tried various other suggestions to 'detach' after and 'reattach' before moving the servo; alter the servo pin to input after and back to output before moving; various changes to the step distance and timing; and making sure I'm not taking readings from the TFMini (software serial) or to the serial monitor during the moves (Serial). As far as I can tell, Futaba servos are considered pretty good - I don't think that's the issue. The servo runs the sweep example code smoothly, but a bigger range than I want and much faster than I want.
My suspicion is that the various serial calls are all asynchronous, and what's happening is that they're stealing the interrupt and screwing up the signal to the servo. That, I think, is what someone else meant when they said calls to Serial might be a problem. (Like, here.)
What I can't seem to find is some explanation of exactly what's going on for one of these calls to position the servo, and what could go wrong with that.
I think the next thing to try is disabling interrupts while moving the motor. At least, I think that's what adding "TIMSK0=0;" in setup would be doing. Any thoughts?
