Wii Motion Plus gyros on LM3S8962 (I2C on CooCox)
January 23, 2011 7 Comments
After the initial discovery and a brief “hello world” on my new Arm Cortex M3 board using the CooCox environment, it’s now time for something more “involved”…
And because I’m still in the middle of my quadcopter project, and refactoring it to use the gyroscopes from a wii motion + , what better test than try to read these sensors from the new board ?
Here’s the code, using CooCox.
All the I2C data transfer is quite verbose and slightly low level, I should have put the calls together in some higher level functions à la Arduino, but couldn’t be bothered 🙂
#include "hw_memmap.h" // for the base address of the memories and peripherals. #include "hw_types.h" #include "gpio.h" #include "sysctl.h" #include "rit128x96x4.h" // OLED functions #include "i2c.h" #include <OsConfig.h> /*!< CoOS configure header file*/ #include <CoOs.h> /*!< CoOS header file */ #define WMP_ADDR 0x52 //0xA4 // Wii Motion Plus #define WMP_ADDR_INIT 0x53 //0xA5 // Wii Motion Plus starts at this address #define LED GPIO_PF2_LED1 #define TASK_STK_SIZE 128 OS_STK taskA_Stk[TASK_STK_SIZE]; volatile int _gyroX, _gyroY, _gyroZ, _gyroX0 = 0, _gyroY0 = 0, _gyroZ0 = 0; void initBoard(void){ /* Set the clocking to run from PLL at 50 MHz */ SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ); /* Enable peripherals */ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); /* Configure Status LED as output */ GPIOPadConfigSet(GPIO_PORTF_BASE, LED, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); GPIODirModeSet (GPIO_PORTF_BASE, LED, GPIO_DIR_MODE_OUT); /* Initialize LCD */ RIT128x96x4Init(1000000); RIT128x96x4Clear(); /* Display Initial message */ char buf[25]; sprintf(buf, "Wii Motion Plus - I2C"); RIT128x96x4StringDraw(buf, 0, 5, 11); /* Init I2C */ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0); GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3 ); // Initialize Master and Slave I2CMasterInitExpClk(I2C_MASTER_BASE, SysCtlClockGet(), false); } void initWMPGyros(){ // Specify slave address and the fact that we SEND I2CMasterSlaveAddrSet(I2C_MASTER_BASE, WMP_ADDR_INIT, false); //WM+ starts out deactivated at address 0x53 //send 0x04 to address 0xFE to activate WM+ I2CMasterDataPut(I2C0_MASTER_BASE, 0xfe); I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_START); while(I2CMasterBusy(I2C0_MASTER_BASE)); I2CMasterDataPut(I2C0_MASTER_BASE, 0x04); I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_CONT); while(I2CMasterBusy(I2C0_MASTER_BASE)); I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH); // WM+ has jumped to another address, so don't wait for it... } void readWMPGyros() { unsigned char buff[6]; // Specify slave address and the fact that we SEND I2CMasterSlaveAddrSet(I2C_MASTER_BASE, WMP_ADDR, false); // send one 0 to ask for data I2CMasterDataPut(I2C0_MASTER_BASE, 0x00); I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_SINGLE_SEND); while(I2CMasterBusy(I2C0_MASTER_BASE)); // Specify slave address and the fact that we RECEIVE I2CMasterSlaveAddrSet(I2C_MASTER_BASE, WMP_ADDR, true); // receive the data back I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START); while(I2CMasterBusy(I2C0_MASTER_BASE)); buff[0] = I2CMasterDataGet(I2C_MASTER_BASE); int i; for(i=1; i<6; i++) { I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); while(I2CMasterBusy(I2C0_MASTER_BASE)); buff[i] = I2CMasterDataGet(I2C_MASTER_BASE); } I2CMasterControl(I2C0_MASTER_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); while(I2CMasterBusy(I2C0_MASTER_BASE)); _gyroZ = ((buff[3] >> 2) << 8) + buff[0] - _gyroZ0; _gyroX = ((buff[4] >> 2) << 8) + buff[1] - _gyroX0; _gyroY = ((buff[5] >> 2) << 8) + buff[2] - _gyroY0; } void calibrateWMPGyrosZeroes(){ char buf[25]; _gyroX0 = 0; _gyroY0 = 0; _gyroZ0 = 0; long tempX=0, tempY=0, tempZ=0; int i; for (i=0; i<10; i++){ readWMPGyros(); tempZ += _gyroZ; tempX += _gyroX; tempY += _gyroY; } // average 10 readings _gyroZ0 = tempZ / 10; _gyroX0 = tempX / 10; _gyroY0 = tempY / 10; sprintf(buf, "X0:%d Y0:%d ", _gyroX0, _gyroY0); RIT128x96x4StringDraw(buf, 0, 25, 11); } void taskA(void* pdata){ char buf[25]; // init the Wii Motion Plus. This is MANDATORY as the WMP starts at a different I2C address initWMPGyros(); calibrateWMPGyrosZeroes(); while(1){ readWMPGyros(); sprintf(buf, "X:%d Y:%d ", _gyroX, _gyroY); RIT128x96x4StringDraw(buf, 0, 45, 11); CoTimeDelay(0, 0, 0, 300); } } int main(void){ initBoard(); CoInitOS(); // name of the task method / NO arguments / priority 1 / the stack to use / stack size CoCreateTask(taskA, (void *)0, 1, &taskA_Stk[TASK_STK_SIZE - 1], TASK_STK_SIZE); CoStartOS(); while(1); }
As usual, don’t hesitate to post any comments, ask questions, or let me know if you found this useful at all…
Pingback: Wii Motion plus Gyros on RaspberryPi | Robotics / Electronics / Physical Computing
Hi,
I tried CoCOX with Naze32, very nice but tasks not preemptive as I thought, I am sure that Naze32 code could be useful for you.
Anyway I am not an expert in RTOS. but I could also port Multiwii to Arduino_DUE ….. http://technicaladventure.blogspot.com/2014/05/porting-multiwii-to-arduino-due.html
Great projects!
Thanks so much!
Thank you very much!
Great program. I´m trying to use CoIDE but I´m having some difficulties how to use its sintaxe to set configurations (like core clock, define pins, etc). Yf you have more examples, could you send me? Thanks a lot.
Wagner
Hi Wagner and thank you for your comment.
Sadly I have very little experience with this board and CoIDE too, about as much as it’s on this post really… 🙂
Last week-end I tried to write a program to decode some PPM signals from a RC remote, but found it very frustrating as I couldn’t make the external interrupts work !
And NO example on the net whatsoever !!!
That’s when you realise that the power of the little Arduino, has nothing to do with the chipset or the (rather crappy IDE 🙂 ) etc. … but with the huuuuge community around it… there’s literally NO subject or project that hasn’t been tried by (plenty of) other people before you…
So sorry for this, I can’t really help, but I’d be curious to know if you manage to find any other examples.
dan
Pingback: Wii Accessories – We've Come So Far Since the Power Glove