Go Down

Topic: Servo operation based on multiple inputs (Read 142 times) previous topic - next topic

poharedontcare

I am using a servo to operate a linkage sliding rail mechanism that holds a cup to pour a drink into. I am trying to have the servo move to different positions based on which button I push and if a limit switch is triggered by the cup in the loading mechanism (to avoid forgetting a cup and causing drink to spill everywhere). When I run the code, I can tell the "if" loop in question starts running, because the LED shuts off like it should and I can hear the valve activate and deactivate, but the servo shows no signs of life, even though other test code I've run gets it to move.
Code: [Select]
#include <Servo.h>


#define valve1o A3           
#define valve1c A4                                /* valve "o" means open, valve "c" means closed for h-bridge operation */
// H-bridge 1 ECB A5

#define button2 2
#define button3 3
#define button1 4
#define cup 5
// linkage servo 6
#define LED 7
// H-bridge 2 ECA 8
#define valve2o 9
#define valve2c 10
#define valve3o 11
#define valve3c 12
// H-bridge 2 ECB 13

void setup() {
 
  pinMode(valve1o, OUTPUT);                       /* define all pins as inputs and outputs appropriately */
  pinMode(valve1c, OUTPUT);
  pinMode(valve2o, OUTPUT);
  pinMode(valve2c, OUTPUT);
  pinMode(valve3o, OUTPUT);
  pinMode(valve3c, OUTPUT);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(LED, OUTPUT);
  pinMode(cup, INPUT);

 
  int delivery = 155;                             /* defines servo angle outputs for postitions of linkage */
  int soda1 = 82;         
  int soda2 = 111;
  int soda3 = 132;
 
  Servo link;                                     /* attach servos to pins with servo library commands */
  link.attach(6);

  digitalWrite(LED, HIGH);
  delay(250);
  digitalWrite(LED, LOW);
  delay(750);
  link.write(delivery);                           /* primes the linkage to starting position */
 
}

