Step 11Predator cannon
Using a modified Wii nunchuck board we can make a "head tracking" system to control an animatronic Predator cannon. This system was designed to look like the cannon mechanism in the first Predator movie.
The nunchuck board is removed from its case, the joystick is removed and the board is placed level in the top of the Predator Bio helmet. The wires are extended for the buttons so they can be used as fingertip buttons to activate the cannon and trigger the firing sequence.
To remove the circuit board from the Wii nunchuck case you'll need a tri-wing screwdriver-
http://www.play-asia.com/paOS-13-71-1e-49-en-70-1fe.html
The sound effect is handled just like the Iron Man repulsor in example 4 using the Adafruit Wave Shield. Since the Wave Shield code used can support six individual sounds you can add five other Predator sounds and activate them using fingertip switches- neat!
There is one servo that is geared 4:1 that raises the cannon arm- in the code you can see this as the servo rotating 180 degrees, thereby raising the cannon arm 45 degrees. The other two servos aim the cannon using the accelerometer inputs. There are transistors that turn on the aiming servos and laser sight when one button is pressed. If the aiming servos were always on then the cannon would rotate even when it was in the lowered position, so they need a way of being turned off when the cannon is lowered.
So push one one button and the cannon raises up, the aiming servos turn on and the laser sight turns on. Push the second button and the cannon fires- two transistors turn on the cannon LED and activate the firing sound. Three red LEDs can be used in place of the laser sight. The cannon LED can be anything from several small LEDs to a high power Luxeon LED. When using a high power Luxeon LED be sure to use a constant current driver to power it.
Servos can draw a fair bit of power so I use a TIP 120 transistor to turn on the aiming servos.
The prototype cannon mechanism was built using Delrin plastic scraps and timing belts and gears from old desktop printers and photocopiers I found in the trash. When I build the final version for the Predator costume it will probably be entirely gear driven to make it more compact and cleaner.
For Predator costuming info check out http://www.thehunterslair.com
Those individuals interested in obtaining a resin cannon casting should contact my friend Carl here- http://www.accurizedhunterparts.com/
Carl's work is absolutely brilliant- check out the photos below of the Predator backpack clay sculpt that he created for this project. That's a lot of clay! When contacting Carl please be patient as he's extremely busy and he has a large backlog of work.
Here's the code-
/*
* Example 7
* Predator Cannon
* This uses a modified Wii nunchuck as a head tracking input device to control an animatronic Predator cannon
* Adafruit Wave shield is used for sound effects
* Honus 2007, updated 2010
* Wii nunchuck reading code modified/extended from nunchuck code by Tod E. Kurt and Windmeadow Labs
* 2007 Tod E. Kurt, http://todbot.com/blog/
* The Wii Nunchuck reading code is taken from Windmeadow Labs, http://www.windmeadow.com/node/42
*/
#include
#include
Servo servo3; // creates an instance of the servo object to control a servo
int controlPin1 = 6; // Control pin for sound effects board using z button
int transistorPin1 = 13; // Control pin for LED using z button
int transistorPin2 = 12; // Control pin for laser sight using c button
int transistorPin3 = 11; // Control pin for servo 1 using c button
int transistorPin4 = 10; // Control pin for servo 2 using c button
int servoPin1 = 7; // Control pin for servo 1 using accelerometer x axis
int servoPin2 = 8; // Control pin for servo 2 using accelerometer y axis
int servoPin3 = 9; // control pin for arm servo
int pulseWidth1 = 0; // Amount to pulse the servo 1
int pulseWidth2 = 0; // Amount to pulse the servo 2
int refreshTime = 20; // the time in millisecs needed in between servo pulses
long lastPulse1;
long lastPulse2;
int minPulse = 700; // minimum servo pulse width
int loop_cnt=0;
boolean button_down = false;
unsigned long start;
void setup()
{
Serial.begin(19200);
servo3.attach(servoPin3); // attaches the servo on pin 9 to the servo object
pinMode(controlPin1, OUTPUT); // Set control pin 1 as output
pinMode(transistorPin1, OUTPUT); // Set transistor pin 1 as output
pinMode(transistorPin2, OUTPUT); // Set transistor pin 2 as output
pinMode(transistorPin3, OUTPUT); // Set transistor pin 3 as output
pinMode(transistorPin4, OUTPUT); // Set transistor pin 4 as output
pinMode(servoPin1, OUTPUT); // Set servo pin 1 as output
pinMode(servoPin2, OUTPUT); // Set servo pin 2 as output
pulseWidth1 = minPulse; // Set the servo position to the minimum
pulseWidth2 = minPulse; // Set the servo position to the minimum
nunchuck_init(); // send the initilization handshake
Serial.print("NunchuckServo ready\n");
}
void loop()
{
checkNunchuck1();
updateServo1(); // update servo 1 position
checkNunchuck2();
updateServo2(); // update servo 2 position
if( nunchuck_cbutton() ) {
digitalWrite(transistorPin2, HIGH); // turn on transistor pin 2 if c button is pressed
digitalWrite(transistorPin3, HIGH); // turn on transistor pin 3 if c button is pressed
digitalWrite(transistorPin4, HIGH); // turn on transistor pin 4 if c button is pressed
servo3.write(180);
}
else {
digitalWrite(transistorPin2, LOW);
digitalWrite(transistorPin3, LOW);
digitalWrite(transistorPin4, LOW);
servo3.write(0);
}
if ( nunchuck_zbutton() )
{
if (!button_down) // if button was just pressed do this
{
digitalWrite(controlPin1, HIGH);
button_down = true;
start = millis();
}
else if (millis() - start > 1200) // if timer has elapsed do this
{
digitalWrite(transistorPin1, HIGH);
}
}
else // if button is up do this
{
button_down = false;
digitalWrite(controlPin1, LOW);
digitalWrite(transistorPin1, LOW);
}
delay(1); // this is here to give a known time per loop
}
void checkNunchuck1()
{
if( loop_cnt > 100 ) { // loop()s is every 1msec, this is every 100msec
nunchuck_get_data();
nunchuck_print_data();
float tilt = nunchuck_accelx(); // x-axis, in this case ranges from ~70 - ~185
tilt = (tilt - 70) * 1.5; // convert to angle in degrees, roughly
pulseWidth1 = (tilt * 9) + minPulse; // convert angle to microseconds
loop_cnt = 0; // reset for
}
loop_cnt++;
}
// called every loop().
// uses global variables servoPin, pulsewidth, lastPulse, & refreshTime
void updateServo1()
{
// pulse the servo again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse1 >= refreshTime) {
digitalWrite(servoPin1, HIGH); // Turn the servo on
delayMicroseconds(pulseWidth1); // Length of the pulse sets the servo position
digitalWrite(servoPin1, LOW); // Turn the servo off
lastPulse1 = millis(); // save the time of the last pulse
}
}
void checkNunchuck2()
{
if( loop_cnt > 100 ) { // loop()s is every 1msec, this is every 100msec
nunchuck_get_data();
nunchuck_print_data();
float tilt = nunchuck_accely(); // y-axis, in this case ranges from ~70 - ~185
tilt = (tilt - 70) * 1.5; // convert to angle in degrees, roughly
pulseWidth2 = (tilt * 9) + minPulse; // convert angle to microseconds
loop_cnt = 0; // reset for
}
loop_cnt++;
}
// called every loop().
// uses global variables servoPin, pulsewidth, lastPulse, & refreshTime
void updateServo2()
{
// pulse the servo again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse2 >= refreshTime) {
digitalWrite(servoPin2, HIGH); // Turn the servo on
delayMicroseconds(pulseWidth2); // Length of the pulse sets the servo position
digitalWrite(servoPin2, LOW); // Turn the servo off
lastPulse2 = millis(); // save the time of the last pulse
}
}
//
// Nunchuck functions
//
static uint8_t nunchuck_buf[6]; // array to store nunchuck data,
// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
void nunchuck_init()
{
Wire.begin(); // join i2c bus as master
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.send(0x40); // sends memory address
Wire.send(0x00); // sends sent a zero.
Wire.endTransmission(); // stop transmitting
}
// Send a request for data to the nunchuck
// was "send_zero()"
void nunchuck_send_request()
{
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.send(0x00); // sends one byte
Wire.endTransmission(); // stop transmitting
}
// Receive data back from the nunchuck,
// returns 1 on successful read. returns 0 on failure
int nunchuck_get_data()
{
int cnt=0;
Wire.requestFrom (0x52, 6); // request data from nunchuck
while (Wire.available ()) {
// receive byte as an integer
nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive());
cnt++;
}
nunchuck_send_request(); // send request for next data payload
// If we recieved the 6 bytes, then go print them
if (cnt >= 5) {
return 1; // success
}
return 0; //failure
}
// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits. That is why I
// multiply them by 2 * 2
void nunchuck_print_data()
{
static int i=0;
int joy_x_axis = nunchuck_buf[0];
int joy_y_axis = nunchuck_buf[1];
int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;
int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;
int z_button = 0;
int c_button = 0;
// byte nunchuck_buf[5] contains bits for z and c buttons
// it also contains the least significant bits for the accelerometer data
// so we have to check each bit of byte outbuf[5]
if ((nunchuck_buf[5] >> 0) & 1)
z_button = 1;
if ((nunchuck_buf[5] >> 1) & 1)
c_button = 1;
if ((nunchuck_buf[5] >> 2) & 1)
accel_x_axis += 2;
if ((nunchuck_buf[5] >> 3) & 1)
accel_x_axis += 1;
if ((nunchuck_buf[5] >> 4) & 1)
accel_y_axis += 2;
if ((nunchuck_buf[5] >> 5) & 1)
accel_y_axis += 1;
if ((nunchuck_buf[5] >> 6) & 1)
accel_z_axis += 2;
if ((nunchuck_buf[5] >> 7) & 1)
accel_z_axis += 1;
Serial.print(i,DEC);
Serial.print("\t");
Serial.print("joy:");
Serial.print(joy_x_axis,DEC);
Serial.print(",");
Serial.print(joy_y_axis, DEC);
Serial.print(" \t");
Serial.print("acc:");
Serial.print(accel_x_axis, DEC);
Serial.print(",");
Serial.print(accel_y_axis, DEC);
Serial.print(",");
Serial.print(accel_z_axis, DEC);
Serial.print("\t");
Serial.print("but:");
Serial.print(z_button, DEC);
Serial.print(",");
Serial.print(c_button, DEC);
Serial.print("\r\n"); // newline
i++;
}
// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
return x;
}
// returns zbutton state: 1=pressed, 0=notpressed
int nunchuck_zbutton()
{
return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1; // voodoo
}
// returns zbutton state: 1=pressed, 0=notpressed
int nunchuck_cbutton()
{
return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1; // voodoo
}
// returns value of x-axis joystick
int nunchuck_joyx()
{
return nunchuck_buf[0];
}
// returns value of y-axis joystick
int nunchuck_joyy()
{
return nunchuck_buf[1];
}
// returns value of x-axis accelerometer
int nunchuck_accelx()
{
return nunchuck_buf[2]; // FIXME: this leaves out 2-bits of the data
}
// returns value of y-axis accelerometer
int nunchuck_accely()
{
return nunchuck_buf[3]; // FIXME: this leaves out 2-bits of the data
}
// returns value of z-axis accelerometer
int nunchuck_accelz()
{
return nunchuck_buf[4]; // FIXME: this leaves out 2-bits of the data
}
CannonSound.WAV199 KB| « Previous Step | Download PDFView All Steps | Next Step » |
10
comments
|
Add Comment
|
Honus (author)
says:
Honus (author)
says:
Honus (author)
says:
Honus (author)
says:
Honus (author)
says:
![]() |
Add Comment
|









































































