CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

tachometer issues

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sonicfire



Joined: 11 Feb 2007
Posts: 19
Location: Cedar Rapids

View user's profile Send private message

tachometer issues
PostPosted: Thu Apr 12, 2007 2:49 pm     Reply with quote

I've been working on building a tachometer for a dc motor. The motor's axel has a gear with 24 teeth (24 teeth per revolution). The teeth go in between a photodiode and sensor. This creates a square wave. I wrote a program for a PIC 16F877 that counts the number of low to high signals that occur in one second. This count is then divided by 4 to give the RPM (in powers of 10) and then display the output. Here's the code:

Code:
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#define TIMER_SET   65535-25000   //holds the initial condition of timer
int8 hundredths;
int8 tenths;
int8 seconds;
int last_value;
int current_value;
unsigned int8 rpm = 0;
unsigned int8 teeth = 0;
unsigned int8 huns;
unsigned int8 tens;
unsigned int8 ones;
//int overflow;


void main() {

  setup_timer_1(T1_INTERNAL); //1Mhz/8 gives us 125000Hz because it originally is
                                // divided by 4 automatically

  hundredths = 0;
  tenths = 0;
  seconds = 0;
  set_timer1(TIMER_SET);
  enable_interrupts(INT_TIMER1);
  enable_interrupts(GLOBAL);

  last_value = input(PIN_C0);

  //only counts
  while( TRUE ) {

    current_value = input(PIN_C0);

    if(last_value == 0) {

        if(current_value == 1) {
       
            teeth = teeth + 1;
            last_value = 1;
           
         }       

     }
    else {         //last_value = 1
   
        if(current_value == 0) {
       
            last_value = 0;
           
         }
    }

}
}


