Pages: [1] 2   Go Down
Author Topic: simple two position servo  (Read 3541 times)
0 Members and 1 Guest are viewing this topic.
95060
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hello: Im a total newb trying to get my first servo sketch working and have spent hours without result desired. I've messed with may examples using potentiometers with success but seem to fail using fixed position attempts. Any assitance will be most appreciated.


 ADDENDUM:
great hints provided caused me to start by declaring myservo object & experimenting with  myservoWrite(values) to determine servo limits
then added logic & additional led
successful sketch below  smiley


Code:
//two position servo
#include <Servo.h>
#define SENSOR 5
int IRvalue = 0;
Servo myservo;  // create servo object
void setup()
{
  pinMode (2 , OUTPUT); // "sensor active" LED 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.writeMicroseconds(600);// assure servo starts in correct position
  delay(400);
  // Serial.begin(9600); used to see actual SENSOR values
}

void loop()
{

  IRvalue = analogRead (SENSOR)/100;// look at sensor and pause
  // Serial.print("IRvalue ="); // text
  // Serial.println(IRvalue);// IRvalue with line feed

  if (IRvalue < 8){ // sensor normally 10
    digitalWrite(2,HIGH); // light up led indicating sensor activated
  }
  else{
    digitalWrite(2,LOW); // no sense active
  }

  delay(1000);// delay before action

  if (IRvalue < 7) {                  //sensor output went below 10
    myservo.writeMicroseconds(2400);  // tell servo to go to  active position in'
    delay(200);                       // wait for the servo to reach the position
    myservo.writeMicroseconds(600);              // tell servo to return to passive position
    delay(100);
  }
}[code]
[/code]
« Last Edit: April 23, 2011, 11:39:51 am by tomswell » Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8856
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You don't use digitalWrite() for the servo pin.  Use myservo.write(position-in-degrees) or myservo.writeMicroseconds(pulse-width-in-microseconds).  Be warned that pulse widths below 1000 or above 2000 may cause the servo to jam against its internal stop.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

0
Offline Offline
Tesla Member
***
Karma: 145
Posts: 9631
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Any assitance will be most appreciated.

Try stating what you are trying to do for best help.
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

San Diego, California
Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The Part 3 (from the ArdBot series in SERVO Magazine) example code shows attaching and detatching. Get it here:

http://www.robotoid.com/servomag/

Simplify your tests by initially including only the servo code. The example "exercises" a servo from one end to the other.

A couple of things about your code:

1. When you create a new servo object its position gets set to 90 (or 1500 microseconds). You can change the initial position with servo.write. You don't have to attach it first.

2. Be sure you delay long enough to the next statement for the servo to transit where you want it to go.

3. You need to re-read the value of your IR pin each time in the loop. You have it as:

 if (IRval == HIGH)

which only checks what you put into the IRval previously, outside the loop. Since the variable will never change your servo will not move.

4. You don't need to set servo pins as OUTPUTs, as the class does that implicitly.

5. When in idle mode standard (non-converted) servos don't consume a lot of current. One good use of the detach method is when you have servos converted to continuous rotation. By detatching the servo won't creep, which can be the case if their center points drifts from the usual 1500 usec.
« Last Edit: April 21, 2011, 04:23:14 pm by GordonMcComb » Logged

95060
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for support
successful result posted within first message smiley
Logged

95060
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm still experimenting but here's an example of having a servo momentarily going more or less full rotation on event;
I'm now fooling with timing ...  include a counter that increments with each (IR_value<7)= servo action ...   after (x) main loop cycles ...  blink counter().... occasionally report how many times servo was actuated


Quote


//two position servo
#include <Servo.h>
#define SENSOR 5
int IRvalue = 0;
Servo myservo;  // create servo object
void setup()

  pinMode (2 , OUTPUT); // "sensor active" LED 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.writeMicroseconds(600);// assure servo starts in correct position
  delay(400);
  // Serial.begin(9600); used to see actual SENSOR values


