Find the Motor Offset

Start 

Calibration in Progress

Powering the Robotics Kit 

The motor and Arduino use different power sources. They both must be on for the kit to work. The I2C Motor Driver uses 6 AAs and the Arduino uses a 9 volt.

Kit and batteries
Kit and batteries
9 volt for Arduino
AAs for motors
Take AAs
Place in holder
Like this
Use tape
To secure the 9 volt
To secure the 9 volt
I like to place it next to the holder
Plug in the barrel jack
Plug in the barrel jack
A fully powered kit
These lights show each part is on

Automagic Calibration Program 

This program uses a feedback loop with the two line finders and the two motors. First we'll upload it and use then we'll talk about how it works. We need to calibrate because there are many small differences in everyone's robot. Motors,

Upload

Upload the following program. Make sure your left line finder is plugged into D3 and the right line finder is plugged into D2. If for any reason the tires are not on the motor axle, place them on now.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//Libraries used in this sketch
#include <Average.h>
#include "Grove_I2C_Motor_Driver.h"

//Address needed to comunicate with the driver
#define I2C_ADDRESS 0x0f

//Variable names for the motors
unsigned char left = MOTOR2;
unsigned char right = MOTOR1;

//Amount of samples to take
int sampleAmount = 16;

//Arrays to hold the samples
Average<float> leftTimeDiff(sampleAmount);
Average<float> rightTimeDiff(sampleAmount);

//Variables used for counting time
unsigned long previousLeftTick;
unsigned long previousRightTick;
unsigned long previousChange;

//Waiting amount for comparisons
int interval = 2000;

//Motor variables
int motorRevUpTime = 2000;
int motorPower = 60;

//Offset variables
int offset = 0;
bool offsetFound = false;

//Error variables
float deltaError = 2;
float error = 100;

void setup() {
//Start Serial communications
  Serial.begin(9600);

  // start motor driver
  Motor.begin(I2C_ADDRESS);
  // correct pwm cycles
  Motor.frequence(F_490Hz);

  attachInterrupt(1, leftTick, CHANGE);
  attachInterrupt(0, rightTick, CHANGE);

}

void loop() {

  Serial.println("Starting Calibration");
  Serial.println("____________________");
  Serial.println("Spinning up Motors");

  Motor.speed(left, -motorPower - offset);
  Motor.speed(right, motorPower - offset);

  delay(motorRevUpTime);

  Serial.println("Motors up to Speed");
  Serial.println("__________________");
  Serial.println("Starting Sampling");

  error = abs(leftTimeDiff.mean() - rightTimeDiff.mean());

  while (!offsetFound) {
    if (millis() - previousChange > interval) {
      error = abs(leftTimeDiff.mean() - rightTimeDiff.mean());

      Serial.println("Left Mean : " + String(leftTimeDiff.mean()));
      Serial.println("Left Dev : " + String(leftTimeDiff.stddev()));

      Serial.println("Right Mean : " + String(rightTimeDiff.mean()));
      Serial.println("Right Dev : " + String(rightTimeDiff.stddev()));

      Serial.println("Current offset of : " + String(offset));
      Serial.println("Current error of : " + String(error));
      Serial.println("Must resolve to : " + String(deltaError));
      Serial.println();

      if (error <= deltaError) {
        offsetFound = true;
        break;
      }

      if (leftTimeDiff.mean() > rightTimeDiff.mean()) {
        offset++;
      } else {
        offset--;
      }

      previousChange = millis();

      Motor.speed(left, -motorPower - offset);
      Motor.speed(right, motorPower - offset);
    }
  }

  Serial.println("Offset found");
  Serial.println("_____________");
  Serial.println("Offset = " + String(offset));

  Motor.stop(left);
  Motor.stop(right);

  while (1) {
  }


}

void leftTick() {
  leftTimeDiff.push(millis() - previousLeftTick);
  previousLeftTick = millis();
}

void rightTick() {
  rightTimeDiff.push(millis() - previousRightTick);
  previousRightTick = millis();
}

Observe

Flip the robot upside-down so it doesn't drive off your workspace. We want the tires on when calibrating the motor because they'll be on when the motor is used. Removed them would change the motor's response and give us less accurate data. Open up the Serial Monitor and check out the output. If your line finders are properly calibrated you should see an output like this.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Starting Calibration
____________________
Spinning up Motors
Motors up to Speed
__________________
Starting Sampling
Left Mean : 22.56
Left Dev : 8.39
Right Mean : 19.06
Right Dev : 2.15
Current offset of : 0
Current error of : 3.56
Must resolve to : 1.00

...

Left Mean : 19.94
Left Dev : 8.14
Right Mean : 19.38
Right Dev : 2.23
Current offset of : 5
Current error of : 0.56
Must resolve to : 1.00

Offset found
_____________
Offset = 5

The offset at the end is the one you should use.

Is the motors seem to be spinning slow try resetting the I2C Motor Driver.

Reset ButtonReset Button

So What is Happening? 

First the motors are spun up before we take measurements. The motors don't immediately spin at the speed we want them to. We use a small delay to let them get to speed before starting our sampling measurements. After the interval the initial measurements are taken. We are measuring how long it takes to go from one slice on the encoder wheel sticker to the next. After taking 2 seconds of measurements, we compare the average of the two encoder. We want the two means to be under the value specified in the deltaError . The lower that deltaError more inaccurate the offset with be. If the means are over the deltaError value then the offset in increased. The motors spin without measurements to get the motors to the right speed. And the whole process repeats.

Diagram

How the Calibration WorksHow the Calibration Works