Go Down

Topic: Eye Blink Help (Read 536 times) previous topic - next topic

Brainfart14

May 20, 2017, 05:37 am Last Edit: May 20, 2017, 05:28 pm by Brainfart14
I'm new to the arduino world, and have always been fascinated by animatronics. I want to create the classic animatronic eye using my arduino uno and some servos. I think I've come up with an effective sketch, but I want to add a 3rd servo for a blinking eyelid (I'm currently using 2 for up/down and left/right movement). I'm shooting for random movement from the servos, to make the eye movement appear lifelike/natural, it'd be great if the blink did the same but right now it's no biggie. Any help or guidance is greatly appreciated! I've added my sketch below:

#include <Servo.h>
Servo horservo;       //servo for left & right movement
Servo vertservo;      //servo for up & down movement

byte randomhor;       //define random horizontal position variable
byte randomvert;      //define random verticle position variable
int randomdelay;      //define random delay variable

#define HLEFTLIMIT 0       //deine left limit on the horizontal servo
#define HRIGHTLIMIT 180    //define right limit on the horizontal servo
#define VBOTTOMLIMIT 180   //define bottom limit on the verticle servo
#define VTOPLIMIT 0        //define top limit on the verticle servo


void setup() {
  horservo.attach(7);         //attach servo to pin 7
  vertservo.attach(9);        //attach servo to pin 9
  randomSeed(analogRead(0));  //create some random values using an unconnected analog pin
 
}

void loop() {
  randomhor = random(HLEFTLIMIT, HRIGHTLIMIT);    //set limits for horizontal servo
  randomvert = random(VTOPLIMIT, VBOTTOMLIMIT);   //set limits for vertval servo
  delay(randomdelay);                             //delay for random amount of time (time length set above)

}

Delta_G

#1
May 20, 2017, 08:17 pm Last Edit: May 20, 2017, 08:17 pm by Delta_G
In the loop function, you find nice random values, but you never write them to the servo.  So it will never move.  Is that the problem? 

You also never get a value for randomdelay, so it will always be a 0. 
If at first you don't succeed, up - home - sudo - enter.

Brainfart14

Yes, it looks like a just need help to overhaul the sketch all together, because I'd also like to add in another servo for a blinking eyelid. The blink doesn't have to be randomized, but if it were, that would be nice. Any suggestions on how to do this? Feel free to make any alterations to the code, I'm open to any advice or improvements. Thanks!

Delta_G

If you want the eye blink to be random in relation to the other movements, then you're going to have to get rid of the delay function and embrace the "Blink Without Delay" style of timing.  See the example by that name in the IDE or any of the thousands of great tutorials on it all over the web. 
If at first you don't succeed, up - home - sudo - enter.

Brainfart14

What do you mean? Like I said, I'm still new to this so I'm a little confused. Wouldn't I need the delay function for the eye movement so that it isn't constantly moving/looking around? Wouldn't "Blink w/o Delay" mean that it would *always* be moving?

Delta_G

#5
May 21, 2017, 11:53 pm Last Edit: May 21, 2017, 11:55 pm by Delta_G
What do you mean? Like I said, I'm still new to this so I'm a little confused. Wouldn't I need the delay function for the eye movement so that it isn't constantly moving/looking around? Wouldn't "Blink w/o Delay" mean that it would *always* be moving?
I'm not going to answer that until you actually have a look at the Blink Without Delay example and at least one tutorial about how it works.  You obviously haven't even tried or you would have realized how nonsensical your comment is.  You have to be willing to put in at least some effort here.
If at first you don't succeed, up - home - sudo - enter.

Brainfart14

I'm not going to answer that until you actually have a look at the Blink Without Delay example and at least one tutorial about how it works.  You obviously haven't even tried or you would have realized how nonsensical your comment is.  You have to be willing to put in at least some effort here.
I did look at that example, and I'm still a bit confused. So by applying that to the code, the previous 'blink' from the servo would become the current blink (if I'm understanding that correctly). So then wouldn't it just continue blinking based on the previous blink, or will there be some space/time between the blinking for the other two servos to actually move the eye around? Movement is my main focus; the blinking eyelid just adds a touch of realism to the final project, I don't want that to take away from my primary intention, if that makes sense. I do see how this sketch would work- in the case of an LED blink, but I'm still a bit wary about it in terms of servo movement :/

Delta_G