void loop()

  delay (4000);
  IRvalue = analogRead (SENSOR)/100;// look at sensor and pause
  // Serial.print("IRvalue ="); // text
  // Serial.println(IRvalue);// IRvalue with line feed

  if (IRvalue < smiley-cool{ // sensor normally 10  delay(2000);// delay before action
    delay(200);

    digitalWrite(2,HIGH); // light up led indicating sensor activated
  }
  else{
    delay (200);
    digitalWrite(2,LOW); // no sense active
  }


  if (IRvalue < 7) {                  //sensor output went below 10
    delay(2200);                       // wait for the servo to reach the position
    myservo.writeMicroseconds(3400);  // tell servo to go to  active position in'
    delay(1200);                       // wait for the servo to reach the position
    myservo.writeMicroseconds(600);              // tell servo to return to passive position
    delay(100);
  }
}











Logged

San Diego, California
Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Good to know you're having success. Just a couple of points about the code.

You've duplicated the lines

Code:
delay(200);

twice within the if block. You might want to delete these and have just one, right after you've read the IR value. These kinds of consolidations can make the code easier to track as you try different values.

You have some extremely long delays waiting for the servo to transit. Are these really necessary or are you adding additional waiting time for demonstration purposes? Example: you have one specifying a delay of over two seconds

Code:
delay(2200);

Following this is a servo position value that looks extraordinarily out-of-bounds for most any servo:

Code:
myservo.writeMicroseconds(3400)

What kind of servo is this? Standard, sail winch, something else?

Some servos will accept out-of-bound limits to prevent internal damage, and I wonder if yours is doing that, giving you a false impression of the usec values you should be using. A more common lower and upper limit is along the lines of 650 us to 2400 us, and even these are outside some brands of servos.
Logged

0
Offline Offline
Tesla Member
***
Karma: 145
Posts: 9631
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think if one digs into the servo library files there are default high and low values set there.
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

San Diego, California
Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm having trouble visualizing your setup if what you're doing is trying to close a bait trap after the rat has come all the way in.

First thing I'd do is replace the IR sensor, which can be be unreliable, with a force sensitive resistor like this one:

http://www.sparkfun.com/products/9376

Place the sensor right at the bait. Connect it between 5V and Gnd in series with a resistor (play with the value of the resistor to get good sensitivity for the weight of the average ravenous rat; start with perhaps 100k and go from there). Connect the output to an analog pin. (For a hookup example use a photoresistor circuit; the concept is exactly the same -- you are converting a resistance to a voltage.)

In the setup() function, set up your servo object, rotate the servo to open the trap, and detach it. If you don't the slight "throbbing" of the servo will cause the rat to run away.

In the loop() function wait for the value to drop to indicate the rat is at the bait. Then close the trap in one swift move.

In pseudocode

Code:
setup() {
  define Servo object
  attach object to servo pin
  rotate servo to open trap
  delay one second for full transit
  detach servo
}

loop {
  read analog input
  is rat on sensor? {
     re-attach servo
     rotate to close trap
     return;
  }
}

The LED code you can add later. I'd not worry about the arc of the servo; rather define the values you need to open and close the trap door. Depending on the mechanics you may not need anything close to the full 180-200 degree arc of the servo.

In any case, you don't really need delays beyond the first one. Be sure to keep the servo attached (energized) after the trap has been sprung, or work up a locking mechanism to keep the door shut.

Anyway, this is how I envision a rat trap might be set up.

-- Gordon

« Last Edit: May 04, 2011, 11:40:00 am by GordonMcComb » Logged

95060
Offline Offline
Newbie
*
Karma: 0
Posts: 26
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

essentially the trap is a half open cylinder that flips over rapidly dumping creature into bucket. Sort of a tumbling funhouse barrel. The advantage of this design is the minimal load on the servo even with a good sized creature chowing down in the trough.
The digital sensor is a Sharp GP2Y0D805Z0F from Pololu that I have I have watched closely and it's output seems very consistent. The primary concern is assuring a consistent delay prior to activating servo. Since I added counter that consistency has diminished. So I'm thinking of driving a couple of seven segment LEDs as opposed to pulsing count output.
« Last Edit: May 05, 2011, 08:13:58 am by tomswell » Logged

