.:: PIC Speedometer ::.
Measures speed of wheel and displays a binary speed in miles per hour

This project uses a PIC microcontroller to measure the speed of rotation and then displays the miles per hour value in binary format. The above screen shot is my software running on a "Real PIC Simulator", allowing me to test the microcontroller in action without actually building anything. In the future I will connect the binary output to a 2 digit, 7 segment, LED module.


This is a debouncing circuit that will smooth any spikes caused by imperfections in a real world switch. Debouncing can be done either with hardware or sofware. I chose the hardware aproach to make the code more readable.

HI-TECH PIC C COMPILER (PINA0 to sensor, PORTB to display)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include <htc.h> #define _XTAL_FREQ 8000000 void main() { // init long wheel_diameter = 26; long time_counter = 0; int speed = 0; TRISA=0XFF; // A input TRISB=0X00; // B output // status for (int i=0;i<10;i++) { PORTB = 255; __delay_ms(50); PORTB = 0; __delay_ms(50); } // measure speed while(1) { time_counter = 0; while(RA0 == 0){} while(RA0 == 1){} while(RA0 == 0) { __delay_ms(1); if (time_counter < 5000) { time_counter++; } } while(RA0 == 0){} speed = (int)((178 * wheel_diameter) / time_counter); PORTB = speed; __delay_ms(1000); } } |
CCS PIC C COMPILER (PINA0 to sensor, PORTB to display)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #include <main.h> #use delay(clock=8000000) #FUSES NOWDT //No Watch Dog Timer #FUSES RC //Resistor/Capacitor Osc with CLKOUT #FUSES NOPUT //No Power Up Timer #FUSES NOPROTECT //Code not protected from reading #FUSES NODEBUG //No Debug mode for ICD #FUSES NOBROWNOUT //No brownout reset #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #FUSES NOCPD //No EE protection #FUSES NOWRT void main(int args[]) { // init long const wheel_diameter = 26; long time_counter = 0; long speed = 0; set_tris_a(0b11111111); // PORTA input set_tris_b(0b00000000); // PORTB output // status for (int i=0;i<10;i++) { output_b(255); delay_ms(50); output_b(0); delay_ms(50); } // measure speed while(1) { time_counter = 0; while(input(pin_A0) == 0){} while(input(pin_A0) == 1){} while(input(pin_A0) == 0) { delay_ms(1); if (time_counter < 5000) { time_counter++; } } while(input(pin_A0) == 0){} speed = (int)((178 * wheel_diameter) / time_counter); output_b(speed); delay_ms(1000); } } |
HI-TECH PIC C COMPILER - Allows you to set wheel diameter (PINA0 to sensor, PINA1 increments/sets wheel diameter, PORTB to display), saves setting to EEPROM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include <htc.h> #define _XTAL_FREQ 8000000 void main() { // init long wheel_diameter = EEPROM_READ(0); // Read wheel diameter from EEPROM long time_counter = 0; int speed = 0; TRISA=0XFF; // A input TRISB=0X00; // B output // status for (int i=0;i<5;i++) { PORTB = 255; __delay_ms(100); PORTB = 0; __delay_ms(100); } // set wheel diameter, RA1 moment = increment, RA1 hold = set int looping = 1; int cnt = 0; PORTB = wheel_diameter; // display new wheel diameter while(looping == 1) { while (RA1 == 0) {} // wait for button to go from 0 to 1 while (RA1 == 1) // loop while button is pressed { __delay_ms(10); cnt++; if (cnt > 100) // if loop count exceeds thresh, break out { looping = 0; break; } } cnt = 0; if (looping == 0) {break;} // break out if looping stops wheel_diameter++; // otherwise increment wheel diameter if (wheel_diameter > 40) // if wheel diameter exceeds limit, set to 1 { wheel_diameter = 1; } PORTB = wheel_diameter; // display new wheel diameter } EEPROM_WRITE(0,wheel_diameter); // Write wheel diameter to EEPROM // status for (int i=0;i<5;i++) { PORTB = 255; __delay_ms(100); PORTB = 0; __delay_ms(100); } // measure speed while(1) { time_counter = 0; while(RA0 == 0){} while(RA0 == 1){} while(RA0 == 0) { __delay_ms(1); if (time_counter < 5000) { time_counter++; } } while(RA0 == 0){} speed = (int)((178 * wheel_diameter) / time_counter); PORTB = speed; __delay_ms(1000); } } |
CCS PIC C COMPILER - Allows you to set wheel diameter (PINA0 to sensor, PINA1 increments/sets wheel diameter, PORTB to display), saves setting to EEPROM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #include <main.h> #use delay(clock=8000000) #FUSES NOWDT //No Watch Dog Timer #FUSES RC //Resistor/Capacitor Osc with CLKOUT #FUSES NOPUT //No Power Up Timer #FUSES NOPROTECT //Code not protected from reading #FUSES NODEBUG //No Debug mode for ICD #FUSES NOBROWNOUT //No brownout reset #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #FUSES NOCPD //No EE protection #FUSES NOWRT //Program memory not write protected void main() { // init long wheel_diameter = read_eeprom(0); // Read wheel diameter from EEPROM long time_counter = 0; int speed = 0; set_tris_a(0b11111111); // PORTA input set_tris_b(0b00000000); // PORTB output // status for (int i=0;i<5;i++) { output_b(255); delay_ms(100); output_b(0); delay_ms(100); } // set wheel diameter, RA1 moment = increment, RA1 hold = set int looping = 1; int cnt = 0; output_b(wheel_diameter); while(looping == 1) { while (input(pin_A1) == 0) {} // wait for button to go from 0 to 1 while (input(pin_A1) == 1) // loop while button is pressed { delay_ms(10); cnt++; if (cnt > 100) // if loop count exceeds thresh, break out { looping = 0; break; } } cnt = 0; if (looping == 0) {break;} // break out if looping stops wheel_diameter++; // otherwise increment wheel diameter if (wheel_diameter > 40) // if wheel diameter exceeds limit, set to 1 { wheel_diameter = 1; } output_b(wheel_diameter); // display new wheel diameter } write_eeprom(0,wheel_diameter); // Write wheel diameter to EEPROM // status for (int j=0;j<5;j++) { output_b(255); delay_ms(100); output_b(0); delay_ms(100); } // measure speed while(1) { time_counter = 0; while(input(pin_A0) == 0){} while(input(pin_A0) == 1){} while(input(pin_A0) == 0) { delay_ms(1); if (time_counter < 5000) { time_counter++; } } while(input(pin_A0) == 0){} speed = (int)((178 * wheel_diameter) / time_counter); output_b(speed); delay_ms(1000); } } |