#7
May 22, 2017, 01:23 am Last Edit: May 22, 2017, 01:23 am by Delta_G
It's really quite simple.  You have a loop function repeating itself over and over thousands of times a second.  On each pass of the loop you compare the current time to what time it was when you last did something.  If the difference is larger than some interval then it is time to do it again and record the current time as the last time you did it. 

Read this and see if it helps to understand.  https://www.gammon.com.au/blink

Pay particular attention to the bit about cooking breakfast.
If at first you don't succeed, up - home - sudo - enter.

Delta_G

Or here's another example.  If I said, call me in ten minutes.  Would you start a countdown timer and stare at it doing absolutely nothing else for ten minutes and then call me when it went off (like delay)?  Or would you look at the clock and note what time it was when I asked and then continue doing what you were doing and periodically looking at the clock to see if ten minutes had passed? 
If at first you don't succeed, up - home - sudo - enter.

Brainfart14

Okay, I have a better understanding now. Thank you! So, in terms of what I want to do, I would axe the delay and essentially be toggling between the eye movements from the other two servos and the blink movement from the third servo? I understand it now. If I had used the delay function the whole thing basically would have stopped- correct? By using this other method the eye will continue to move in between the blinking. That definitely makes more sense. Thank you so much! :D  :D

Delta_G

I think you've got it.  Take a stab at the code and come back here if you run into problems. 
If at first you don't succeed, up - home - sudo - enter.

Brainfart14

Okay, so I've come up with a practice code to check my progress. For the most part, the servos move okay (I only have 2 out of the 3 needed servos at the moment, I need to order another one so right now I'm subbing the 3rd servo with an LED light). Not sure if it's something I did wrong in the code, but the LED isn't functioning the way I want  :smiley-confuse: As of now, what I'm going for is to have the 2 servos controlling the eye move in unison, while the 3rd servo independently controls the blink. The "eye servos" are moving correctly- albeit slow, I think I need new ones, these are kinda beat up- but the blink function isn't working correctly. I applied the function you sent me, but it continues to move in unison with the servos. Did I leave something out? Thanks.

#include <Servo.h>     //servo library
Servo servo1;
Servo servo2;

const byte blueLED = 12;   //LED attached at pin 12

const unsigned long blueLEDinterval = 200;

unsigned long blueLEDtimer;

//servo position in degrees
int servoPos = 0;

void setup() {
  // put your setup code here, to run once:
servo1.attach(3);
servo2.attach(6);
pinMode (blueLED, OUTPUT);
blueLEDtimer = millis ();
}

void toggleBlueLED ()
  {
    if (digitalRead (blueLED) == LOW)    //blue LED turn OFF
       digitalWrite (blueLED, HIGH);     //blue LED turn ON
    else
       digitalWrite (blueLED, LOW);      //blue LED turn OFF
  //remember when we toggled it
  blueLEDtimer = millis ();
  }    //end of blue LED toggle

void loop() {
  //scan from 0 to 180 degrees
  for(servoPos = 0; servoPos < 180; servoPos++)
  {
    servo1.write(servoPos);
    servo2.write(servoPos);
    delay(10);
  }

  //now scan back from180 to 0
  for(servoPos = 180; servoPos > 0; servoPos--)
  {
    servo1.write(servoPos);
    servo2.write(servoPos);
    delay(15);
  }
 
  {
  //Handling the blink on LED
  if ( (millis () - blueLEDtimer) >= blueLEDinterval)
     toggleBlueLED ();
}

}

Delta_G

Code: [Select]
  for(servoPos = 0; servoPos < 180; servoPos++)
  {
    servo1.write(servoPos);
    servo2.write(servoPos);
    delay(10);
  }


These are your problem now.  Those for loops with the evil delays in them block for almost 2 seconds each.  While the code is in the for loop going over and over, it's not checking the if statement at the end for the LED.  You'll have to take the same approach with the servos as well.  Take one small step at a time, when it is time and let the loop keep running.  You can't trap the code anywhere doing anything and waiting for it to be all the way done. 
If at first you don't succeed, up - home - sudo - enter.

Brainfart14

Ok, so I'm going to try and attack my eye-blink sketch from a different angle. I'm thinking about applying the basic 'sweep' sketch, times 3, for the 3 servos I'm using. I want two of the servos to move in unison, while the third servo does it's own thing (controlling the blink). Would that be possible, founded on just the sweep sketch?

Go Up