Although I’ve posted previous tutorials on adding a shaft encoder to your DIY robocar, sometimes you want the additional precision of wheel encoders. That’s because when you’re turning, the wheels move at different speeds and you can’t measure that from just the main shaft.
The problem is that it’s pretty hard to retrofit wheel encoders to these small cars; there just isn’t much room inside those wheels, especially if you’re trying to add hall-effect sensors, quadrature rotary encoders or even just the usual optical wheel with a LED/photodiode combination to read the regular cutouts as they spin.
However, most wheel already have cutouts! Maybe we don’t need to use an LED at all. Perhaps a photodiode inside the wheel could look out at the lights outside the car and just count the pulses as the wheel turns, with the gaps in the wheel letting the light through.
I used these cheap photodiodes, which have both digital and analog outputs, as well as a little potentiometer to calibrate them for the available light.
Then I just connected them to an Arduino and mounted them inside the wheel, as close to the wheel as possible without binding, to avoid light leakage. The Arduino code is below. Just connect the DO pin to Arduino pin 8, and the VCC and GND pins to the Arduino’s VCC and GND pins (it will work with 3.3v or 5v). No need to connect the AO pin.
const int encoderIn = 8; // input pin for the interrupter
const int statusLED = 13; // Output pin for Status indicator
int detectState=0; // Variable for reading the encoder status
int prevState = 1;
int counter = 0;
void setup()
{
Serial.begin(115200);
pinMode(encoderIn, INPUT); //Set pin 2 as input
pinMode(statusLED, OUTPUT); //Set pin 13 as output
}
void loop() {
detectState=digitalRead(encoderIn);
if (detectState == HIGH) {
detectState=digitalRead(encoderIn); // read it again to be sure (debounce)
if (detectState == HIGH) {
if (prevState == 0) { //state has changed
digitalWrite(statusLED, HIGH); //Turn on the status LED
counter++;
Serial.println(counter);
prevState = 1;}
}
}
if (detectState == LOW && prevState == 1) { //If encoder output is low
digitalWrite(statusLED, LOW); //Turn off the status LED
prevState = 0;
}
}