C:\> Rostislav Persion's Projects

.:: 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);
       }
   }