LEDs say yes, but Input pins say nothing, or too many things?!

Hi All,

I’ve hooked up an Optical Mouse to my Arduino Nano, by

  • opening the mouse
  • locating the IR led and Phototransistor (Dual, which can provide a direction to the scrollwheel rotation)
  • breaking off the section of PCB that these were attached to
  • soldering wires to the pins of these components
  • wired them to the Arduino as follows:

I’ve looked at almost every online resource regarding how encoders are hooked up, and tried many different ways, but could not get any successful reading from the serial monitor using Arduino playground code.

As a last resort, I did the following:

I’ve attached red LEDs (with 100ohm resistors so the LEDs don’t burn out) into the circuit to check that when i break the IR beam using my finger, or the mousewheel, that the output of the Phototransistor is working. So far this works, and the LEDs go dark when I break the IR beam. I just don’t know why the Arduino won’t read this on/off properly.

I think i’ve added 10K pulldown resistors to digital pins 2 and 3 correctly, pulling them to ground. And I’m using pins 2 and 3 since they are interrupts.

What I can’t get to work is any sort of encoder code. From either the Arduino playground, or different people’s websites.

Either the serial monitor shows up with no movement, or just keep counting upwards, or counts upwards SUPER fast! It doesn’t look like the input pins are reading what I want them to.

Can anyone point me to some simple code that will print something in the serial monitor to let me know that the Arduino Nano pins 2 and 3 are getting the signal from channel A and B of the phototransistor?

I’m in the process of trying to build a robot, and i want to use mousewheel-quadrature encoders on the wheels. I’ve made much progress so far, learning arduino, electronic circuits, components etc…but I am really stumped on this.

Any help would be much appreciated. I’ve spent several days, and this past entire night trying to solve this and am fully burnt out.
Thanks for your assistance!

I can't see from your picture how the sensor is connected to the Arduino.

You need to provide a proper wiring schematic instead of a picture of the physical layout.

A photo of a pencil drawing will be fine.

...R

Hi Robin2, thanks in advance for taking a look. Here's a schematic of the circuit:

You realize that those LEDs drop a couple of volts? That is reducing the voltage to the Arduino.

So the LEDs light up, but too low a voltage gets to the Arduino inputs.

Take the LEDs out. Now put your DMM across one of the 10k resistors and read the voltage, blocked and unblocked.

You may also be picking up interference from fluorescent, CFL, or LED lights in the room. Try shading it.

That diagram is much better.

It looks like the device with 2 LEDs attached has no GND connection - that doesn't seem correct.

I agree with @polymorph about removing the LEDs - or at least connect the Arduino upstream of them.

...R

Ok I removed the LEDs (and corresponding resistors) and got the same Serial Monitor output. I decided to unhook everything, except for the IR Led, which i know works, and the strange thing is that the Arduino is still giving the same Serial Monitor output, even with nothing connected?!

Heres a code example i tried, followed by the output:

 /* Read Quadrature Encoder
  * Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
  *
  * Sketch by max wolf / www.meso.net
  * v. 0.1 - very basic functions - mw 20061220
  *
  */  


 int val; 
 int encoder0PinA = 2;
 int encoder0PinB = 3;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;

 void setup() { 
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   Serial.begin (57600);
 } 

 void loop() { 
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     Serial.print (encoder0Pos);
     Serial.print ("/");
   } 
   encoder0PinALast = n;
 }

and the output which steadily streams

Code example 2

/* read a rotary encoder with interrupts
   Encoder hooked up with common to GROUND,
   encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
   it doesn't matter which encoder pin you use for A or B  

   uses Arduino pullups on A & B channel outputs
   turning on the pullups saves having to hook up resistors 
   to the A & B channel outputs 

*/ 

#define encoder0PinA  2
#define encoder0PinB  3

volatile unsigned int encoder0Pos = 0;

void setup() { 


  pinMode(encoder0PinA, INPUT); 
  digitalWrite(encoder0PinA, HIGH);       // turn on pullup resistor
  pinMode(encoder0PinB, INPUT); 
  digitalWrite(encoder0PinB, HIGH);       // turn on pullup resistor

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
  Serial.begin (57600);
  Serial.println("start");                // a personal quirk

} 

void loop(){
// do some stuff here - the joy of interrupts is that they take care of themselves
}

