I'm new here. I'm not a native speaker, so pardon my English.

I just received my Arduino Leonardo today. I tried some basic calculations and stuff like blinking and LCD interfacing. Its interesting.

I am now trying to make a tachometer with the Leonardo. I'm following this tutorial.

I guess the board they've used differs from the Arduino Leonardo (ie pin 3 is interrupt0 in the Leonardo but it is pin 2 in the Arduino Uno board used in the tutorial). I tried changing the pins on the program and reconnecting the circuit but it doesn't work.


This is the code from the tutorial:

/* Optical Tachometer
 * Uses an IR LED and IR phototransistor to implement an optical tachometer.
 * The IR LED is connected to pin 13 and ran continually.
 * Pin 3 (interrupt 0) is connected across the IR detector.
 * Code based on: www.instructables.com/id/Arduino-Based-Optical-Tachometer/
 * Coded by: arduinoprojects101.com

int ledPin = 13; // IR LED connected to digital pin 13
volatile byte rpmcount;
unsigned int rpm;
unsigned long timeold;
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void rpm_fun() {
  //Each rotation, this interrupt function is run twice,
  //so take that into consideration for calculating RPM
  //Update count

void setup() {
  lcd.begin(16, 2); // intialise the LCD
  //Interrupt 0 is digital pin 2, so that is where the IR detector is connected
  //Triggers on FALLING (change from HIGH to LOW)
  attachInterrupt(0, rpm_fun, FALLING);
  //Turn on IR LED
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  rpmcount = 0;
  rpm = 0;
  timeold = 0;

void loop() {
  //Update RPM every second
  //Don't process interrupts during calculations
  //Note that this would be 60*1000/(millis() - timeold)*rpmcount if the interrupt
  //happened once per revolution instead of twice. Other multiples could be used
  //for multi-bladed propellers or fans
  rpm = 30*1000/(millis() - timeold)*rpmcount;
  timeold = millis();
  rpmcount = 0;
  //Print out result to LCD
  //Restart the interrupt processing
  attachInterrupt(0, rpm_fun, FALLING);

Can anyone help me to fix the project? Has anyone here tried this project before?

Thank you!

  • Try removing the phototransistor, get a jumbercable from ground and insert and remove it a few time at the point where the resistor and the photodiode were connected. If any rpm shows up on the lcd, you'd know it's that photodiode that is faulty, or just not near enough to the ir-diode. The code looks fine, and INT0 is indeed on pin D3 instead of D2. – Gerben Jul 10 '14 at 15:59
  • Your circuit looks wrong to me (although I haven't worked much with phototransistors). Why do you not have a resistor for the LED? Is it one built for 5V? Also, as far as I know, phototransistors only conduct when there's light. It seems odd to add a pull up resistor so it always reads high... – Anonymous Penguin Jul 10 '14 at 20:36
  • What specifically did you do when you said you tried changing the pins in the program? have you tried running the program stock and changing the wiring to use pin 3? Also, can you be more specific how it is not working? is it always printing 0 RPM? – BrettAM Jul 11 '14 at 17:08
  • yeah it is always writing rpm = 0. I've changed the interrupt0 to pin 3 on leonardo. would you guys suggest some simple way to test attachInterrupt() with ir transistor, i have both 2 pinned ( ?, ? )and 3 pinned (+, out , -) ir transistors/sensors. thank you! – x0x Jul 12 '14 at 19:26

First, make sure that your LCD routines and wiring are working, by trying to display something on it.

Second, the code isn't correct - it will have some fluctuations from one measurement to another.

One way to do it is to start timing only after the first pulse has arrived, and stop timing only after the last pulse has passed.

Something like this:

  • Wait until a falling edge.
  • Time0 is millis().
  • Wait for N pulses to pass.
  • Time0 is millis() minus time0.

Now with time0 and N you can calculate your rpm.


Here is the above code at work, running Arduino on a PIC24.

enter image description here

The input signal is 10Hz, 1 pulse per revolution, aka 600 rpm.

As you can see the rpm read-out is precisely 600rpm. I'm running the code at 8x oversampling.

As I indicated earlier, your code will introduce uncertainty, as much as one period for the pulses. So in a single pulse measurement, the rpm can be anywhere from 0.5x of the true value to 1.0x of the true value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.