void loop() {
  Servo link;                                     /* declare servo pin for void loop scope */
  link.attach(6);
 
  int valve = 2000;                               /* defines the time a valve stays open */
  int servo = 7000;                               /* defines time delay after servo moves */
  int delivery = 155;                             /* defines servo angle outputs for delivery postition of linkage */
  int soda1 = 82;                                 /* defines linkage positions under each valve */
  int soda2 = 111;
  int soda3 = 132;
 
 
  if (digitalRead(cup) == HIGH && digitalRead(button1) == HIGH && digitalRead(button2) == HIGH && digitalRead(button3) == HIGH){                /* when no sensors are triggered, waiting for cup to be loaded */
    link.write(delivery);                         /* sets linkage in delivery position if it isn't already*/     
    digitalWrite(valve1o, LOW);                   /* turns everything off while waiting for limit switch to be triggered */
    digitalWrite(valve1c, LOW);
    digitalWrite(valve2o, LOW);
    digitalWrite(valve2c, LOW);
    digitalWrite(valve3o, LOW);
    digitalWrite(valve3c, LOW);
    digitalWrite(LED, LOW);
    }
  if(digitalRead(cup) == LOW && digitalRead(button1) == HIGH && digitalRead(button2) == HIGH && digitalRead(button3) == HIGH){              /* when limit switch is triggered by cup and nothing else */
     digitalWrite(LED, HIGH);                      /* watchdog LED activates, blinks until button 1 2 or 3 is pressed */
     delay(250);
     digitalWrite(LED, LOW);
     delay(750);   
  }
  if (digitalRead(cup) == LOW && digitalRead(button1) == LOW && digitalRead(button2) == HIGH && digitalRead(button3) == HIGH){              /* cup loaded and button 1 triggered */
    digitalWrite(LED, HIGH);                      /* turns LED on and off to notify user of iminent activity */
    delay(250);
    digitalWrite(LED, LOW);
    delay(750);
    link.write(soda1);                            /* moves linkage to under valve 1 */
    delay(servo);                                  /* waits for servo to get into position */
    digitalWrite(valve1o, HIGH);                  /* opens valve */
    digitalWrite(valve1c, LOW);
    delay(valve);
    digitalWrite(valve1o, LOW);                   /* turns off valve after set amount of time */
    digitalWrite(valve1c, LOW);
    link.write(delivery);                         /* moves linkage back to delivery position */
    delay(servo);

Note: the buttons and limit switch operate with "LOW" meaning they are being pressed and "HIGH" is not being pressed.

I have the servo running off the Arduino 5V output and GND (recommended by manufacturer is 4.8V to 7V). The buttons and limit switch are wired with external pull up resistors (1100 ohms each) in parallel. They also all operate properly in test code. Servo link

slipstick

The Arduino 5V pin is not suitable for running servos, not enough current, though you usually get away with if it's only one micro servo. Exactly what servo are you using?

Why are you creating a new local Servo 'link' and attaching it every time round loop(). That's really going ro confuse the poor old servo. The "Servo link;" should be global - just below the #include is a good place for it. Then you need ONE attach() in setup(). And your variables like soda1 etc should also be global NOT local to setup() or another set that's local to loop().

I think you need to read up on C/C++ scope rules. If you define something inside a function like setup() or loop() it can only be used in that function. Almost everything that you have defined twice should actually be global i.e. up at the top not inside either setup() or loop().

Steve

JCA34F

Also, I don't see any "pinMode(x,INPUT_PULLUP)" statements, do you have external pullup resistors (10k) on the input pins?

Robin2

This style of programming makes problems very hard to debug
Code: [Select]
if (digitalRead(cup) == HIGH && digitalRead(button1) == HIGH && digitalRead(button2) == HIGH && digitalRead(button3) == HIGH

Every time you do a digitalRead() you might get a different result. Much better to read all the inputs at the start of loop() and save the values. Then used the saved values in your tests. That way all the tests use the same values. Also  by saving the values you can print then so you can see the inputs to the tests.

It will also help with development and testing if you take care to use very descriptive variable names rather than generic things like button1 and button2. For example maybe something like
Code: [Select]
cupInPlace = digitalRead(cupTestPin);
if (cupInPlace == true and ........

I don't know what your buttons represent so I can't make suggestions for renaming them

Also I suggest changing
Code: [Select]
  int valve = 2000;   
to
Code: [Select]
  int valveOpenTime = 2000;    
and then you won't need an explanatory comment.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

poharedontcare

Also, I don't see any "pinMode(x,INPUT_PULLUP)" statements, do you have external pullup resistors (10k) on the input pins?
Yes, I was using 1k external resistors. I thought that the buttons might be using too much current, so I added more resistors in parallel for 1100 ohms each.
The Arduino 5V pin is not suitable for running servos, not enough current, though you usually get away with if it's only one micro servo. Exactly what servo are you using?

Why are you creating a new local Servo 'link' and attaching it every time round loop(). That's really going ro confuse the poor old servo. The "Servo link;" should be global - just below the #include is a good place for it. Then you need ONE attach() in setup(). And your variables like soda1 etc should also be global NOT local to setup() or another set that's local to loop().

I think you need to read up on C/C++ scope rules. If you define something inside a function like setup() or loop() it can only be used in that function. Almost everything that you have defined twice should actually be global i.e. up at the top not inside either setup() or loop().

Steve
I put the link to where I got the servo on the bottom of my original post. Sorry, I don't know how to use the code commands in Quick Reply to put it here, I'm new to this forum (and forums in general). Thank you for this organizing advice. The thing is, with other code my servo works great off the arduino 5V pin, it's just this code for some reason.

slipstick

If you really added a 100 Ohm a resistor in PARALLEL with a 1K resistor the total resistance is now less than 100 Ohms and that's way too low for safety.

And if you ever try to drive any useful load with that MG996R it will kill the Arduino. An MG996R can draw over 1A from a pin that can only safely deliver 0.2A. Of course you can always ignore the advice and find out for yourself.

Steve


poharedontcare

If you really added a 100 Ohm a resistor in PARALLEL with a 1K resistor the total resistance is now less than 100 Ohms and that's way too low for safety.

And if you ever try to drive any useful load with that MG996R it will kill the Arduino. An MG996R can draw over 1A from a pin that can only safely deliver 0.2A. Of course you can always ignore the advice and find out for yourself.

Steve


Sorry, I meant that I have 1100 ohms and a button in series, just that setup repeated 3 times in parallel.

Robin2

Sorry, I meant that I have 1100 ohms and a button in series, just that setup repeated 3 times in parallel.
That is still not crystal clear.

What does "in parallel" mean within the phrase I have highlighted. I would expect that you have three separate buttons connected to three separate Arduino I/O pins and with each button having its own 1100 ohm resistor. However the words "in parallel" make me suspect that things are connected differently.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

slipstick

It's surely time to draw a simple circuit connection diagram. Just a picture of a pencil on paper drawing would be a lot easier to understand than your confusing "added more resistors in parallel" and "repeated 3 times in parallel".

Steve

zoomkat

"I have the servo running off the Arduino 5V output and GND (recommended by manufacturer is 4.8V to 7V)."

As others have said, every time the servo tries to move it may be causing a brown/black out on the Arduino, causing it to reset. You probably check that by having a serial print to the serial monitor in the setup part of the code after the serial port is initialized saying "rebooting".
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

Go Up