Sunday, February 16, 2014

Reverse engineering the Roomba

Since I was having difficulties with the Roomba's battery, and because it looked interesting, I decided to take my Roomba apart and see if controlling the individual components was feasible. Taking it apart took a couple of hours, and the first component I decided to play with was the motor.

I knew that it had some sort of encoder, but I was surprised how basic it was. The encoder consisted of a single photodiode and a toothed wheel... I presume that the engineers must have used additional information from the motor driver (current direction?) to resolve the direction of the rotation. I connected the diode to a 220 ohm resistor, 5 V power source, and reverse biased the photodiode with a 560 KOhm (also 5 V source). I then ran this through a comparator (LM311) against a 2.5V reference (I just used two 120 KOhm resistors in a voltage divider) to digitize the output.



With an Arduino, I wrote a simple sketch (posted after the break) to take the input from the comparator and increment a counter. I tested that turning the wheel increments the encoder. I ran the signal to an interrupt pin as well as a digital input, so that I didn't have to keep polling the pin. Should allow me to add extra inputs from my other wheel to the system easily I hope.

I don't want to drive the motor from my Arduino so I'm going to have to figure out a second power source and motor driver (perhaps a shield might be easiest) before going too much further with this.

Also below the break I posted a few more photos of the Roomba disassembly.


// encoder read
// reads the custom photodiode encoders on the Roomba motors

// encoders interrupt on pin 2, and also have digital connections to pins 7 and 8
const int encoderRightPin = 8;
const int encoderLeftPin = 7;
const int encoderInterruptPin = 2;

volatile int countEncoderLeft;  // left wheel encoder
volatile int countEncoderRight;  // right wheel encoder



void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  // reset the encoder counts
  countEncoderLeft = 0;
  countEncoderRight = 0;
  
  // attach an interrupt to the encoder pin
  attachInterrupt(0, EncoderISR, RISING);
  
}

void loop() {
  
  delay(1000);
  Serial.print(countEncoderLeft);
  Serial.print(" ");
  Serial.println(countEncoderRight);
}

// ISR for encoder pulses
// 1 - find which encoder delivered the pulse
// 2 - increment the count for that encoder


void EncoderISR(){
  // increment the left count
  if (digitalRead(encoderLeftPin) == 1)
    countEncoderLeft++;
  
  // increment the right count
  if (digitalRead(encoderRightPin) == 1)
    countEncoderRight++;

}




 

No comments:

Post a Comment