Tras los proyectos de domótica realizados, me atraía la idea de hacer un robot un poco más dinámico y menos aburrido que hacer subir y bajar la persiana. Desde que vi un Segway quedé fascinado por el funcionamiento, la suavidad y el manejo tan simple que tenía, a la vez que combinaba una tecnología compleja para permanecer en equilibrio. Con los avances tecnológicos que ha habido en el siglo XX, parece mentira que hasta el siglo XXI (alrededor del 2000 o 2001) no se haya inventado este medio de transporte individual. Hoy en día es usado en las grandes industrias para que los empleados se desplacen de un lugar a otro, también lo usan los agentes de seguridad en aeropuertos, en zonas peatonales… Así que me propuse hacer un segway, o más bien, un minisegway con lo que tenía por casa, el controlador sería como no nuestra placa arduino, con el controlador de motores,  como acelerómetro usaríamos el del mando nunchuck de la wii, un par de motores y listo, sólo quedaría la programación, que no es poco. Así que monté todo el chasis instalé todos los componentes y me puse manos a la obra con el código. En primer lugar probé un código simple, que leyese el ángulo del acelerómetro y si pasase del punto de equilibrio hacia un lado o hacia otro andase adelante o hacia atrás, dependiendo. Evidentemente no fue así de fácil, tenía que tener en cuenta la aceleración, conforme se fuese cayendo fuera acelerando para contrarrestar la caída, así que tras varios intentos fallidos hice el siguiente código:

// Miguel Angel Torres de la Camara, matc2068@gmail.com, openmechatronics.wordpress.com
//Robotica, mecatronica libre: Segway

#include <Servo.h>

#include <CursoArduino.h>

#include <WiiNChuck.h>

#include <Wire.h>

WiiNChuck chuck;
//acelerometros
int accx;
int accy;
int e = 95; //angulo de equilibrio
void setup(){
Wire.begin();
inicializa();
chuck.begin();
Serial.begin(9600);
}
void aceleraMotor(){ //funcion de aceleracion del motor
int x = 15;
if (accy < 40 && accy > 140){ // si el angulo que sale es < 40 o > 140 acelera mas
x = 2*x;
}
else{
x = 2*x;
}
if (accy < e){  //conforme caiga hacia la izquierda retrocede
retrocede(-((accy-e)-x));
}
else if (accy > e){ //conforme caiga a la derecha avanza
avanza((accy-90)+x);
}
}

void loop(){
chuck.update();
//acelerometros
accx=chuck.AccelX();
accy=((chuck.AccelY()) – 385); // al restar 385 el valor minimo pasa a ser 0, y el maximo 180

Serial.print(»  Acc X: «); //imprime acelerometro eje x
Serial.print(accx);
Serial.print(»  Acc Y: «); //imprime acelerometro eje y
Serial.print(accy);

Serial.println();     //salto de linea
delay(10);

//control de motores
int der = 180; //angulo maximo
int izq = 0; //angulo minimo
if (accy > izq && accy < der){ //si se sale de ese rango, o sea si vuelca, para
aceleraMotor();
}

else {
para();
}
}

Pues aunque en la teoría debía funcionar, en la práctica permanece en pie pocos segundos, así que si alguien sabe cómo se puede solucionar le invito a que modifique el código. Como pista os puedo dar que hay que usar un sistema PID.