Please Help.
My project I am connecting a 16 x 12-bit PWM & Servo Shield to 3-4 servos control each by a button to my Servo Shield. I am having trouble finding an example code to help me get started. (I delete my old one on accident). I just need the example for turning on and off servos by pressing one button per servo. If you have an example code I'd appreciate it to help me get idea of how to write the code and get started on my project.
Thanks,
Annie
Help with 16 x 12-bit PWM & Servo Shield
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- annietcu
- Posts: 2
- Joined: Tue Sep 02, 2014 5:02 pm
Help with 16 x 12-bit PWM & Servo Shield
- Attachments
-
- moving art 2.jpeg (261.68 KiB) Viewed 811 times
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: Help with 16 x 12-bit PWM & Servo Shield
What exactly do you want the button to do? What exactly should a servo do when the button is pressed? What should the servo do when the button is released?
- annietcu
- Posts: 2
- Joined: Tue Sep 02, 2014 5:02 pm
Re: Help with 16 x 12-bit PWM & Servo Shield
I would like the servos to move from 0 degrees to 180 degrees when the button is pressed. If one presses the button for a second time the servo horn would go from 180 degrees back to 0 degrees.
Thank you for getting back to me so fast Rick!
-Annie
Thank you for getting back to me so fast Rick!
-Annie
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: Help with 16 x 12-bit PWM & Servo Shield
This tutorial shows how to move servos using the Adafruit PWM Servo Library
https://learn.adafruit.com/16-channel-p ... it-library
Go through the tutorial and make sure you can control the servos with the 'servo' example sketch.
This tutorial will show you how to hook up a button
https://learn.adafruit.com/adafruit-ard ... tal-inputs
When you have those both working, you want to combine them into your actual sketch. Use this debounce routine to read the button presses:
Assuming your button is connected to pin 2, your code for a single button and servo will look something like this:
That should be enough to get you started.
https://learn.adafruit.com/16-channel-p ... it-library
Go through the tutorial and make sure you can control the servos with the 'servo' example sketch.
This tutorial will show you how to hook up a button
https://learn.adafruit.com/adafruit-ard ... tal-inputs
When you have those both working, you want to combine them into your actual sketch. Use this debounce routine to read the button presses:
Code: Select all
uint8_t debounceRead(int pin)
{
uint8_t pinState = digitalRead(pin);
uint32_t timeout = millis();
while (millis() < timeout+10)
{
if (digitalRead(pin) != pinState)
{
pinState = digitalRead(pin);
timeout = millis();
}
}
return pinState;
}
Code: Select all
uint8_t buttonState = HIGH;
uint8_t previousButtonState = HIGH;
void loop()
{
buttonState = debounceRead(2);
if ((LOW == buttonState) and (HIGH == previousButtonState))
{
moveServo(servonum, SERVOMIN, SERVOMAX);
}
if ((HIGH == buttonState) and (LOW == previousButtonState))
{
moveServo(SERVOMAX, SERVOMIN);
}
previousButtonState = buttonState;
}
void moveServo(int servonum, int from, int to)
{
if (from < to)
for (uint16_t pulselen = from; pulselen < to; pulselen++) {
pwm.setPWM(servonum, 0, pulselen);
}
else
for (uint16_t pulselen = from; pulselen > to; pulselen--) {
pwm.setPWM(servonum, 0, pulselen);
}
}
uint8_t debounceRead(int pin)
{
uint8_t pinState = digitalRead(pin);
uint32_t timeout = millis();
while (millis() < timeout+10)
{
if (digitalRead(pin) != pinState)
{
pinState = digitalRead(pin);
timeout = millis();
}
}
return pinState;
}
- richard905
- Posts: 7
- Joined: Fri May 25, 2012 6:28 pm
Re: Help with 16 x 12-bit PWM & Servo Shield
Thank you, Rick & Annie, your code is very helpful for me, my application is very similar.
I'd like to drive 5 servos, by using one pushbutton,(PIN2) , when the button is pressed, all 5 servos move from 0 degree to 100 degrees; when the button is pressed for a second time, all 5 servos move from 100 degrees back to 0 degree.
How to modify your code? (Could you post the complete code?) appreciate!
I'd like to drive 5 servos, by using one pushbutton,(PIN2) , when the button is pressed, all 5 servos move from 0 degree to 100 degrees; when the button is pressed for a second time, all 5 servos move from 100 degrees back to 0 degree.
How to modify your code? (Could you post the complete code?) appreciate!
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: Help with 16 x 12-bit PWM & Servo Shield
I would modify the moveServo function to move all five servos at once:
Code: Select all
uint8_t buttonState = HIGH;
uint8_t previousButtonState = HIGH;
void loop()
{
buttonState = debounceRead(2);
if ((LOW == buttonState) and (HIGH == previousButtonState))
{
moveServos(SERVOMIN, SERVOMAX);
}
if ((HIGH == buttonState) and (LOW == previousButtonState))
{
moveServos(SERVOMAX, SERVOMIN);
}
previousButtonState = buttonState;
}
void moveServos(int from, int to)
{
if (from < to)
for (uint16_t pulselen = from; pulselen < to; pulselen++) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
else
for (uint16_t pulselen = from; pulselen > to; pulselen--) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
}
uint8_t debounceRead(int pin)
{
uint8_t pinState = digitalRead(pin);
uint32_t timeout = millis();
while (millis() < timeout+10)
{
if (digitalRead(pin) != pinState)
{
pinState = digitalRead(pin);
timeout = millis();
}
}
return pinState;
}
- richard905
- Posts: 7
- Joined: Fri May 25, 2012 6:28 pm
Re: Help with 16 x 12-bit PWM & Servo Shield
Hi Rick:
Thank you very much for your help, the code works! but when the button is pressed, the servos move back & forth once rather than 0 degree to 100 degrees; another issue is little noise. (I use Tower Pro SG90 micro 9g servos). Here is my complete code, Could you check for me? Thanks again.
Thank you very much for your help, the code works! but when the button is pressed, the servos move back & forth once rather than 0 degree to 100 degrees; another issue is little noise. (I use Tower Pro SG90 micro 9g servos). Here is my complete code, Could you check for me? Thanks again.
Code: Select all
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 150
#define SERVOMAX 600
uint8_t servonum = 0;
uint8_t buttonState = HIGH;
uint8_t previousButtonState = HIGH;
void setup() {
Serial.begin(9600);
Serial.println("16 channel Servo test!");
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
}
// 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 /= 60; // 60 Hz
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000;
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}
void loop()
{
buttonState = debounceRead(2);
if ((LOW == buttonState) and (HIGH == previousButtonState))
{
moveServos(SERVOMIN, SERVOMAX);
}
if ((HIGH == buttonState) and (LOW == previousButtonState))
{
moveServos(SERVOMAX, SERVOMIN);
}
previousButtonState = buttonState;
}
void moveServos(int from, int to)
{
if (from < to)
for (uint16_t pulselen = from; pulselen < to; pulselen++) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
else
for (uint16_t pulselen = from; pulselen > to; pulselen--) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
}
uint8_t debounceRead(int pin)
{
uint8_t pinState = digitalRead(pin);
uint32_t timeout = millis();
while (millis() < timeout+10)
{
if (digitalRead(pin) != pinState)
{
pinState = digitalRead(pin);
timeout = millis();
}
}
return pinState;
}
Last edited by adafruit_support_rick on Sun Nov 09, 2014 7:14 pm, edited 1 time in total.
Reason: please use code tags (</> button)when posting code
Reason: please use code tags (</> button)when posting code
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: Help with 16 x 12-bit PWM & Servo Shield
Code: Select all
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 150
#define SERVOMAX 600
uint8_t servonum = 0;
uint8_t buttonState = HIGH;
uint8_t previousButtonState = HIGH;
int servoState = SERVOMIN;
void setup() {
Serial.begin(9600);
Serial.println("16 channel Servo test!");
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
}
// 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 /= 60; // 60 Hz
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000;
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}
void loop()
{
buttonState = debounceRead(2);
if ((LOW == buttonState) and (HIGH == previousButtonState))
{
if (servoState == SERVOMIN) {
moveServos(SERVOMIN, SERVOMAX);
servoState = SERVOMAX;
}
else {
moveServos(SERVOMAX, SERVOMIN);
servoState = SERVOMIN;
}
}
previousButtonState = buttonState;
}
void moveServos(int from, int to)
{
if (from < to)
for (uint16_t pulselen = from; pulselen < to; pulselen++) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
else
for (uint16_t pulselen = from; pulselen > to; pulselen--) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
}
uint8_t debounceRead(int pin)
{
uint8_t pinState = digitalRead(pin);
uint32_t timeout = millis();
while (millis() < timeout+10)
{
if (digitalRead(pin) != pinState)
{
pinState = digitalRead(pin);
timeout = millis();
}
}
return pinState;
}
- richard905
- Posts: 7
- Joined: Fri May 25, 2012 6:28 pm
Re: Help with 16 x 12-bit PWM & Servo Shield
Rick, I'd like to drive 2x5 servos(2 groups) for my project, by using two pushbutton,(PIN2, PIN3) ,
when the button1 is pressed, Only Group-A 5 servos(0,1,2,3,4) move from 0 degree to 100 degrees;
when the button1 is pressed for a second time, those 5 servos move from 100 degrees back to 0 degree;
when the button2 is pressed, Only Group-B 5 servos(5,6,7,8,9) move from 0 degree to 100 degrees;
when the button2 is pressed for a second time, those 5 servos move from 100 degrees back to 0 degree;
I modify the code, seems some mistake, Could you check for me again? Thanks so much again!
Code:
when the button1 is pressed, Only Group-A 5 servos(0,1,2,3,4) move from 0 degree to 100 degrees;
when the button1 is pressed for a second time, those 5 servos move from 100 degrees back to 0 degree;
when the button2 is pressed, Only Group-B 5 servos(5,6,7,8,9) move from 0 degree to 100 degrees;
when the button2 is pressed for a second time, those 5 servos move from 100 degrees back to 0 degree;
I modify the code, seems some mistake, Could you check for me again? Thanks so much again!
Code:
Code: Select all
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 150
#define SERVOMAX 600
uint8_t servonum = 0;
uint8_t buttonState1 = HIGH;
uint8_t previousButtonState1 = HIGH;
uint8_t buttonState2 = HIGH;
uint8_t previousButtonState2 = HIGH;
int servoState = SERVOMIN;
void setup() {
Serial.begin(9600);
Serial.println("16 channel Servo test!");
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
}
// 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 /= 60; // 60 Hz
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000;
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}
void loop()
{
buttonState1 = debounceRead(2);
buttonState2 = debounceRead(3);
if ((LOW == buttonState1) and (HIGH == previousButtonState1));
((LOW == buttonState2) and (HIGH == previousButtonState2));
{
if (servoState == SERVOMIN) {
moveServos(SERVOMIN, SERVOMAX);
servoState = SERVOMAX;
}
else {
moveServos(SERVOMAX, SERVOMIN);
servoState = SERVOMIN;
}
}
previousButtonState1 = buttonState1;
previousButtonState2 = buttonState2;
}
void moveServos(int from, int to)
{
if (from < to)
for (uint16_t pulselen = from; pulselen < to; pulselen++) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
pwm.setPWM(5, 0, pulselen);
pwm.setPWM(6, 0, pulselen);
pwm.setPWM(7, 0, pulselen);
pwm.setPWM(8, 0, pulselen);
pwm.setPWM(9, 0, pulselen);
}
else
for (uint16_t pulselen = from; pulselen > to; pulselen--) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
pwm.setPWM(5, 0, pulselen);
pwm.setPWM(6, 0, pulselen);
pwm.setPWM(7, 0, pulselen);
pwm.setPWM(8, 0, pulselen);
pwm.setPWM(9, 0, pulselen);
}
}
uint8_t debounceRead(int pin)
{
uint8_t pinState = digitalRead(pin);
uint32_t timeout = millis();
while (millis() < timeout+10)
{
if (digitalRead(pin) != pinState)
{
pinState = digitalRead(pin);
timeout = millis();
}
}
return pinState;
}
Last edited by adafruit_support_rick on Sat Nov 15, 2014 9:58 am, edited 1 time in total.
Reason: please use Code tags when posting code (</> button)
Reason: please use Code tags when posting code (</> button)
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: Help with 16 x 12-bit PWM & Servo Shield
The easiest thing is to just duplicate all of the relevant code in loop. And you need a separate routine for each group of servos:
Code: Select all
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 150
#define SERVOMAX 600
uint8_t servonum = 0;
uint8_t buttonState1 = HIGH;
uint8_t previousButtonState1 = HIGH;
uint8_t buttonState2 = HIGH;
uint8_t previousButtonState2 = HIGH;
int servoState1 = SERVOMIN;
int servoState2 = SERVOMIN;
void setup() {
Serial.begin(9600);
Serial.println("16 channel Servo test!");
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
}
// 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 /= 60; // 60 Hz
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000;
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}
void loop()
{
//Check button for servo group 1
buttonState1 = debounceRead(2);
if ((LOW == buttonState1) and (HIGH == previousButtonState1))
{
if (servoState1 == SERVOMIN) {
moveServoGroup1(SERVOMIN, SERVOMAX);
servoState1 = SERVOMAX;
}
else {
moveServoGroup1(SERVOMAX, SERVOMIN);
servoState1 = SERVOMIN;
}
}
previousButtonState1 = buttonState1;
//check button for servo group 2
buttonState2 = debounceRead(3);
if ((LOW == buttonState2) and (HIGH == previousButtonState2))
{
if (servoState2 == SERVOMIN) {
moveServoGroup2(SERVOMIN, SERVOMAX);
servoState2 = SERVOMAX;
}
else {
moveServoGroup2(SERVOMAX, SERVOMIN);
servoState2 = SERVOMIN;
}
}
previousButtonState2 = buttonState2;
}
//Servo group 1 is servos 0, 1, 2, 3, 4
void moveServoGroup1(int from, int to)
{
if (from < to)
for (uint16_t pulselen = from; pulselen < to; pulselen++) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
else
for (uint16_t pulselen = from; pulselen > to; pulselen--) {
pwm.setPWM(0, 0, pulselen);
pwm.setPWM(1, 0, pulselen);
pwm.setPWM(2, 0, pulselen);
pwm.setPWM(3, 0, pulselen);
pwm.setPWM(4, 0, pulselen);
}
}
//Servo group 2 is servos 5, 6, 7, 8, 9
void moveServoGroup2(int from, int to)
{
if (from < to)
for (uint16_t pulselen = from; pulselen < to; pulselen++) {
pwm.setPWM(5, 0, pulselen);
pwm.setPWM(6, 0, pulselen);
pwm.setPWM(7, 0, pulselen);
pwm.setPWM(8, 0, pulselen);
pwm.setPWM(9, 0, pulselen);
}
else
for (uint16_t pulselen = from; pulselen > to; pulselen--) {
pwm.setPWM(5, 0, pulselen);
pwm.setPWM(6, 0, pulselen);
pwm.setPWM(7, 0, pulselen);
pwm.setPWM(8, 0, pulselen);
pwm.setPWM(9, 0, pulselen);
}
}
uint8_t debounceRead(int pin)
{
uint8_t pinState = digitalRead(pin);
uint32_t timeout = millis();
while (millis() < timeout+10)
{
if (digitalRead(pin) != pinState)
{
pinState = digitalRead(pin);
timeout = millis();
}
}
return pinState;
}
- richard905
- Posts: 7
- Joined: Fri May 25, 2012 6:28 pm
Re: Help with 16 x 12-bit PWM & Servo Shield
Rick: Based on your post "duplicate all of the relevant code in loop. And you need a separate routine for each group of servos", I tried different modified codes, unfortunately, all failed, I am mechanical guy, not good at Arduino code, Could you give me hints? appreciate!!
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: Help with 16 x 12-bit PWM & Servo Shield
Did you try running the code I posted?
- richard905
- Posts: 7
- Joined: Fri May 25, 2012 6:28 pm
Re: Help with 16 x 12-bit PWM & Servo Shield
Rick, Your code works great! Thank you so much!!
- adafruit_support_rick
- Posts: 35092
- Joined: Tue Mar 15, 2011 11:42 am
Re: Help with 16 x 12-bit PWM & Servo Shield
You're welcome!
Please be positive and constructive with your questions and comments.