Art project w/ Arduino HELP:)

I’m an art student and I am working with the Arduino for my thesis. I am new to all of this so bare with me, please :slight_smile: essentially, I am trying to make a mechanical butterfly, using two servos and a sensor.

At this point, I have the two servos connected to my Arduino and running at the same time exactly the way that I want them to run with the following code:

#include <Servo.h>

Servo myservo1; Servo myservo2;// create servo object to control a servo
// a maximum of eight servo objects can be created

int pos = 360; // variable to store the servo position ;

void setup()
{
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); //attaches the servo on pin 10 to the servo object
}

void loop()
{
for(pos = 0; pos < 90; pos +=1) // goes from 0 degrees to 90 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
for(pos = 90; pos>=1; pos -=1) // goes from 90 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
}

The power from the servo is connected to the 5v on the Arduino, ground on servo is connected to Gnd, and the signals on the servos are connected to digital pins 9 and 10. I want to run the servos through a sensor, as if it is a switch - so that when an individual walks up to the sensor, the servo motors will run and then when one moves away, the motors will stop running. I have the PING sensor and a Sharp GP2Y0A02YK0F Proximity sensor.

I was told that either sensor would be fine, the ping has a little more range than the sharp. I am not aware of how I should manipulate the code in order to run the servos through the sensor. help would be greatly appreciated! :slight_smile:

Welcome to the community!

I would think something like this ought to work:
[UNTESTED CODE]

#include <Servo.h>

// create servo object to control a servo
// a maximum of eight servo objects can be created
Servo myservo1; Servo myservo2;

int pos = 360; // variable to store the servo position ;
byte pingPin = 7;

byte distanceThreshold = 50; //you need to stand closer than 50 cm

void setup()
{
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); //attaches the servo on pin 10 to the servo object
}

void loop()
{
//if it is true that the current distance is below the threshold: execute code
if (getDistance() <= distanceThreshold ){
for(pos = 0; pos < 90; pos +=1) // goes from 0 degrees to 90 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
for(pos = 90; pos>=1; pos -=1) // goes from 90 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
} else {
//nothing
}
}

//Tutorial/Ping
byte getDistance(){
long duration=0;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return duration / 29 / 2;
}

I uploaded it with no issues, the servos are continuing to run just fine, but the green light on the ping doesn't seemed to be blinking and the distance is not effecting anything. could it be that my code for the servos is interfering in some way?

Ok, I’ve come up with this code now:

#include <Servo.h>

// create servo object to control a servo
// a maximum of eight servo objects can be created
Servo myservo1; Servo myservo2;

int pos = 360; // variable to store the servo position ;
byte pingPin = 7;

byte distanceThreshold = 5; //you need to stand closer than 5 cm

void setup()
{
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); //attaches the servo on pin 10 to the servo object
}

void loop()
{
//if it is true that the current distance is below the threshold: execute code
if (getDistance() <= distanceThreshold ){
for(pos = 5; pos < 75; pos +=1) // goes from 5 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(10); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(10);
}
for(pos = 75; pos > 5; pos -=1) // goes from 75 degrees to 5 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(10); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(10);
}
} else {
}
}

long duration, cm;

//Tutorial/Ping
byte getDistance(){
long duration=0;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return duration / 29 / 2;

cm = duration;

Serial.print(cm);
Serial.print(“cm”);
Serial.println();

delay(100);
}

This seems to help the problem a little bit, except that it is my intention for the servos to sit completely still when no one is in front of the PING, but the first thing they do is freak out and move really fast back and forth. When I move in front of the PING, it starts that motors that way I would like, but when I move away, they continue, and I would really like them to stop completely. Any suggestions?
Thanks for your help. :slight_smile:

A bit strange that they continue to move…

Maybe it’s because the ping has/detects some jitter / noise.

How about this: (added avaraging)
[UNTESTED CODE]

/*
|| The code behind the butterfly
||
|| Contributed:
|| srmyh
|| Alexander Brevig
*/

#include <Servo.h>

#define NUMBER_OF_READINGS 10

