Menu

headtracker with wiimotePlus and T9x transmitter

Features
Anonymous
2013-04-13
2013-04-16
  • Anonymous

    Anonymous - 2013-04-13

    hi,
    thanks for your work about this RC lib. i am trying to control pan-tilt cam on my rc rover with wiiMplus (trying to make a headtracker basically). i am reading wiiMPlus and can control 2 servos for pan-tilt. now i am trying to integrate my T9X transmitter and send mixed PPMout signals to the trainer port of my tx using your RC Lib. here is my code:

    #include <PPMOut.h>
    #include <Timer1.h>
    #include <Streaming.h>
    #include <Wire.h>
    //#include <Servo.h>
    
    //Servo yawServo;
    //Servo pitchServo;
    #define CHANNELS 2
    
    //uint8_t  g_pins[CHANNELS] = {A0, A1, A2, A3}; // Input pins
    uint16_t g_input[CHANNELS];                   // Input buffer in microseconds
    uint8_t  g_work[PPMOUT_WORK_SIZE(CHANNELS)];  // we need to have a work buffer for the PPMOut class
    rc::PPMOut g_PPMOut(CHANNELS, g_input, g_work, CHANNELS);
    
    int yawServoVal;
    int pitchServoVal;
    
    #define steps_per_deg_slow 20
    #define steps_per_deg_fast 4
    
    byte data[6];       //six data bytes
    int yaw, pitch, roll;  //three axes
    int yaw0, pitch0, roll0;  //calibration zeroes
    int time, last_time;
    float delta_t;
    int last_yaw[3], last_pitch[3], last_roll[3];
    float yaw_deg, pitch_deg, roll_deg;
    int yaw_deg2, pitch_deg2, roll_deg2;
    int startTag=0xDEAD;
    int accel_x_axis, accel_y_axis, accel_z_axis;
    
    void wmpOn(){
      Wire.beginTransmission(0x53);    //WM+ starts out deactivated at address 0x53
      Wire.write(0xfe);          //send 0x04 to address 0xFE to activate WM+
      Wire.write(0x04);
      Wire.endTransmission();       //WM+ jumps to address 0x52 and is now active
    }
    
    void wmpSendZero(){
      Wire.beginTransmission(0x52);    //now at address 0x52
      Wire.write(0x00);          //send zero to signal we want info
      Wire.endTransmission();
    }
    
    void calibrateZeroes(){
      for (int i=0;i<10;i++){
        wmpSendZero();
        Wire.requestFrom(0x52,6);
        for (int i=0;i<6;i++){
        data[i]=Wire.read();
        }
        yaw0+=(((data[3]>>2)<<8)+data[0])/10;     //average 10 readings for each zero
        pitch0+=(((data[4]>>2)<<8)+data[1])/10;
        roll0+=(((data[5]>>2)<<8)+data[2])/10;
      }
      Serial.print("Yaw0:");
      Serial.print(yaw0);
      Serial.print("  Pitch0:");
      Serial.print(pitch0);
      Serial.print("  Roll0:");
      Serial.println(roll0);
    }
    
    void receiveData(){
      wmpSendZero();             //send zero before each request (same as nunchuck)
      Wire.requestFrom(0x52,6);   //request the six bytes from the WM+
      for (int i=0;i<6;i++){
        data[i]=Wire.read();
      }
      if(bitRead(data[3], 1)==1) yaw=(((data[3]>>2)<<8)+data[0]-yaw0)/steps_per_deg_slow;     //see http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus
      else yaw=(((data[3]>>2)<<8)+data[0]-yaw0)/steps_per_deg_fast;
      if(bitRead(data[3], 0)==1) pitch=(((data[4]>>2)<<8)+data[1]-pitch0)/steps_per_deg_slow;    //for info on what each byte represents
      else pitch=(((data[4]>>2)<<8)+data[1]-pitch0)/steps_per_deg_fast;
      if(bitRead(data[4], 1)==1) roll=(((data[5]>>2)<<8)+data[2]-roll0)/steps_per_deg_slow;
      else roll=(((data[5]>>2)<<8)+data[2]-roll0)/steps_per_deg_fast;
    }
    
    float trapIntegrate(int y2, int y1, float deltax){
      float area=0;
      area=(y2+y1)/2*deltax/1000;
      return area;
    }
    
    float rk4Integrate(int y4, int y3, int y2, int y1, float deltax){
      float area=0;
      area=((y4+2*y3+2*y2+y1)/6)*deltax/1000;
      return area;
    }
    
    void setup()
      {
      Serial.begin(57600);
      Serial.println("WM+ Tuning");
      Wire.begin();
      wmpOn();              //turn WM+ on
      calibrateZeroes();          //calibrate zeroes
      delay(1000);
    
      //yawServo.attach(8);
      //pitchServo.attach(9);
      pinMode(4, INPUT);
    
            // Initialize timer1, this is required for all features that use Timer1
        // (PPMIn/PPMOut/ServoIn/ServoOut) 
            rc::Timer1::init();
            // fill input buffer, convert raw values to microseconds
            g_input[1] = map(yawServoVal, 0, 179, 1000, 2000);
            g_input[2] = map(pitchServoVal, 0, 179, 1000, 2000);
    
            // initialize PPMOut with some settings
        g_PPMOut.setPulseLength(448);   // pulse length in microseconds
        g_PPMOut.setPauseLength(10448); // length of pause after last channel in microseconds
        // note: this is also called the end of frame, or start of frame, and is usually around 10ms
    
        // start PPMOut, use pin 9 (pins 9 and 10 are preferred)
        g_PPMOut.start(9);
      }
    
    void loop(){
      receiveData();            //receive data and calculate yaw pitch and roll
      time=millis();
      delta_t=(time-last_time);
    
      /* Runge-kutta 4th Order Integration */
      yaw_deg+=rk4Integrate(yaw, last_yaw[0], last_yaw[1], last_yaw[2], delta_t);
      pitch_deg+=rk4Integrate(pitch, last_pitch[0], last_pitch[1], last_pitch[2], delta_t);
      roll_deg+=rk4Integrate(roll, last_roll[0], last_roll[1], last_roll[2], delta_t);
      last_yaw[2]=last_yaw[1];
      last_pitch[2]=last_pitch[1];
      last_roll[2]=last_roll[1];
      last_yaw[1]=last_yaw[0];
      last_pitch[1]=last_pitch[0];
      last_roll[1]=last_roll[0];
      last_yaw[0]=yaw;
      last_pitch[0]=pitch;
      last_roll[0]=roll;
      last_time=time;
      /* Runge-kutta 4th Order Integration */
    
      if (digitalRead(4) == 1)
        {
        last_yaw[2]=0;
        last_pitch[2]=0;
        last_roll[2]=0;
        last_yaw[1]=0;
        last_pitch[1]=0;
        last_roll[1]=0;
        last_yaw[0]=0;
        last_pitch[0]=0;
        last_roll[0]=0;
        yaw = 0;
        pitch = 0;
        roll = 0;
        yaw_deg = 0;
        pitch_deg = 0;
        roll_deg = 0;
        }
    
      yawServoVal = map(yaw_deg, -90, 90, 0, 179);
      if (yawServoVal < 0){yawServoVal = 0;};
      if (yawServoVal > 179){yawServoVal = 179;};
      //yawServo.write(yawServoVal);
      //delay(10);
    
      pitchServoVal = map(roll_deg, -90, 90, 0, 179);
      if (pitchServoVal < 0){pitchServoVal = 0;};
      if (pitchServoVal > 179){pitchServoVal = 179;};
      //pitchServo.write(pitchServoVal);
      //delay(10);
      g_input[1] = map(yawServoVal, 0, 179, 1000, 2000);
      g_input[2] = map(pitchServoVal, 0, 179, 1000, 2000);
    
      g_PPMOut.update();   // tell PPMOut there are new values available in the input buffer
    
      Serial.print("Yaw:");
      Serial.print(yawServoVal);
      Serial.print("  Pitch:");
      Serial.print(pitchServoVal);
      Serial.print("  Roll:");
      Serial.println(roll_deg);
      delay(10);
    
    }
    

    i am not a master on neither programming nor electronics, just an experienced hobbyist. i couldnt get the system working. on serial monitor i can see good pan-tilt angles but cant send ppm through tx. is there a way to see whether the code is creating valid ppm data? or is there something wrong with my code... this old hobbyist is awaiting help... :)

    Dincer

     

    Last edit: dvdouden 2013-04-15
    • dvdouden

      dvdouden - 2013-04-15

      Thanks for your interest in ArduinoRCLib! I can see at least one issue in your code:

      g_input[1] = map(yawServoVal, 0, 179, 1000, 2000);
      g_input[2] = map(pitchServoVal, 0, 179, 1000, 2000);
      

      should have been

      g_input[0] = map(yawServoVal, 0, 179, 1000, 2000);
      g_input[1] = map(pitchServoVal, 0, 179, 1000, 2000);
      

      Right now you're writing out of bounds (and probably directly into the work buffer of PPMOut.
      There's also still a bug in PPMOut which needs fixing. I haven't had time to release a patch yet, but it's easy to fix by hand.
      Open PPMOut.h (it's in the ArduinoRCLib directory) and find the line which says

      #define PPMOUT_WORK_SIZE(channels) ((channels) + (((channels) + 1) * 4))
      

      replace it with

      #define PPMOUT_WORK_SIZE(channels) (((channels) + ((channels) + 1) * 2) * sizeof(uint16_t))
      

      Then try again and see if it works :)

      Good luck!

      PS.

      By initializing timer1 like this:

      rc::Timer1::init(true);
      

      You can slow down the PPM output by a factor 256. If you then attach an LED (with the right resistor) to pin 9 you should be able to actually see the PPM signal. Just don't forget to revert the timer1 init when you're done.

       

      Last edit: dvdouden 2013-04-15
  • Anonymous

    Anonymous - 2013-04-15

    many thks for your assistance... this lib is really easy to use releiving us from burdens of many libes of code... i will make the changes you have pointed and try again... thks also for the tip you have given about monitoring the ppm out. it will be helpful because i dont have an osciloscope. i was just wondering about the timing of setPulseLenght and setPauseLenght for my particular tx which is Turnigy9x which is said to have a 22us gap btw ppm pulses... thks again and i will post results here... hoping to be helpful for others...
    Dincer

     
    • dvdouden

      dvdouden - 2013-04-15

      You're welcome!

      My experience with PPM is that most transmitters/receivers aren't particularly picky about pulse and pause lengths. It's the time between the start of two pulses that actually matters, not the length of the pulse. See also: https://sourceforge.net/p/arduinorclib/wiki/PPM%20Signal/

      I'm not familiar with the Turnigy 9X though...

       
  • Anonymous

    Anonymous - 2013-04-15

    changed the g_input() lines as you said to 0,1 and changed the #define line in ppmout.h but still no luck... :( cant utilize the ppmout to my tx trainer port. i am using 2 aux channels on my tx for pan-tilt servos, i can move them with two knobs on my tx at trainer mode. but cant move them with ppm which i send from trainer port... serial monitor shows perfect control with wiimplus but cant pass to tx... :(

     
  • Anonymous

    Anonymous - 2013-04-15

    i will now try to monitor pin9 for ppmout using the led trick you have mentioned but i dont think there is a bad connection. i am frustrated with this project... :( maybe i should revert to a dedicated imu like, gy-85 9dof and a arduino nano328...
    dincer

     
    • dvdouden

      dvdouden - 2013-04-15

      One possible reason could be that the transmitter expects at least 4 or 6 channels instead of two. You could try increasing CHANNELS and initializing all channels to 1500 in the setup function.

       
  • Anonymous

    Anonymous - 2013-04-15

    i dont think that can help.. i am customizing trainer input and restricting to 2 channells i want in the trainer menu of my tx. i will try your point anyway.. 'initializing all channels to 1500 in the setup function.' what you mean by that? sorry i didnt understand, do you mean making values in g-input() statements 1500?
    thks for your help and patience and understanding this 56yr old hobbyist... :)
    dincer

     
    • dvdouden

      dvdouden - 2013-04-15

      It's just as you think. Set CHANNELS to 6 and add the following to the setup function:

      for (uint8_t i = 0; i < CHANNELS; ++i)
      {
          if (i == 2)
              g_input[i] = 2000; // throttle channel
          else
              g_input[i] = 1500;
      }
      

      and make sure you disconnect any motor you have on channel 3, just to be safe ;)

      The TX is usually expecting a full 4, 6 or 9 channel signal on the trainer port. Its firmware will filter out any channels you've disabled, but it'll still expect the other channels as input. At least that's how it works on a Futaba radio.

      And no problem, glad to be of help :)

       

      Last edit: dvdouden 2013-04-15
  • Anonymous

    Anonymous - 2013-04-15

    thank you i will try that... but T9X is a 9ch radio, indeed 8 ch on ppm. then i must set CHANNELS to 8 and set them 1500 except throttle ch. which will be 2000... but still dont understand why we are setting all channels to 1500? where will be our g_input servoVAL values?

     
    • dvdouden

      dvdouden - 2013-04-15

      Because 1500 (microseconds, or 1.5 milliseconds) is the center value for a channel (servo center). We need to set them because by default it will be initialized to 0, and 0 microseconds is not a valid channel value.

      For Futaba (and a lot of other brands) the channels are mapped like this:
      CH1 (g_input[0]) = aileron
      CH2 (g_input[1]) = elevator
      CH3 (g_input[2]) = throttle
      CH4 (g_input[3]) = rudder
      CH5 (g_input[4]) = gyro/gear
      CH6 (g_input[5]) = pitch/flaps
      CH7 (g_input[6]) = AUX1
      CH8 (g_input[7]) = AUX2
      CH9 (g_input[8]) = AUX3
      I've just looked it up in a manual for the Turnigy 9X, and it seems to use the same channel mapping.

      g_input contains the values for each channel, and PPMOut uses those values to generate a PPM signal containing those values. So by setting CHANNELS to 8, it will generate an 8 channel PPM signal using the values it finds in g_input. Of course you will need to specify values that make sense, that's why we set all channels to 1500. Throttle is set to 2000 since the throttle channel is usually inverted, so that means 0 throttle (1000 would be full throttle).

      In the loop function you overwrite the values for the channels you want to use (in this case we've mapped yaw to channel 1 (g_input[0]) and pitch to channel 2 (g_input[1]), if you want to put them on AUX 1 and 2 you'll have to use g_input[6] and g_input[7]. After you've set the channel values you can tell g_PPMOut that new values are available in g_input by calling update, this will cause PPMOut to read all the channel values and start generating a PPM signal from those values.

       
  • Anonymous

    Anonymous - 2013-04-15

    No way... :( it didnt work that way either... this is the last version of the code after i made changes for a complete 8ch ppmout build up:

    #include <PPMOut.h>
    #include <Timer1.h>
    #include <Streaming.h>
    #include <Wire.h>
    //#include <Servo.h>
    
    //Servo yawServo;
    //Servo pitchServo;
    #define CHANNELS 8
    
    //uint8_t  g_pins[CHANNELS] = {A0, A1, A2, A3}; // Input pins
    uint16_t g_input[CHANNELS];                   // Input buffer in microseconds
    uint8_t  g_work[PPMOUT_WORK_SIZE(CHANNELS)];  // we need to have a work buffer for the PPMOut class
    rc::PPMOut g_PPMOut(CHANNELS, g_input, g_work, CHANNELS);
    
    int yawServoVal;
    int pitchServoVal;
    
    #define steps_per_deg_slow 20
    #define steps_per_deg_fast 4
    
    byte data[6];       //six data bytes
    int yaw, pitch, roll;  //three axes
    int yaw0, pitch0, roll0;  //calibration zeroes
    int time, last_time;
    float delta_t;
    int last_yaw[3], last_pitch[3], last_roll[3];
    float yaw_deg, pitch_deg, roll_deg;
    int yaw_deg2, pitch_deg2, roll_deg2;
    int startTag=0xDEAD;
    int accel_x_axis, accel_y_axis, accel_z_axis;
    
    void wmpOn(){
      Wire.beginTransmission(0x53);    //WM+ starts out deactivated at address 0x53
      Wire.write(0xfe);          //send 0x04 to address 0xFE to activate WM+
      Wire.write(0x04);
      Wire.endTransmission();       //WM+ jumps to address 0x52 and is now active
    }
    
    void wmpSendZero(){
      Wire.beginTransmission(0x52);    //now at address 0x52
      Wire.write(0x00);          //send zero to signal we want info
      Wire.endTransmission();
    }
    
    void calibrateZeroes(){
      for (int i=0;i<10;i++){
        wmpSendZero();
        Wire.requestFrom(0x52,6);
        for (int i=0;i<6;i++){
        data[i]=Wire.read();
        }
        yaw0+=(((data[3]>>2)<<8)+data[0])/10;     //average 10 readings for each zero
        pitch0+=(((data[4]>>2)<<8)+data[1])/10;
        roll0+=(((data[5]>>2)<<8)+data[2])/10;
      }
      Serial.print("Yaw0:");
      Serial.print(yaw0);
      Serial.print("  Pitch0:");
      Serial.print(pitch0);
      Serial.print("  Roll0:");
      Serial.println(roll0);
    }
    
    void receiveData(){
      wmpSendZero();             //send zero before each request (same as nunchuck)
      Wire.requestFrom(0x52,6);   //request the six bytes from the WM+
      for (int i=0;i<6;i++){
        data[i]=Wire.read();
      }
      if(bitRead(data[3], 1)==1) yaw=(((data[3]>>2)<<8)+data[0]-yaw0)/steps_per_deg_slow;     //see http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus
      else yaw=(((data[3]>>2)<<8)+data[0]-yaw0)/steps_per_deg_fast;
      if(bitRead(data[3], 0)==1) pitch=(((data[4]>>2)<<8)+data[1]-pitch0)/steps_per_deg_slow;    //for info on what each byte represents
      else pitch=(((data[4]>>2)<<8)+data[1]-pitch0)/steps_per_deg_fast;
      if(bitRead(data[4], 1)==1) roll=(((data[5]>>2)<<8)+data[2]-roll0)/steps_per_deg_slow;
      else roll=(((data[5]>>2)<<8)+data[2]-roll0)/steps_per_deg_fast;
    }
    
    float trapIntegrate(int y2, int y1, float deltax){
      float area=0;
      area=(y2+y1)/2*deltax/1000;
      return area;
    }
    
    float rk4Integrate(int y4, int y3, int y2, int y1, float deltax){
      float area=0;
      area=((y4+2*y3+2*y2+y1)/6)*deltax/1000;
      return area;
    }
    
    void setup()
      {
      Serial.begin(57600);
      Serial.println("WM+ Tuning");
      Wire.begin();
      wmpOn();              //turn WM+ on
      calibrateZeroes();          //calibrate zeroes
      delay(1000);
    
      //yawServo.attach(8);
      //pitchServo.attach(9);
      pinMode(4, INPUT);
    
            // Initialize timer1, this is required for all features that use Timer1
        // (PPMIn/PPMOut/ServoIn/ServoOut) 
            rc::Timer1::init();
            // fill input buffer, convert raw values to microseconds
            for (uint8_t i = 0; i < CHANNELS; ++i)
    {
        if (i == 2)
            g_input[i] = 2000; // throttle channel
        else
            g_input[i] = 1500;
    }
    
            // initialize PPMOut with some settings
        g_PPMOut.setPulseLength(448);   // pulse length in microseconds
        g_PPMOut.setPauseLength(10448); // length of pause after last channel in microseconds
        // note: this is also called the end of frame, or start of frame, and is usually around 10ms
    
        // start PPMOut, use pin 9 (pins 9 and 10 are preferred)
        g_PPMOut.start(9);
      }
    
    void loop(){
      receiveData();            //receive data and calculate yaw pitch and roll
      time=millis();
      delta_t=(time-last_time);
    
      /* Runge-kutta 4th Order Integration */
      yaw_deg+=rk4Integrate(yaw, last_yaw[0], last_yaw[1], last_yaw[2], delta_t);
      pitch_deg+=rk4Integrate(pitch, last_pitch[0], last_pitch[1], last_pitch[2], delta_t);
      roll_deg+=rk4Integrate(roll, last_roll[0], last_roll[1], last_roll[2], delta_t);
      last_yaw[2]=last_yaw[1];
      last_pitch[2]=last_pitch[1];
      last_roll[2]=last_roll[1];
      last_yaw[1]=last_yaw[0];
      last_pitch[1]=last_pitch[0];
      last_roll[1]=last_roll[0];
      last_yaw[0]=yaw;
      last_pitch[0]=pitch;
      last_roll[0]=roll;
      last_time=time;
      /* Runge-kutta 4th Order Integration */
    
      if (digitalRead(4) == 1)
        {
        last_yaw[2]=0;
        last_pitch[2]=0;
        last_roll[2]=0;
        last_yaw[1]=0;
        last_pitch[1]=0;
        last_roll[1]=0;
        last_yaw[0]=0;
        last_pitch[0]=0;
        last_roll[0]=0;
        yaw = 0;
        pitch = 0;
        roll = 0;
        yaw_deg = 0;
        pitch_deg = 0;
        roll_deg = 0;
        }
    
      yawServoVal = map(yaw_deg, -90, 90, 0, 179);
      if (yawServoVal < 0){yawServoVal = 0;};
      if (yawServoVal > 179){yawServoVal = 179;};
      //yawServo.write(yawServoVal);
      //delay(10);
    
      pitchServoVal = map(roll_deg, -90, 90, 0, 179);
      if (pitchServoVal < 0){pitchServoVal = 0;};
      if (pitchServoVal > 179){pitchServoVal = 179;};
      //pitchServo.write(pitchServoVal);
      //delay(10);
      g_input[5] = map(yawServoVal, 0, 179, 1000, 2000);
      g_input[6] = map(pitchServoVal, 0, 179, 1000, 2000);
    
      g_PPMOut.update();   // tell PPMOut there are new values available in the input buffer
    
      Serial.print("Yaw:");
      Serial.print(yawServoVal);
      Serial.print("  Pitch:");
      Serial.print(pitchServoVal);
      Serial.print("  Roll:");
      Serial.println(roll_deg);
      delay(10);
    
    }
    

    unfortunately it didnt work... thank you for your help.. i really appreciated that... i think i will have to work on this a little bit by myself... i bothered you a lot... i will post this project to Arduino site if i succeed...

    Dincer

     

    Last edit: dvdouden 2013-04-15
    • dvdouden

      dvdouden - 2013-04-15

      You're welcome and sorry we couldn't get it to work. Which type of Arduino are you using by the way?

      If I were you I'd start with testing whether PPMOut is outputting anything at all, use the timer1 debug mode and an LED on the PPMOut output pin. It should look something like this: http://www.youtube.com/watch?v=KikSzL0Yilo

      I admit it's a bit difficult to debug without a scope though... I've also used a second Arduino with PPMIn to catch the signal and output its values.

       
  • Anonymous

    Anonymous - 2013-04-15

    thank you again... i am planning to do that now.. i will somehow monitor ppmout at pin9... first i will try your led trick... monitoring pin9 using a second arduino may be a good choice too... i have various arduinos at hand, i love them... :) arduino duemillanove, boardino328, arduino uno, ardweeny, arduino nano and some other clones which i made (ardupilot boards etc)... the one i am using for this project is a Boardino328 (adafruit one)... as u may have noticed from the code i changed config of tx to ch6&ch7 because i plan to use ch8 for Ardupilot autupilot switching on/off later...
    Dincer

     
    • dvdouden

      dvdouden - 2013-04-15

      Ah cool. I'm asking because I've only tested ArduinoRCLib on Atmega168/328 devices, so I'm not sure whether it works on a Mega or Leonardo (it's on my todo list).

      Anyway, good luck, and feel free to ask any questions you have!

       
  • Anonymous

    Anonymous - 2013-04-15

    did some research and found out something about + or - ppm population... which one are we creating here? while browsing RCGroups forums i found at Dennis Frie diy headtracker thread that turnigy9x uses - ppm population, like Futaba Jr atc, unlike Graupner... can this be my problem? are we creating -ppm population with this RClibrary?..
    Dincer

     
    • dvdouden

      dvdouden - 2013-04-15

      I think (can't remember exactly) that we're using negative PPM here, you can invert the signal by using a second parameter on the start function

      g_PPMOut.start(9, true); // inverts the PPM signal
      

      you could give that a try.

       
  • Anonymous

    Anonymous - 2013-04-16

    i am happy to inform you that i managed my headtracker work last night after few hrs of mindstorming... i am also happy to inform you thatyour rc lib is working flawlessly... i was linking my tx to the HT from trainer port at first. later i realized that tx is not seeing the new ppm signal from there. i rewired the HT totally from inside and made a dedicated plug for the new ht and it worked... :) some points to mention though. your rc lib is creating -ppm which is fine for my T9X. the ppm must be a sum of full channels. mine is 8ch as we have done in the last version of the code. i.e populate all 8ch and then only update the necessarry 2ch... thks for your assistance... one thing i couldnt solve is the yaw and pitch is working reversed and i cant change them from tx. when i reverse the 2ch which im using nothing changes... :(
    Dincer

     
    • dvdouden

      dvdouden - 2013-04-16

      Glad to hear you got it working! I noticed the following:

      pitchServoVal = map(roll_deg, -90, 90, 0, 179);
      

      shouldn't that be roll_deg?
      You could also clamp the source value first like this:

      if (pitch_deg < -90){pitch_deg = -90;}
      if (pitch_deg > 90){pitch_deg = 90;};
      

      If you want to invert the channel you'd just to

      pitch_deg = -pitch_deg;
      

      and then map it directly to g_input

      g_input[6] = map(pitch_deg, -90, 90, 1000, 2000);
      

      Glad to be of help!

       

      Last edit: dvdouden 2013-04-16
  • Anonymous

    Anonymous - 2013-04-16

    forgot to give you my mail address to you in case you want to contact me... want to hear about updates on RClib... thks again and wish u a nice day...
    Dincer Hepguler
    dhepguler@hotmail.com

     

    Last edit: dvdouden 2013-04-16
    • dvdouden

      dvdouden - 2013-04-16

      You're welcome! And fixed that typo for ya ;)

      You can also subscribe to the project (I think there's a button on the main project page). Then you'll automatically receive an e-mail when new updates are released.

       

      Last edit: dvdouden 2013-04-16
  • Anonymous

    Anonymous - 2013-04-16

    thank you again for the reversing tip... will do that now...i didnt write the whole code but collected bits of code from various sources, adding some code by myself for my needs and compiled, the roll_deg variable is actually the pitch_deg... the programmer who wrote the wiiMplus reading routine established it wrong and i kept it like that, only swapped the axis for my needs...
    dincer

     
  • Anonymous

    Anonymous - 2013-04-16

    unfortunately reversing by assigning -val to yaw and pitch didnt work... indeed headtracker stopped working... after few trials on the code i gave up and decided to use the wiiMplus rotated... :) i hold the wiiMplus reversed on power up (or reset) and the axes zero calibration remembers the position and it works on normal axes.. left is left, up is up etc... :)
    Dincer

     

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.