User talk:Billiard26
Jump to navigation
Jump to search
Are you still active? If you are, im having trouble trying to update a wiimotion plus sensor using an arduino nano and an IMU called the BNO055. Its 9DOF and autocalibrates using an onboard microcontroller. So far, I've read the wiimotion plus's request to register 0xfe for identification, yet for some reason it wont accept my response and it keeps sending requests. Do you think you could help?
I have a lot of regoser maps which i am going to add functionality for as i grow my code, so there's a lot of unused variables for registers here:
// All values are big-endian.
// Assume data is tightly packed.
// The i2c stream is 0x100 bytes long, and it is mirrored across the entire 16-bit address space up to 0xa4FFFF
// Peripheral Protocol is 400kHz "fast" I2C
// NOTE: the structure of this code does not allow for passthrough devices
// References:
// https://github.com/denizkoekden/arduino-wiimote
// http://wiibrew.org/wiki/Wiimote/Extension_Controllers
// http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus
// http://randomhacksofboredom.blogspot.com/
#include "Wire.h"
#define EMPTY_BYTE 0xFF
#define SERIAL_BAUD 115200
#define REGISTER_LENGTH 0x100
#define MAX_REQUEST_SIZE 32
#define CLOCK_FREQ 400000
// Got this from the registers of an actuall wiimotion plus in an un-iniialized and inactivated state. Serves as starting point
byte wiimote_registers[REGISTER_LENGTH] = {0xB5,0x26,0x42,0x7F,0x7E,0x7E,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8,0xFF,0xFF,0x0,0x0,0xA4,0x20,0x0,0x5,0x7A,0x8A,0x77,0x2B,0x77,0x3A,0x31,0x48,0xD5,0x27,0x27,0xE6,0xC8,0x30,0xB1,0xF9,0x83,0x4D,0x78,0x45,0x78,0xE0,0x36,0xDA,0xD1,0xDC,0x2A,0xCC,0x2D,0x4F,0x48,0xCD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x25,0xE0,0x8E,0xCE,0xFA,0x1E,0x25,0x8A,0x9F,0xCB,0x8B,0xFC,0x5,0x96,0xFF,0x1A,0xD3,0xC8,0x15,0x97,0xCF,0xAF,0xB7,0xCC,0x72,0x79,0x87,0x78,0x35,0x9B,0x27,0x6C,0x9C,0x6A,0x1C,0xD4,0x88,0x8E,0xD6,0xA,0xE1,0xDA,0xBD,0x38,0xA5,0xD5,0xB,0x9D,0x3A,0xAC,0x26,0x1A,0x4D,0xFA,0x5,0x21,0x24,0xD8,0x6A,0xA3,0xED,0x60,0xEB,0x1A,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8,0xFF,0xFF,0x0,0x0,0xA4,0x20,0x0,0x5,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8,0xFF,0xFF,0x0,0x0,0xA4,0x20,0x0,0x5,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8,0xFF,0xFF,0x0,0x0,0xA4,0x20,0x0,0x5,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8,0xFF,0xFF,0x0,0x0,0xA4,0x20,0x0,0x5,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8,0xFF,0xFF,0x0,0x0,0xA4,0x20,0x0,0x5,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8,0xFF,0xFF,0x0,0x0,0xA4,0x20,0x0,0x5,0x55,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2,0xFF,0xFF,0x0,0x0,0xA6,0x20,0x0,0x5};
static byte state = 0;
const byte inactive_expansion[2] = {0x00, 0x05};
const byte active_expansion[2] = {0x04, 0x05};
const byte inactive_address = 0x53; // starts at 0xa60000
const byte active_address = 0x52; // starts at 0xa40000
const byte inactive_id[6] = {0x00,0x00,0xA6,0x20,0x00,0x05};
const byte active_id[6] = {0x00,0x00,0xA4,0x20,0x04,0x05};
// IMPORTANT REGISTERS AND WHAT THEY SHOULD HOLD
const byte id_reg = 0xa600fa;
// holds id, used to identify extension type, holds ID
const byte activate_reg = 0xa600fe;
// activates the wmp when 0x04 is written to it
// activation changes the extension identifier and makes the wmp start reporting motion data
// writing 0x05 or 0x07 to this register can also implement passthrough mode
// but we wont allow for other extensions to be connected, making that feature useless
const byte deactivate_reg = 0xa400f0;
// deactivates the wmp when 0x55 is written to it
// writing 0x55 to it also activates whatever extesion is connected to the wmp
// deactivation reverts whatever changes activation has made
const byte init_reg = 0xa600f0;
// starts initialization of the wmp when 0x55 is written to it
// initialization does little, except for changing init-shift and init_rand_shift registers
const byte init_reg_2 = 0xa500fb;
// would normally start initialization process once 0x00 was written to it
// however wmp games dont do this, so its useless
const byte init_shift_reg = 0xa600f7;
// during initialization it changes from 0x02 to 0x04 to 0x08 to 0x0C to 0x0E then stays at 0x0E
// yet wmp games dont read this, making it useless
const byte init_shift_rand_reg = 0xa60050;
// after initialization, registers 0xa60050 to 0xa600cf will change briefly, but randomly, for a total of 128 bytes
const byte calibration_reg = 0xa60020;
// 32 bytes of calibration information which are reported once activated
const byte motion_reg = 0xa40008; // (or sometimes 0xa40000)
// 6 bytes of gyro information which are reported once activated
/*
This is a representation of the data to be stored in motion_reg and calibration_reg
The motion data's bits of data are split into two parts.
The first part is the first 0-7 bits of data
The last part is the last 8-13 bits of data
Unused Bytes are filled with 0x00
struct motion_data {
byte yaw_down_7_0;
// Byte 0, <7:0>
byte roll_left_7_0;
// Byte 1, <7:0>
byte pitch_left_7_0;
// Byte 2, <7:0>
byte yaw_down_13_8;
// Byte 3, <13:8>
// Bit 1 reserved for Yaw Slow Mode & Bit 0 reserved for Pitch Slow Mode
byte roll_left_13_8;
// Byte 4, <13:8>
// Bit 1 reserved for Roll Slow Mode & Bit 0 reserved for Extension Connected
byte pitch_left_13_8;
// Byte 5, <13:8>
// Bit 1&0 are unused, Bit 1 is left as 1, and Bit 2 is left as 0
};
As for the calibration data,
uid_1,2 seem to be just a unique ID.
crc32_msb,lsb is a crc32 of all calibration data except the checksum bytes.
struct calibration_block {
// Gyro values at 0 deg/sec to 16 bits of precision.
u16 yaw_zero;
u16 roll_zero;
u16 pitch_zero;
// Gyro values at "scale" deg/sec.
u16 yaw_scale;
u16 roll_scale;
u16 pitch_scale;
// Angular velocity of the above scale values in deg/sec divided by 6.
// e.g. A value of 45 would mean the "scale" values represent the gyro at 270 deg/sec.
u8 degrees_div_6;
};
struct calibration_data {
// Calibration for "fast" mode.
calibration_block fast;
u8 uid_1;
u16 crc32_msb;
// Calibration for "slow" mode.
calibration_block slow;
u8 uid_2;
u16 crc32_lsb;
};
*/
/*
* This function pointer informs the Arduino that a byte has been
* written to one of the registers corresponding to the Extension.
* Specifically, if you assign the function foo to this pointer and
* you write yy bytes starting at the register address 04a400xx of
* the Wiimote, then this library will call foo(xx, yy). The bytes
* are written to the global array wiimote_registers.
*
* Note that count will always be less than eight. If you write
* eight or more bytes to the Wiimote, this callback will be
* invoked several times.
*/
void (*wiimote_receive)(byte offset, byte count) = NULL;
static void receive_bytes(int count) {
Serial.println("");
Serial.println("Recieving information...");
delay(100);
if (count == 1) {
state = Wire.read();
}
else if (count > 1) {
byte addr = Wire.read();
byte curr = addr;
Serial.print("Recieved bytes to register ");
Serial.println(addr);
delay(100);
Serial.print("Incoming bytes... ");
for (int i = 1; i < count; i++) {
byte d = Wire.read();
wiimote_registers[curr++] = d;
Serial.print(d);
delay(100);
}
Serial.println("");
if (wiimote_receive) {
wiimote_receive(addr, (byte) count - 1);
}
}
}
static void handle_request() {
static byte last_state = EMPTY_BYTE;
static byte offset = 0; // apparently offset starts at 0x08? im not sure if this is true
int bytes_remaining;
switch (state) {
case id_reg:
offset = 0;
bytes_remaining = 6;
break;
case activate_reg:
offset = 0;
bytes_remaining = 2;
break;
default:
if(last_state == state) offset += MAX_REQUEST_SIZE;
else {
last_state = state;
offset = 0;
}
bytes_remaining = state + offset + MAX_REQUEST_SIZE > REGISTER_LENGTH ? REGISTER_LENGTH - (state + offset): MAX_REQUEST_SIZE;
break;
}
Serial.print("Handling request to register 0x");
Serial.print(state, HEX);
Serial.print(" with offset 0x");
Serial.println(offset, HEX);
delay(100);
if(bytes_remaining > 0){
Serial.print(" Sending bytes: ");
for(int i = 0; i < bytes_remaining; i++){
Serial.print(i == 0 ? "0x" : ",0x");
Serial.print(wiimote_registers[state+offset+i], HEX);
delay(50);
}
Serial.println("");
delay(100);
Wire.write(wiimote_registers + state + offset, bytes_remaining);
}
else Serial.println(" No more bytes available for that que!");
}
void setup() {
Serial.begin(115200);
Serial.println("WM+ tester");
Wire.begin(inactive_address);
Wire.setClock(CLOCK_FREQ);
Wire.onReceive(receive_bytes);
Wire.onRequest(handle_request);
delay(5000);
}
void loop() {
}
Thank you!