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

RPM giving multiples of 60 .help?

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



Joined: 16 Jan 2013
Posts: 15

View user's profile Send private message MSN Messenger

RPM giving multiples of 60 .help?
PostPosted: Wed Jan 16, 2013 1:10 am     Reply with quote

I have compiled a code for RPM. using an opt101 photodiode and led and getting pulses. the problem is it only gives me multiples of 60 e.g 60 or 120 or 3600 rpm etc. i have only one slot in the disk. can any one help ?

++++++++++++++++++++++++
UWK - No more repeating 10 posts.

Do 1 post only.

Final working.

- Forum Moderator
++++++++++++++++++++++++


Code:

#include <16F877A.h>
#device adc=8
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#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 WRT_50%                  //Lower half of Program Memory is Write Protected
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//#define LCD_TYPE 1
#include <lcd.c>
#bit t1_overflow=0x0C.0
int x,numofdigs,opcode,cycle,count=0,check;
int32  result,digit1,digit2,hunsdig,tensdig,onesdig;
   int cycles8, cycles;
   int32 freq;
   long freqc_high;
   long freqc_low;
   int16 time;
void makenum(); int getkey();
void main()
{
   lcd_init();
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_ccp1(ccp_pwm);
   setup_timer_2(T2_DIV_BY_4, 140, 1);

printf(lcd_putc,"Enter value");delay_ms(1000);lcd_putc('\f');
   while(1)
{x=0;
numofdigs=hunsdig=tensdig=onesdig=0;
printf(lcd_putc,"\f");

while(x!=90)
{
x=getkey();

if(x!=90)
{
printf(lcd_putc,"%u",x);delay_ms(250);
makenum();
}
else
{}

}
digit1=onesdig+(tensdig*10)+(hunsdig*100);

cycle = digit1;
set_pwm1_duty(cycle);

     
numofdigs=hunsdig=tensdig=onesdig=0;

           //x=140;
           
        // set_pwm1_duty(digit1); // Defined as x=Fraction of 140=duty cycle(In percentage)
         //delay_ms(100);
 
   
         //x=70;
      /*   set_pwm1_duty(x); // Defined as x=Fraction of 140=duty cycle(In percentage)
         delay_ms(100);
         putc(254);putc(1);
         delay_ms(5000);*/

   while (TRUE) {
      cycles8=0;
      cycles=0;
      freqc_high=0;
      t1_overflow=0;
      set_timer1(0);
      setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
/* ___ wait one second ___  */
      while (cycles!=0xFF) { //true=3, false=4
       cycles8=0; //1 cycle
       //start inner loop
       while (cycles8!=0xFF) { //true=3, false=4
         if (t1_overflow)//true=2,false=3             //----|
            {t1_overflow=0;freqc_high++;}//6 cycles   //    |
         else                                         //    |-- 8 cycles
            {delay_cycles(5);}                        //----|
         delay_cycles(62); //x
         cycles8++; //1
 ///2 cycles to jump to top
 //math: end inner loop
 //math: total inner loop=((3+8+x+1+2)*255 + 4)*255
 //math: if x=62.87781 then inner loops takes 5mil instructions
 //math: if x=62 then inner loop takes 4942920, have to fill 57080 cycles
  }
 delay_cycles(216);      //y
 cycles++;          ///1 cycle
 ///2 cylces to jump to top
 //math: outer=(3+1+y+1+2)*255+4=57080
 //math: y=(57080-4)/255)-(3+1+0+0+1+2)
 //math: if y=216.827450980392156862745098039216 then outer loop cylces is 57080
 //math: if y=216 then outer loop cycles is off by 211 cycles.  z=211
}
      delay_cycles(211);   //z
/* ___ end waiting 1 second ___ */
      setup_timer_1(T1_DISABLED);   //turn of counter to prevent corruption while grabbing value
      if (t1_overflow)            //check one last time for overflow
          freqc_high++;
      freqc_low=get_timer1();      //get timer1 value as the least sign. 16bits of freq counter
      freq=make32(freqc_high,freqc_low);   //use new make32 function to join lsb and msb
      //printf(lcd_putc,"%LU Hz\r\n",freq/3);//and print frequency
    delay_ms(1000);lcd_putc('\f');
    printf(lcd_putc,"%LU0 RPM\r\n",freq*60);      //and print RPM
   }}}




 int getkey()
{
int con;
x=0;
while(1)
{
output_low(PIN_B0);output_high(PIN_A1);output_high(PIN_A2);output_high(PIN_B3);
con=0;
while(con<10)
{
if(!input(PIN_B4))
{while(!input(PIN_B4));return 1;break;}
else if(!input(PIN_b5))
{while(!input(PIN_B5));return 2;break;}
else if(!input(PIN_B6))
{while(!input(PIN_B6));return 3;break;}
//if(!input(PIN_B7))
//{while(!input(PIN_B7));opcode=93;printf(lcd_putc,"\f");return 93;break;}
con=con+1;delay_ms(5);
}
output_high(PIN_B0);output_low(PIN_a1);output_high(PIN_a2);output_high(PIN_B3);
con=0;
while(con<10)
{
if(!input(PIN_B4))
{while(!input(PIN_B4));return 4;break;}
if(!input(PIN_b5))
{while(!input(PIN_B5));return 5;break;}
if(!input(PIN_B6))
{while(!input(PIN_B6));return 6;break;}
//if(!input(PIN_B7))
//{while(!input(PIN_B7));opcode=92;printf(lcd_putc,"\f");return 92;break;}
con=con+1;delay_ms(5);
}
output_high(PIN_B0);output_high(PIN_a1);output_low(PIN_a2);output_high(PIN_B3);
con=0;
while(con<10)
{
if(!input(PIN_B4))
{while(!input(PIN_B4));return 7;break;}
if(!input(PIN_b5))
{while(!input(PIN_B5));return 8;break;}
if(!input(PIN_B6))
{while(!input(PIN_B6));return 9;break;}
//if(!input(PIN_B7))
//{while(!input(PIN_B7));opcode=91;printf(lcd_putc,"\f");return 91;break;}
con=con+1;delay_ms(5);
}

output_high(PIN_B0);output_high(PIN_a1);output_high(PIN_a2);output_low(PIN_B3);
con=0;
while(con<10)
{
if(!input(PIN_B4))
{while(!input(PIN_B4));opcode=90;printf(lcd_putc,"\f");return 90; break;}
if(!input(PIN_b5))
{while(!input(PIN_B5));return 0;break;}
con=con+1;delay_ms(5);
}
}  }
void makenum()
{

numofdigs++;
if(numofdigs==3)
{ hunsdig = tensdig; tensdig = onesdig; onesdig = x; }
if(numofdigs==2)
{ tensdig=onesdig; onesdig = x; }
if(numofdigs==1)
onesdig = x;
}
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Wed Jan 16, 2013 8:07 am     Reply with quote

