The power supply and the sensor input portion schematic:
Connectors for LCD and ISP
The controller portion, ATMEGA8
The source code is provided below in the READ MORE LINK, otherwise the project page would have gone a bit too long, for ALL the files related to the project, use this link: http://zaidpirwani.com/1246/tachtastic-avr-tachometer-2/
The Code: [ALL OF IT]
// Tachtastic 2.0 // By The iTeam // ATmega8 - 8MHz Internal // Sensor - INT0 at PD.2 // T0 Overflow Interrupt // 16x2 LCD at PB0-6 in 4-bit Mode // START/Stop/Exit BTN at PD.3 // Menu/Select BTN at PD.5 // Next BTN at PD.7 // Prev BTN at PD.6 // COUNT#######TIME - LCD FORMAT // -RPM-#######-Hz- - LCD FORMAT #include <stdlib.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "lcd.h" // For Simplifying Bitvise Operations #define CLEAR(port,pin) PORT ## port &= ~(1<<pin) #define SET(port,pin) PORT ## port |= (1<<pin) #define TOGGLE(port,pin) PORT ## port ^= (1<<pin) #define READ(port,pin) PIN ## port & (1<<pin) #define BITVAL(n) (1<<(n)) #define DB_DELAY 10 // Debounce Delay - in ms #define START 3 #define MENU 5 #define NEXT 7 #define PREV 6 void init_all(); void print_title(); void print_int(unsigned char x, unsigned char y, unsigned int temp); void count_rev(); void comp_volt(); // Global Variables unsigned long inc = 0, cnt = 0, cnt1 = 0, cnt2 = 0, cnt3 = 0, time = 0, count = 0, temp = 0, countpr= 1; // Counts Per Revolution unsigned char menu_index = 0, // 1:Count/Rev, 2:Comp V status = 0, // 0:Normal, 1:Measuring, 2: Menu, 3: Setting reset = 0, compvolt = 0; // Boolean - 0: NOT in 1, 1:Comp V Setting char tempstr[4]; int main(void) { init_all(); print_title(); while(1) { if(~READ(D,START) && status==0) { // START/STOP/EXIT Button - PortD.3 - Status: Normal _delay_ms(DB_DELAY); lcd_clrscr(); inc = 0; cnt = 0; cnt1 = 0; cnt2 = 0; cnt3 = 0; time = 0; count = 0; status = 1; reset = 0; sei(); while(~READ(D,START)) ; _delay_ms(DB_DELAY); } else if(~READ(D,START) && status==1) { // START/STOP/EXIT Button - PortD.3 - Status: Measuring _delay_ms(DB_DELAY); while(~READ(D,START)) ; _delay_ms(DB_DELAY); cli(); status = 0; reset = 1; } else if(~READ(D,START) && status==2) { // START/STOP/EXIT Button - PortD.3 - Status: Menu _delay_ms(DB_DELAY); cli(); status = 0; print_title(); while(~READ(D,START)) ; _delay_ms(DB_DELAY); } if(~READ(D,MENU) && status==0 && reset==0) { // MENU/SELECT Button - PD.5 - Status: Normal _delay_ms(DB_DELAY); lcd_clrscr(); lcd_gotoxy(0,0); lcd_puts("> Counts / Rev"); lcd_gotoxy(0,1); lcd_puts(" Comparator V"); menu_index = 1; status = 2; while(~READ(D,MENU)) ; _delay_ms(DB_DELAY); } else if(~READ(D,MENU) && status==0 && reset==1) { // MENU/SELECT Button - PD.5 - Status: Normal-BLANK _delay_ms(DB_DELAY); cli(); status = 0; reset = 0; print_title(); while(~READ(D,MENU)) ; _delay_ms(DB_DELAY); } else if(~READ(D,MENU) && status==2) { // MENU/SELECT Button - PD.5 - Status: Menu _delay_ms(DB_DELAY); status = 3; switch(menu_index) { case 1: // Counts / Revolutions count_rev(); break; case 2: // Comparator Voltage compvolt = 1; comp_volt(); break; } while(~READ(D,MENU)) ; _delay_ms(DB_DELAY); } else if(~READ(D,MENU) && status==3) { // MENU/SELECT Button - PortD.5 - Status: In Setting _delay_ms(DB_DELAY); lcd_clrscr(); lcd_gotoxy(0,0); if(menu_index==1) { lcd_puts("> Counts / Rev"); lcd_gotoxy(0,1); lcd_puts(" Comparator V"); } else { lcd_puts(" Counts / Rev"); lcd_gotoxy(0,1); lcd_puts("> Comparator V"); compvolt = 0; } status = 2; compvolt = 0; temp = 0; ADCSRA = 0b10000000; while(~READ(D,MENU)) ; _delay_ms(DB_DELAY); } if(~READ(D,NEXT) && status==2) { // Next Button - PortD.7 - Status: In-Menu _delay_ms(DB_DELAY); while(~READ(D,NEXT)) ; _delay_ms(DB_DELAY); lcd_clrscr(); lcd_gotoxy(0,0); if(menu_index==1) { lcd_puts(" Counts / Rev"); lcd_gotoxy(0,1); lcd_puts("> Comparator V"); menu_index = 2; status = 2; } else if(menu_index==2) { lcd_puts("> Counts / Rev"); lcd_gotoxy(0,1); lcd_puts(" Comparator V"); menu_index = 1; status = 2; } } else if(~READ(D,NEXT) && status==3 && menu_index==1) { // Next Button - PortD.7 - Status: In-Setting _delay_ms(DB_DELAY); countpr++; count_rev(); while(~READ(D,NEXT)) ; _delay_ms(DB_DELAY); } if(~READ(D,PREV) && status==2) { // Prev Button - PortD.6 - Status: In-Menu _delay_ms(DB_DELAY); while(~READ(D,PREV)) ; _delay_ms(DB_DELAY); lcd_clrscr(); lcd_gotoxy(0,0); if(menu_index==1) { lcd_puts(" Counts / Rev"); lcd_gotoxy(0,1); lcd_puts("> Comparator V"); menu_index = 2; status = 2; } else if(menu_index==2) { lcd_puts("> Counts / Rev"); lcd_gotoxy(0,1); lcd_puts(" Comparator V"); menu_index = 1; status = 2; } } else if(~READ(D,PREV) && status==3 && menu_index==1) { // Prev Button - PortD.6 - Status: In-Setting _delay_ms(DB_DELAY); if(countpr>1) countpr--; count_rev(); while(~READ(D,PREV)) ; _delay_ms(DB_DELAY); } if(compvolt) { // Show Voltage on LCD unsigned char adcval=0; ADCSRA = 0b11000111; while(ADCSRA & BITVAL(ADSC)) ; ADCSRA |= BITVAL(ADIF); adcval = (ADCH*50)/255; temp++; if(temp>5000) { lcd_gotoxy(3,1); itoa(adcval/10,tempstr,10); lcd_puts(tempstr); lcd_puts("."); itoa(adcval%10,tempstr,10); lcd_puts(tempstr); lcd_puts(" Volts "); temp = 0; } } } return(0); } void comp_volt() { lcd_clrscr(); lcd_gotoxy(0,0); lcd_puts(" Comp. Voltage "); } void count_rev() { lcd_clrscr(); lcd_gotoxy(0,0); lcd_puts(" Counts / Rev "); lcd_gotoxy(2,1); lcd_puts("-"); lcd_gotoxy(6,1); itoa(countpr,tempstr,10); lcd_puts(tempstr); lcd_gotoxy(11,1); lcd_puts("+"); } void print_int(unsigned char x, unsigned char y, unsigned int temp) { char tempstr[4]; if(temp) { itoa(temp,tempstr,10); lcd_gotoxy(x,y); lcd_puts(tempstr); } else { lcd_gotoxy(x,y); lcd_puts(" "); } } void print_title() { lcd_init(LCD_DISP_ON); lcd_clrscr(); _delay_ms(500); lcd_puts(" Tach-Tastic"); _delay_ms(500); lcd_gotoxy(0,1); lcd_puts("iTeam IIEE"); } void init_all() { GICR = 0b01000000; // INT0: On MCUCR = 0b00000011; // Mode: Rising Edge TCCR0 = 0b00000101; // TC0 Init - Mode: Normal TCNT0 = 0b00000000; // Clock source: System Clock/1024 TIMSK = 0b00000001; // OC0 output: Disconnected ADMUX = 0b00100000; // ADC00 at PC.0 ADCSRA = 0b00000111; // ADC Disabled cli(); // Disbale all Interrupts DDRB = 0xFF; // PortB Output DDRD = 0x00; // PortC Input PORTD = 0xFF; // Pulled Up } ISR(INT0_vect) // INT0 Routine { cnt++; count++; print_int(0,0,count); } ISR(TIMER0_OVF_vect) // Timer0 Overflow Routine { inc++; if(inc>30) { time++; cnt3 = cnt2; cnt2 = cnt1; cnt1 = cnt/countpr; print_int(12,0,time); print_int(0,1,((cnt1+cnt2+cnt3)/3)*60); print_int(12,1,(cnt1+cnt2+cnt3)/3); inc = 0; cnt = 0; } }