// create servo object to control a servo
// a maximum of eight servo objects can be created
Servo myservo1; Servo myservo2;

int pos = 360; // variable to store the servo position ;
byte pingPin = 7;

byte distanceThreshold = 5; //you need to stand closer than 5 cm

void setup()
{
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); //attaches the servo on pin 10 to the servo object
}

void loop()
{
//if it is true that the current distance is below the threshold: execute code
if (getDistanceAvarage() <= distanceThreshold ){
for(pos = 5; pos < 75; pos +=1) // goes from 5 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(10); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(10);
}
for(pos = 75; pos > 5; pos -=1) // goes from 75 degrees to 5 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(10); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(10);
}
} else {
while (getDistance() > distanceThreshold){ ; }
}
}

byte getDistanceAvarage(){
byte avarageDistance = getDistance();
for (byte i=0; i<NUMBER_OF_READINGS; i++){
avarageDistance += getDistance();
avarageDistance /= 2;
}
return avarageDistance;
}
//Tutorial/Ping
byte getDistance(){
long duration=0;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return duration / 29 / 2;
}

#define NUMBER_OF_READINGS 10

Change this to suit your needs.

That's great! Any idea why there is so much hesitation between turns? Thank you so much! :D

oops! nevermind, there is no delay when i use the ext power source! great :) Thanks again!

Looks like you've got it working now, but the general rule is to use an external power supply if you have more than one servo. In some cases, you'll need an external power supply for just a single servo. They pull quite a lot of power!

ok, so now i’ve decided to do a little more with this, the butterfly’s wings will move back and forth at a steady pace while a green led blinks in at the same time, then when one walks in front of it, the wings will pick up speed and a red led will start blinking at the same time. based on the code developed earlier this is what i came up with:

#include <Servo.h>

#define NUMBER_OF_READINGS 10

// create servo object to control a servo
// a maximum of eight servo objects can be created
Servo myservo1; Servo myservo2;

int ledPin1 = 13; // LED connected to digital pin 13
int ledPin2 = 8; // LED connected to digital pin 8

int pos = 360; // variable to store the servo position ;
byte pingPin = 7;

byte distanceThreshold = 5; //you need to stand closer than 5 cm

void setup()
{
pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT);
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); //attaches the servo on pin 10 to the servo object
}

void loop()
{
//if it is true that the current distance is below the threshold: execute code
if (getDistanceAverage() <= distanceThreshold ){
for(pos = 0; pos < 75; pos +=1) // goes from 0 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(5); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(5);
}
for(pos = 75; pos > 0; pos -=1) // goes from 75 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(5); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(5);
}
{
digitalWrite(ledPin1, HIGH); // sets the LED on
delay(500); // waits for a second
digitalWrite(ledPin1, LOW); // sets the LED off
delay(500); // waits for a second
}
} else {
while (getDistance() > distanceThreshold){
for(pos = 0; pos < 75; pos +=1) // goes from 0 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
for(pos = 75; pos > 0; pos -=1) // goes from 75 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
{
digitalWrite(ledPin2, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin2, LOW); // sets the LED off
delay(1000); // waits for a second
}
}
}
}

byte getDistanceAverage(){
byte averageDistance = getDistance();
for (byte i=0; i<NUMBER_OF_READINGS; i++){
averageDistance += getDistance();
averageDistance /= 2;
}
return averageDistance;
}
//Tutorial/Ping
byte getDistance(){
long duration=0;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return duration / 29 / 2;
}

At this point, it doesn’t do anything until i move up to it and then it interchanges speeds and the leds only blink between wing turns.

I also tried it with the first code that you developed:

#include <Servo.h>

#define NUMBER_OF_READINGS 10

// create servo object to control a servo
// a maximum of eight servo objects can be created
Servo myservo1; Servo myservo2;

int ledPin1 = 13; // LED connected to digital pin 13
int ledPin2 = 8; // LED connected to digital pin 8

int pos = 360; // variable to store the servo position ;
byte pingPin = 7;

byte distanceThreshold = 5; //you need to stand closer than 5 cm

void setup()
{
pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT);
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); //attaches the servo on pin 10 to the servo object
}

void loop()
{
//if it is true that the current distance is below the threshold: execute code
if (getDistance() <= distanceThreshold ){
for(pos = 0; pos < 75; pos +=1) // goes from 0 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(5); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(5);
}
for(pos = 75; pos > 0; pos -=1) // goes from 75 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(5); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(5);
}
{
digitalWrite(ledPin1, HIGH); // sets the LED on
delay(500); // waits for a second
digitalWrite(ledPin1, LOW); // sets the LED off
delay(500); // waits for a second
}
} else (getDistance() > distanceThreshold); {
for(pos = 0; pos < 75; pos +=1) // goes from 0 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
for(pos = 75; pos > 0; pos -=1) // goes from 75 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
{
digitalWrite(ledPin2, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin2, LOW); // sets the LED off
delay(1000); // waits for a second
}
}
}

//Tutorial/Ping
byte getDistance(){
long duration=0;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return duration / 29 / 2;
}

the leds do the same thing, im not sure if i need to have a seperate while for each one so that the leds can blink along with the servos. it works fine otherwise, except that when one moves in front of it, it will only do the faster movement one time and then it goes back to being slow again and i’d really like for it to continue to go fast the entire time that someone is in front of it.
I really hope all of that made sense. :o
/me

At a first glance I saw this:

} else (getDistance() > distanceThreshold)[glow];[/glow] {

and it should be this:

} else (getDistance() > distanceThreshold){

the arduino software gives me an error message without the ;

How about this then:

#include <Servo.h>

#define NUMBER_OF_READINGS 10

// create servo object to control a servo
// a maximum of eight servo objects can be created
Servo myservo1; Servo myservo2;

int ledPin1 = 13; // LED connected to digital pin 13
int ledPin2 = 8; // LED connected to digital pin 8

int pos = 360; // variable to store the servo position ;
byte pingPin = 7;

byte distanceThreshold = 5; //you need to stand closer than 5 cm

void setup()
{
pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT);
myservo1.attach(9); // attaches the servo on pin 9 to the servo object
myservo2.attach(10); //attaches the servo on pin 10 to the servo object
}

void loop()
{
//if it is true that the current distance is below the threshold: execute code
if (getDistanceAverage() <= distanceThreshold ){

for(pos = 0; pos < 75; pos +=1) // goes from 0 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(5); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(5);
}
for(pos = 75; pos > 0; pos -=1) // goes from 75 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(5); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(5);
}
digitalWrite(ledPin1, HIGH); // sets the LED on
delay(500); // waits for a second
digitalWrite(ledPin1, LOW); // sets the LED off
delay(500); // waits for a second

} else if(getDistanceAverage() > distanceThreshold){

for(pos = 0; pos < 75; pos +=1) // goes from 0 degrees to 75 degrees
{ // in steps of 1 degree
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
for(pos = 75; pos > 0; pos -=1) // goes from 75 degrees to 0 degrees
{
myservo1.write(pos); // tell servo to go to position in variable ‘pos’
delay(15); // waits 15ms for the servo to reach the position
myservo2.write(pos);
delay(15);
}
digitalWrite(ledPin2, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin2, LOW); // sets the LED off
delay(1000); // waits for a second
}

}

byte getDistanceAverage(){
byte averageDistance = getDistance();
for (byte i=0; i<NUMBER_OF_READINGS; i++){
averageDistance += getDistance();
averageDistance /= 2;
}
return averageDistance;
}

//Tutorial/Ping
byte getDistance(){
long duration=0;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return duration / 29 / 2;
}

that seems to work wonders! thank you once again :)

Good!

As far as I remember the only thing I did was to add the avarage function, and change } else (getDistance() > distanceThreshold){ to } else if (getDistance() > distanceThreshold){

This sounds very interesting! I would definitely like to see pics/video if you get a chance

This sounds very interesting! I would definitely like to see pics/video if you get a chance

I just had to second that! (I know it is a bit unorthodox but I simply had to)

as soon as it’s finished, i will definitely do so! :slight_smile: