Photo tachometer with digital output (completed project)

hi all,

This is how I obtained a non-contact rotation speed reading using a very inexpensive photo tachometer (in the USA, you can get this to your door for under $30). I purchased the Neiko branded tach from Amazon and I am sure it can be found elsewhere and under different or even no brand label. Mine uses 3x1.5 AA batteries for an operating voltage near 5V. The interface is very simple.

+5V from Arduino - connected to the circuit side of the "Test" button on the tachometer (circled RED in the picture)
GND from Arduino - connected to the battery negative in the battery tray on the tachometer (circled Yellow in the picture)
SIGNAL to Arduino - connected to pin 12 of the micro on the Tachometer which is an interrupt-enabled pin on the micro in the tach and is fed from an HC4050 Buffer chip

The cable used is a shielded headphone extension cable with TRS (tip ring sleeve) connectors. The shield in this cable has a braided wire that I used for ground. I used the Black (Left Audio) for the signal and the Red (Right Audio) for +5V. The tachometer body also luckily had a plastic plug in the side for some non-existing feature. I drilled 3 holes in this piece to get a tie location for a zip-tie fastener and of course a hole to bring the cable through.

On Arduino I used attach interrupt with FALLING option.

Here are some picture thumbnails from photobucket. If you click the picture you should be able to see a large version. I am sorry about missing a picture of my connection to the button. On the tach, the battery is normally an open circuit and when you press the "Test" button it closes the circuit to power up and take readings. I connected +5V to the other side of the switch so when Arduino is connected the tachometer is always powered.

I know that a completed project could go into the exhibition forum, but this project is a complete sensor rather than a complete Arduino solution. It could also be considered a hacked object but this is so simple I don't think it quite qualifies as hacked. One thing to look out for; while my tach is powered by 3 1.5V cells, I saw one described as powered from a 9V battery. If the 9V device is not regulated to 5V, then you would need additional components to do the interface but it should still be quite easy.

Here are some code snippets that may help a person get started

short getTachSpeed(){

  //Calculate the most recent tach speed here, considering
  // it is only polled 1 time per second anyway.

  long tachspeed=0;


  case 0:
    return tachspeed/(tachTime[2]-tachTime[1]);

  case 1:
    return tachspeed/(tachTime[0]-tachTime[2]);

  case 2:
    return tachspeed/(tachTime[1]-tachTime[0]);


timer setup

void setupTimer0 (){  //An 8 bit timer clocked to the CPU

  /*bit values BEFORE this function (probably set by Arduino Environment
   due to the fact the millis() function is used in the setup()
   B1    TIMSK0
   B11   TCCR0A
   B11   TCCR0B
   B0    OCR0A
   bit values AFTER this function
   B10   TIMSK0
   B10   TCCR0A
   B100  TCCR0B
   B1011 OCR0A
  cli();                  // disable interrupts while changing settings

  //reset all bits in the setup registers to 0.  Not all are R/W but the 
  //compiler does not seem to mind:  breaks Arduino millis(), micros()
  //and delay()

  TIMSK0 = 0 ; 
  TCCR0A = 0;     
  TCCR0B = 0;

  //set to 256 prescaler  (CS02:0 = B100)
  //prescaler means that this timer clocks 256X slower than the CPU
  sbi(TCCR0B, CS02);   

  //set to CTC mode (clears timer when it reaches count)
  sbi(TCCR0A, WGM01); 

     256 prescaler, and interrupt on 6 counts causes this timer to
   interrupt at a rate of 10,416.666 Hz which gives a resolution that we
   need and it also has the IDEAL condition that it is perfectly scaled
   with the Timer2 that has been set up. It is EXACTLY 336 times faster

  //OCR0A = 11;  //every 12th count gives a rate of 5208.33333 HZ 
  OCR0A = 5; //every 6th count gives a rate of 10,416.6666666 Hz

  sbi(TIMSK0,OCIE0A); //enable the timer to raise overflow interrupts

  sei();              // turn interrupts back on
//call this in setup
 attachInterrupt(0, ISRtachpulse, FALLING);
void ISRtachpulse(){  //An ISR defined using the Arduino command set


    //time stamp and memorize number of pulses accrued
    tachTime[tach01]=counter0; //put the current time into the waiting spot


    case 0:
    case 1:
    case 2:


  else {
    // the most common result of this ISR is to simply count


hope it helps. I tried to post my whole code but I was over some character limit

Hi mk3,

I am trying to duplicate your project but have never programmed an Arduino Uno before. I made the connections you suggested and now would like help to create and Upload the code that works for the reading. Could you tell me the steps I have to follow. My email address is