San Diego, California
Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The GP2Y0D80's are more consistent than the older style, and they update at about 300 Hz, giving better accuracy.

As these aren't expensive, even on the breakboard boards that Pololu provides, have you considered using two? One for when the rat enters, and one when it's at the feeding area. You could use the two to pretty much eliminate any false triggers, and it (I would think) avoid the problems of having to use a delay.

In any case, a simple delay when the sensor hits its trigger point ought to do it. You shouldn't have to use the counter. Simply:

Code:
read IR sensor
is rat there? {
  delay(nnn);
  rotate servo
  return;
}

The nnn for delay is whatever you want to make it. A couple seconds perhaps? So delay(2000); will give a two second delay once the IR sensor has detected said rat.

-- Gordon
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8856
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm toying with thoughts of storing (total_counts) where as (count) would be cleared with reset or battery change.  I'm guessing that it would be not be worth having small aux battery to preserve memory ... or the inclusion additional no volatile ram ( if that’s even possible.)

You could use the built-in EEPROM to save values while power is off.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Arlington, MA, USA
Offline Offline
Sr. Member
****
Karma: 0
Posts: 259
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your interest ... component count / cost is part of design decision making. I posted under programming a question about nested If statements and I think I'll go with that approach:
Code:
// to test to test if IRvalue <3 still persists over time to avoid false triggering

if (IRvalue < 3) {                                         //sensor output went low  TRIGGERED
    delay (6000);                                         // wait a  while for validation that rattie is munching
                                                              // may include pot value for easy adjustment in final build
    if (IRvalue < 3) {                                    //sensor output still low
       myservo.writeMicroseconds(1200);         // tell servo to go to active position
       delay(1200);                                      // wait for the servo to flip over open cylinder in trough 180°
       myservo.writeMicroseconds(600);          // tell servo to return to passive position
       count=count+1;                                  //tally time validated event
       serial print (count);                            //  thru Max7219 & twin 8 segment leds     
 }
    } // ... loop again
I'm toying with thoughts of storing (total_counts) where as (count) would be cleared with reset or battery change.  I'm guessing that it would be not be worth having small aux battery to preserve memory ... or the inclusion additional no volatile ram ( if that’s even possible.)


Sorry, I may be missing something here, but without re-establishing IRvalue again (e.g.
Code:
IRvalue = analogRead (SENSOR)/100
What's the point in recomparing it to 3??
Logged

San Diego, California
Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

if (IRvalue < 3) {                                         //sensor output went low  TRIGGERED
    delay (6000);                                         // wait a  while for validation that rattie is munching
...

I assume you're posting code fragments, which makes it a bit hard to follow. But in any case, you're testing for (IRvalue < 3) twice, one right after the other. You only need one, unless you're re-establishing IRvalue with a new reading.

Maybe your rats are slower eaters than the ones that bother our house, but in six seconds ours will have gone in, got the food, and run back out. Remember that because of the way the delay statement works for those six seconds the Arduino is a hung process, and doesn't do anything else.

Here's where you may want to delay for 500 or 1000 milliseconds at a time, each time re-reading the input to check if the rat is still eating. Assuming 1000 delays, you'd repeat that loop six times. You still have a six second total delay, but each second you're re-reading the input and can more quickly act upon a change.

-- Gordon
« Last Edit: May 09, 2011, 04:57:14 pm by GordonMcComb » Logged

San Diego, California
Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The reassessment of ir value is to prevent servo action if value does not persist after delay.

The code you posted doesn't re-read the I/O pin, so the value in the IRvalue variable will not have changed between the two if statements. (This is a common mistake in Arduino programming, treating the variable that holds an I/O value the same as the I/O itself.)

If you're posting code fragments, and merely left out the part where you re-read the pin, it's best to include all the relevant code. Otherwise it's not possible to see how the sketch will work.

-- Gordon
Logged

Pages: [1] 2   Go Up
Jump to: