wii nunchuck 4 servo control

Discussion in 'Predator Props' started by ksj, Oct 25, 2017.

  1. ksj

    ksj Unblooded

    Does anyone have any good code to control 4 servos with a wii nunchuck?

    I can find code all day long to control 2 servos with just an arduino and a wii nunchuck.

    Honus code base seems to only work with his specific setup ( finally have all the parts in to build it with his board layouts. I am hoping to have better luck with his code with that setup.
     
  2. ksj

    ksj Unblooded

    OK, I figured out how Honus did it 2 servos controlled with the joystick and 2 more with the yaw/pitch functionality. Can't believe I missed that little tidbit after looking through his code numerous times.
     
  3. ksj

    ksj Unblooded

    Will test to see if I can control 2 servos on the same channel PWM pin to see if I can run dual plasma casters.
     
    Shogun likes this.
  4. Shogun

    Shogun Blooded

    Just OMG ksj ... I really cannot help you mate :confused: these animatronics programming stuff gets me confused soooooo much
     
  5. ksj

    ksj Unblooded

    Programming is like any language, there are rules, some have to be followed absolutely others, not so much.

    One guy figured out that language can be equated to math and when you follow the formula you can write legal documents that are well written and very much legally binding.

    Programming is not too terribly different. Instead of conveying a message you are conveying a command that has to be received in a certain manner.

    As with all things you learn and get better the more you practice and with the more mis steps that you have. A mistake is only a failure if you learn nothing from the experience.
     
    Shogun likes this.
  6. ksj

    ksj Unblooded

  7. ksj

    ksj Unblooded

  8. ksj

    ksj Unblooded

    Take it back I have some bugs I am working through. I think I found a fix though...
     
  9. ksj

    ksj Unblooded

    OK, I have it working and I am calling things done at this point. I couldn't get fading to work properly, but I will live with the results at this point:

    Code:
    /*
     * Example 6
     * Nunchuck control for four servos and two button inputs
     * Honus 2007
     * This allows the use of a Wii nunchuck as an input device and is modified/extended from the original 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
     * ArduinoNunchuk.cpp - Improved Wii Nunchuk library for Arduino
     *
     * Copyright 2011-2013 Gabriel Bianconi, http://www.gabrielbianconi.com/
     *
     * Project URL: http://www.gabrielbianconi.com/projects/arduinonunchuk/
     *
     * Based on the following resources:
     *   http://www.windmeadow.com/node/42
     *   http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/
     *   http://wiibrew.org/wiki/Wiimote/Extension_Controllers
     *   http://www.gammon.com.au/blink
     *
     */
    // www.facebook.com/ArduinoCenter
    // https://blog.underc0de.org/arduino-wii-nunchuck-servo-motores/
    // Original Code base credited to Undercode
    // Code adapted from Sean Maio Crybabyfx setup
    //https://github.com/outcry27/crybabyFX
    // Updated by knoxvilles_joker 2017
    // http://facebook.com/knoxvillesjoker
    // more instructions documented at
    // http://alienslegacy.com
     
    
    #include <Wire.h>
    #include "ArduinoNunchuk.h"
    #include <Servo.h>
    
    //Creates the objects to control the servos
    ArduinoNunchuk nunchuk = ArduinoNunchuk();
    
    const int ledPin1 = 13;       // Control pin for LED 1
    const byte ledPin2 = 12;       // Control pin for LED 2
    const unsigned long ledPin2interval = 500;
    unsigned long ledPin2timer;
    const int servoPin1 = 9;      // Control pin for servo motor
    const int servoPin2 = 11;      // Control pin for servo motor
    const int servoPin3 = 10;      // Control pin for servo motor
    const int servoPin4 = 6;      // Control pin for servo motor
    // sound pins for firing sounds
    const int firePin1 = 4;
    const int firePin2 = 5;
    const int firePin3 = 16;
    const int startSoundPin = 17;
     int pulseWidth1 = 0;    // Amount to pulse the servo 1
     int pulseWidth2 = 0;    // Amount to pulse the servo 2
     int pulseWidth3 = 0;    // Amount to pulse the servo 3
     int pulseWidth4 = 0;    // Amount to pulse the servo 4
     int refreshTime = 20;  // the time in millisecs needed in between pulses
    //Initializes the variables
    int xjoystick;
    int yjoystick;
    int xtilt;
    int ytilt;
    long lastPulse1;
    long lastPulse2;
    long lastPulse3;
    long lastPulse4;
    int minPulse = 700;   // minimum pulse width
    int loop_cnt=0;
    
    void setup() {
      // put your setup code here, to run once:
    // sound pins are setup before initialization of serial interfaces.
      // initialize the audio pins
      pinMode(startSoundPin, OUTPUT);
      pinMode(firePin1, OUTPUT);
      pinMode(firePin2, OUTPUT);
      pinMode(firePin3, OUTPUT);
      // set up the audio trigger pins to give a path to GND when set to OUTPUT
      analogWrite(startSoundPin, LOW);
      analogWrite(firePin1, LOW);
      analogWrite(firePin2, LOW);
      analogWrite(firePin3, LOW);
    
      pinMode(servoPin1, OUTPUT);  // Set servo pin as an output pin
      pinMode(servoPin2, OUTPUT);  // Set servo pin as an output pin
      pinMode(servoPin3, OUTPUT);  // Set servo pin as an output pin
      pinMode(servoPin4, OUTPUT);  // Set servo pin as an output pin
     
      pulseWidth1 = minPulse;      // Set the motor position to the minimum
      pulseWidth2 = minPulse;      // Set the motor position to the minimum
      pulseWidth3 = minPulse;      // Set the motor position to the minimum
      pulseWidth4 = minPulse;      // Set the motor position to the minimum
      pinMode(ledPin1, OUTPUT);  // sets the LED pin as output
      pinMode(ledPin2, OUTPUT);
      ledPin2timer = millis ();
      digitalWrite(ledPin1, LOW); // sets the LED pin LOW (turns it off)
      digitalWrite(ledPin2, LOW);
    
    Serial.begin(19200);
     Serial.print("loading sound card init\n");
      delay(1000); 
      Serial.print("card initialized");
       //give the audio board time to power up.
      // Otherwise bootup sound will be called before audio
      // board is ready.
      // this plays an initialization sound.
      digitalWrite(startSoundPin, HIGH);
      //Serial.print("#00\n");
      delay(300);
      digitalWrite(startSoundPin, LOW);
      delay(300);
        //Initializes nunchuck and servos
      nunchuk.init();
    
    }
    
    void ledPin2toggle ()
      {
       if (digitalRead (ledPin2) == LOW)
          digitalWrite (ledPin2, HIGH);
       else
          digitalWrite (ledPin2, LOW);
    
      // remember when we toggled it
      ledPin2timer = millis (); 
      }  // end of toggleGreenLED
    
    void loop() {
      // put your main code here, to run repeatedly:
      checkNunchuck1();
      updateServo1();   // update servo 1 position
      checkNunchuck2();
      updateServo2();   // update servo 2 position
      checkNunchuck3();
      updateServo3();   // update servo 3 position
      checkNunchuck4();
      updateServo4();   // update servo 4 position
    
       if(nunchuk.zButton == 1)  {    // light the LED if z button is pressed
        digitalWrite(ledPin1, HIGH);
        digitalWrite(firePin1, HIGH);
      //  Serial.print("#3\n");
        //  3 = 1
        delay(300);
        digitalWrite(ledPin1,LOW);
        digitalWrite(firePin1, LOW);
        delay(300);
       }
    
        if (nunchuk.cButton == 1)  {
          if ( (millis () - ledPin2timer) >= ledPin2interval) {
         ledPin2toggle ();
          }
        digitalWrite(firePin2, HIGH);
    //  Serial.print("#4\n");
    //  4 = 4
    //    delay(300);
        
        digitalWrite(firePin2, LOW);
    //    delay(300);
       }
    
    
    
        delay(1);        // this is here to give a known time per loop
    
     //Guardamos los valores que nos manda el Nunchuk en las variables
      xjoystick = nunchuk.analogX;
      xjoystick = constrain(xjoystick, 26, 226);
      xjoystick = map(xjoystick, 26, 226, 0, 180);
     
      yjoystick = nunchuk.analogY;
      yjoystick = constrain(yjoystick, 26, 226);
      yjoystick = map(yjoystick, 26, 226, 180, 0);
     
      xtilt = nunchuk.accelX;
      xtilt = constrain(xtilt, 320, 720);
      xtilt = map(xtilt, 320, 720, 180, 0);
     
      ytilt = nunchuk.accelY;
      ytilt = constrain(ytilt, 320, 720);
      ytilt = map(ytilt, 320, 720, 0, 180);
    // This prints the serial status of the nunchuck.
      Serial.print ("Joystick X: ");
      Serial.print (xjoystick, DEC);
      Serial.print ("\t");
     
      Serial.print ("Joystick Y: ");
      Serial.print (yjoystick, DEC);
      Serial.print ("\t");
     
      Serial.print ("X: ");
      Serial.print (xtilt, DEC);
      Serial.print ("\t");
     
      Serial.print ("Y: ");
      Serial.print (ytilt, DEC);
      Serial.print ("\t");
     
      nunchuk.update();
     
      if (nunchuk.cButton == 1) {
        Serial.print("--C--  ");
      }
     
      if (nunchuk.zButton == 1) {
        Serial.print("--Z--  ");
      }
     
      if (nunchuk.cButton == 1 && nunchuk.zButton == 1) {
        Serial.print("--Z-C--");
      }
    
    
     
      Serial.print ("\r\n");
    
    
    }
    
    void checkNunchuck1()
    {
      if( loop_cnt > 100 ) {  // loop()s is every 1msec, this is every 100msec
      
    
    
        float tilt = xjoystick;    // 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
    
    //   servoPin1.write(xjoystick);
      
        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 motor on
        delayMicroseconds(pulseWidth1);   // Length of the pulse sets the motor position
        analogWrite(servoPin1, LOW);    // Turn the motor 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 = yjoystick;    // 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 motor on
        delayMicroseconds(pulseWidth2);   // Length of the pulse sets the motor position
        analogWrite(servoPin2, LOW);    // Turn the motor off
        lastPulse2 = millis();            // save the time of the last pulse
      }
    }
    
    void checkNunchuck3()
    {
      if( loop_cnt > 100 ) {  // loop()s is every 1msec, this is every 100msec
      
    //    nunchuck_get_data();
    //    nunchuck_print_data();
    
        float tilt = xtilt;    // x-axis, in this case ranges from ~70 - ~185
        tilt = (tilt - 70) * 1.5;        // convert to angle in degrees, roughly
        pulseWidth3 = (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 updateServo3()
    {
      // pulse the servo again if rhe refresh time (20 ms) have passed:
      if (millis() - lastPulse3 >= refreshTime) {
        digitalWrite(servoPin3, HIGH);   // Turn the motor on
        delayMicroseconds(pulseWidth3);   // Length of the pulse sets the motor position
        analogWrite(servoPin3, LOW);    // Turn the motor off
        lastPulse3 = millis();            // save the time of the last pulse
      }
    }
    
    void checkNunchuck4()
    {
      if( loop_cnt > 100 ) {  // loop()s is every 1msec, this is every 100msec
      
    //    nunchuck_get_data();
    //    nunchuck_print_data();
    
        float tilt = ytilt;    // y-axis, in this case ranges from ~70 - ~185
        tilt = (tilt - 70) * 1.5;        // convert to angle in degrees, roughly
        pulseWidth4 = (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 updateServo4()
    {
      // pulse the servo again if rhe refresh time (20 ms) have passed:
      if (millis() - lastPulse4 >= refreshTime) {
        digitalWrite(servoPin4, HIGH);   // Turn the motor on
        delayMicroseconds(pulseWidth4);   // Length of the pulse sets the motor position
        analogWrite(servoPin4, LOW);    // Turn the motor off
        lastPulse4 = millis();            // save the time of the last pulse
      }
    }
    
     
  10. ksj

    ksj Unblooded

    I will add more thorough documentation on the code itself soon. I have done what I could to ensure I included all sites where I pulled information from.

    This works with off the shelf components and is something anyone can build if they can use a soldering iron. estimated cost in parts is under a 100.

    I will focus on building the canon backpack. I would also note that this would be easy to do dual canons with. I just have not figured out a cheap and easy way to split canon rotation on both ends of the canon arm. I am not happy that I can not get the arm any smaller than I will have it now.

    My builds are more for functionality and easy field maintenance with low investment cost. I will do my best to get something darn close to movie looks.

    I was almost thinking lego had some sort of setup I could use.

    Any servo gear sets I see are very expensive. I would also note that this setup would work well for a robotic arm manipulator as well.

    If anyone has Karl's 3-d arm files please let me know. that arm would allow me to condense the space to something approximating movie scale.
     
  11. ksj

    ksj Unblooded

    in action:

     
  12. ksj

    ksj Unblooded

    I think I will do a wooden mock up until I can get the backpack hashed out. I will need that at least for a table prototype...

    I am trying to figure out how I can do a two DOF servo setup. That setup would allow hiding two servos in the bottom at the base.
     

Share This Page