[SOLVED] Trouble using an optical encoder salvaged from an HP scanner/printer

Thanks for reading my post!
I recently took apart an HP scanner/printer and pulled out some interesting parts. I can't seem to get an optical encoder/motor assembly to work, and there are no part numbers or markings that lead me to a datasheet.

Attached pictures below show two photos of the assembly itself, and a schematic I made to keep track of things. A-F connected to a ribbon cable. Here is how I interpreted it:
A and B are clearly for powering the motor
The two 1.8kOhm resistors serve as pull-up resistors for the two outputs (E and F)
The 101Ohm resistor is current-limiting resistor for the IR emitter.
C is the cathode for the emitter, and powers the pull-up resistors.
D is the anode for the emitter, and a common emitter for both channels of the phototransistor detectors.
E and F are the two outputs, pulled high when in the dark and low when illuminated.

So, I connected C directly to 5V, D directly to ground, and alternated trying E and F in Pin8 and ran the very simple code below (which works fine for a simple slot IR interrupter) while I slowly turned the motor shaft. Surprisingly, pin 8 always reads high.
Has anyone else pulled these out of a printer and made them work? Have I overlooked something? Any help is much appreciated!

int InputPin = 8;
int LEDPin = 13;
void setup() {
  pinMode(InputPin,INPUT);
  pinMode(LEDPin, OUTPUT);
}

void loop() {
  digitalWrite(LEDPin,digitalRead(InputPin));
}

Encoder Assembly.png

Wait... If C goes to the Cathodes and D goes to the Anodes wouldn't D be +5 and C be Ground? That would make the resistors Pull-Down resistors. Give that a try.

1 Like

John- You're exactly right and it's working beautifully now that I've swapped the 5V and ground leads.
I thought I had tried that before, but I found I had another problem as well. I had been working earlier with an IR slot interrupter which required an external current-limiting resistor in series with the 5V power. I still had the resistor there, which now created a voltage divider with the on-board resistor for the encoder. The pull-up (down) resistors were pulled to 2V (3V) instead of 5V (0V), messing up the digitalRead.
Thanks for your help!

Cool guys! I just removed such a motor from an old HP scanner/printer yesterday and I was wondering if some information was available on it. You saved me much time, thanks a lot.

1 Like

My code may be helpful

Note: According to previous picture Encoder Assembly.png
A - GND
B - +5V
C - GND
D - +5V
E - D3 (connect with 20k to ground)
F - D2 (connect with 20k to ground)

and D8 go outer LED for strobe

/*

const int sensorPin1 = 2 ,sensorPin2 = 3;

//LED blinks when interval is end
const int ledPin = 13;
int ledState = LOW;

//LED blinks as strobo, shows velocity
const int ledPinStrobo = 8;
int ledStateStrobo = LOW;

int sensorValue1 = 0, sensorValue2 = 0;
int preVal1 = 0,preVal2 = 0;

/*

  • uses for calculate how mush interrupts
  • we have inside one interval of time
    */
    int interrupCounter = 0;
    int directionCounter = 0;
    int interrupCounterPrev = 0; // uses for strobo

/*

  • vars for checking time which uses
  • for calculating a speed
    */
    unsigned long previousMillis = 0;
    unsigned long previousMillisStrobo = 0;

const long interval = 100;
long intervalStrobo = 0;
const long intervalStroboOn = 30;

void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(ledPinStrobo, OUTPUT);
}

void loop() {

unsigned long currentMillis = millis();

if(currentMillis - previousMillisStrobo >= intervalStrobo) {

previousMillisStrobo = currentMillis;

ledStateStrobo = HIGH;

// set the LED with the ledState of the variable:
digitalWrite(ledPinStrobo, ledStateStrobo);
}

if(currentMillis - previousMillisStrobo >= intervalStroboOn) {

ledStateStrobo = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPinStrobo, ledStateStrobo);
}

if(currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

Serial.print(interrupCounter);
Serial.print(" - ");
Serial.println(directionCounter);

//work with strobo
if(interrupCounterPrev!=interrupCounter){

intervalStrobo = (600 - interrupCounter);
if(intervalStrobo < intervalStroboOn)
{
intervalStrobo = intervalStroboOn;
}
interrupCounterPrev = interrupCounter;
}

interrupCounter = 0;

if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}

preVal1 = sensorValue1;
preVal2 = sensorValue2;

sensorValue1 = digitalRead(sensorPin1);
sensorValue2 = digitalRead(sensorPin2);

if((sensorValue1 != preVal1))// || (sensorValue2 != preVal2))
{

interrupCounter++;

if (sensorValue1 == HIGH)
{
if(sensorValue2 == HIGH)
{
directionCounter++;
}else{
directionCounter--;
}
}else{
if(sensorValue2 == HIGH)
{
directionCounter--;
}else{
directionCounter++;
}
}

//if we wand tount steps clean it
if(directionCounter > 100)
{
directionCounter = 100;
}else{
if (directionCounter < -100)
{
directionCounter = -100;
}
}

}

//delay(10);
}

1 Like