Connecting 16F877A to Wiimote using I2C

Status
Not open for further replies.

Sodrohu

New Member
Hello and Hi. I'm new to I2C and had been searching around for some code. What I want to do is to make the Wiimote able to get data from the PIC by making the PIC act like the Nunchuk. The original project was done here **broken link removed**. My intention is to finally create the firefighting robot **broken link removed**, but I want to start from scratch to understand everything.

Currently this is the code that I have come up with. It is based on Mike Alon's code Microchip PIC micros and C - source and sample code. I've modified to the best of my current knowledge to mimic the original code, which uses Arduino.

This code I've tried several times with several modifications with no success so far. To detect if the PIC is sending data to the Wiimote, I used a Wiimote Driver (Bian Peek's WiimoteLib). If it works, then it should be indicated on the driver's UI.

I'm not entirely sure if my approach is correct. There are several things I am still unsure of, like:

1. in the original project, the red wire(3.3V ) goes to AREF. I connect mine to the ground. Is that correct? I only did so because otherwise connecting the I2C port to the Wiimote crashes the driver.
The rest of code related thinsg I do not understand are commented in the codes. The PIC runs a s master

Code:
/******************************************************************************************/

#include <pic.h>
#include "Delay.h"
#include "Delay.C"
#include  "877_i2c.h"

__CONFIG ( 0x3F32 ); //configuration for the  microcontroller, is this necessary?

uint8_t outbuf[6]; //buffer to send to Wiimote, need to be send 6 bytes at a time


//original Mike Alon code, for reference
void write_ext_eeprom(unsigned char address, unsigned char data)
 {
   i2c_start();
   i2c_write(0xa0);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();
   DelayMs(11);
}

/******************************************************************************************/
//original Mike Alon code, for reference
unsigned char read_ext_eeprom(unsigned char address)
{
   unsigned char data;

   i2c_start();
   i2c_write(0xa0);
   i2c_write(address);
   i2c_repStart();
   i2c_write(0xa1);
   data=i2c_read(0);
   i2c_stop();
   return(data);
}

/******************************************************************************************/

//this is where it should send data to the Wiimote
void write_six_bytes(unsigned char address)
 {
   i2c_start();
   i2c_write(0xa0);//don't understand this part, is it to initialise the connection?
   i2c_write(address);
   //i2c_write(outbuf);//I'm not sure if should send the entire outbuf in one go
   i2c_write(outbuf[0]);//or outbuf[0],1,2...somehow trying both didn't work
   i2c_write(outbuf[1]);
   i2c_write(outbuf[2]);
   i2c_write(outbuf[3]);
   i2c_write(outbuf[4]);
   i2c_write(outbuf[5]);
   i2c_stop();
   DelayMs(11);
}

/******************************************************************************************/

void init_nunchuk ()
{
//  outbuf[0] = nunchuk_encode_byte (125);  // joystick X
//  outbuf[1] = nunchuk_encode_byte (126);  // joystick Y
//  outbuf[2] = nunchuk_encode_byte (227);  // Axis X
//  outbuf[3] = nunchuk_encode_byte (241);  // Axis Y
//  outbuf[4] = nunchuk_encode_byte (140);  // Axis Z
//  outbuf[5] = nunchuk_encode_byte (1);  // Press C button, byte[5] is buttons 
                                        //C,Z and accelaration data
  //outbuf[5] = nunchuk_encode_byte(2); // Press Z button
  //outbuf[5] = nunchuk_encode_byte(0); // Press Z and C button

//the byte allocation without the encryption
  outbuf[0] = 125
  outbuf[1] = 126
  outbuf[2] = 227
  outbuf[3] = 241
  outbuf[4] = 140
  outbuf[5] = 1
}

/******************************************************************************************/

// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_encode_byte (char x)
{
  x = x - 0x17;
  x = (x ^ 0x17);
  return x;
}

/******************************************************************************************/

void main()
{
 unsigned char i=0;

 PORTB=0x00;    // port
 PORTC=0x00;    // port

 //setup ADC
 ADCON1 = 0b00000110;

 TRISB=0x00;    //portb out
 TRISC=0x00;    //portc out

i2c_init();    // init i2c 

 init_nunchuk();
 

 while(1)   
  {        
		//PORTB=i;                  //
		  write_six_bytes(0xA4);   // 
		 
		  DelayMs(255);
  }


}
/******************************************************************************************/
 
Some updates:

I managed to get the PIC to send data to the Wiimote. Unfortunately, the driver is not receiving it as Nunchuk data, but instead as IR data. I am not sure where I got things wrong. I've tried to send data to address 0x52 and 0xA4, which is the CCS convention that I've got from here CCS :: View topic - Reading multi-bytes from an i2c slave - Wii Nunchuck

This is the new code:

Code:
#include <pic.h>
#include "delay.h"
//#include "delay.c"
#include  "877_i2c.h"

__CONFIG ( 0x3F32 );		//configuration for the  microcontroller

#define	SW1			RB0			
#define	SW2			RB1			

#define	LED1		RB6			
#define	LED2		RB7
#define LED			RA1
#define addA4		0xa4
#define add52		0x52 
//#define addA4		0xa4

