Innerbreed Pull-Pull Animatronics (3D Printed)

The following code is for the bird project but has not been tested as i currently need to purchase another BAP.
Its function is designed to start working as soon as power is applied. The example i have written at this point is for the eye blinks only.

For the programmers out there, does this look correct?

My expectations for this test code is that once power is applied, the eye lids will start in the open position (1500) then blink slow then fast.
If this is the correct way to use the HServo command then i can start programming the other routines.

[code];------------------
Enablehservo; Activate HSERVO function

;Servo pin connections
Blink con 0
Head_Rotate con 1
Head_Left_Right con 2
Head_Front_Back con 3
Neck_Front_Back con 4
Neck_Right_Left con 5
Wings_OC con 6
Left_Wing con 7
Right_Wing con 8

;Variables
cBlink var Sword
cHead_Rotate var Sword
cHead_Left_Right var Sword
cHead_Front_Back var Sword
cNeck_Front_Back var Sword
cNeck_Right_Left var Sword
cWings_OC var Sword
cLeft_Wing var Sword
cRight_Wing var Sword

;[Init]------------------

;HSERVO [pin\pos\speed]

;pin =
;pin number to generate servo signal on

;pos =
;position to move servo arm too. range ±12000.
;position is in clock cycles(1/16000000 of a second,.0625us), centered at 1500us

;speed =
;how fast to move to new position. Must already be at a known position to use.
;First time using HSERVO should use a speed of 0. Speed of 0 means move to position immediately.

HSERVO [Blink\1500\0]
HSERVO [Head_Rotate\1500\0]
HSERVO [Head_Left_Right\1500\0]
HSERVO [Head_Front_Back\1500\0]
HSERVO [Neck_Front_Back\1500\0]
HSERVO [Neck_Right_Left\1500\0]
HSERVO [Wings_OC\1500\0]
HSERVO [Left_Wing\1500\0]
HSERVO [Right_Wing\1500\0]
pause 100
;------------------------------------
;************************************
;[MAIN]

Main
;HSERVO [Blink\1500, Head_Rotate\1500] ’ Send control pulses to servos
gosub Center_ALL
pause 3000
gosub Blink_Active
pause 1000
Goto Main

;************************************
;------------------------------------
;Sub Routines
Blink_Active
HSERVO [Blink\1500\0] ’ hold open
pause 1000 ’ for one second
HSERVO [Blink\12000\255] ’ Close eys slowly
HSERVO [Blink\1500\255] ’ Open eyes slowly
pause 2000 ’ for two seconds
HSERVO [Blink\12000\0] ’ Close eys fast
HSERVO [Blink\1500\0] ’ Open eyes fast

return
;------------------

Center_ALL
HSERVO [Blink\1500\122]
HSERVO [Head_Rotate\1500\122]
HSERVO [Head_Left_Right\1500\122]
HSERVO [Head_Front_Back\1500\122]
HSERVO [Neck_Front_Back\1500\122]
HSERVO [Neck_Right_Left\1500\122]
HSERVO [Wings_OC\1500\122]
HSERVO [Left_Wing\1500\122]
HSERVO [Right_Wing\1500\122]

return[/code]

… 7 …?

Well all together there will be a total of 9 servos in this project. 8 will be inside the casing and another one in the head for Head Rotate.

but yes i need to order another one to control the eyelids. as i have not yet done much work on the head im waiting to see what i need.
So far this is the new Printed head and mech.
shapeways.com/model/695970/i … 4462e962c0

head and mech.PNG

Iv also been working on ideas for a Peregrine Falcon:

modeling 1.PNG
modeling 2.PNG

OR…

modeling 5.PNG

ok so While i wait for the DiaLFonZo-Copter Shield and Arduino ProMini kindly donated to the project by Eric, i have been looking at learning to program the thing. :confused:

working with Eric for the main code he has derived a sample for mew to learn with. I must say, although im still learning, im finding Arduino quite similar to MBasic witht the exception of a few symbols and characters i keep forgetting to include. :unamused:

iv been working on the blink function of the code. if there is any Arduino coders out there you can look at my “poor” or “ok” efforts and programming this part…

