4

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.

Circuit

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
  rpmcount++;
}

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
  delay(1000);
  //Don't process interrupts during calculations
  detachInterrupt(0);
  //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
  lcd.clear();
  lcd.print("RPM=");
  lcd.print(rpm);
  //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!

dda
  • 1,595
  • 1
  • 12
  • 17
x0x
  • 149
  • 4

1 Answers1

1

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.

Edit:

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.

the busybee
  • 2,313
  • 9
  • 17
dannyf
  • 2,793
  • 11
  • 13