I am new to Arduino and have written a sketch using the Adafruit_PWMServoDriver library to control two servos.
The intent here is to replace a Pololu Maestro servo controller that did not quite fit our needs.
Using the Pololu, the script allowed the target pulse widths to be entered in μs. I've tried to mimic the target pulse widths that were used in the Pololu here in my sketch. The program executes properly on a button press and steps through the desired sequence, but the pulse width values that are output are scaled about 4.6X higher than what I've used in my sketch. I used an oscilloscope and pulse width meters to measure the pulse width.
For example pwm.setPWM(0, 0, 1491); results in a measured pulse width of 6925μs
There's obviously a units or scaling problem with the setup or library, but the solution eludes me.
Any servo-savants out there that see what's not obvious to me ?
/***************************************************
This is an example for our Adafruit 16-channel PWM & Servo driver
Servo test - this will drive 8 servos, one after the other on the
first 8 pins of the PCA9685
Pick one up today in the adafruit shop!
------> http://www.adafruit.com/products/815
These drivers use I2C to communicate, 2 pins are required to
interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, &Wire);
// Depending on your servo make, the pulse width min and max may vary, you
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN 600 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 2400 // this is the 'maximum' pulse length count (out of 4096)
// our servo # counter
uint8_t servonum = 0;
const int buttonPin = 2; //push button attached to this pin
int buttonState = LOW; //this variable tracks the state of the button, low if not pressed, high if pressed
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
Serial.begin(9600);
Serial.println("Servo Sequence");
pinMode(buttonPin, INPUT);
pwm.begin();
pwm.setPWMFreq(50); // Analog servos run at ~60 Hz updates
delay(10);
}
// you can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise!
void setServoPulse(uint8_t n, double pulse) {
double pulselength;
pulselength = 1000000; // 1,000,000 us per second
pulselength /= 50; // 50 Hz
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000000; // convert to us
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}
void driveServos() {
Serial.println("Sequence Started");
// Drive each servo one at a time
//Start Frame0 Y+
Serial.println("Starting with Y+");
pwm.setPWM(0, 0, 2244);
pwm.setPWM(1, 0, 1491);
delay(1000);
Serial.println("Pause While Measuring");
//Stop Servos
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
delay(5000);
//Frame1 X-
Serial.println("Moving to X- Position");
pwm.setPWM(0, 0, 1857);
pwm.setPWM(1, 0, 1491);
delay(4500);
Serial.println("Pause While Measuring");
//Stop Servos
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
delay(8000);
Serial.println("Moving to Y- Position");
//Frame2 Y-
pwm.setPWM(0, 0, 1463);
pwm.setPWM(1, 0, 1491);
delay(4500);
Serial.println("Pause While Measuring");
//Stop Servos
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
delay(8000);
//Frame3 X+
Serial.println("Moving to X+ Position");
pwm.setPWM(0, 0, 1053);
pwm.setPWM(1, 0, 1491);
delay(4500);
Serial.println("Pause While Measuring");
//Stop Servos
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
delay(8000);
//Frame4 Z+
Serial.println("Moving to Z+ Position");
pwm.setPWM(0, 0, 1074);
pwm.setPWM(1, 0, 1116);
delay(4500);
Serial.println("Pause While Measuring");
//Stop Servos
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
delay(9500);
//Frame5 Z-
Serial.println("Moving to Z- Position");
pwm.setPWM(0, 0, 1074);
pwm.setPWM(1, 0, 1898);
delay(6500);
Serial.println("Pause While Measuring");
//Stop Servos
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
delay(8000);
//Return to Start
Serial.println("Returning to Start Position");
pwm.setPWM(0, 0, 2244);
pwm.setPWM(1, 0, 1491);
delay(10000);
Serial.println("Sequence Complete");
//Stop Servos
pwm.setPWM(0, 0, 0);
pwm.setPWM(1, 0, 0);
delay(6500);
Serial.println("Ready to Start");
}
void loop() {
//sample the state of the button - is it pressed or not?
buttonState = digitalRead(buttonPin);
//filter out any noise by setting a time buffer
if ( (millis() - lastDebounceTime) > debounceDelay) {
//if the button has been pressed, drive the servos
if ( ((buttonState == HIGH)) ) {
driveServos();
lastDebounceTime = millis(); //set the current time
}
}
}