one of the things i have noticed with working with Arduino is that the Millis() and Delay() functions can sometimes conflict but not only this that the delay function Stops everything and not just the instruction given in the code.

not a major problem as the architecture the code doesn’t really call for things to pause while others elements are active.
For instance an owl doesnt just blink its eyes continuously while moving its head. They kinda close there eyes, move there head then open them again.
The following code is for the eye blink. showing a fast and a slow blink using the attach/detach method. i hope…

[code]

#include <Servo.h>
//========Define Servos
Servo Blink;

int Blink_Pos = 90;
int Blink_Pos2 = 170;

int ServoDelay_1 = 5;
int ServoDelay_2 = 20;

void setup() {
Blink.attach(9); //Pin 9 for servo
Blink.write(Blink_Pos);// Start at center

}

void loop() {

//Fast blink
Blink.attach(9); // Attach and apply power (eyes open on power up)
delay(3000); // Wait 3 seconds
Blink.write(Blink_Pos2); // Position servo center (eyes close)
delay(ServoDelay_1); // Allow transit time (can be variable)
Blink.detach(); // Detach and remove power
Blink.attach(9); // Re-attach and apply power (eyes open on power up)

delay(4000); // Wait 4 seconds

//Slow Blink
Blink.attach(9); // Attach and apply power (eyes open on power up)
delay(3000); // Wait 3 seconds
Blink.write(Blink_Pos2); // Position servo center (eyes close)
delay(ServoDelay_2); // Allow transit time (can be variable)
Blink.detach(); // Detach and remove power
delay(2000); // Wait 2 seconds
Blink.attach(9); // Re-attach and apply power (eyes open on power up)
delay(ServoDelay_2); // Allow transit time (can be variable)
delay(4000); // Wait 4 seconds

//Return loop
}[/code]

Working on the code for the Blink…
I added a sequence but i don’t know if it will work 100% of the time … depending of the rest of the code.
Also the variable “int EyeBlinkFast_ServoDelay = 250;” which give at which rate the thing is updated… sometime work and sometime don’t (on the actual servo i mean)

[code]//— With the help of James Clifford and Eric Nantel —
//— Control for Jonny Poole - InnerbreedFX Animatronics —

#include <Servo.h>
#include “ServoMovements.h”

//— Value for the Blinking of LED —
const int ledPin = 13;
int ledState = LOW;
long previousMillis_LED = 0;
long interval_LED = 50;

Servo Eye_Blink;
Servo Head_Rotate;
Servo Head_UpDown;
Servo Head_LeftRight;
Servo Neck_UpDown;
Servo Neck_LeftRight;
Servo Wing_Right;
Servo Wing_Left;
Servo Wings;

int Eye_Blink_Pos = 90;
int Head_Rotate_Pos = 90;
int Head_UpDown_Pos = 90;
int Head_LeftRight_Pos = 90;
int Neck_LeftRight_Pos = 90;
int Neck_UpDown_Pos = 90;
int Wing_Right_Pos = 90;
int Wing_Left_Pos = 90;
int Wings_Pos = 90;

unsigned long lastServoMillis_1 = 0;
unsigned long lastServoMillis_2 = 0;

unsigned long lastEyeBlinkMillis = 0;
int EyeBlinkFast_ServoDelay = 250;
int ServoDelay_1 = 10;
int ServoDelay_2 = 20;

int EyeBlink_pos = 1;
int EyeBlink_Count = 1;

int Head_Rotate_posDirection = 1;
int Head_UpDown_posDirection = 1;
int Head_LeftRight_posDirection = 1;
int Neck_UpDown_posDirection = 1;
int Neck_LeftRight_posDirection = 1;
int Wing_Right_posDirection = 1;
int Wing_Left_posDirection = 1;
int Wings_posDirection = 1;

//Servo ServoPin3;

