Since motor speeds can be slightly different, I’m interested in automating the process of calibrating the motors on a robot. I’ve done this by hand before but it was a bit tedious and error prone.
Toward this end I stumbled across a description of a robot that used downward facing reflectance sensors to accomplish this. The robot could calibrate itself by turning each wheel forward and backward while on a sheet of paper that had a black line drawn on it. It apparently measured the time between detection at various speeds.
Has anyone done this?
Thanks Tom
To err is human.
To really foul up, use a computer.
Having built my first robot with a downward facing reflectance sensor and wheel encoders, I decided to try to code a self calibrating robot.
So why would I want to do that?
I mostly program my robots with a cooperative scheduler that generates rotational and translational velocities for the motors. Those velocities need to be turned into PWM duty cycle values for each wheel. That’s where the motor calibration comes in. With a table of motor duty cycles to wheel velocities (distance/time) I can usually create linear equations and plug them into a steer procedure.
In my cooperative scheduler each robot behavior that I’ve coded gets a chance at controlling the robot’s actuators (wheels in this case). Each behavior updates two arrays, left_vel[beh_id] and right_vel[beh_id], with their preferences by calling the steer procedure. The scheduler decides which behavior wins and will execute the winner’s motor speed commands after which the whole thing starts over again…
void _steer(float rotation, float translation, unsigned char beh_id) { float radius = baseline/1000.0; // the radius of rotation = baseline, only in meters not mm float velRight, velLeft, leftWheelSpeed, rightWheelSpeed = 0; // Calculation of left and right wheel velocities // from forward velocity v(t) and rotational velocity w(t). // Let L = the baseline in meters, velocities are in units of meters/sec, // rotational velocity is in radians/sec. // vRight = v + (wL/2); // vLeft = v - (wL/2); so -w => clockwise and +w => counter clockwise // velLeft = translation - (rotation * radius)/2; velRight = translation + (rotation * radius)/2; if (rotation == 0.0 && translation == 0.0) { left_vel[beh_id] = 0; right_vel[beh_id] = 0; } else { // calculate wheel speeds (ie duty cycle) from velocity rightWheelSpeed = 621.98 * fabs(velRight) + 6.56; right_vel[beh_id] = rightWheelSpeed * signfloat(velRight); // float to int16 leftWheelSpeed = 629.06 * fabs(velLeft) + 5.72; left_vel[beh_id] = leftWheelSpeed * signfloat(velLeft); // float to int16 } }
This is the table of results I got when grabbing duty cycle and its velocity for both wheels. My program just spins the robot over a dark line one wheel at a time to collect the data points. If any duty cycle takes more than 10 seconds to cross the dark line the first time I consider it a dead zone and ignore it. I do have to physically move the robot when the program switches wheels.
I calculate the linear equation using the min and max duty cycle data points like this:
// figure out the slope y2-y1 / x2 - x1; rise/run float slopeRight = (maxRightDC - minRightDC) / (maxRightVel - minRightVel); // substitute slope into slope intercept form of a line: y = mx+b; using the first observation, then find b. // eg. minRightDC = slopeRight * minRightVel + bRight float bRight = minRightDC - (slopeRight * minRightVel); // and for the left wheel float slopeLeft = (maxLeftDC - minLeftDC) / (maxLeftVel - minLeftVel); float bLeft = minLeftDC - (slopeLeft * minLeftVel); printf("Left wheel linear equation: y = %3.4f x + %2.3f\n", slopeLeft, bLeft); printf("Right wheel linear equation: y = %3.4f x + %2.3f\n", slopeRight, bRight);
Here are the graphs from a spreadsheet that fits the best linear equation using all of the data points.
Although my self calibrating robot doesn’t go perfectly straight, it’s close enough...
Tom
To err is human.
To really foul up, use a computer.
@thrandell WOW, that's not at all how I thought it was done.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.