//interupt
#INT_TIMER1
void time_increment_isr()
{
  set_timer1(TIMER_SET + get_timer1() + 26);

        hundredths ++;

        if (hundredths == 10)
        {
           hundredths = 0;
           tenths++;
        }

        if (tenths == 10)
        {
           tenths = 0;
           seconds++;
        }

        if (seconds == 1)
        {
         //fancy output time...
         //teeth/4 comes from (teeth)(1Rev/24teeth)(60seconds/min)(divided by 10).  Value is RPMx10
         //divide by 4 will be done by right shifting the digits to the right by two spaces, no need to do this math, just output what is desired

         rpm = (teeth/4);

         //NEED TO CONVERT THE RPM INT INTO DECIMAL BINARY EQUIVALENT FOR 7 SEGMENT DISPLAYS...
     
         huns = rpm/100;
         tens = (rpm - (huns*100) )/10;
         ones = rpm - ((huns*100)+(tens*10));
         
         //convert the huns
         switch (huns) {
            case 0:
               output_low(PIN_B7);
               output_low(PIN_B6);
               output_low(PIN_B5);
               output_low(PIN_B4);
               break;
            case 1:
               output_low(PIN_B7);
               output_low(PIN_B6);
               output_low(PIN_B5);
               output_high(PIN_B4);
               break;
            case 2:
               output_low(PIN_B7);
               output_low(PIN_B6);
               output_high(PIN_B5);
               output_low(PIN_B4);
               break;
            case 3:
               output_low(PIN_B7);
               output_low(PIN_B6);
               output_high(PIN_B5);
               output_high(PIN_B4);
               break;
            case 4:
               output_low(PIN_B7);
               output_high(PIN_B6);
               output_low(PIN_B5);
               output_low(PIN_B4);
               break;
            case 5:
               output_low(PIN_B7);
               output_high(PIN_B6);
               output_low(PIN_B5);
               output_high(PIN_B4);
               break;
            case 6:
               output_low(PIN_B7);
               output_high(PIN_B6);
               output_high(PIN_B5);
               output_low(PIN_B4);
               break;
            case 7:
               output_low(PIN_B7);
               output_high(PIN_B6);
               output_high(PIN_B5);
               output_high(PIN_B4);
               break;
            case 8:
               output_high(PIN_B7);
               output_low(PIN_B6);
               output_low(PIN_B5);
               output_low(PIN_B4);
               break;
            case 9:
               output_high(PIN_B7);
               output_low(PIN_B6);
               output_low(PIN_B5);
               output_high(PIN_B4);
               break;
            default:
               output_high(PIN_B7);
               output_high(PIN_B6);
               output_high(PIN_B5);
               output_high(PIN_B4);
               break;
         }
         
         //convert the tens
         switch (tens) {
            case 0:
               output_low(PIN_B3);
               output_low(PIN_B2);
               output_low(PIN_B1);
               output_low(PIN_B0);
               break;
            case 1:
               output_low(PIN_B3);
               output_low(PIN_B2);
               output_low(PIN_B1);
               output_high(PIN_B0);
               break;
            case 2:
               output_low(PIN_B3);
               output_low(PIN_B2);
               output_high(PIN_B1);
               output_low(PIN_B0);
               break;
            case 3:
               output_low(PIN_B3);
               output_low(PIN_B2);
               output_high(PIN_B1);
               output_high(PIN_B0);
               break;
            case 4:
               output_low(PIN_B3);
               output_high(PIN_B2);
               output_low(PIN_B1);
               output_low(PIN_B0);
               break;
            case 5:
               output_low(PIN_B3);
               output_high(PIN_B2);
               output_low(PIN_B1);
               output_high(PIN_B0);
               break;
            case 6:
               output_low(PIN_B3);
               output_high(PIN_B2);
               output_high(PIN_B1);
               output_low(PIN_B0);
               break;
            case 7:
               output_low(PIN_B3);
               output_high(PIN_B2);
               output_high(PIN_B1);
               output_high(PIN_B0);
               break;
            case 8:
               output_high(PIN_B3);
               output_low(PIN_B2);
               output_low(PIN_B1);
               output_low(PIN_B0);
               break;
            case 9:
               output_high(PIN_B3);
               output_low(PIN_B2);
               output_low(PIN_B1);
               output_high(PIN_B0);
               break;
            default:
               output_high(PIN_B3);
               output_high(PIN_B2);
               output_high(PIN_B1);
               output_high(PIN_B0);
               break;
         }
         
         //convert the ones
         switch (ones) {
            case 0:
               output_low(PIN_D7);
               output_low(PIN_D6);
               output_low(PIN_D5);
               output_low(PIN_D4);
               break;
            case 1:
               output_low(PIN_D7);
               output_low(PIN_D6);
               output_low(PIN_D5);
               output_high(PIN_D4);
               break;
            case 2:
               output_low(PIN_D7);
               output_low(PIN_D6);
               output_high(PIN_D5);
               output_low(PIN_D4);
               break;
            case 3:
               output_low(PIN_D7);
               output_low(PIN_D6);
               output_high(PIN_D5);
               output_high(PIN_D4);
               break;
            case 4:
               output_low(PIN_D7);
               output_high(PIN_D6);
               output_low(PIN_D5);
               output_low(PIN_D4);
               break;
            case 5:
               output_low(PIN_D7);
               output_high(PIN_D6);
               output_low(PIN_D5);
               output_high(PIN_D4);
               break;
            case 6:
               output_low(PIN_D7);
               output_high(PIN_D6);
               output_high(PIN_D5);
               output_low(PIN_D4);
               break;
            case 7:
               output_low(PIN_D7);
               output_high(PIN_D6);
               output_high(PIN_D5);
               output_high(PIN_D4);
               break;
            case 8:
               output_high(PIN_D7);
               output_low(PIN_D6);
               output_low(PIN_D5);
               output_low(PIN_D4);
               break;
            case 9:
               output_high(PIN_D7);
               output_low(PIN_D6);
               output_low(PIN_D5);
               output_high(PIN_D4);
               break;
            default:
               output_high(PIN_D7);
               output_high(PIN_D6);
               output_high(PIN_D5);
               output_high(PIN_D4);
               break;
         }
         
         //make sure everthing is reset before resuming the count     
         teeth = 0;
         hundredths = 0;
         tenths = 0;
         seconds = 0;
        }

}


Thanks!
Ttelmah
Guest







PostPosted: Thu Apr 12, 2007 3:32 pm     Reply with quote

You don't say what your 'issues' are. However there are some glaring things. Your #use delay statement, is for a 10MHz clock, not a 1Mhz clock. This would also make sense of the 'HS' fuse. Then your timer setup, gives a rate of 2.5MHz (if this is right), or 250KHz, if the source is 1MHz.The clock is being divided by four. For /8, you need T1_INTERNAL | T1_DIV_BY_2
Then you are doing vastly too much in the interrupt handler.

Best Wishes
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Thu Apr 12, 2007 4:24 pm     Reply with quote

Like Ttelmah said, there is WAY too much going on in the ISR. Keep it as short as possible. Set a few things and then bail out. Let the main() section take care of the calculation stuff. The ISR is going to take so much time that it's likely that your input(PIN_C0) statement could miss a few pulses.

Quote:
set_timer1(TIMER_SET + get_timer1() + 26);

Even though this is being done as the first instruction of the ISR you'll be half way down the block by the time it's done and will cause inaccuracies.

Ronald
sonicfire



Joined: 11 Feb 2007
Posts: 19
Location: Cedar Rapids

View user's profile Send private message

PostPosted: Fri Apr 13, 2007 12:15 pm     Reply with quote

The PIC is being run off of a 10 MHz oscillator. The problem is simply that it is giving me bogus values. The values it gives are proportional to changes in speed, but are nothing resembling the RPMs. I realize that I am putting a lot of command requirements on the PIC. Is there a way to reduce this? Also, could there be a problem in the way the PIC handles math that would cause errors?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group