void doEncoder() {
  /* If pinA and pinB are both high or both low, it is spinning
   * forward. If they're different, it's going backward.
   *
   * For more information on speeding up this process, see
   * [Reference/PortManipulation], specifically the PIND register.
   */
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
    encoder0Pos++;
  } else {
    encoder0Pos--;
  }

  Serial.println (encoder0Pos, DEC);
}

/* See this expanded function to get a better understanding of the
 * meanings of the four possible (pinA, pinB) value pairs:
 */
void doEncoder_Expanded(){
  if (digitalRead(encoder0PinA) == HIGH) {   // found a low-to-high on channel A
    if (digitalRead(encoder0PinB) == LOW) {  // check channel B to see which way
                                             // encoder is turning
      encoder0Pos = encoder0Pos - 1;         // CCW
    } 
    else {
      encoder0Pos = encoder0Pos + 1;         // CW
    }
  }
  else                                        // found a high-to-low on channel A
  { 
    if (digitalRead(encoder0PinB) == LOW) {   // check channel B to see which way
                                              // encoder is turning  
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }

  }
  Serial.println (encoder0Pos, DEC);          // debug - remember to comment out
                                              // before final program run
  // you don't want serial slowing down your program if not needed
}

/*  to read the other two transitions - just use another attachInterrupt()
in the setup and duplicate the doEncoder function into say, 
doEncoderA and doEncoderB. 
You also need to move the other encoder wire over to pin 3 (interrupt 1). 
*/

The output just prints startCR on the screen and then nothing happens afterwards

Code example 3

#define encoder0PinA 2

#define encoder0PinB 3

volatile unsigned int encoder0Pos = 0;

void setup() {

  pinMode(encoder0PinA, INPUT); 
  pinMode(encoder0PinB, INPUT); 
// encoder pin on interrupt 0 (pin 2)

  attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)

  attachInterrupt(1, doEncoderB, CHANGE);  
  Serial.begin (57600);
}

void loop(){ //Do stuff here 
}

void doEncoderA(){

  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) { 
    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }
  else   // must be a high-to-low edge on channel A                                       
  { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinB) == HIGH) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
  Serial.println (encoder0Pos, DEC);          
  // use for debugging - remember to comment out
}

void doEncoderB(){

  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {   
   // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }
  // Look for a high-to-low on channel B
  else { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinA) == LOW) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
}

and the output prints really fast

Here's a photo of the setup, i've disconnected the arduino and its really strange why its giving the same output as when I connected the phototransistor.

I can't find a datasheet for this transistor nor know its model number. The ones i took out from other mice have EL embossed on the top, which probably stands for Everlight electronics ltd. This one has LT embossed on the top.

Looking at the leads , i'm now noticing that only one of them is thicker, perhaps this phototransistor is not in the usual pin configuration

http://www.seattlerobotics.org/encoder/200311/johnson/Mousebot.html Theodore Johnson explains "The three-pin detector consists of two photodiodes arranged vertically. The outputs must be pulled to ground by, e.g. a 10K Ohm resistor." And provides the following diagram:

http://www.stevekamerman.com/2010/12/understanding-a-mouse-scroll-wheel/ Steve Kamerman uses a 5 pin unit, where the first 3 pins are for the phototransistor, and the last 2 are to power the IR led

Pin 1: Photo Sensor 1 Pin 2: Vcc Pin 3: Photo Sensor 2 Pin 4: IR LED + Pin 5: IR LED -

He comments "There are two 10k resistors. First, connect pin 1 directly to arduino input 2, then put the 10k from ground to input 2. This creates a voltage divider since pin 1 will be slightly positive and the resister will pull it slightly towards ground. Repeat for the other encoder output – pin 3 to input 3, 10k from ground to input 3."

http://www.mcmanis.com/chuck/robotics/projects/lab-x3/quadratrak.html Here's an image of a Rotary Encoder setup from Chuck McManis' site

http://www.hobbytronics.co.uk/arduino-tutorial6-rotary-encoder Here's another setup from Hobbytronics

Here's a pinout of the Everlight Electronics dual phototransistor from the datasheet

I'm also going to stare at the above information long enough, now that its all in one place, and see if the issue will sort itself out that way. But further help is much appreciated too. Thanks!

Measure. Measure. Measure.

In my most recent breadboard patching manouever, the IR led got connected to 5V without a resistor in series, then I hear a hissing sound and smelled burnt plastic.

On the bright side, I did manage to check if if was working using a digital camera, and it was. I unplugged the power of the IR Led while still looking into the camera viewfinder, and its glow went off, and then on again when i plugged its power back in.

