Adafruit PWM 16 channel Servoshield, how to include trigger?

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
ghost911
 
Posts: 18
Joined: Fri Feb 21, 2014 8:54 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by ghost911 »

adafruit_support_bill wrote:
5cm-30cm, send signal to servo
while 5cm is 90° and 30cm is 0° (rotation)
You can use the map() function to do that:

Code: Select all

  int d=distanceM(); // Messe Distanz und gebe ihn in der Variablen “d” aus
  Serial.println(d, DEC); // Gib die Variable “d” im Serial Monitor aus.
  if (d < 30)  // only move if less than 30cm
  {
    int angle = map(d, 5, 30, 90, 0);  // map 5-30cm to 90-0 degrees
    // add some code to move your servos here
  }
Thank you very much,

I am not really sure how to include code for moving servos since I have already this listed

Code: Select all

  pwm.setPWM(2, 0, pulseWidth(0));
  pwm.setPWM(3, 0, pulseWidth(0));
  pwm.setPWM(4, 0, pulseWidth(0));
  pwm.setPWM(5, 0, pulseWidth(0));
  pwm.setPWM(6, 0, pulseWidth(0));
  pwm.setPWM(7, 0, pulseWidth(0));
  pwm.setPWM(8, 0, pulseWidth(0));
  pwm.setPWM(9, 0, pulseWidth(0));
  pwm.setPWM(10, 0, pulseWidth(0));
  pwm.setPWM(11, 0, pulseWidth(0));
  pwm.setPWM(12, 0, pulseWidth(0));
  pwm.setPWM(13, 0, pulseWidth(0));
  pwm.setPWM(14, 0, pulseWidth(0));
  pwm.setPWM(15, 0, pulseWidth(0));
                              
  delay(1000);
  pwm.setPWM(0, 0, pulseWidth(180));
  pwm.setPWM(1, 0, pulseWidth(180));
  pwm.setPWM(2, 0, pulseWidth(180));
  pwm.setPWM(3, 0, pulseWidth(180));
  pwm.setPWM(4, 0, pulseWidth(180));
  pwm.setPWM(5, 0, pulseWidth(180));
  pwm.setPWM(6, 0, pulseWidth(180));
  pwm.setPWM(7, 0, pulseWidth(180));
  pwm.setPWM(8, 0, pulseWidth(180));
  pwm.setPWM(9, 0, pulseWidth(180));
  pwm.setPWM(10, 0, pulseWidth(180));
  pwm.setPWM(11, 0, pulseWidth(180));
  pwm.setPWM(12, 0, pulseWidth(180));
  pwm.setPWM(13, 0, pulseWidth(180));
  pwm.setPWM(14, 0, pulseWidth(180));
  pwm.setPWM(15, 0, pulseWidth(180));
I included the map() function and servors are now turning full 90° as soon as I get closer, but they are not responding stepwise, or holding on this position.

Code: Select all

#include <Servo.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Servo servo;   
int angle = 0;   // Position des Servos in Grad
int mycell = 0;  // Pin des analogen Servos

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define MIN_PULSE_WIDTH       600
#define MAX_PULSE_WIDTH       1200
#define DEFAULT_PULSE_WIDTH   1500
#define FREQUENCY             50
int trigPin = 8; // Beziehe Signal 
int echoPin = 7; // Erhalte Signal
float v=331.5+0.6*20; // Ausbreitungsgeschwindigkeit des Schalls bei 20°C (ca 340 m/s) 


void setup() {
  pwm.begin();
  pwm.setPWMFreq(FREQUENCY);

Serial.begin (9600);
pinMode(trigPin, OUTPUT); // Löse Schaltsignal aus
pinMode(echoPin,INPUT); // Messe die Dauer bis zum Eintreffen des Schalls
}

float distanceM() {
  digitalWrite(trigPin,LOW);
  delayMicroseconds(3);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(trigPin, LOW);
  float tUs = pulseIn(echoPin, HIGH);
  float t= tUs / 1000.0 / 1000.0 / 1;
  float d= t*v;
  return d*100;
}


