O Nunchuk do Wii, é ótimo para ser utilizado em projetos, hacks e etc por possuir um acelerômetro 3 eixos, um joystick analógico. Ele se comunica com o Wiimote por  fast I²C 400kHz, então bastou colocar um sniffer par obtermos os dados e um pouco de tempo e pesquisa para entender o significado de cada um. Aqui descreveremos passo a passo para você.

O que há dentro do Nunchuk? Caso você esteja curioso para saber o que há e como é dentro do Nunchuk, mas não tem a chave adequada para abrir ou está com medo de estragar, seguem algumas fotos.

O que é o que dentro do Nunchuk:

Funcão Hardware
C switch
Z switch
Joystick X potenciômetro axial 30Kohm
Joystick Y potenciômetro axial 30Kohm
Acelerômetro ST 8XRJ 3L02AE 820 MLT
Microcontrolador FNURVL 405 849KM

O acelerômetro acredito ser uma versão OEM do LIS30L2A da ST apesar de no datasheeet dizer que a tensão de operação dele é de 2,7V a 3,6V, já mantive o Nunchuk operando a 5V sem problemas, porem recomendo cautela ao usar ele fora do padrão.

O MCU não encontrei nada compatível, deve ser OEM também.

OK, vamos a gambiarra.

Primeiro passo: Identificando os fios do Nunchuk

Como a interface de comunicação utilizada pelo Nunchuk é I²C temos somente um fio para dados, um para o clock, Vcc e GND. Como já vi Nunchuks com fios de cores diferentes, não postarei aqui as cores, pois não quero ninguém reclamando que coloquei as cores erradas. Darei a dica; ao cortar o conector, deixe um pedaço de fio e com um multímetro teste a continuidade de cada fio com cada pino do conector seguindo a imagem a baixo você encontra-rá o que é cada fio.

#####POSTAR IMAGEM

Segundo passo: Configurando o hardware

Independente do MCU que você utilizar o padrão I2C utiliza resistores de pull up no bus, estes resistores já estão presentes dentro do Nunchuk. Como disse antes, o acelerômetro é 3,3V, porem já mantive o mesmo funcionando a 5V por bastante tempo sem problemas, mas tenha cautela.

Terceiro passo: Inicializando a comunicação

O Nunchuk está localizado no endereço 0×52 do I²C, para inicializa-lo você deve enviar 0×55 0×00, apos isso você pode começar a ler os dados dos sensores, basta ler 6 bytes do endereço 0×00 do Nunchuk, caso você ache que os dados estão errados, é poque estão encriptados bastar usar esta simples lógica para decriptá-los

(byte XOR 0×17) + 0×17 -> em linguagem C decriptado = ((encriptado ^ 0×17) + 0×17)  & 0xFF;

Os dados virão organizados da seguinte forma

Bit
Byte 7 6 5 4 3 2 1 0
0 JX<7:0>
1 JY<7:0>
2 AX<9:2>
3 AY<9:2>
4 AZ<9:2>
5 AZ<1:0> AY<1:0> AX<1:0> BC BZ

O primeiro e o segundo byte, contem os dados do joystick, os 3 próximos bytes contem os 8 últimos bits de cara eixo do acelerômetro, e o quinto byte contem os 2 primeiro bits de cada eixo do acelerômetro e os 2 botões. Vale lembrar que os botão são lógica inversa, isto é quando pressionados retornam zero.

Passo extra: transformando os dados

Desculpe a falta de imagens nesta parte, estou providenciando ;D

O acelerômetro quando estático, isto é, quando está só sobre a ação da aceleração da gravidade, podemos usá-la como referencia de um sistema de coordenadas e com um pouco de geometria conseguimos calcular o angulo de posicionamento do acelerômetro em 3 dimensões. Definiremos rho(ρ)  como angulo de X em relação ao chão, phi(φ) como o angulo de Y em relação ao chão e theta (θ) como o angulo de Z em relação com a gravidade teremos:

\rho =\arctan \left ( \frac{A_{X}}{\sqrt{A_{Y}^{2}+A_{Z}^{2}}} \right )

\phi =\arctan \left ( \frac{A_{Y}}{\sqrt{A_{X}^{2}+A_{Z}^{2}}} \right )

\theta =\arctan \left ( \frac{\sqrt{A_{X}^{2}+A_{Y}^{2}}}{A_{Z}}\right )

*resultado em Radianos

Quando o acelerômetro está estático, a soma das acelerações deve ser 1g, isto é

\sqrt{A_{X}^{2}+A_{Y}^{2}+A_{Z}^{2}}=1g

Para obtermos o valor de Ax, Ay e Az devemos antes encontrar os valores de calibração do acelerômetro, de acordo com o datasheet a maioria dos acelerômetros reporta para 0g = 0,66V, como seu AD interno é 10bits e Vref = 3,3V, temos que 0g = 204, 1g=716 e -1g=307 para obter resultados mais precisos pode encontrar estes valores testando seu Nunchuk na pratica, rotacionado ele em todos os ângulos até obter o valor máximo e minimo para cada eixo(observe que você deve manter o Nunchuk estático). Outra forma mais fácil é lendo os dados de calibração que são armazenados dentro do próprio controle são 8 bytes localizados a partir do endereço 0×20 estão organizados como os dados de leitura

Bit
Byte 7 6 5 4 3 2 1 0
0 X0G<9:2>
1 Y0G<9:2>
2 Z0G<9:2>
3 Z0G<1:0> Y0G<1:0> X0G<1:0>
4 X1G<9:2>
5 X1G<9:2>
6 X1G<9:2>
7 Z1G<1:0> Y1G<1:0> X1G<1:0>

Não tenho certeza da configuração dos bytes 3 e 7, porem meus testes indicam que esta configuração está correta.

Seguindo desta maneira, para encontrar os valores para -1g basta subtrair do valor de 0g a diferença entre 0g e 1g, em “palavras” matemáticas

X_{-1}G=X_{0}G-(X_{1}G-X_{0}G)

Encontramos agora as componentes da aceleração de cada eixo subtraindo do valor lido de cada eixo, o seu respectivo og

F_x=X-X_0G F_y=Y-Y_0G F_z=Z-Z_0G

Finalmente encontramos Ax, Ay e Az

A_x=F_x*((X_1G-X_{-1}G)/180) A_y=F_y*((Y_1G-Y_{-1}G)/180) A_z=F_z*((Z_1G-Y_{-1}G)/180)

Feito, agora basta calcular rho, phi e theta e multiplicar por 180/Pi para transformar para graus os valores.

Seguem o trecho descrito acima em linguagem C

    fx = x_val-g0x; //x_val = valor lido do nunchuk
    fy = y_val-g0y; // iden
    fz = z_val-g0z; // iden
 
    ax = fx*((x1g-xm1g)/180.0); //xm1g = X-1g -O valor de X para -1g
    ay = fy*((y1g-ym1g)/180.0);
    az = fz*((z1g-zm1g)/180.0);
 
    rho = atan(ax/sqrt(pow(ay,2)+pow(az,2)))*(180.0/M_PI); //M_PI = Pi da math.h
    phi = atan(ay/sqrt(pow(ax,2)+pow(az,2)))*(180.0/M_PI);
    theta = atan(sqrt(pow(ay,2)+pow(ax,2))/az)*(180.0/M_PI);
 
    if(theta&lt;0)rho=180.0-rho;  // descobre o sinal do angulo
    if(rho&lt;0)rho=360.0+rho;
    if(theta&lt;0)phi=180.0-phi;
    if(phi&lt;0)phi=360.0+phi;

Até a proxima.