Modificar angulo de giro de servo + nuchuck

Buenas a todo el foro, en primer lugar gracias de antemano, y enhorabuena por todos los proyectos, y ahora voy con el mio...

estoy montado una cámara giroscópica para grabar en la moto cuando vamos al circuito, y he montado un sistema con un servo y el acelerómetro del nunchuck de la wii,
el funcionamiento en bueno pero el alulo de giro del servo es mayor que el angulo de giro del acelerómetro por lo que la cámara no queda recta...

donde podría cambiar el ángulo del giro del servo en el siguiente código... GRACIAS otra vez...

#include <Wire.h>
#include <string.h>
#include <stdio.h>

uint8_t outbuf[6];
uint8_t ctrlr_type[6];
int cnt = 0;
int ledPin = 13;

int servoPin = 7;
int servoPin2 = 6;

int pulseWidth = 0;
int pulseWidth2 = 0;

long lastPulse = 0;
long lastPulse2 = 0;

int z_button = 0;
int c_button = 0;

int refreshTime = 20;

int minPulse = 1000;
int minPulse2 = 500;

int dtime=10;

#define pwbuffsize 10
long pwbuff[pwbuffsize];
long pwbuffpos = 0;
long pwbuff2[pwbuffsize];
long pwbuffpos2 = 0;

void setup()
{
// beginSerial (19200);
Wire.begin ();
nunchuck_init ();
pinMode(servoPin, OUTPUT);
pinMode(servoPin2, OUTPUT);

pulseWidth = minPulse;
pulseWidth2 = minPulse2;
Serial.print ("Finished setup\n");
}

void nunchuck_init()
{
byte cnt;

Wire.begin();

// init controller PARA NUNCHAKU NO ORIGINAL
//_________________________________________
delay(1);
Wire.beginTransmission(0x52); // device address
Wire.send(0xF0); // 1st initialisation register
Wire.send(0x55); // 1st initialisation value
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0xFB); // 2nd initialisation register
Wire.send(0x00); // 2nd initialisation value
Wire.endTransmission();
delay(1);

