A Digital Tachometer is an electronic instrument which is used for measuring the speed of a motor or any device which has a rotating component in it (Eg: shaft or disc). It displays the revolutions per minute (rpm) or revolutions per second (rps) depending on how the timer has been programmed in the micro controller. Our robot can calculate the revolutions per minute (rpm), revolutions per second (rps). It also calculates the distance that was travelled by the robot till it is switched off. It displays these values using a JHD 162A Liquid Crystal Display.

Video demo of the project:

List of components used:



  • We used the ATmega16 micro-controller for our project. It has a clock frequency of 1 MHz.
  • Two different breadboards were used in the circuit, one primarily supplied voltage to the ATmega16 micro-controller and the L293D motor driver, while the other supplied to the Liquid Crystal Display.
  • A metal chassis was used as the base of the robot, to which the DC geared motors were connected.
  • The wheels were connected to the DC geared motors and controlled by ATmega16 micro-controller.
  • A metal extension is used from the chassis for a more precise placement of the IR sensor.
  • There are two IR sensors that were used, one IR sensor was connected to the extension and placed over the wheel, to measure the revolution of the wheel. It was connected to the micro-controller using a three pin RMC cable at pin PD2. The other IR sensor was connected to the PD7 pin of the micro-controller to switch ON/OFF the robot.
  • We made use of the JHD 162A Liquid Crystal Display which is a 16×2 LCD. The Hitachi HD44780 LCD controller was used.
  • Custom characters, numbers were displayed on this. They have a parallel interface.
  • —There are 16 pins on this specific LCD. They were connected to the micro-controller as follows-—


Connections from LCD to the ATmega16:

Pin 1 (Vss) –Gnd—
Pin 2 (Vcc)- 5 Volt—
Pin 3 (Vee)- Potentiometer third pin.
—Pin 4 (Rs)- PA0
—Pin 5 (R/W)-PA1
—Pin 6 (Enable)-PA2
—Pin 7-14 (DB0-DB7) -PD0-PD7
—Pin 15 (LED+)  -5 Volt
—Pin 16 (LED-)  – Gnd

Programming !!!

  • We used Atmel Studios 6.2 as the software for our project.
  • The platform requires pre-requisite knowledge in general about C programming.
  • A brief study of the ATmega16 datasheet is encouraged before starting with the project especially the timers and counters section.

Header files involved:

—#include <avr/io.h>  :  It contains appropriate input output definition for the ATmega16 controller to be used. The register set and the bit values and their significance are recognized only if this header file is declared.

#include <avr/interrupt.h>  :  The concept of programmed interrupt can be done only if this header file is introduced. It contains all the relevant registers and functions required to enable and disable interrupts.

#include <util/delay.h>  :  This header file contains the functions for specifying any time delays in terms of actual values rather than mentioning the number of cycles to wait for.

—#include <string.h>  :  This header file contains commands used for manipulating strings that are to be displayed on the LCD as far as this project is concerned. For example determining the length of string that is to be displayed.

Macro definitions  :  This is a special feature available in C as well as Atmel Studios 6.2 for giving alias name(user defined) to certain keywords that are used just to make the program more readable and understandable.
It’s a Global constant declaration that is used throughout the program.

#define F_CPU 1000000UL  :   This macro word F_CPU is used to specify the internal Clock frequency of ATmega16 micro controller.

#define ldata PORTB  :  
This macro word ldata is used for PORTB of the ATmega16 (micro-controller) to specify that the port is being used as a data port and is interfaced with the LCD.

Into the main !!!!! 

—Initially the respective ports were declared as input and output ports based on how they were to be used


As mentioned earlier PORTB was declared as output port so that it can be connected to the LCD.
The PORTA was also declared as output port for reading, writing and enabling the LCD and additionally for the motors as well.
The PORTD was declared as an input port for the IR sensor input as well as the on/off IR sensor input used so that the program can be interrupted accordingly.
Pulling up was done as shown above to avoid fluctuations.
All this was done using the DDRX (Data Direction Register)

Dealing with timers and counters:

TCCR1A  :  The timer/counter-1 control register A was set to a value of all zeros to operate as a normal mode counter. This mode uses a counter which is incremented in one direction and counter clear is not performed which is required for this application. It counts from minimum(0000) to maximum(FFFF) value and then overflows where the interrupt is triggered automatically.



The last two bits decide the mode of operation and they are set to a combination of 00 for normal mode of operation.  Other bits are set to initial values as pwm mode, CTC mode of operations is not required for this application.




The timer/counter control register B was set to a value of 03H so that a pre-scale by 64 is achieved specifically. The other bits denoting input capture noise cancellation, reserved bit, waveform generation mode are set to zero since they are not required for this application.
The last three bits CS12, CS11, CS10 were set to 011 specifically to achieve a pre-scale by 64.




The timer and counter-1 register is a 16 bit registers which is split into two as shown above into TCNT1H and TCNT1L. These two represent the upper and lower bytes of the value that is fed to the entire register. These registers are basically used to show the starting count. They were by default set to a value of 00H. 

Concept of Interrupts:

Once the interrupt.h has been declared a procedure has to be followed to make meaningful use of the interrupts.
In the programming part of it we made use of the following special interrupt functions they are cli() and sei(). These two functions cli and sei functions were used for clearing and enabling global interrupts.

—The important registers we used in the case of interrupts are the following:

GICR-(Global Interrupt Control Register):  This register is used to select which type of interrupt request we are going to use.


—SREG(Status register) : This register is used to enable/disable a specific interrupt. It informs the micro-controller if it has to respond to the interrupt when triggered or not.

It is arbitrary to set the 7th bit high in order to enable the interrupts in general. One disadvantage  is that the 7th bit gets reset whenever the interrupt request has been responded to by the micro-controller . Hence the bit has to be monitored. sei() function solves this problem.

—MCUCR(MCU control register)  :  This register tells for how long the interrupt has to be triggered or under what condition the micro-controller has to respond to the request.


Programming Algorithm

Basically an infinite loop is introduced where a check for the on off sensor is done which behaves like a switch.
Now basically two possibilities arise, the first case is when the switch is on within the loop, the pins of the micro-controller are made high and low in such a way that the robot is driven forward.
Now a check is performed to detect the completion of a second this is achieved using the TCNT1 register. This was done as follows  if(TCNT1>=15624)

The value of 15624 was obtained by making use of a 64 bit pre-scaler i.e. the clock frequency of 1000000 is divided by the pre-scaler 64 which gives the number of cycles per second.
Now within this the rps was obtained by multiplying the count variable with 0.25. The multiplication was done by 0.25 since 4 paper clips were inserted on the wheel in our project.

Any number of paper clips can be introduced on the wheel and depending on it the multiplication must be done. For example if 8 paper clips are used a multiplication by 0.125 must be done.

—A simple conversion between rps and rpm was done by multiplying the rps by 60.

Moving on to the case where the IR sensor behaves as an off state switch then the respective motor pins on the micro-controller were driven to zero so that motor stops.

Once the motor stops the distance was displayed based on the following calculation

In case of perfectly divisible values of rps the zeros were printed on the LCD screen using the variable control. This was achieved by following piece of code


After this the count values were reset to zero

—Apart from these aspects an interrupt service routine was called during low value of the internal clock pulse in ATmega 16. In the ISR a constant check on PD7 was done to check if the switch is on at all times. Once this was checked for a check on whether a black was detected by the IR sensor at PD2. If not the count is incremented continuously.

The final robot:



Share This