Pages: 1 ... 9 10 [11] 12   Go Down
Author Topic: Kalman Filtered Nunchuck & Wii Motion Plus  (Read 29003 times)
0 Members and 2 Guests are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I don't understand the details, but would it be possible to sacrifice the button and joystick data on the nunchuck in order to increase the resolution of the accelerometer reporting?

Unfortunately, I don't think so... when I was initially figuring out the controller remapping for the Nunchuck and Classic Controller, I thought maybe we could use the Classic Controller mapping, which moves the last two bits of byte 5 into the last bit of byte 0 and 1, but for some odd reason even though a 1 is hardcoded into the Classic Controller byte 4 bit 0, it seems that the MotionPlus manually hardcodes that bit as well rather than just passing it through.

Because of that, when you use a Nunchuck in Classic Controller mode, you lose the LSBit of each joystick axis (good), but then also the LSBit of byte 4, which is the Z-Axis bit 2... which really screws things up.  The X and Y axes have full resolution, but unless you want a 2 axis accelerometer, that's probably not very helpful.

DogP
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 88
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The X and Y axes have full resolution, but unless you want a 2 axis accelerometer, that's probably not very helpful.
Actually I would like to look into that  smiley (I'm interested to see the performance limits of these accelerometers). Could you point me in the direction of what I need to learn to implement the classic controller mapping on the nunchuck? I am assuming it is possible to combine this with the passthrough method?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeah, sure... download my object from: http://obex.parallax.com/objects/471/ , and read the top of the MotionPlus.spin file... that has the mapping for the Nunchuck and Classic Controller in Passthrough mode.  Of course the non-passthrough mappings are available here: http://wiibrew.org/wiki/Wiimote/Extension_Controllers .  When you initialize the MotionPlus, just initialize with 0x07 rather than 0x04 (MP by itself) or 0x05 (MP w/ Nunchuck).

If you compare the mapping for the Classic Controller passthrough w/ the regular Classic Controller mapping, you'll see the difference is just the two bits, except the hardcoded 1 in byte 4 bit 0 seems to be actually hardcoded in the MotionPlus as well :/ .  The MotionPlus doesn't know which controller is actually connected... it just acts differently depending on which initialization was used.

Oh... and to make sure I was clear... I don't mean it gives you the full resolution of the sensor... I mean the full original resolution as it was before the dropped bit from the passthrough.

DogP
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 65
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried to use MP+ on standalone mode yesterday, but I was getting all 0 readings... hmmm
Does the reading address change when you change the mode?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@duckhead: "do you have working DCM code that you can share?  I've read the theory but I guess I don't interpret it the same as you.  I'd like to learn more about it and for me working code is more intuitive than theory."

No I don't  -  I spent few hours over the weekend working on it but it's not done yet - need more time ( I am first trying to get yaw-pitch to work before tackling yaw....and for yaw you need either GPS or mag.).
You can find links to documentation and code at:
http://diydrones.ning.com/page/uav-devboard

(look for roll-pitch  or roll-pitch-yaw). There are links to code for Bill P.'s implementation on another chip. Bill P. is the one who developed this approach based on Mahony's papers.
As far as I know Jordi ( who's Kalman filter approach was referenced at the beginning of this thread) worked on implementing DCM on Arduino and should release the code soon (apparently he worked on this for 6 months with help from Bill P. - and six months included not just code but board development and testing for ArduPilot shield, etc. if I understood things correctly...)



As far as loss of bit data in pass through mode

 - this is just a though and I haven't tested this (will do if I get some time next week) - separate Nunchuck and WM+ and run them (address them) separately. Run one using wire lib and connecting data and clock to Analog 4 and Analog 5 pins, and run the other in the manner DogP (and krulkip) showed, connected to Digital 4 and Analog 0 pin,  and using Ports lib. Just a thought....
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 11
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

As a follow up of my previous statement about some recent WMP having different gyros : it is not the case. I opened it and it's the same old IDG-600 in the C6VF100 as it was in the C4GF500.
What strikes me is that i get clearly better results using 4.5 instead of 4 or 5 as the coefficient between slow and fast (which is why I first thought it was an IDG-650 in the first place). Could it be a change in the WMP firmware?
« Last Edit: September 14, 2009, 08:51:14 am by xevel » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 113
Arduino paper
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
- this is just a though and I haven't tested this (will do if I get some time next week) - separate Nunchuck and WM+ and run them (address them) separately. Run one using wire lib and connecting data and clock to Analog 4 and Analog 5 pins, and run the other in the manner DogP (and krulkip) showed, connected to Digital 4 and Analog 0 pin,  and using Ports lib. Just a thought....

Whilst from an engineering perspective, its a good idea.. I think thats slipping down the other side of the bellcurve in terms of 'effort-for-gain-for-cost'... You have then 2 libraries to compile in, extra ram used, a more complicated program etc etc... You also blow 2 extra pins on the 'duino.

Allin all seems a bit off effort to get not really much more.. if its all that important, isn't it probably better at that stage to just switch to a 'proper' gyro/accelerometer combo...
*shrug*.. just my thoughts.. smiley
« Last Edit: September 14, 2009, 08:58:59 am by adr1an » Logged

Checkout my projects development blog @ SLiDA

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 88
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Duckhead's original code scaled the raw x and y axis accelerometer values into radians via normalisation by a value of 1023. I think a value of ~430 is possibly more appropriate:

     Example of the accelerometer rotation values for y axis on my nunchuk.
    
     Exact values differ between x and y axis, and probably between nunchuks, but the range value may be constant:
    
                  298 ayMIN
                        _|_
                      /      \
   ayMID 513 - |        | - 513 ayMID
                      \ _ _ /
                          |
                  728 ayMAX
              
      ayRange = (ayMID - ayMIN)*2 = ayMAX - ayMIN = 430

Scaling:
Code:

        //Zero the values on a#MID.
        ax_m -= axMID;
        ay_m -= ayMID;
        az_m -= azMID;
      
        // Convert to radians by mapping 180 deg of rotation to PI
        x = angleInRadians(ayRange, ax_m);
        y = angleInRadians(ayRange, ay_m);
        z = angleInRadians(azRange, az_m);

Scaling:
Code:
//Nunchuk accelerometer value to radian conversion.
float angleInRadians(int range, int measured) {
  float x = range;
  return (float)(measured/x) * PI;
}

Constants:
Code:
// Exact values differ between x and y axis, and probably between nunchuks, but the range value may be constant:
static const int axMIN = 290;
static const int axMAX = 720;
static const int axMID = (axMAX - axMIN)/2 + axMIN;
static const int axRange = (axMID - axMIN)*2;

static const int ayMIN = 298;
static const int ayMAX = 728;
static const int ayMID = (ayMAX - ayMIN)/2 + ayMIN;
static const int ayRange = (ayMID - ayMIN)*2;

// Not sure what a meaningful scale is for the z accelerometer axis so:

static const int azMID = ayMID;
static const int azRange = ayRange;

Any thoughts?
« Last Edit: September 14, 2009, 11:03:39 am by ardvark » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 88
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ DogP: thanks very much for the mapping info, I will give it a try :-)
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 88
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As an alternative to the Kalman approach, I implemented a complementary filter in the pass-through code. It combines the accel and gyro as inputs and outputs drift-free orientation angles and strongly suppresses the movement artifacts coming from the accel input. This filter approach is simple to understand and tweak, quite effective, and only takes a couple of lines of code. Anyway, if it is of interest I can clean it up and post it.

BTW, have people lost interest in this thread? Or is it just too hard to access? If you think a smaller thread might perform better we could start another as a sequel.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 113
Arduino paper
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well I'm certainly interested still! smiley

Post up the complementary filter by all means... it can only help! smiley

Does it handle yaw well ??
Logged

Checkout my projects development blog @ SLiDA

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 88
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

At the moment I am still testing it for the x axis (pairing the corresponding gyro and accel axes) and I am not using trig to combine the axis data yet (which I guess is necessary for yaw). I will annotate a bit and post it.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 65
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I haven t been able to access the thread for a few days now. Plus I haven t worked on my code either since I m waiting for my new sensors, magnetometer, gps etc.
The nunchuck's 10bits (9 in pass-through) proved to be too few for my project, although I love the 16bit gyros from mp+ smiley-grin.

However, I am still working on refactoring the code to be able to accommodate input from any angle metering sensor, so I will be able to post some more stuff as soon as I get some testing on the magnetometer and gps stuff.

I have also incorporated a scheme to save zeroing calibration data to the eeprom and reading it back when arduino executes setup.
Calibration and saving the data should be triggered either through software choice, or using an interrupt.

I would surely love to see your implementation of the complementary filter. I am running low on program space and I still haven t worked on the UI stuff....
And I agree, it might be better/clearer to put it on a separate thread.
« Last Edit: September 17, 2009, 09:24:24 am by dimkasta » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 113
Arduino paper
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have also incorporated a scheme to save zeroing calibration data to the eeprom and reading it back when arduino executes setup.
Calibration and saving the data should be triggered either through software choice, or using an interrupt.

Can you share this ? I've been thinking about doing exactly that smiley
Logged

Checkout my projects development blog @ SLiDA

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 65
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@And1an

Well it is part of some bigger refactoring changes I have made to the code which include keeping variables in structs to better help identify how and where I manipulate them.

The actual storing thing was implemented using the epprom save anything code from playground.

The code is not complete yet, so I cannot post it, but that is the main idea.
« Last Edit: September 17, 2009, 04:47:36 pm by dimkasta » Logged

Pages: 1 ... 9 10 [11] 12   Go Up
Jump to: