Beginners: please read this post and this post before posting to the forum.
0 Members and 1 Guest are viewing this topic.
#define UART_TX_BUFFER_SIZE 20 //These are defined to reduce the delay//#define UART_RX_BUFFER_SIZE 40 //and data loss in the send and recieve buffers#include "sys/atmega328P.h" //These are the includes required by the webbotlib library.#include "uart.h"#include "rprintf.h"#include "i2cBus.h"uint8_t data[6]; // data container for Calibrate dataint yaw, pitch, roll; //three axesint yaw0, pitch0, roll0; //calibration zeroesGENERIC_I2C_DEVICE WMDevOff = MAKE_GENERIC_I2C_DEVICE(0x53);GENERIC_I2C_DEVICE WMDevOn = MAKE_GENERIC_I2C_DEVICE(0x52);static I2C_DEVICE_LIST PROGMEM i2c_list[] = {&WMDevOff.i2cInfo,&WMDevOn.i2cInfo};I2C_HARDWARE_BUS i2c = MAKE_I2C_HARDWARE_BUS(i2c_list);void Calibrate(){ for (int i=0;i<10;i++) { i2cMasterSend(&WMDevOn.i2cInfo, 1, 0x00); boolean Recieve = i2cMasterReceive(&WMDevOn.i2cInfo, 6, data); if (Recieve == FALSE) rprintfStr("Cal Fail"); 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; } rprintfStr("Yaw0: "); rprintfNum(10, 4, TRUE, ' ', yaw0); rprintfStr("Pitch0: "); rprintfNum(10, 4, TRUE, ' ', pitch0); rprintfStr("Roll0: "); rprintfNum(10, 4, TRUE, ' ', roll0); }void receiveData(){ i2cMasterSend(&WMDevOn.i2cInfo, 1, 0x00); boolean Recieve = i2cMasterReceive(&WMDevOn.i2cInfo, 6, data); if (Recieve == FALSE) rprintfStr("Fail"); yaw=((data[3]>>2)<<8)+data[0]-yaw0; //see http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus pitch=((data[4]>>2)<<8)+data[1]-pitch0; //for info on what each byte represents roll=((data[5]>>2)<<8)+data[2]-roll0; }void appInitHardware(void){ uartInit(UART0, (BAUD_RATE)115200); rprintfInit(&uart0SendByte); i2cBusInit(&i2c); i2cBusSetBitRate(&i2c, 400);}TICK_COUNT appInitSoftware(TICK_COUNT loopStart)//This is the main loop that provides timing by delaying by 1 cycle{ rprintfStr("WM Test"); i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xFE, 0x04); i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xF0, 0x55); i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xFB, 0x00); //Turns the WM+ on Calibrate(); return 10000;}TICK_COUNT appControl(LOOP_COUNT loopCount, TICK_COUNT loopStart){ receiveData(); rprintfStr("\nYaw: "); rprintfNum(10, 4, TRUE, ' ', yaw); rprintfStr("Pitch: "); rprintfNum(10, 4, TRUE, ' ', pitch); rprintfStr("Roll: "); rprintfNum(10, 4, TRUE, ' ', roll); return 100000; }
Yes - but I would want to change the code slightly.....not coz your code is wrong but I would want to make it into a standard 'gyro' object and hence make it return values in degrees/second rather than just 'raw' values.Once you've got it working, I'll do a short tutorial on how to do that so you can see what's involved and the steps to move from 'your' code to 'WebbotLib friendly' code.
Incidentally: I'm not sure the calibration code looks correct (it isn't is the Arduino sketch either). It looks like the intention is to take 10 readings and then divide the sum by 10 to give an average. But the current code divides by 10 on each iteration around the loop.Also: looking at http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus it appears that you should be testing the 3 bits to detect for slow vs fast mode as the data bytes are then treated differently.
(all addresses are doubled, including the register addresses?)
GENERIC_I2C_DEVICE WMDevOff = MAKE_GENERIC_I2C_DEVICE(0x53);GENERIC_I2C_DEVICE WMDevOn = MAKE_GENERIC_I2C_DEVICE(0x52);
GENERIC_I2C_DEVICE WMDevOff = MAKE_GENERIC_I2C_DEVICE(0xA6);GENERIC_I2C_DEVICE WMDevOn = MAKE_GENERIC_I2C_DEVICE(0xA4);
i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xFE, 0x04);//Turns the WM+ on
i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xFE, 0x04); i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xF0, 0x55); i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xFB, 0x00); //Turns the WM+ on
i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xF0, 0x55); i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xFB, 0x00); //Turns the WM+ on i2cMasterWriteRegister(&WMDevOff.i2cInfo, 0xFE, 0x04);
The URL I linked to earlier gives you a way to read some signature bytes to see if the gyro is the default device or not. You could check this in your initialisation code - and you could also use it to test if the device is plugged in and working or not.
void wmpOn(){ Wire.beginTransmission(0x53); //WM+ starts out deactivated at address 0x53 Wire.send(0xfe); //send 0x04 to address 0xFE to activate WM+ Wire.send(0x04); Wire.endTransmission(); //WM+ jumps to address 0x52 and is now active}
void wmpSendZero(){ Wire.beginTransmission(0x52); //now at address 0x52 Wire.send(0x00); //send zero to signal we want info Wire.endTransmission();} wmpSendZero(); Wire.requestFrom(0x52,6); for (int i=0;i<6;i++){ data[i]=Wire.receive(); }
i2cMasterTransfer(&WMDevOn.i2cInfo, 1, 0x00, 6, data);
Webbotlib:Code: [Select]i2cMasterTransfer(&WMDevOn.i2cInfo, 1, 0x00, 6, data);
i2cMasterReadRegisters(&WMDevOn.i2cInfo, 0, 6, data);
so, i have to ask, What is the difference between transfer and readregisters?
uint8_t reg = 0;i2cMasterTransfer(&WMDevOn.i2cInfo, 1, ®, 6, data);