First prototype testing in school, it runs pretty slow here as we are not confidence with our 1st riding.....
Modified into a seated version together with my friend, the centre was the seated version prototype. We are happy that it was so stable that we can sit on it and do stuff like a normal chair, or ride around with it.
Next, is to put some fiber glass to make the design more cool....I will try to upload the components used for the big prototype when free...
Ok after getting all the parts, just assemble up and start writing the code. I don't start the code myself from scratch, I take the a reference of the code from here http://tlb.org/scooter.html, the original code was written in C, so i changed it to arduino language... it looks much simpler with arduino.
Because the prototype is very small and I have no background in the mechanical, so this design is not the perfect design, just to prove that the algorithm and code works correctly before starting to build the human scale segway. This is my most successful build after a lot of tuning on the PD value. Note I only used PD, haven't tried the I, which is the PID control loop.
and here is the code,
#define PwmPinMotorA 10 //pin connected to motor left#define PwmPinMotorB 11 //pin connected to motor right#define DirectionPinMotorA 12 //pin to control the left motor forward/reverse#define DirectionPinMotorB 13 //pin to control the right motor forward/reverse constintgyro=0;constintxpin=1;// x-axis of the accelerometerfloatgyro_angle=0;floatgyro_offset=0;floatangle=0;floatgyro_integration=0;floatxZero=0;floatangle_offset=0;floatdistance=0;floatp=3;// This value is the constant for tuning P floati=0; // The I was not used in this code yetfloatd=10;//This value is the constant for tuning Dfloatangle_old=0;floatangle_real=0;floatangle_integral=0;floatbalancetorque=0;intpwmA=0;intpwmB=0;voidsetup(){pinMode(PwmPinMotorA,OUTPUT);pinMode(PwmPinMotorB,OUTPUT);pinMode(DirectionPinMotorA,OUTPUT);pinMode(DirectionPinMotorB,OUTPUT);Serial.begin(115200); //initialize the usb serial commanddelay(1000);xZero=analogRead(xpin);gyro_offset+=analogRead(gyro);gyro_offset+=analogRead(gyro);gyro_offset+=analogRead(gyro);gyro_offset+=analogRead(gyro);gyro_offset+=analogRead(gyro);gyro_offset+=analogRead(gyro);gyro_offset+=analogRead(gyro);gyro_offset+=analogRead(gyro);gyro_offset=gyro_offset/8;for(intz=0;z<300;z++){calculatei();angle_offset+=angle;}angle_offset=angle_offset/300;}voidloop(){calculate();motor_speed();motor_control();Serial.print(analogRead(xpin));Serial.print("\t");Serial.print(gyro_angle);Serial.print("\t");Serial.print(angle_real);Serial.print("\t");Serial.print(pwmA);Serial.println();angle_old=angle;}voidinit_pos(){angle=xZero-350;distance=(sin(angle*3.141592654/180))*7;if(distance<0){distance=distance*(-1);pwmA=distance/0.1+60;pwmB=distance/0.1+60;analogWrite(PwmPinMotorA,pwmA);digitalWrite(DirectionPinMotorA,LOW);analogWrite(PwmPinMotorB,pwmB);digitalWrite(DirectionPinMotorB,HIGH);}else{pwmA=distance/0.1+60;pwmB=distance/0.1+60;analogWrite(PwmPinMotorB,pwmB);digitalWrite(DirectionPinMotorB,LOW);analogWrite(PwmPinMotorA,pwmA);digitalWrite(DirectionPinMotorA,HIGH);}}voidcalculatei(){floatacc_reading=0;acc_reading=((analogRead(xpin)-xZero));gyro_angle=((analogRead(gyro)-gyro_offset))*1/80;gyro_integration=gyro_angle+gyro_integration;angle=(gyro_integration*0.99)+(acc_reading*0.01);//angle = angle - angle_offset;gyro_integration=angle;distance=(sin(angle*3.141592654/180))*11;}voidcalculate(){floatacc_reading=0;acc_reading=((analogRead(xpin)-xZero));gyro_angle=((analogRead(gyro)-gyro_offset))*1/80;gyro_integration=gyro_angle+gyro_integration;angle=(gyro_integration*0.98)+(acc_reading*0.02);angle_real=angle-angle_offset;gyro_integration=angle;distance=(sin(angle*3.141592654/180))*11;}voidmotor_speed(){if(distance<0){distance=distance*(-1);}angle_integral+=angle;balancetorque=(angle_real*p)+(gyro_angle*d);//pwm = (((distance/(0.044444444))/0.5)+80);if(balancetorque>180){balancetorque=180;}if(balancetorque<-180){balancetorque=(-180);}}voidmotor_control(){if(balancetorque<0){pwmA=(((-1)*balancetorque));pwmB=(((-1)*balancetorque));analogWrite(PwmPinMotorA,pwmA);digitalWrite(DirectionPinMotorA,LOW);analogWrite(PwmPinMotorB,pwmB);digitalWrite(DirectionPinMotorB,HIGH);}if(balancetorque>=0){pwmA=(balancetorque);pwmB=(balancetorque);analogWrite(PwmPinMotorB,pwmB);digitalWrite(DirectionPinMotorB,LOW);analogWrite(PwmPinMotorA,pwmA);digitalWrite(DirectionPinMotorA,HIGH);}}
Some part in the code was redundant, as I had tried many different ways to fine tune it, however I didn't remove the line after that.... but basically you just need to know that the robot was controlled using the angle of the tilt, so the most important part is the calculate() function which uses complementary filter to get the tilted angle.