60 RPM resolution is inevitable if you count an integer number of slots in one second and multiply to 60 to get slots/minute.
To get finer resolution you need more slots in the disk or to count for more than one second. Or you can invert the process by measuring the period between slots.

I once had a customer that wanted 1Hz updates of RPM to 1 RPM resolution with only four slots per revolution. When I pointed out to them that at 1 RPM I only had input every 15 seconds they had to go back to the contract lawyers and get the contract specs changed.
_________________
The search for better is endless. Instead simply find very good and get the job done.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Jan 16, 2013 6:01 pm     Reply with quote

I don't propose to decipher your code, it's too long.

You need to read the forum guidelines on how to get help.

I'm assuming you're counting the number of rotations in one second, then multiplying by 60.

If the rate is 2.5 per second you'll get counts of 2 and 3 for each alternate second which translate to 120 and 180 RPM.

Instead, time the period for one rotation as 400ms.
Then convert to RPM as 60000/400 = 150.
This process avoids using floats.

Mike
UWK



Joined: 16 Jan 2013
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Wed Jan 16, 2013 9:19 pm     Reply with quote

Mike can you explain in detail what do you mean by set the time period at 400 ms
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Wed Jan 16, 2013 11:44 pm     Reply with quote

Measure the period of the rotation instead of number of rotations in a given period. You can't get rapid updates on slow rotations by measuring how many in a period. Typically you will also want to average that measured period over several rotations to smooth the readings a bit, but for a start, measure the period of the rotation.