// read the extension type from the register block
Wire.beginTransmission(0x52);
Wire.send(0xFA); // extension type register
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6); // request data from controller
for (cnt = 0; cnt < 6; cnt++) {
if (Wire.available()) {
ctrlr_type[cnt] = Wire.receive(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
}
}
Wire.endTransmission();
delay(1);

// send the crypto key (zeros), in 3 blocks of 6, 6 & 4.
Wire.beginTransmission(0x52);
Wire.send(0xF0); // crypto key command register
Wire.send(0xAA); // sends crypto enable notice
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.send(0x40); // crypto key data address
for (cnt = 0; cnt < 6; cnt++) {
Wire.send(0x00); // sends 1st key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40); // sends memory address
for (cnt = 6; cnt < 12; cnt++) {
Wire.send(0x00); // sends 2nd key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.send(0x40); // sends memory address
for (cnt = 12; cnt < 16; cnt++) {
Wire.send(0x00); // sends 3rd key block (zeros)
}
Wire.endTransmission();
delay(1);
// end device init
}

void send_zero()
{
Wire.beginTransmission (0x52);
Wire.send (0x00);
Wire.endTransmission ();
}

int t = 0;

void loop()
{
t++;
long last = millis();

if( t == 1) {

t = 0;

Wire.requestFrom (0x52, 6);

while (Wire.available ()) {
outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());
digitalWrite (ledPin, HIGH);
cnt++;
}

if (cnt >= 5) {

// printNunchuckData();

int z_button = 0;
int c_button = 0;

if ((outbuf[5] >> 0) & 1)
z_button = 1;
if ((outbuf[5] >> 1) & 1)
c_button = 1;

switch (c_button) {
case 1:
switch (z_button) {
case 0:
break;
case 1:
muovi();
break;
}
break;
case 0:
switch (z_button) {
case 0:
delay(10000);
break;
case 1:
delay(3000);
break;
}
break;
}
}

cnt = 0;
send_zero();

} // if(t==)

updateServo();

delay(dtime);
}

void updateServo() {

if (millis() - lastPulse >= refreshTime) {

digitalWrite(servoPin, HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(servoPin, LOW);

digitalWrite(servoPin2, HIGH);
delayMicroseconds(pulseWidth2);
digitalWrite(servoPin2, LOW);

lastPulse = millis();
}
}

int i=0;
void printNunchuckData()
{
int joy_x_axis = outbuf[0];
int joy_y_axis = outbuf[1];
int accel_x_axis = outbuf[2]; // * 2 * 2;
int accel_y_axis = outbuf[3]; // * 2 * 2;
int accel_z_axis = outbuf[4]; // * 2 * 2;

int z_button = 0;
int c_button = 0;

if ((outbuf[5] >> 0) & 1)
z_button = 1;
if ((outbuf[5] >> 1) & 1)
c_button = 1;
if ((outbuf[5] >> 2) & 1)
accel_x_axis += 2;
if ((outbuf[5] >> 3) & 1)
accel_x_axis += 1;

if ((outbuf[5] >> 4) & 1)
accel_y_axis += 2;
if ((outbuf[5] >> 5) & 1)
accel_y_axis += 1;

if ((outbuf[5] >> 6) & 1)
accel_z_axis += 2;
if ((outbuf[5] >> 7) & 1)
accel_z_axis += 1;

Serial.print (i,DEC);
Serial.print ("\t");

Serial.print ("X: ");
Serial.print (joy_x_axis, DEC);
Serial.print ("\t");

Serial.print ("Y: ");
Serial.print (joy_y_axis, DEC);
Serial.print ("\t");

Serial.print ("AccX: ");
Serial.print (accel_x_axis, DEC);
Serial.print ("\t");

Serial.print ("AccY: ");
Serial.print (accel_y_axis, DEC);
Serial.print ("\t");

Serial.print ("AccZ: ");
Serial.print (accel_z_axis, DEC);
Serial.print ("\t");

Serial.print (z_button, DEC);
Serial.print (" ");
Serial.print (c_button, DEC);
Serial.print ("\r\n");
i++;
}

char nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
return x;
}

void muovi (){
float tilt = (700 - outbuf[3]22);
float tilt2 = outbuf[2]22;

tilt = (tilt);
pulseWidth = (tilt * 5) + minPulse;

tilt2 = (tilt2-288);
pulseWidth2 = (tilt2 * 5) + minPulse2;

pwbuff[pwbuffpos] = pulseWidth;
pwbuff2[pwbuffpos2] = pulseWidth2;

if( ++pwbuffpos == pwbuffsize ) pwbuffpos = 0;
if( ++pwbuffpos2 == pwbuffsize ) pwbuffpos2 = 0;

pulseWidth=0;
pulseWidth2=0;

for( int p=0; p<pwbuffsize; p++ ){
pulseWidth += pwbuff[p];
pulseWidth2 += pwbuff2[p];
}

pulseWidth /= pwbuffsize;
pulseWidth2 /= pwbuffsize;

}

ZASCA¡¡¡¡
No esperes que la gente se ponga a leer tanto código :smiley: tela .... :smiley:

te cuento... el nunchuk te da valores de aceleracion, cuando la moto acelere, decelere, esté dando una curva etc tendras muchas variaciones. Lo puedes resolver con un filtro con con un PID, hay una libreria para utilar estos ultimos.

el acelerómetro te da valores entre 0 y 255 según sea la aceleracion, si tan solo lo sostienes con la mano tendrás valores medidos de la gravedad.

al margen de esto si quieres adecuar un rango de valores a otro rango de valores utiliza la funcion map()

tiens la informacion en http://arduino.cc/es/Reference/Map

de esta manera adecuas los valores del sensor a un angulo máximo y minimo que quieras en el servo

un saludo.

dices que ya funciona este codigo?
yo tambien entro en a circuito con moto por lo que me interesa mucho tu invento. tienes alguna foto?

pensaba que estas camaras funcionarian sobre un giroscopio tipo este:

pero parece que funcionan como tu dices:

a ver si puedes poner alguna fotito que siempre motiva al personal :wink:

V'sssss

Ahora mismo tengo montado un prototipo en un coche de rc,
Aqui teneis el enlace de como funciona, el servo que he montado es de prueba y es muy lento ( cuando lo ajuste y pruebe lo cambiare por uno mas rapido...
Pero el problema es el comentado, el servo gira mas que lo que se inclina el coche...

gracias a todos...

Hacer un Map de los valores no lo veo muy preciso. Yo me hice como un mando para le ordenador con un nuchuck (Video: Arcade Handgun - First Test on Modern Warfare 2 (Teensy 2.0 & Arduino Soft.) - YouTube) y hice este código:

///MOVE MOUSE Y
if(accel_y_axis > 630){
Mouse.move(0,(accel_y_axis-630)/4);
}
if(accel_y_axis < 580){
Mouse.move(0,(accel_y_axis-580)/4);
}

Variando el 4 de la división conseguía más o menos precisión en los movimientos.

Yo en tu caso, cogería y leería los valores del acelerometro por serial y enviaría por serial un angulo al servo, cuando el servo estuviera en la posición ideal me apuntaría el valor del acelerometro y el angulo del servo, comprobaría si es constante el valor del acelerometro con el angulo del servo, si es así puedes hacer un Map global, si no por if dependiendo del valor que haga un Map u otro.

También yo por algunas experiencias que he tenido con muchos servos, cuando lo mueves a un angulo Xº luego lo mueves a otro Yº y vuelves a Xº no se queda exactamente igual siempre se tuerce un poco.

crees que con un solo acelerometro vas a poder determinar el angulo de giro correcto?
lo digo porque cuando la moto este en circuito vas a tener aceleraciones, frenadas, derrapadas, caballitos, hundimiento de horquilla delantera etc etc que pienso yo que haran que se vuelva loco el acelerometro.
lo digo porque en esta web habla de que usan 2 acelerometros para determinar la inclinación de la moto.

http://img.motorpasionmoto.com/2010/07/gyroscopic-motogp-cam.jpg

gracias por el video ! seguire muy de cerca tu post y es posible que este verano me anime a montar una.
por si te interesa, tengo planeado hacer cositas con arduino y mi suzuki, desde alarma con gps hasta .... ya veremos jeje

Despues de mucho tocar el codigo, he modificado un parametro.. ( si es efectivo ya lo pondre ) y el resultado es el siguiente

Mas cositas en www.lisergio-z.com

Pues ya lo he probado montado en un coche, pero como bien comentaban en una respuesta anterior, en parado funciona ok, pero andando se suma la inclinación a la inercia y compensa demasiado... solo se me ocurre disminuir el giro para compensar la inercia... o se puede eliminar este parametro? y dejar solo en angulo de giro?