Hi. i been trying to get gyro data from a Wii Motion Plus trough I2C module.
i get no response from the device, so i think i've made a mistake in configuration of IIC module.
this is how i configured the module. baud rate is 400kbps.
void IIC1_Init(void){ IIC1C1=0xC0; //IIC habilitado, Interrupcion por IIC habilitada, Modo esclavo habilitado, transmision apagada,no hay recibido ACK,No se repite start. IIC1S=0x10; //Bandera transferencia en proceso, No direccionamiento a esclavo, bus ocupado, bus operando normal, master escribe esclavo recibe, no hay interrupciones, recibe ACK. //IIC1F=0x1F; //Factor MULT: 1, rata de baudios 100KHz para WM+ (24Mhz/1*100Khz)=240=0x1F, 100Khz. IIC1F=0x45; //Factor MULT: 2, rata de baudios 400KHz para WM+ (24Mhz/2*400Khz)=30=0x05, 400Khz.}
start and stop condition procedures:
void IIC1_StartBit(){ //while(IIC1S_BUSY); //espere a que el IIC se desocupe IIC1C_TX=1; //habilite modo TX por el maestro //se envia ACK IIC1C_MST=1; //modo maestro.}void IIC1_StopBit(void){ IIC1C = 0xC0; //genere una condicion de STOP //while(IIC1S_BUSY); //espere a que el IIC se desocupe }
writing condition:
void IIC1_PutChar(unsigned char Tx1_Data){ IIC1_Flag=0; //Baje la bandera de atención a interrupción IIC1D=Tx1_Data; //Cargue dato a registro. while(!IIC1S_BUSY); //espere a que el IIC se desocupe while(IIC1S_IICIF); //espere a que el modulo IIC no tenga interrupciones pendientes //IIC1S &= ~0X02; IIC1S_IICIF=0; }
and reading:
unsigned char IIC1_GetChar(unsigned char Ack_Req){ unsigned char Dummy_Byte=0; IIC1C_TX=0; //Modo de recepcion. Dummy_Byte= IIC1D; //Lea dato de basura para despejar el buffer. while(IIC1S_IICIF); //espere a que el modulo IIC no tenga interrupciones pendientes //IIC1S &= ~0X02; IIC1S_IICIF=0; if(Ack_Req){ IIC1C_TXAK=0; //Habilitar ACK } else if (Ack_Req==0){ IIC1C_TXAK=1; //Deshabilitar ACK } IIC1RX_Data=IIC1D; //lea el dato solicitado return(IIC1RX_Data);}
what do you think???
main routine has the following structure:
IIC1_StartBit(); IIC1_PutChar((0X53<<1)|I2C_WRITE); //Adressing IIC1_PutChar(0XFE); //Register IIC1_PutChar(0X04); //Register Value IIC1_StopBit();
reading route looks like:
IIC1_StartBit(); IIC1_PutChar((0X52<<1)|I2C_READ); IIC1_PutChar(0X00); IIC1_StopBit(); for (i=0;i<5;i++){ Dato[i]=IIC1_GetChar(1); } Dato[5]=IIC1_GetChar(0);
what do you think? does anybody have worked with Wii Motion Plus???
i've tested a routime made for arduino with same structure, registers and data and works fine!!
Thank you so much;
IIC1_PutChar((0X53<<1)|I2C_WRITE); //Adressing...IIC1_PutChar((0X52<<1)|I2C_READ);
0x53 and 0x52. Is that intentional?
Warious references give the address as 0x52:
http://wiibrew.org/wiki/Wiimote/Extension_Controllers
Has the code somehow confused the I2C_READ bit with the LSB of the address? I always get confused by the "7 bit address shifted left one and the read/write bit stuck on the bottom".
> i've tested a routime made for arduino with same structure, registers and data and works fine!!
Can you look at the I2C bus with a CRO when driven by the Arduino and when driven by the ColdFire to see what's different?
Check that you've got pullup resistors and they're low enough. If the signals look good on a CRO then this is OK.
Tom
Hi Tom.
i've some research about it. found that wire.h library on arduino, add a R/W bit after 7 bit control word, that's why there're some propertires for object Wire
Wire.begintransmission (xxxx): sends R/W bit before xxxx
Wire.Send (xxxx) : sends data as is.
i got a example to control Wii motion plus with arduino from "any website jeje". to wake up the WMP sends 0X53 as a command, 0XFE as adress and 0X04 as data.
then sends a zero (don't know why, but...) starts with 0X52 as command, and 0X00 as data.
to read data, sends 0X52 with R/W bit set as READ. then, MCU should wait for 6 byte data, last byte followed by a Nack bit.
i've tested this commands with the arduino.. works fine. with JM128 not.!
there're some pull up resistors installed on both pins, SDA and SCL. (10k). i found in internet also that WMP has its own pull up's.
MCU is working with 3.3v supply, so there's no needed any level shifter, and MCU pull ups are conected to MCU VDD.
trying to find the problem, i used a oscilloscope to see signal levels and shapes. looks normal.
Regards;
Tom, i couldn't attach main.c file into las post, i don't know why.. anyway, i'v made some changes on the code, based on document AN3291.
these are routines to read, write, start, restart and stop over IIC module.
void IIC1_Init(void){ IIC1C_IICEN = 1; // Enable I2C; IIC1C_IICIE = 1; // Enable I2C; IIC1C_TXAK = 1; // not generate ACK by master after transfer; IIC1C_MST = 0; // Slave mode actually; //IIC1F=0x45; //Factor MULT: 2, rata de baudios 400KHz para WM+ (24Mhz/2*400Khz)=30=0x05, 400Khz. IIC1F=0x1F; //Factor MULT: 1, rata de baudios 100KHz para WM+ (24Mhz/1*240Khz)=30=0x1F, 100Khz. IIC1S_SRW = 0; // R/W bit = 0;}unsigned char IIC1_GetChar(unsigned char Ack){ if(Ack=0X00){ IIC1C_TXAK = 1; // acknowledge disable; } else if (Ack=0X01){ IIC1C_TXAK = 0; // acknowledge Enable; } IIC1C_TX = 0; // set up to receive; IIC1RX_Data = IIC1D; // dummy read; //while (!IIC1S_IICIF); // wait until IBIF; while (IIC1S_IICIF); // wait until IBIF; IIC1_StopBit(); IIC1RX_Data = IIC1D; // read right data; return IIC1RX_Data;}void IIC1_PutChar(unsigned char Tx_Data){ IIC1D = Tx_Data; //while (!IIC1S_IICIF); // wait until IBIF; while (IIC1S_IICIF); // wait until IBIF; IIC1S_IICIF=1; // clear the interrupt event flag; //while(IIC1S_RXAK); // check for RXAK; //while(IIC1S_BUSY); // check for RXAK;} void IIC1_StartBit(){ IIC1C_TXAK = 0; // RX/TX = 1; MS/SL = 1; TXAK = 0; IIC1C |= 0x30; // And generate START condition;}void IIC1_RepeatStart(void){ IIC1C_RSTA = 1; // set up repeated start; }void IIC1_StopBit(void){ IIC1S_IICIF=1; // clear the interrupt event flag; IIC1C_MST = 0; // generate STOP condition; }
as you can see, im making poling over some flags, like IICF. i don't ready know why the example of document reads this flag like this:
while (!IIC1S_IICIF); // wait until IBIF;
it doesn't work.....
im reading also on interrupt routine TCF, IAAS and ARBL flags. every reading or reading cicle y always get a TCF confirmation (received data or command)....
#pragma TRAP_PROCvoid IIC1X_ISR(void) { if(IIC1S_TCF){ //Se completó transferencia Confirmacion=1; } else if (IIC1S_IAAS){ //direccionado como esclavo Confirmacion=2; } else if (IIC1S_ARBL){ //Perdió Arbitramiento Confirmacion=3; } IIC1S_IICIF=1; //aclare bandera de interrupción //IIC1S_IICIF!=IIC1S_IICIF; //aclare bandera de interrupción //State_Led=IIC1S_SRW;}
this is main routine. as you can see, i added a restart command.
void main(void) { IIC1_Init(); EnableInterrupts; DelayMs(100);//Wake up Wii Motion Plus IIC1_StartBit(); IIC1_PutChar((0X53<<1)|I2C_WRITE); //send 0XA6 IIC1_PutChar(0XFE); IIC1_PutChar(0X04); IIC1_StopBit(); //Send Zero to Wii Moiton Plus IIC1_StartBit(); IIC1_PutChar((0X52<<1)|I2C_WRITE); //Send 0XA5 IIC1_PutChar(0X00); IIC1_StopBit(); //Calibrate zero for Wii Motion Plus. for (a=0;a<1;a++){//Send zeros again IIC1_StartBit(); IIC1_PutChar((0X52<<1)|I2C_WRITE); //Send 0XA4 IIC1_PutChar(0X00); IIC1_RepeatStart(); IIC1_PutChar((0X52<<1)|I2C_READ); //Send 0XA5 for (i=0;i<6;i++){ Dato[i]=IIC1_GetChar(); } IIC1_StopBit(); yaw0+=(((Dato[3]>>2)<<8)+Dato[0])/10; pitch0+=(((Dato[4]>>2)<<8)+Dato[1])/10; roll0+=(((Dato[5]>>2)<<8)+Dato[2])/10; } for(;;) {//Enviar cero al Wii Moiton Plus IIC1_StartBit(); IIC1_PutChar((0X52<<1)|I2C_WRITE); //Send 0XA5 IIC1_PutChar(0X00); IIC1_RepeatStart(); IIC1_PutChar((0X52<<1)|I2C_READ); // Send 0XA6 for (i=0;i<6;i++){ Dato[i]=IIC1_GetChar(); } IIC1_StopBit(); yaw=((Dato[3]>>2)<<8)+Dato[0]-yaw0; pitch=((Dato[4]>>2)<<8)+Dato[1]-pitch0; roll=((Dato[5]>>2)<<8)+Dato[2]-roll0; State_Led=~State_Led; DelayMs(300); }}
hope this information can help..
Regards;
Sorry, I can't help by reading your code.
I'm runnng I2C on a different Freescale CPU, an MCF5329 anyway.
I started with this source:
That link may or may not work. Go to the normal Freescale site and search for "MCF5282I2C". Then download that and compare with your code. Since it is for a different CPU (V2 and not V1) the I2C controller may be the same, may be different and may have different #defines for the registers.
I still advise looking at working and not-working signals with a CRO.
Tom