void loop() {

  int d=distanceM(); // Messe Distanz und gebe ihn in der Variablen “d” aus
  Serial.println(d, DEC); // Gib die Variable “d” im Serial Monitor aus.
  if (d < 30)  // only move if less than 30cm
  {
    int angle = map(d, 5, 30, 90, 0);  // map 5-30cm to 90-0 degrees
      pwm.setPWM(0, 0, pulseWidth(0));
      
        pwm.setPWM(1, 0, pulseWidth(0));
  pwm.setPWM(2, 0, pulseWidth(0));
  pwm.setPWM(3, 0, pulseWidth(0));
  pwm.setPWM(4, 0, pulseWidth(0));
  pwm.setPWM(5, 0, pulseWidth(0));
  pwm.setPWM(6, 0, pulseWidth(0));
  pwm.setPWM(7, 0, pulseWidth(0));
  pwm.setPWM(8, 0, pulseWidth(0));
  pwm.setPWM(9, 0, pulseWidth(0));
  pwm.setPWM(10, 0, pulseWidth(0));
  pwm.setPWM(11, 0, pulseWidth(0));
  pwm.setPWM(12, 0, pulseWidth(0));
  pwm.setPWM(13, 0, pulseWidth(0));
  pwm.setPWM(14, 0, pulseWidth(0));
  pwm.setPWM(15, 0, pulseWidth(0));
                              
  delay(1000);
  pwm.setPWM(0, 0, pulseWidth(180));
  pwm.setPWM(1, 0, pulseWidth(180));
  pwm.setPWM(2, 0, pulseWidth(180));
  pwm.setPWM(3, 0, pulseWidth(180));
  pwm.setPWM(4, 0, pulseWidth(180));
  pwm.setPWM(5, 0, pulseWidth(180));
  pwm.setPWM(6, 0, pulseWidth(180));
  pwm.setPWM(7, 0, pulseWidth(180));
  pwm.setPWM(8, 0, pulseWidth(180));
  pwm.setPWM(9, 0, pulseWidth(180));
  pwm.setPWM(10, 0, pulseWidth(180));
  pwm.setPWM(11, 0, pulseWidth(180));
  pwm.setPWM(12, 0, pulseWidth(180));
  pwm.setPWM(13, 0, pulseWidth(180));
  pwm.setPWM(14, 0, pulseWidth(180));
  pwm.setPWM(15, 0, pulseWidth(180));
  delay(1000);// add some code to move your servos here
  }
    delay(200); 
}

int pulseWidth(int angle)
{
  int pulse_wide, analog_value;
  pulse_wide   = map(angle, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
  analog_value = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);
  return analog_value;

  int reading = analogRead(mycell); 
  int newAngle = reading/5 - 30; // Zwischen Wert 5 und 30 messen
  //Serial.print(newAngle);
  //Serial.print("\n");
  servo.write(newAngle);           
  delay(50);  
}

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by adafruit_support_bill »

You are calling pulseWidth() with either 0 or 180. So the servo will always move to those 2 positions. You need to use the 'angle' that you calculated with the map() function.

User avatar
ghost911
 
Posts: 18
Joined: Fri Feb 21, 2014 8:54 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by ghost911 »

adafruit_support_bill wrote:You are calling pulseWidth() with either 0 or 180. So the servo will always move to those 2 positions. You need to use the 'angle' that you calculated with the map() function.
I understand what are you mean, but unfortunately I have big trouble to apply the idea, do you mean it like so?