void setup() {

Eye_Blink.attach(9); //Pin-LCD on diaLFonZo-Copter Shield
Head_Rotate.attach(4); //Pin-9 on DiaLFonZo-Copter Shield
Head_UpDown.attach(3); //Pin-3 on DiaLFonZo-Copter Shield
Head_LeftRight.attach(10); //Pin-10 on DiaLFonZo-Copter Shield
Neck_UpDown.attach(11); //Pin-11 on DiaLFonZo-Copter Shield
Neck_LeftRight.attach(8); //Pin-A0 on DiaLFonZo-Copter Shield
Wing_Right.attach(7); //Pin-A1 on DiaLFonZo-Copter Shield
Wing_Left.attach(6); //Pin-A2 on DiaLFonZo-Copter Shield
Wings.attach(5); //Pin-A3 on DiaLFonZo-Copter Shield

pinMode(ledPin, OUTPUT);

delay(2000);
}

//— Main Loop —
void loop(){

EyeBlinkFast();
//HeadRotate();
//HeadUpDown();
//Blink_LED();

}

//— Blinking fast —
void EyeBlinkFast(){

unsigned long currentEyeBlinkMillis = millis();

if (currentEyeBlinkMillis - lastEyeBlinkMillis >= EyeBlinkFast_ServoDelay) {  // Delay of EyeBlinkFast_ServoDelay so the millis update those value at that rate
  lastEyeBlinkMillis = currentEyeBlinkMillis;
  
  // The count is lower than 5*EyeBlinkFast_ServoDelay go at 170deg
  if (EyeBlink_Count <= 5) {                   
    EyeBlink_Count = (EyeBlink_Count + 1);
    Eye_Blink.write(170);
  }
  
  // The count is higher than 6*EyeBlinkFast_ServoDelay go at 10deg
  if (EyeBlink_Count >= 6){
    EyeBlink_Count = (EyeBlink_Count + 1);
    Eye_Blink.write(10);
  }
  
  // The count is higher than 7*EyeBlinkFast_ServoDelay reset the counter
  if (EyeBlink_Count >= 7){
    EyeBlink_Count = 1;
    Blink_LED();
  }
}

}

//— Turn 160deg all the time —
void HeadRotate(){

unsigned long currentMillis_1 = millis();

if (currentMillis_1 - lastServoMillis_1 >= ServoDelay_1) {
    Head_Rotate.write(Head_Rotate_Pos);
    lastServoMillis_1 = currentMillis_1;
    Head_Rotate_Pos += Head_Rotate_posDirection;
    
    if (Head_Rotate_Pos == 170 || Head_Rotate_Pos == 10) {
        Head_Rotate_posDirection = -Head_Rotate_posDirection;
    }  
}

}

//— Turn 160deg all the time —
void HeadUpDown(){

unsigned long currentMillis_2 = millis();

if (currentMillis_2 - lastServoMillis_2 >= ServoDelay_2) {
    Head_UpDown.write(Head_UpDown_Pos);
    lastServoMillis_2 = currentMillis_2;
    Head_UpDown_Pos += Head_UpDown_posDirection;
    
    if (Head_UpDown_Pos == 170 || Head_UpDown_Pos == 10) {
        Head_UpDown_posDirection = -Head_UpDown_posDirection;
    }
}

}

void Blink_LED(){

unsigned long currentMillis_LED = millis();
if(currentMillis_LED - previousMillis_LED > interval_LED) {
  previousMillis_LED = currentMillis_LED;  
if (ledState == LOW)
  ledState = HIGH;
else
  ledState = LOW;
digitalWrite(ledPin, ledState);

}
}

//— Initialisation —
void PowerInit(){

Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
delay(500);
Head_Rotate.write(10);
Head_UpDown.write(10);
Head_LeftRight.write(10);
Neck_UpDown.write(10);
Neck_LeftRight.write(10);
Wing_Right.write(10);
Wing_Left.write(10);
Wings.write(10);
delay(500);
Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
delay(500);
Head_Rotate.write(170);
Head_UpDown.write(170);
Head_LeftRight.write(170);
Neck_UpDown.write(170);
Neck_LeftRight.write(170);
Wing_Right.write(170);
Wing_Left.write(170);
Wings.write(170);
delay(500);
Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
}[/code]

Ok… found a way to have the blink sequence randomly…

[code]//— With the help of James Clifford and Eric Nantel —
//— Control for Jonny Poole - InnerbreedFX Animatronics —

#include <Servo.h>
//#include “ServoMovements.h”

//— Value for the Blinking of LED —
const int ledPin = 13;
int ledState = LOW;
long previousMillis_LED = 0;
long interval_LED = 50;

Servo Eye_Blink;
Servo Head_Rotate;
Servo Head_UpDown;
Servo Head_LeftRight;
Servo Neck_UpDown;
Servo Neck_LeftRight;
Servo Wing_Right;
Servo Wing_Left;
Servo Wings;

int Eye_Blink_Pos = 90;
int Head_Rotate_Pos = 90;
int Head_UpDown_Pos = 90;
int Head_LeftRight_Pos = 90;
int Neck_LeftRight_Pos = 90;
int Neck_UpDown_Pos = 90;
int Wing_Right_Pos = 90;
int Wing_Left_Pos = 90;
int Wings_Pos = 90;

unsigned long lastServoMillis_1 = 0;
unsigned long lastServoMillis_2 = 0;

unsigned long lastEyeBlinkMillis = 0;
int EyeBlinkFast_ServoDelay = 1; //— I put “1” to have one milisecond
int ServoDelay_1 = 10;
int ServoDelay_2 = 20;

unsigned long Blink_Trigger_lastMillis = 0;
boolean Blink_Trigger = false;
int Blink_Trigger_Interval = random(1000, 10000);

int EyeBlink_pos = 1;
int EyeBlink_Count = 0;

int Head_Rotate_posDirection = 1;
int Head_UpDown_posDirection = 1;
int Head_LeftRight_posDirection = 1;
int Neck_UpDown_posDirection = 1;
int Neck_LeftRight_posDirection = 1;
int Wing_Right_posDirection = 1;
int Wing_Left_posDirection = 1;
int Wings_posDirection = 1;

//Servo ServoPin3;

void setup() {

Eye_Blink.attach(9); //Pin-LCD on diaLFonZo-Copter Shield
Head_Rotate.attach(4); //Pin-9 on DiaLFonZo-Copter Shield
Head_UpDown.attach(3); //Pin-3 on DiaLFonZo-Copter Shield
Head_LeftRight.attach(10); //Pin-10 on DiaLFonZo-Copter Shield
Neck_UpDown.attach(11); //Pin-11 on DiaLFonZo-Copter Shield
Neck_LeftRight.attach(8); //Pin-A0 on DiaLFonZo-Copter Shield
Wing_Right.attach(7); //Pin-A1 on DiaLFonZo-Copter Shield
Wing_Left.attach(6); //Pin-A2 on DiaLFonZo-Copter Shield
Wings.attach(5); //Pin-A3 on DiaLFonZo-Copter Shield

pinMode(ledPin, OUTPUT);

delay(1000);
}

//— Main Loop —
void loop(){

EyeBlinkFast();
//HeadRotate();
//HeadUpDown();
//Blink_LED();

}

//---------------- Blinking fast ----------------
void EyeBlinkFast(){

//---------------- Part that trigger the blink sequence ----------------
unsigned long Blink_Trigger_currentMillis = millis();

if (Blink_Trigger_currentMillis - Blink_Trigger_lastMillis >= Blink_Trigger_Interval) {
  Blink_Trigger_lastMillis = Blink_Trigger_currentMillis;
  Blink_Trigger_Interval = random(1000, 10000);
  EyeBlink_Count = 0;
}

unsigned long currentEyeBlinkMillis = millis();

//---------------- Part that do the blink once triggered ----------------
if (currentEyeBlinkMillis - lastEyeBlinkMillis >= EyeBlinkFast_ServoDelay) { // Delay of EyeBlinkFast_ServoDelay so the millis update those value at that rate
lastEyeBlinkMillis = currentEyeBlinkMillis;
EyeBlink_Count = (EyeBlink_Count + 1);

  switch (EyeBlink_Count) {
    case 10:
      Eye_Blink.write(170);
      break;
    case 250:
      Eye_Blink.write(10);
      break;
    case 500:
      Eye_Blink.write(170);
      break;
  }    
}

}

//— Turn 160deg all the time —
void HeadRotate(){

unsigned long currentMillis_1 = millis();

if (currentMillis_1 - lastServoMillis_1 >= ServoDelay_1) {
    Head_Rotate.write(Head_Rotate_Pos);
    lastServoMillis_1 = currentMillis_1;
    Head_Rotate_Pos += Head_Rotate_posDirection;
    
    if (Head_Rotate_Pos == 170 || Head_Rotate_Pos == 10) {
        Head_Rotate_posDirection = -Head_Rotate_posDirection;
    }  
}

}

//— Turn 160deg all the time —
void HeadUpDown(){

unsigned long currentMillis_2 = millis();

if (currentMillis_2 - lastServoMillis_2 >= ServoDelay_2) {
    Head_UpDown.write(Head_UpDown_Pos);
    lastServoMillis_2 = currentMillis_2;
    Head_UpDown_Pos += Head_UpDown_posDirection;
    
    if (Head_UpDown_Pos == 170 || Head_UpDown_Pos == 10) {
        Head_UpDown_posDirection = -Head_UpDown_posDirection;
    }
}

}

void Blink_LED(){

unsigned long currentMillis_LED = millis();
if(currentMillis_LED - previousMillis_LED > interval_LED) {
  previousMillis_LED = currentMillis_LED;  
  if (ledState == LOW)
    ledState = HIGH;
  else
    ledState = LOW;
  digitalWrite(ledPin, ledState);

}
}

//— Initialisation —
void PowerInit(){

Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
delay(500);
Head_Rotate.write(10);
Head_UpDown.write(10);
Head_LeftRight.write(10);
Neck_UpDown.write(10);
Neck_LeftRight.write(10);
Wing_Right.write(10);
Wing_Left.write(10);
Wings.write(10);
delay(500);
Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
delay(500);
Head_Rotate.write(170);
Head_UpDown.write(170);
Head_LeftRight.write(170);
Neck_UpDown.write(170);
Neck_LeftRight.write(170);
Wing_Right.write(170);
Wing_Left.write(170);
Wings.write(170);
delay(500);
Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
}[/code]

Yes. I think that works better than the bytetable we talked about. Nice. :wink:

[code]//— With the help of James Clifford and Eric Nantel —
//— Control for Jonny Poole - InnerbreedFX Animatronics —

#include <Servo.h>
//#include “ServoMovements.h”

//— Value for the Blinking of LED —
const int ledPin = 13;
int ledState = LOW;
long previousMillis_LED = 0;
long interval_LED = 50;

//— Value for all Servos —
Servo Eye_Blink;
Servo Head_Rotate;
Servo Head_UpDown;
Servo Head_LeftRight;
Servo Neck_UpDown;
Servo Neck_LeftRight;
Servo Wing_Right;
Servo Wing_Left;
Servo Wings;

int Eye_Blink_Pos = 90;
int Head_Rotate_Pos = 90;
int Head_UpDown_Pos = 90;
int Head_LeftRight_Pos = 90;
int Neck_LeftRight_Pos = 90;
int Neck_UpDown_Pos = 90;
int Wing_Right_Pos = 90;
int Wing_Left_Pos = 90;
int Wings_Pos = 90;

int Head_Rotate_posDirection = 1;
int Head_UpDown_posDirection = 1;
int Head_LeftRight_posDirection = 1;
int Neck_UpDown_posDirection = 1;
int Neck_LeftRight_posDirection = 1;
int Wing_Right_posDirection = 1;
int Wing_Left_posDirection = 1;
int Wings_posDirection = 1;

//— Value for timings —
unsigned long lastServoMillis_1 = 0;
unsigned long lastServoMillis_2 = 0;

unsigned long lastEyeBlinkMillis = 0;
int EyeBlinkFast_ServoDelay = 1; //— I put “1” to have one milisecond
int ServoDelay_1 = 10;
int ServoDelay_2 = 20;

unsigned long Blink_Trigger_lastMillis = 0;
int Blink_Trigger_Interval = random(1000, 15000);

int EyeBlink_pos = 1;
int EyeBlink_Count = 0;

void setup() {

Eye_Blink.attach(9); //Pin-LCD on diaLFonZo-Copter Shield
Head_Rotate.attach(5); //Pin-9 on DiaLFonZo-Copter Shield
Head_UpDown.attach(3); //Pin-3 on DiaLFonZo-Copter Shield
Head_LeftRight.attach(10); //Pin-10 on DiaLFonZo-Copter Shield
Neck_UpDown.attach(11); //Pin-11 on DiaLFonZo-Copter Shield
Neck_LeftRight.attach(8); //Pin-A0 on DiaLFonZo-Copter Shield
Wing_Right.attach(7); //Pin-A1 on DiaLFonZo-Copter Shield
Wing_Left.attach(6); //Pin-A2 on DiaLFonZo-Copter Shield
Wings.attach(5); //Pin-A3 on DiaLFonZo-Copter Shield

pinMode(ledPin, OUTPUT);

PowerInit();

delay(1000);
}

//— Main Loop —
void loop(){

EyeBlinkFast();
//HeadRotate();
//HeadUpDown();
//Blink_LED();

}

//---------------- Blinking fast ----------------
void EyeBlinkFast(){

//---------------- Part that trigger the blink sequence ----------------
unsigned long Blink_Trigger_currentMillis = millis();

if (Blink_Trigger_currentMillis - Blink_Trigger_lastMillis >= Blink_Trigger_Interval) {
  Blink_Trigger_lastMillis = Blink_Trigger_currentMillis;
  Blink_Trigger_Interval = random(1000, 10000);
  EyeBlink_Count = 0;
  Blink_LED();
}

unsigned long currentEyeBlinkMillis = millis();

//---------------- Part that do the blink once triggered ----------------
if (currentEyeBlinkMillis - lastEyeBlinkMillis >= EyeBlinkFast_ServoDelay) { // Delay of EyeBlinkFast_ServoDelay so the millis update those value at that rate
lastEyeBlinkMillis = currentEyeBlinkMillis;
EyeBlink_Count = (EyeBlink_Count + 1);

  switch (EyeBlink_Count) {
    case 1:
      Eye_Blink.write(135);
      break;
    case 200:
      Eye_Blink.write(45);
      break;
    case 400:
      Eye_Blink.write(135);
      break;
  }    
}

}

//— Turn 160deg all the time —
void HeadRotate(){

unsigned long currentMillis_1 = millis();

if (currentMillis_1 - lastServoMillis_1 >= ServoDelay_1) {
    Head_Rotate.write(Head_Rotate_Pos);
    lastServoMillis_1 = currentMillis_1;
    Head_Rotate_Pos += Head_Rotate_posDirection;
    
    if (Head_Rotate_Pos == 170 || Head_Rotate_Pos == 10) {
        Head_Rotate_posDirection = -Head_Rotate_posDirection;
    }  
}

}

//— Turn 160deg all the time —
void HeadUpDown(){

unsigned long currentMillis_2 = millis();

if (currentMillis_2 - lastServoMillis_2 >= ServoDelay_2) {
    Head_UpDown.write(Head_UpDown_Pos);
    lastServoMillis_2 = currentMillis_2;
    Head_UpDown_Pos += Head_UpDown_posDirection;
    
    if (Head_UpDown_Pos == 170 || Head_UpDown_Pos == 10) {
        Head_UpDown_posDirection = -Head_UpDown_posDirection;
    }
}

}

void Blink_LED(){

unsigned long currentMillis_LED = millis();
if(currentMillis_LED - previousMillis_LED > interval_LED) {
  previousMillis_LED = currentMillis_LED;  
  if (ledState == LOW)
    ledState = HIGH;
  else
    ledState = LOW;
  digitalWrite(ledPin, ledState);

}
}

//— Initialisation —
void PowerInit(){

Eye_Blink.write(90);
Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
delay(500);
Eye_Blink.write(10);
Head_Rotate.write(10);
Head_UpDown.write(10);
Head_LeftRight.write(10);
Neck_UpDown.write(10);
Neck_LeftRight.write(10);
Wing_Right.write(10);
Wing_Left.write(10);
Wings.write(10);
delay(500);
Eye_Blink.write(90);
Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
delay(500);
Eye_Blink.write(170);
Head_Rotate.write(170);
Head_UpDown.write(170);
Head_LeftRight.write(170);
Neck_UpDown.write(170);
Neck_LeftRight.write(170);
Wing_Right.write(170);
Wing_Left.write(170);
Wings.write(170);
delay(500);
Eye_Blink.write(90);
Head_Rotate.write(90);
Head_UpDown.write(90);
Head_LeftRight.write(90);
Neck_UpDown.write(90);
Neck_LeftRight.write(90);
Wing_Right.write(90);
Wing_Left.write(90);
Wings.write(90);
}[/code]