mikey
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Jan 17, 2013 2:38 am     Reply with quote

Quote:
Mike can you explain in detail what do you mean by set the time period at 400 ms
I was continuing my example of what happens at 2.5 rev per second.

At 2.5 rev per second, one period of rotation happens to be 400ms.
(I did NOT say SET the period at 400ms.)

For starters measure just one period, calculate RPM from that.

In practice you'll need to measure several periods to get a decent average, but one will do for now at your level.

Mike
UWK



Joined: 16 Jan 2013
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Thu Jan 17, 2013 2:42 am     Reply with quote

ok... i will try
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Jan 17, 2013 2:57 am     Reply with quote

Don't expect it to work perfectly first time.

There are loads of examples on this forum and in the CCS library to guide you.

If (when) you get stuck there are people here who will help you provided that you can show that you've put in some effort.

Mike
UWK



Joined: 16 Jan 2013
Posts: 15

View user's profile Send private message MSN Messenger

PostPosted: Thu Jan 17, 2013 3:49 am     Reply with quote

Maximum RPM of my motor is 3600 RPM when i slowly increase the duty cycle and about 3480 RPM when directly given full duty cycle. Because it gives multiples of 60. The opt101 is giving output to a comparator LM324 which gives 0V when light is blocked and 3.6 volts when there is a slot, and output of comparator is connected to pin C0.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Jan 17, 2013 5:14 am     Reply with quote

More questions

1) How wide is the slot?
2) What is disc size?
3) What does waveform fed to PIC look like at max speed?

Mike
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Thu Jan 17, 2013 7:43 am     Reply with quote

If your max speed is 3600 pulses/minute and you want a resolution of 10 RPM then you need to get a different count for 3590 p/m than you do for 3600 p/m.

3600 p/m = 16667 microseconds/pulse
3590 p/m = 16713 microseconds/pulse
The difference is 46 microseconds, so you need to measure period with a clock of at least 1/46 us = 21.7 kHz

For 1 RPM resolution you need a timing clock of at least 217 kHz to distinguish 3600 RPM from 3599 RPM.
_________________
The search for better is endless. Instead simply find very good and get the job done.
Ttelmah



Joined: 11 Mar 2010
Posts: 19236

View user's profile Send private message

PostPosted: Thu Jan 17, 2013 8:27 am     Reply with quote

I think Mike's question is probably the key one. The LM324, is a _very_ slow chip indeed for this type of application. While most op-amps can be used to an extent as comparators, if this is running off 5v, the slew rate is only a very few volts per msec (only a couple of manufacturers even give guide figures down at this low voltage). To swing from 0v to 3v, and back again, then easily take over a mSec. If the slot is less than perhaps 1/10th the circumference, the output probably won't swing far enough to actually be detected by the PIC.....

Use a comparator, with some hysteresis. Cleaner signal, and faster edges.

The OPT101, is also not a fast device. It is aimed at giving an accurate linear response to light levels, not quick detection of edges. Much better to use something like an IR photodiode (avoids the detector being affected so much by ambient light), designed for detecting switching like this. Use one of the off the shelf optical slot detector modules, and you won't need another amplifier anyway.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Jan 18, 2013 5:28 am     Reply with quote

OK

Ttelmah has explained the reason for my previous questions.
You need to ensure that the hardware works correctly before thinking about coding.
Do NOT even consider using Proteus to provide answers.
Test with a 'scope on REAL hardware.
(The problem with slow edges is that you'll encounter severe timing issues.)

You will need to complete an analysis along the lines indicated by SherpaDoug, and certainly before you proceed further.

Mike
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