//------------------------------------------------------------

int xPin = 2; // select the input pin for the potentiometer

int gyroPin = 1;

int steerPin = 3;

int ledPin = 13; // select the pin for the LED

int pwmPinL = 9;

int pwmPinR = 10;

int enPin = 7;

float angle = 0;

float angle_old = 0;

float angle_dydx = 0;

float angle_integral = 0;

float balancetorque = 0;

float rest_angle = 0;

float currentspeed = 0;

int steeringZero = 0;

int steering = 0;

int steeringTemp = 0;

float p = 8; //2

float i = 0; //0.005

float d = 1300; //1000

float gyro_integration = 0;

float xZero = 0;

int gZero = 445; //this is always fixed, hence why no initialisation routine

unsigned long time, oldtime;

int pwmL;

int pwmR;

boolean over_angle = 0;

void setup() {

unsigned int i = 0;

unsigned long j = 0; //maximum possible value of j in routine is 102300 (100*1023)

pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT

Serial.begin(115200);

analogReference(EXTERNAL);

//----------------------------------------------------

TCCR1B = TCCR1B & 0b11111000 | 0x01;

analogWrite(pwmPinL,127);

analogWrite(pwmPinR,127);

digitalWrite(enPin,HIGH);

pinMode(enPin,OUTPUT);

digitalWrite(enPin,LOW);

//-----------------------------------------------------

delay(100);

for (i = 0; i < j =" j" steeringzero =" analogRead(steerPin);" xzero =" j/100;" oldtime =" micros();" time =" micros();">= (oldtime+5000)){

oldtime = time;

calculateAngle();

steering = (analogRead(steerPin) - steeringZero)/(15+(abs(angle)*8));

//-----OVER ANGLE PROTECTION-----

if (angle > 20 || angle < -20) { digitalWrite(enPin,HIGH); over_angle = 1; delay(500); } //-----END----- if (over_angle) { //if over_angle happened, give it a chance to reset when segway is level if (angle <> -1) {

digitalWrite(enPin, LOW);

over_angle = 0;

}

}

else {

//-----calculate rest angle-----

if (currentspeed > 10)

{

rest_angle = 0;

//-----END-----

angle_integral += angle;

balancetorque = ((angle+rest_angle)*p) + (angle_integral*i) + (angle_dydx*d);

angle_dydx = (angle - angle_old)/200; //now in degrees per second

angle_old = angle;

currentspeed += (balancetorque/200);

pwmL = (127 + balancetorque + steering);

//-----COERCE-----

if (pwmL < pwml =" 0;"> 255)

pwmL = 255;

//-----END-----

pwmR = (127 - balancetorque + steering);

//-----COERCE-----

if (pwmR < pwmr =" 0;"> 255)

pwmR = 255;

//-----END-----

analogWrite(pwmPinL, pwmL);

analogWrite(pwmPinR, pwmR);

}

}

}

void calculateAngle() {

//Analogref could be as small as 2.2V to improve step accuracy by ~30%

//uses small angle approximation that sin x = x (in rads). maybe use arcsin x for more accuracy?

//analogref is off the gyro power supply voltage, and routine is calibrated for 3.3V. maybe run acc/gyro/ref off 1 3.3V regulator, an

//accurately measure that.

//routine runs at 200hz because gyro maximum response rate = 200hz

float acc_angle = 0;

float gyro_angle = 0;

acc_angle = (((analogRead(xPin)-xZero)/310.3030)*(-57.2958);

gyro_angle = ((analogRead(gyroPin) - gZero)*4.8099)/200;

gyro_integration = gyro_integration + gyro_angle; //integration of gyro and gyro angle calculation

angle = (gyro_integration * 0.99) + (acc_angle * 0.01); //complementary filter

gyro_integration = angle; //drift correction of gyro integration

}

## Monday, 2 November 2009

### Arduino code

I see some of you are interested in the code.. well here it is, unedited:

## Monday, 29 June 2009

## Saturday, 20 June 2009

## Wednesday, 3 June 2009

### ESCs, power wiring and fuses...

At the top are the 2 electronic speed controllers, in the centre are the 2 fuses (1 40amp fuse for each controller). At the bottom is a test placement of the batteries, I've yet to make a mounting for them.

## Sunday, 26 April 2009

### OSMC

I have finished the Open Source Motor Controller boards:

I am using Deans T Connectors which I've read can handle upto 100A, but I doubt this could be sustained, but it does have the fact the body of the connector is made of nylon style plastic, not acrylic, so heat wouldn't deform it. So 100A could well be possible.

I am using Deans T Connectors which I've read can handle upto 100A, but I doubt this could be sustained, but it does have the fact the body of the connector is made of nylon style plastic, not acrylic, so heat wouldn't deform it. So 100A could well be possible.

## Sunday, 18 January 2009

### Calculating platform angle

I have written arduino code to calculate the platform angle and it works perfectly!

This is a graph made in Processing which is taking the angle calculated by the arduino from the serial port. I am oscillating the board quickly.

I am using the complementary filter approach documented by alot of balancing robots. The actual code is something like:

val = ((((analogRead(xPin)-xZero)/148.48)* 180/3.1415926535897932384626433832795))*-1); //accelerometer angle calculation

valG = valG + ((analogRead(gyroPin) - gZero)*4.8099347014925373134328358208962)/200; //integration of gyro and gyro angle calculation

angle = (val * 0.005) + (valG * 0.995); //complementary filter

valG = angle; //drift correction of gyro integration

I can tell it works as intended, because if i rotate the board flat on the table, the gyro senses it, whilst the accelerometer is still flat, so you see it increase and then decay slowly back to zero, rather like a capacitor discharge curve. This shows the accelerometer correcting the gyro's 'drift'.

Subscribe to:
Posts (Atom)