Setting up the tuning for your T-Bot
Tuning Steps
- Adjusting the Gyro Trim
- Setting the PID parameters
- Adjusting the Rotational Trim
Adjusting the Gyro Trim
When you're getting started, the most important parameter to change will be the trim. You might have to change it by up to ±10 degrees.
Hold your T-Bot in the upright position off the floor. Press the autotrim button. Now place the T-Bot on the floor and press the autotrim again.
When the T-Bot stops drifting forwards or backwards, take note of the gtrim value. Find the section of code in TBot.ino that looks like this:
//////////////////// Speed and Stability tunings ///////////////////////// float gtrim = 0.0; // Compensated for drift in forward or reverse direction.and set the gtrim according to the value returned in the T-Bot Controller.
Manual adjustment of Gyro Trim
If your T-Bot is rushing forward, make the gtrim more negative, conversely if it is rushing backward, make the gtrim more positive. You can also use the Bluetooth controller to adjust the gtrim. You might want to increase the increment step size temporarily when you’re adjusting this for the first time. To do this, locate the following snippet of code in functions.ino:
// ----------------- BUTTON #5 ----------------------- case 'I': // configured as momentary button gtrim += 0.05; break; case 'J': buttonStatus &= B101111; // OFF gtrim += 0.05; break; // ----------------- BUTTON #6 ----------------------- case 'K': buttonStatus |= B100000; // ON gtrim -= 0.05; break; case 'L': gtrim -= 0.05; break;
Change 0.05 to 1. Once your are close, set the increment back 0.05 and hard code the gtrim to the value you have discovered.
Adjusting the Combination Filter Coefficient
See the Kalman Filter Tutorial. You probibly wont need to change this value but is central to understanding how your T-Bot balances.
The value can be changed in TBot.ino
float filter_weighting = 0.015; // See Combination_Filter.h
Setting the PID parameters
Please read the PID Tutorial if you haven’t already. The PID tuning should already be good but there is always room for improvement. The T-Bot uses a cascading PI loop. There is a speed control loop that feeds into a stability control loop. Locate the section of code in Tbot.ino that looks like this:
double speedKp=0.10, speedKi=0, speedKd=0.0, KPS = 0.10, KP = 4.2, KI = 65, KPS_last, KP_last, KI_last; double gyroKp=4.2, gyroKi=65, gyroKd=0.0; double speedSetpoint, speedInput, speedOutput; PID speedPID(&speedInput, &speedOutput, &speedSetpoint, speedKp, speedKi, speedKd, DIRECT); double gyroySetpoint, gyroyInput, gyroyOutput; PID gyroyPID(&gyroyInput, &gyroyOutput, &gyroySetpoint, gyroKp, gyroKi, gyroKd, DIRECT);
- speedKp, KPS is the speed proportional coefficient
- speedKi is the speed integral coefficient
- gyroKp, KP is the stability proportional coefficient
- gyroKi, KI is the stability integral coefficient
- gyroKd, is the stability derivative coefficient
The awkward naming here is to accomodate incrimental changes via the controller. Note speedKp and KPS, gyroKp and KP etc. sohould have the same value.
Try experimenting with the values.
Adjusting the Rotational Trim to Prevent Unwanted Rotation
There are two elements to this:- Rotational Trim - rtrim
- Motor calibration and Deadbands
The rotational trim can be adjusted using:
float rtrim = 0.0; // Compensated for rotational drift.
This might achieve the desired result but it is probably better to take the time to calibrate the motors.
Calibrating the Motors
Determine the deadband of the motors
You can use DCMotorCalibrate.ino for this step. The speed of the motors is controlled by a PWM (Pulse width modulation) voltage. The PWM frequency is too high for the motors to keep up with the rise and fall of the PWM voltage. Instead, the motor runs with a current which is proportional to the effective voltage given by the fraction of the duty cycle (see PWM Tutorial 1 and PWM Tutorial 2). Unfortunately, in the real world motors don’t quite conform to this ideal behaviour. Assuming we have an 8-bit controller, we should have 256 values for the duty cycle and we do. However, the motors typically don’t respond to values less than 25. In other words, the motors won’t respond to values below 14 % of the duty cycle.
The motor driver has two deadband settings for each motor; a positive deadband and a negative deadband. Beginning with Motor 1, set m1ndb and m2pdb to 0. Change the value in m1.speed(0) to 20 and upload the code to the T-Bot. Slowly increase the value until the wheel just begins to turn then reduce it again by 2. You now have the value for the positive deadband. Repeat for the negative direction and again for Motor 2. All values should be positive even though the you will have used negative values for the reverse direction.
Set the mpsfactor (metres per second factor) for the motors.
Setting up a PID loop for the T-Bot is easier when the inputs are closely related to the outputs. We want to control the speed of the T-Bot so is reasonable to convert the speed of the motors to metres per second. You can do a single point calibration by setting the motor speed to 255 (with the the mpsfactor set to 1) and using a stopwatch to time several revolutions. It is quite tricky to keep track of the revolutions. A little bit of tape attached to the wheel helps. The diameter of the wheel is 48 mm so if the wheel turns at 7 revs per second, then:
mpsfactor = 255/(0.048*pi*7).
If you want to be more precise, you can do this for several speeds and fit with a polynomial.
#include// Setup Motors // Set motor deadbands // m1 is the right motor m2 is the left const int m1ndb = 0 , m1pdb = 0, m2ndb = 0 , m2pdb = 0; //const int m1ndb = 34 , m1pdb = 34, m2ndb = 34 , m2pdb = 34; // T-Bot // Set pins and metres per second factor const int m2stby = 6, m2ain1 = 4, m2ain2 = 5, m2pwmpin = 9, mpsfactor = 1, mpsfactor2 = 1; Motor m1 = Motor(m2ain1, m2ain2, m2stby, m2pwmpin, m1ndb, m1pdb, mpsfactor); const int m1stby = 6, m1ain1 = 8, m1ain2 = 7, m1pwmpin = 10; Motor m2 = Motor(m1ain1, m1ain2, m1stby, m1pwmpin, m2ndb, m2pdb, mpsfactor2); void setup() { int Eraser = 7; // this is 111 in binary and is used as an eraser TCCRnB where n int Prescaler = 1;// this could be a number in [1 , 5]. In this case, 3 corresponds in binary to 011. TCCR1B &= ~Eraser; // this operation (AND plus NOT), set the three bits in TCCR3B to 0 TCCR1B |= Prescaler;//this operation (OR), replaces the last three bits in TCCR2B with our new value 011 //Serial.begin(38400); } void loop() { // m1.speed(0.3); // m2.speed(-0.3); // delay(2000); m1.speed(0); // Right Motor m2.speed(0); // Left Motor }
See Videos to see performance of tuned T-Bots