That’s excellent work Eric.
Really happy with the result.
Only another 8 servos to go. Lol

i mat also use that command for head rotate.
Works perfectly. Full credit.

Need to implement a speed variable to be use for slower movements

I wasn’t going to ask 'as you’ve done more than expect,
… But yes that would be cool. :wink:

Ok…
One of my friend at work did a quick sketch to help me.
But since it’s getting complicated fast… i can’t really debug

The servo movements are Jerky…

The command to servo are in the setup

addServoMotion(&servoStates[0], 150, 60); // move slowly to 30 degrees addServoMotion(&servoStates[0], 30, 60); // then move more quickly to 150 degrees

should be a call for which servo - Which position - Which speed

Here is the code
I put also the .zip file with it

[code]//====================— I N N E R B R E E D F X —=========================
//Project; Animatronic Owl for InnerbreedFX
//Description: Control code for Jonny Poole - InnerbreedFX Animatronics
//Software version: V1.0
//Date: 18-09-2012
//Programmer/s: Eric Nantel, James Clifford
//Project Developer/s: Jonny Poole, Eric Nantel
//
//
// This version of the code runs on the DiaLFonZo-Copter Shield with ProMini
//for the Arduino Environement
//
//=============================================================================
//

#include <Servo.h>
#include <stdarg.h>

typedef struct ServoMotionStruct {
int targetAngle;
float degsPerSecond;
} ServoMotion;

#define MAX_PENDING_MOTIONS 10

typedef struct ServoStateStruct {
Servo servo;
int currentAngle;
int targetAngle;
int lastMillis;
float accum;
float speed;
// hard coded 10, could change this to whatever a
// reasonable max value would be, or just use
// pointers (can’t remember whether Arduino can
// do malloc or not, or whether there are complications
// for doing so).
ServoMotion scheduledMotions[MAX_PENDING_MOTIONS];
int currentMotion;
int lastMotion;
} ServoState;

#define SERVO_COUNT 9

ServoState servoStates[SERVO_COUNT];

#define EYE_BLINK 0
#define HEAD_ROTATE 1
#define HEAD_UPDOWN 2
#define HEAD_LEFTRIGHT 3
#define NECK_UPDOWN 4
#define NECK_LEFTRIGHT 5
#define WING_RIGHT 6
#define WING_LEFT 7
#define WINGS 8

#define EYE_BLINK_PIN 9
#define HEAD_ROTATE_PIN 5
#define HEAD_UPDOWN_PIN 4
#define HEAD_LEFTRIGHT_PIN 10
#define NECK_UPDOWN_PIN 11
#define NECK_LEFTRIGHT_PIN 8
#define WING_RIGHT_PIN 7
#define WING_LEFT_PIN 6
#define WINGS_PIN 5

int servoPin] = {
EYE_BLINK_PIN,
HEAD_ROTATE_PIN,
HEAD_UPDOWN_PIN,
HEAD_LEFTRIGHT_PIN,
NECK_UPDOWN_PIN,
NECK_LEFTRIGHT_PIN,
WING_RIGHT_PIN,
WING_LEFT_PIN,
WINGS_PIN
};

int lastMillis = 0;

void addServoMotion(void *statePtr, int angle, float degsPerSecond);
void updateServoPositions();

void p(char *fmt, … ){
char tmp[128]; // resulting string limited to 128 chars
va_list args;
va_start (args, fmt );
vsnprintf(tmp, 128, fmt, args);
va_end (args);
Serial.print(tmp);
}

int callCount = 0;

void setup() {

Serial.begin(9600); // maybe higher?

// Initialize the servos, this might be too
// simple.
for (int i = 0; i < SERVO_COUNT; i++) {        
    servoStates*.servo.attach(servoPin*);
    servoStates*.lastMotion = 0;
    servoStates*.servo.write(5);
    // May need to initialize the other ServoState
    // members here as well!
}

// for example
addServoMotion(&servoStates[0], 150, 60);   // move slowly to 30 degrees
addServoMotion(&servoStates[0], 30, 60);  // then move more quickly to 150 degrees
//addServoMotion(&servoStates[1], 30, 1);   // move slowly to 30 degrees

}