When I measured the output voltage from one channel of the phototransistor, it seemed very low, 0.5V. I’m not sure why it would be that low especially when there’s 5V feeding it.

I think I’m just going to give up on trying to hack the 2 remaining mouses that I have, and get a couple of cheap encoder motors to work with. At least those will generate the on/off signals that I’m looking for.

Do you have any theories as to how I can remove this code disc assembly without wrecking the disc?

These Mabuchi encoder motors are approx. $5 on ebay. But the motor part is a bit too bulky. I want to attach the code disc assembly to the output shaft of an N20 geared motor.

The code disc hole is 2.3mm while the output shaft of the N20 motor is 3mm. So it looks like I’ll have to take the code disc to the drill press (at my school) very carefully. I’ve seen this device to remove gears, but it doesn’t look wide enough to fit around the disc.

Anyhow, maybe i’ll give this another go after i get a good night’s sleep. Thanks for the help so far!

exwhyzed: Ok I removed the LEDs (and corresponding resistors) and ...........

Your post is much too long and has far too much information.

Plan your posts around questions that the reader can understand in about 30 seconds.

In circumstances where you can't exactly identify your parts posting alternative schematics is not likely to be much help. You could, for example post a photo of your board and ask the simple question "does anyone know how to connect this to an Arduino?"

I would start with a short piece of code that just lights an LED when it gets a pulse from the encoder and I would move the disc slowly with my finger. When that seems to work reliably I would feel that I understood the electronics and then I could concentrate on the software.

byte enc =  digitalRead(encoderPin);
digitalWrite(ledPin, enc);

...R

Hi, if the detector assembly is the one that you have posted the specification for, PT5529B.

You will note that the detectors are ONE ABOVE THE OTHER, not side by side so you must use the encoder wheel that came with it and ALIGN it precisely to get it to work.

Tom.... :)

Ok now i'm making some progress, yaay! I've checked and double checked, and:

  • the IR LED works (tested using digital camera), its being powered by the Arduino 5V (in series with a resistor)
  • 5.2V is coming out of the wall adapter
  • the wall adapter is powering the Phototransistor
  • 2.4V is coming out of the Photransistor when it is in direct contact with the IR Led
  • 0.01V is coming out of the Photransistor when I put a piece of paper in between it and the IR Led

So I can finally say that this sensor assembly is connected and behaving correctly.

As for the Arduino... - Pin 2 (input) reads high/low when I connect it to the wall adapter ground, i guess its floating - Pin 2 (input) reads low (and stays there) when I connect it to the Arduino ground, so I guess it belongs there. - no matter where i plug in the 2.4V Phototransistor output, I can't get the input pin to read it.

exwhyzed: - no matter where i plug in the 2.4V Phototransistor output, I can't get the input pin to read it.

I think that that 2.4V isn't really a valid High. (Is it? Try it with a pot or a couple of resistors.)

You have 220? in series with your IR emitter. IREDs can run more current than LEDs, lots more (typ.) I think you could do with more current, which would result better opto transfer. This arrangement is like a photo-dependent emitter follower - pretty shaky. Try 100? (appx 40mA)

So, increase IRED output and check for more opto out voltage. [Or see if there's something similar without a shared collector, so that they can be pulled high.]

I believe the 328p has a High Logic Level of at least 3V when used with a 5V supply.

The 100ohm resistor brought the Phototransistor output up to 4.1V, amazing!!! I tried many combinations of internal Arduino resistor on/off, and external pulldown resistors, and also pulling the Arduino input to either Arduino-ground or the 5V wall adapter ground, but the input either prefers one of the grounds and stays low all of the time, or otherwise jumps around from low to high (floating).

I know I'm very close to resolving this, especially since i'm now dealing with a logic level that the Arduino can read as high.

exwhyzed:
The 100ohm resistor brought the Phototransistor output up to 4.1V, amazing!!!

Good that.

exwhyzed:
prefers one of the grounds and stays low all of the time, or otherwise jumps around from low to high (floating).

I don’t understand this part at all.
Is there a separate 5V supply? If so, then its Ground should be connected to Arduino Gnd, too.

OK to get it working I:

  • connected both the separate 5V ground and the Arduino ground
  • removed R2 and R3 (see above diagram)
  • removed the "circuit testing" LEDs
  • and upped R4 to 316k Ohms, and R5 to 316K Ohms

Thanks for the help everyone. That's a lot more Ohms than I was expecting!