Code: Select all

  if (d < 30)  // only move if less than 30cm
  {
    int angle = map(d, 5, 30, 90, 0);  // map 5-30cm to 90-0 degrees
 
  pwm.setPWM(0, 0, map(d, 5, 30, 90, 0));      
  pwm.setPWM(1, 0, map(d, 5, 30, 90, 0));                              
  delay(1000);

  pwm.setPWM(0, 0, map(d, 90, 30, 5, 0));
  pwm.setPWM(1, 0, map(d, 90, 30, 5, 0));

Now they are turning into one direction 720° and also never coming back

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by adafruit_support_bill »

Code: Select all

  if (d < 30)  // only move if less than 30cm
  {
    int angle = map(d, 5, 30, 90, 0);  // map 5-30cm to 90-0 degrees
    pwm.setPWM(2, 0, pulseWidth(angle));
    pwm.setPWM(3, 0, pulseWidth(angle));
    pwm.setPWM(4, 0, pulseWidth(angle));
    etc...

User avatar
ghost911
 
Posts: 18
Joined: Fri Feb 21, 2014 8:54 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by ghost911 »

adafruit_support_bill wrote:

Code: Select all

  if (d < 30)  // only move if less than 30cm
  {
    int angle = map(d, 5, 30, 90, 0);  // map 5-30cm to 90-0 degrees
    pwm.setPWM(2, 0, pulseWidth(angle));
    pwm.setPWM(3, 0, pulseWidth(angle));
    pwm.setPWM(4, 0, pulseWidth(angle));
    etc...
This helped me a lot, at least they are moving somekind I wanted it to. I also added the "backwards" movement for the servos, just hoping in the right way.

this is the code so far

Code: Select all

#include <Servo.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Servo servo;   
int angle = 0;   // Position des Servos in Grad
int mycell = 0;  // Pin des analogen Servos

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define MIN_PULSE_WIDTH       600
#define MAX_PULSE_WIDTH       1200
#define DEFAULT_PULSE_WIDTH   1500
#define FREQUENCY             50
int trigPin = 8; // Beziehe Signal 
int echoPin = 7; // Erhalte Signal
float v=331.5+0.6*20; // Ausbreitungsgeschwindigkeit des Schalls bei 20°C (ca 340 m/s) 

void setup() {
  pwm.begin();
  pwm.setPWMFreq(FREQUENCY);

Serial.begin (9600);
pinMode(trigPin, OUTPUT); // Löse Schaltsignal aus
pinMode(echoPin,INPUT); // Messe die Dauer bis zum Eintreffen des Schalls
}

float distanceM() {
  digitalWrite(trigPin,LOW);
  delayMicroseconds(3);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(trigPin, LOW);
  float tUs = pulseIn(echoPin, HIGH);
  float t= tUs / 1000.0 / 1000.0 / 1;
  float d= t*v;
  return d*100;
}

void loop() 

{  int d=distanceM(); // Messe Distanz und gebe in der Variablen “d” aus
  Serial.println(d, DEC); // Gib die Variable “d” im Serial Monitor aus.
  if (d < 30)  // only move if less than 30cm
  {
    int angle = map(d, 5, 30, 45, 0);  // map 5-30cm to 90-0 degrees
           
{  pwm.setPWM(0, 0, pulseWidth(angle));      // testing it out with only 3 servos
  pwm.setPWM(1, 0, pulseWidth(angle));
  pwm.setPWM(2, 0, pulseWidth(angle));
  }}

 delay (100);
 if (d > 30)
 {
   int rangle = map(d, 5, 30, -45, 0);  // map 5-30cm to 90-0 degrees
  pwm.setPWM(0, 0, pulseWidth(rangle));      
  pwm.setPWM(1, 0, pulseWidth(rangle));
  pwm.setPWM(2, 0, pulseWidth(rangle)); 
                            
  delay(1000);// add some code to move your servos here
  }
    delay(200); 
}

int pulseWidth(int angle)
{
  int pulse_wide, analog_value;
  pulse_wide   = map(angle, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
  analog_value = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096);
  return analog_value;

  int reading = analogRead(mycell); 
  int newAngle = reading/5 - 30; // Zwischen Wert 5 und 30 messen
  //Serial.print(newAngle);
  //Serial.print("\n");
  servo.write(newAngle);           
  delay(50);  
}
Unfortunately there are some sporadic breakouts, sometimes the servos are stuttering and spinning from 90 up to 180 degrees backwards, its happening when I am drastically changing the distance of my hand infront of the sensor and the sonsor is hitting values of 2-4m. I am assuming that the spikes are coming from the sensor perhaps its possible to limit the range of the sensors or at least send the servos to "sleep", as soon as the impediment leaves a specific "detection" zone?

The only Reason I dont want that, is that the servos aren't going to be allowed to move more than 90 degrees much less in another direction for several times.
Here is an example of what I am planing to do.
sam-0895-jpg_1392691319.jpg
sam-0895-jpg_1392691319.jpg (617.18 KiB) Viewed 851 times

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by adafruit_support_bill »

Unfortunately there are some sporadic breakouts, sometimes the servos are stuttering and spinning from 90 up to 180 degrees backwards, its happening when I am drastically changing the distance of my hand infront of the sensor and the sonsor is hitting values of 2-4m. I am assuming that the spikes are coming from the sensor
Whenever you are dealing with sensors, it is important to first understand the response of the sensor. If you print out the sensor values and the calculated angles to the serial monitor, it will help you to understand how the sensor responds to the motion of your hand, so you can write code to handle it appropriately.

User avatar
ghost911
 
Posts: 18
Joined: Fri Feb 21, 2014 8:54 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by ghost911 »

adafruit_support_bill wrote:
Unfortunately there are some sporadic breakouts, sometimes the servos are stuttering and spinning from 90 up to 180 degrees backwards, its happening when I am drastically changing the distance of my hand infront of the sensor and the sonsor is hitting values of 2-4m. I am assuming that the spikes are coming from the sensor
Whenever you are dealing with sensors, it is important to first understand the response of the sensor. If you print out the sensor values and the calculated angles to the serial monitor, it will help you to understand how the sensor responds to the motion of your hand, so you can write code to handle it appropriately.
Yes I can totaly agree on that one, I already included that line so I can monitor the values through the serial monitor, there are values calculated in cm so whenever I put my Hand away, the changing distance from 2 up to 4 meters, probably the scatter from the wall seems affecting the servos, which letting them stutter and do some weird things.

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by adafruit_support_bill »

I'm don't have much experience with the sensor you are using. Not to mention the environment you are using it in. If you are seeing spurious readings, then you need to write code to filter those.
the changing distance from 2 up to 4 meters, probably the scatter from the wall seems affecting the servos
The code I posted tests for values < 30cm. So readings of 2-4 meters would not even be considered.

You have added this bit, which maps distances greater than that to values that are not even valid for a servo. Not sure what you intended there. And not sure how the servo would respond to those invalid position signals.

Code: Select all

 if (d > 30)
 {
   int rangle = map(d, 5, 30, -45, 0);  // map 5-30cm to 90-0 degrees
  pwm.setPWM(0, 0, pulseWidth(rangle));      
  pwm.setPWM(1, 0, pulseWidth(rangle));
  pwm.setPWM(2, 0, pulseWidth(rangle)); 
                            
  delay(1000);// add some code to move your servos here
  }
    delay(200); 
}

User avatar
ghost911
 
Posts: 18
Joined: Fri Feb 21, 2014 8:54 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by ghost911 »

adafruit_support_bill wrote:I'm don't have much experience with the sensor you are using. Not to mention the environment you are using it in. If you are seeing spurious readings, then you need to write code to filter those.
the changing distance from 2 up to 4 meters, probably the scatter from the wall seems affecting the servos
The code I posted tests for values < 30cm. So readings of 2-4 meters would not even be considered.

You have added this bit, which maps distances greater than that to values that are not even valid for a servo. Not sure what you intended there. And not sure how the servo would respond to those invalid position signals.

Code: Select all

 if (d > 30)
 {
   int rangle = map(d, 5, 30, -45, 0);  // map 5-30cm to 90-0 degrees
  pwm.setPWM(0, 0, pulseWidth(rangle));      
  pwm.setPWM(1, 0, pulseWidth(rangle));
  pwm.setPWM(2, 0, pulseWidth(rangle)); 
                            
  delay(1000);// add some code to move your servos here
  }
    delay(200); 
}
This part I added to drive the servos back in their starting position. Otherwise they are standing still as soon the position

Code: Select all

 int angle = map(d, 5, 30, 45, 0)
accomplished.

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by adafruit_support_bill »

Valid angles for the pulseWidth function are 0-180. You are passing it values from -45 to 0. If you want to move back to zero, there is no need to map anything, just pass zero.

User avatar
ghost911
 
Posts: 18
Joined: Fri Feb 21, 2014 8:54 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by ghost911 »

adafruit_support_bill wrote:Valid angles for the pulseWidth function are 0-180. You are passing it values from -45 to 0. If you want to move back to zero, there is no need to map anything, just pass zero.
You were right, many thanks for the hint, I changed it to

Code: Select all

void loop() 

{  int d=distanceM(); // Messe Distanz und gebe in der Variablen “d” aus
  Serial.println(d, DEC); // Gib die Variable “d” im Serial Monitor aus.
  if (d < 30)  // only move if less than 30cm
  {
    int angle = map(d, 5, 30, 180, 0);  // map 5-30cm to 90-0 degrees
           
{  pwm.setPWM(0, 0, pulseWidth(angle));      
  pwm.setPWM(1, 0, pulseWidth(angle));
  pwm.setPWM(2, 0, pulseWidth(angle));

  delay(1000);
  pwm.setPWM(0, 0, pulseWidth(0));
  pwm.setPWM(1, 0, pulseWidth(0));
  }}

 delay (100);
 {if (d > 30);
 int pos = 0;
and everything seems to be working fine without any breakouts or stuttering.

One last thing.

I wanted to add an filter to the loop so the servos are only moving to their starting position when I am leaving the detection radius of 30cm, otherwise it should refresh the loop, so I can get dynamically closer and let the angle readjust

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by adafruit_support_bill »

Not sure what is in the rest of your loop function. But these lines will unconditionally move back to zero after one second. If you want to track distance continuously, you should not have any delays in your loop at all.

Code: Select all

  delay(1000);
  pwm.setPWM(0, 0, pulseWidth(0));
  pwm.setPWM(1, 0, pulseWidth(0));

User avatar
ghost911
 
Posts: 18
Joined: Fri Feb 21, 2014 8:54 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by ghost911 »

adafruit_support_bill wrote:Not sure what is in the rest of your loop function. But these lines will unconditionally move back to zero after one second. If you want to track distance continuously, you should not have any delays in your loop at all.

Code: Select all

  delay(1000);
  pwm.setPWM(0, 0, pulseWidth(0));
  pwm.setPWM(1, 0, pulseWidth(0));
Hello, you were totally right, I just got rid of any delays in the loop function and after that it seemed to work perfectly. I was totally excited to see it finally working the proper way, aswell with all 16 servos connected.
Once more, thank you very much for your brilliant support Bill, there is nothing I can say greater than that!

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: Adafruit PWM 16 channel Servoshield, how to include trig

Post by adafruit_support_bill »

Good to hear it's al working for you. Thanks for the follow-up.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”