uint8_t outbufnocode[6];
uint8_t outbufencode[6];
uint8_t receive;

//	function prototype		(every function must have a function prototype)
void delay(unsigned long data);			
void send_config(unsigned char data);
void send_char(unsigned char data);
void lcd_goto(unsigned char data);
void lcd_clr(void);
void send_string(const char *s);
void uart_send(unsigned char data);
void write_ext_eeprom(unsigned char address, unsigned char data);
unsigned char read_ext_eeprom(unsigned char address);

void write_six_bytes_nocode(unsigned char address);
void write_six_bytes_encode(unsigned char address);
unsigned char read_six_bytes(unsigned char address);
void init_nunchuk_nocode (void);
void init_nunchuk_encode (void);
char nunchuk_encode_byte (char x);
//void nunchuck_init(void);
void DelayMs(unsigned char);
void DelaySec(char sec);

void main()
{
	unsigned long delay_time=5000;

	//set I/O input output
	
	TRISB = 0b00000011;				//configure PORTB I/O direction
	TRISD = 0b00000000;				//configure PORTD I/O direction
	TRISA = 0b00000111;				//configure PORTA I/O direction
	
	//setup ADC
	ADCON1 = 0b00000110;				//set ADx pin digital I/O

	LED1=0;								//OFF LED1
	LED2=0;								//OFF LED2

i2c_init();    // init i2c 

 init_nunchuk_nocode();
 init_nunchuk_encode();
 

 while(1)   
  {        
		//PORTB=i;
		  LED = 1;                  //
		  //write_six_bytes(0xa4);   // 
		 
		  DelayMs(255);
//		  write_six_bytes_nocode(0xa4);   // 
//		  DelayMs(255);
//
		  write_six_bytes_nocode(0x52);   // 
		  DelayMs(255);

//		  write_six_bytes_encode(0xa4);   // 
//		  DelayMs(255);
//
//		  write_six_bytes_encode(0x52);   // 
//		  DelayMs(255);


          read_six_bytes(0x52);   // 
		  DelayMs(255);
		  LED = 0;

		if(!SW1)						//check if SW1 is pressed
		{
			while (!SW1);				//wait SW1 pressed
			{
				delay_time+=1000;		//delay
			}
		}
		else if(!SW2)					//check if SW2 is pressed
		{
			while (!SW2);				//wait SW2 pressed
			{
				delay_time-=1000;		//delay
			}
		}
		
		LED1^ = 1;					//toggle LED1
		delay(delay_time);				
		LED2^ = 1;					//toggle LED2			
		delay(delay_time);	
  }
}

//	functions
//==========================================================================
void delay(unsigned long data)			//delay function, the delay time
{										//depend on the given value
	for( ;data>0;data--);
}

//
void write_six_bytes_nocode(unsigned char address) 
 {
   i2c_start();
   //i2c_write(0xa0);
   i2c_write(address);
//   i2c_write(outbufnocode);
   i2c_write(outbufnocode[0]);
   i2c_write(outbufnocode[1]);
   i2c_write(outbufnocode[2]);
   i2c_write(outbufnocode[3]);
   i2c_write(outbufnocode[4]);
   i2c_write(outbufnocode[5]);
   i2c_stop();
   DelayMs(11);
}

void write_six_bytes_encode(unsigned char address) 
 {
   i2c_start();
   //i2c_write(0xa0);
   i2c_write(address);
   //i2c_write(outbufencode);
   i2c_write(outbufencode[0]);
   i2c_write(outbufencode[1]);
   i2c_write(outbufencode[2]);
   i2c_write(outbufencode[3]);
   i2c_write(outbufencode[4]);
   i2c_write(outbufencode[5]);
   i2c_stop();
   DelayMs(11);
}

unsigned char read_six_bytes(unsigned char address)
{
   unsigned char data;

   i2c_start();
   //i2c_write(0xa0);
   i2c_write(address);
   //i2c_repStart();
   //i2c_write(0xa1);
   receive =i2c_read(0);
   i2c_stop();
   return(data);
}

void init_nunchuk_nocode ()
{
  outbufnocode[0] = 125;
  outbufnocode[1] = 126;
  outbufnocode[2] = 227;
  outbufnocode[3] = 241;
  outbufnocode[4] = 140;
  outbufnocode[5] = 1;
//return outbuf;
}

void init_nunchuk_encode ()
{
  outbufencode[0] = nunchuk_encode_byte (125);  // joystick X
  outbufencode[1] = nunchuk_encode_byte (126);  // joystick Y
  outbufencode[2] = nunchuk_encode_byte (227);  // Axis X
  outbufencode[3] = nunchuk_encode_byte (241);  // Axis Y
  outbufencode[4] = nunchuk_encode_byte (140);  // Axis Z
  outbufencode[5] = nunchuk_encode_byte (1);  // Press C button, byte[5] is buttons 
//return outbuf;
}

char nunchuk_encode_byte (char x)
{
  x = x - 0x17;
  x = (x ^ 0x17);
  return x; 
}
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…