SOLVED Randomized actions on animatronic eye

Hey there,

i`m working on the code for my 3d-printed eye-mechanism with an arduino uno and the adafruit servo-shield and i want to randomize everything as far as possible.

Right now, i have three servos in my code (see the attachment). Servo 1 and servo 2 for Looking Up/Down and Looking Left/Right and Servo 3 for the Blinking of the Eyelid.

Right now the LOOP is like this:

  1. Servo 1 - moves in one direction
  2. Servo 1 - moves in the other direction
  3. Servo 2 - moves in one direction
  4. Servo 2 - moves in the other direction
  5. Servo 3 - moves in one direction
  6. Servo 3 - moves in the other direction

My question is: How can i customize the code, so that the actions 1-6 will work randomly, so the eye movement looks more realistic?

Thanks for any help with this!
Stefan

servo_TEST_September_NEU.ino (2.04 KB)

Have you looked at the random() function ? You can use it to generate (semi)random numbers to use as servo positions.

Was there a reason why you did not post your code here to make it easier to provide advice without the need to download it ?

My question is: How can i customize the code, so that the actions 1-6 will work randomly, so the eye movement looks more realistic?

Randomly moving up and down, left and right, and blinking will NOT look at all realistic. More like an eye that needs to see a doctor.

Thanks for the answers.

You can find the code in the attachment of the first post!

And of course you are right, that complete randomized actions will not look realistic,
but i want to use it just very rare. If the action always looks the same, you can see the pattern.
Thatss what im trying to avoid.

For example the blinking of the eye on servo3.
How can i change the code, so that this blinking-action sometimes happens one time, sometimes for 2 times..?

Thanks again,
Stefan

How can i change the code, so that this blinking-action sometimes happens one time, sometimes for 2 times..?

  int timesToBlink = random(0, 10000);

  for(int b=0; b<timesToBlink; b++)
  {
     blink();
  }

You can find the code in the attachment of the first post!

Yes, I saw that, but it would have been easier if you had posted it here rather than attached it which would have avoided the need to download it.

At the time I am writing this your post has been viewed 36 times but the code has only been downloaded once. If you had posted it then it would have been seen 36 times instead of once.

Right. Here we go.

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);


#define SERVOMIN  (250) // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  (400) // this is the 'maximum' pulse length count (out of 4096)


int servo0 = 0;
int servo1 = 1;
int servo2 = 2;

void setup() {
 Serial.begin(9600);


 pwm.begin();

 pwm.setPWMFreq(60); 
}

// you can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise!
void setServoPulse(uint8_t n, double pulse) {
 double pulselength;

 pulselength = 1000000;   // 1,000,000 us per second
 pulselength /= 60;   // 60 Hz
 Serial.print(pulselength); Serial.println(" us per period");
 pulselength /= 4096;  // 12 bits of resolution
 Serial.print(pulselength); Serial.println(" us per bit");
 pulse *= 1000;
 pulse /= pulselength;
 Serial.println(pulse);
 pwm.setPWM(n, 0, pulse);
}

void loop() {

 
 /// Servo 0 (Up/Down)
 Serial.println(servo0);
 for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen += random(1, 5)) {
   pwm.setPWM(servo0, 0, pulselen);
   delay(random(3,6));
 }
 delay(600);// Delay 
 for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen -= random(1, 3)) {
   pwm.setPWM(servo0, 0, pulselen);
   delay(random(1,6));
 }
 delay(random(50,400)); // Delay between 2 servos
 
 
/// SERVO 2 (Left/Right)
 for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
   pwm.setPWM(servo1, 0, pulselen);
   delay(random(3,8));
 }
 delay(600);// Delay 
 for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
   pwm.setPWM(servo1, 0, pulselen);
   delay(random(3,9));
 }
 delay(random(50,1000)); // Delay zwischen 2 servos
 
/// Servo3 (Blinking)

   for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
   pwm.setPWM(servo2, 0, pulselen);
   
 }
 delay(50);// Delay 
 for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
   pwm.setPWM(servo2, 0, pulselen);
 
 }
 delay(600); 
 
 
 
}

Better, but it would be even better if it were in code tags. Edit your post, select the code and click on the </> icon at the left above the editor window. The code will be displayed in a scrolling window with an option to select it all ready for copy/paste.

Ok. Thanks. Like i said, Just starting, but willing to learn!

One thing you should do is put the code to move the servo left and right in a function. Put the code to move up and down in another function. Put the code to blink in a third function.

Then, you'd see that all that loop() is doing is

void loop()
{
   lookLeftAndRight();
   lookUpAndDown();
   blink();
}

Perhaps THAT is the real problem.

Ok. Got it. Now i implemented the function, what certainly was very important :slight_smile:

But how do i use the random() command on my functions?
Let`s say the blinking() should come with a chance of 20 Percent in every loop:

void loop() 
{
  lookLeftAndRight();
   lookUpAndDown();
   blinking();
   
 }

Here is the actual code with functions...

/// Randomize functions




#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);


#define SERVOMIN  (250) // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  (400) // this is the 'maximum' pulse length count (out of 4096)


int servo0 = 0;
int servo1 = 1;
int servo2 = 2;

void setup() {
  Serial.begin(9600);


  pwm.begin();

  pwm.setPWMFreq(60); 
}

// you can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise!
void setServoPulse(uint8_t n, double pulse) {
  double pulselength;

  pulselength = 1000000;   // 1,000,000 us per second
  pulselength /= 60;   // 60 Hz
  Serial.print(pulselength); Serial.println(" us per period");
  pulselength /= 4096;  // 12 bits of resolution
  Serial.print(pulselength); Serial.println(" us per bit");
  pulse *= 1000;
  pulse /= pulselength;
  Serial.println(pulse);
  pwm.setPWM(n, 0, pulse);
}

void loop() 
{
  lookLeftAndRight();
   lookUpAndDown();
   blinking();
   
 }
   /// Servo 0
  void lookLeftAndRight(){
 
  Serial.println(servo0);
  for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen += random(1, 5)) {
    pwm.setPWM(servo0, 0, pulselen);
    delay(random(3,6));
  }
  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen -= random(1, 3)) {
    pwm.setPWM(servo0, 0, pulselen);
    delay(random(50,800));
  }}


  /// SERVO 1 
  void lookUpAndDown()
  {

  for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(random(3,8));
 }
  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(random(50,800));
  }}

  
/// Servo 2 
void blinking() {
    for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
    pwm.setPWM(servo2, 0, pulselen);
    
 
  delay(20);// Delay 
  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(servo2, 0, pulselen);
  
  }


  
  
  
}}

Let`s say the blinking() should come with a chance of 20 Percent in every loop:

void loop()
{
  lookLeftAndRight();
   lookUpAndDown();
   
   if(random(0, 101) > 20)
   {
     blinking();
   }
 }

GREAT. Thanks a lot again for your help! Big step forward for me :wink:
That´s exactly what i was looking for!
St

Let`s say the blinking() should come with a chance of 20 Percent in every loop:

void loop()

{
 lookLeftAndRight();
  lookUpAndDown();
 
  if(random(0, 101) > 20)
  {
    blinking();
  }
}

Strictly speaking that gives an 80% chance of calling the blinking() function rather than 20%, but it looks like the OP got the general idea.

Strictly speaking that gives an 80% chance of calling the blinking() function rather than 20%

Point one stinking symbol the wrong way... 8)