kd5uzz
Joined: 28 May 2006 Posts: 56
|
Servo control via Nunchuck |
Posted: Tue Nov 27, 2007 5:45 pm |
|
|
I'm trying to use a wii nunchuck to control a pan/tilt servo mount. When I manually change the values sent to servo() I have very fine control. When I use a pot on ADC channel 0, I have rather fine control. When I use the values from the nunchuck it is horrid. Looking at it on a scope the waveform isn't well formed. I think the i2c functions slow my code down to the point it can't create the correct forms. I've tried only reading the nunchuck every 20ms, but I have the same problem. How would you guys write a servo controller to control many many servos? It doesn't need to talk to the nunchuck directly, but it will need to talk to another PIC (and that pic will talk to the nunchuck, later on in the project.)
Code: |
#include "16f876.h"
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=57600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(Master, sda=PIN_c4, scl=PIN_c3)
#define NUNCHUCK_I2C_WRITE_ADDR 0xA4
#define NUNCHUCK_I2C_READ_ADDR 0xA5
#define HeartBeat PIN_B5
#define HeartBeatOn output_high(HeartBeat)
#define HeartBeatOff output_low(HeartBeat)
#define PAN_SERVO PIN_B3
#define TILT_SERVO PIN_B4
#define PAN_POS 800
#define TILT_POS 900
#define SERVORIGHT 500
#define SERVOLEFT 2500
int16 tv;
int16 R;
int16 x,y,P1,P2;
int8 buffer[6] = {0};
void nunchuck_init(void){
i2c_start();
i2c_write(NUNCHUCK_I2C_WRITE_ADDR);
i2c_write(0x40);
i2c_write(0x00);
i2c_stop();
}
void nunchuck_read_data(){
i2c_start();
i2c_write(NUNCHUCK_I2C_WRITE_ADDR);
i2c_write(0);
i2c_stop();
delay_us(150); // This delay is necessary.
i2c_start();
i2c_write(NUNCHUCK_I2C_READ_ADDR);
buffer[0] = i2c_read();
buffer[1] = i2c_read();
buffer[2] = i2c_read();
buffer[3] = i2c_read();
buffer[4] = i2c_read();
buffer[5] = i2c_read(0);
i2c_stop();
}
void Servos(long Pos1, long Pos2){
tv = get_timer1();
if (tv >= Pos1){
output_low(PAN_SERVO);
}
if (tv >= Pos2 ){
output_low(TILT_SERVO);
}
if (tv >= 12500){
//20ms passed
set_timer1(0);
output_high(PAN_SERVO);
output_high(TILT_SERVO);
}
}
//---------------------------------
void main(){
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports( ALL_ANALOG );
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
set_timer1(0);
R=7.8;
printf("\n\r\n\rNunchuck + Servo Test 1.0\n\r\n\r");
nunchuck_init();
delay_ms(100);
while (TRUE) {
nunchuck_read_data();
P1=(long)buffer[0]*R;
P2=(long)buffer[1]*R;
//printf("\n\rX: %ld/%U Y: %ld/%U",P1,buffer[0],P2,buffer[1]);
Servos(P1,P2 );
}
}
|
|
|