void loop() {

updateServoPositions();

}

void addServoMotion(void *statePtr, int angle, float degsPerSecond) {
ServoState *state = (ServoState *)statePtr;

state->lastMotion += 1;
if (state->lastMotion == MAX_PENDING_MOTIONS) {
    // Note: need to check to see whether we're allowed to wrap...
    state->lastMotion = 0;
}

state->scheduledMotions[state->lastMotion].targetAngle = angle;
state->scheduledMotions[state->lastMotion].degsPerSecond = degsPerSecond;

}

void updateServoPositions() {

int currentMillis = millis();

// for (int i = 0; i < SERVO_COUNT; i++) {
for (int i = 0; i < 1; i++) {
ServoState state = &servoStates;

    if (state->currentAngle != state->targetAngle) {
        int dir;
        if (state->currentAngle < state->targetAngle) {
            dir = 1;
        } 
        else {
            dir = -1;
        }
        
        Serial.print("  Start");
        Serial.print("(");
        Serial.print(currentMillis);
        Serial.print(")");
        Serial.print(" ");
        Serial.print(i);
        Serial.print(", ");
        Serial.print(state->targetAngle);
        Serial.print(" ");
        Serial.print(state->accum);
        Serial.print(" ");
        
        state->accum += (state->speed * (currentMillis - lastMillis));
        
        Serial.print("new: ");
        Serial.print(state->accum);
        Serial.print(" after ");
        Serial.print(currentMillis - lastMillis);
        Serial.print("ms ");

        Serial.print("(dps = ");
        Serial.print(state->speed);
        Serial.print(") ");
        
        if (state->accum > 1.0) {
            state->currentAngle += dir;
            
            state->servo.write(state->currentAngle);
            
            Serial.print(state->currentAngle);
            Serial.print("' ");
            
            if (state->currentAngle == state->targetAngle) {
                // We've reached our target angle, throw away any
                // unused accumulated degrees.
                state->accum = 0.0;
                break;
            } else {
                state->accum -= 1.0;
            }
        }

        Serial.print(state->accum);
        Serial.print(" ");
        Serial.println("End");

    }
    
    // unoptimized
    if (state->currentAngle == state->targetAngle) {
        if (state->currentMotion != state->lastMotion) {
            state->currentMotion += 1;
            if (state->currentMotion > MAX_PENDING_MOTIONS) {
                state->currentMotion = 0;
            }
            
            state->targetAngle = state->scheduledMotions[state->currentMotion].targetAngle;
            state->speed = state->scheduledMotions[state->currentMotion].degsPerSecond / 1000.0;
    
            p("%d: %d -> %d, %f\r\n", i, state->currentAngle, state->targetAngle, state->scheduledMotions[state->currentMotion].degsPerSecond);
        }
    }    
}

lastMillis = currentMillis;

}[/code]*****
DiaLFonZo_ArduinoServo.zip (1.97 KB)

yes its starting to look very complicated. :confused:
but its progress. :wink:

The new (i might also add “third”) eye mech has been ordered, along with the last Pullpull case and horn.
3rd October it should arrive. :smiley:

But… Where are the pictures of that so nice electronics casing… :stuck_out_tongue:

Photo Bomb…
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0667_zpsf84e2f31.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0668_zpscadc7ec2.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0673_zpsb7a626eb.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0669_zps59cf66eb.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0670_zps6352eab8.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0671_zpsd7a7bb13.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0672_zps7d6a7ff3.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0674_zps61397e97.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0675_zpsd3ca41dd.jpg
http://i531.photobucket.com/albums/dd355/innerbreed/SAM_0676_zps3428213b.jpg

Just … wow. :open_mouth:

I’v ran short on the Cable tubing so i still have the left wing to connect up but apart from that its all working correctly.

I hope to shoot a short video tomorrow. :wink:
Watching the neck move is kinda freaky! 8)

TOMORROW…??