View previous topic :: View next topic |
Author |
Message |
UWK
Joined: 16 Jan 2013 Posts: 15
|
RPM giving multiples of 60 .help? |
Posted: Wed Jan 16, 2013 1:10 am |
|
|
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
|
|
Posted: Wed Jan 16, 2013 8:07 am |
|
|
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
|
|
Posted: Wed Jan 16, 2013 6:01 pm |
|
|
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
|
|
Posted: Wed Jan 16, 2013 9:19 pm |
|
|
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
|
|
Posted: Wed Jan 16, 2013 11:44 pm |
|
|
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
|
|
Posted: Thu Jan 17, 2013 2:38 am |
|
|
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
|
|
Posted: Thu Jan 17, 2013 2:42 am |
|
|
ok... i will try |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Jan 17, 2013 2:57 am |
|
|
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
|
|
Posted: Thu Jan 17, 2013 3:49 am |
|
|
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
|
|
Posted: Thu Jan 17, 2013 5:14 am |
|
|
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
|
|
Posted: Thu Jan 17, 2013 7:43 am |
|
|
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: 19539
|
|
Posted: Thu Jan 17, 2013 8:27 am |
|
|
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
|
|
Posted: Fri Jan 18, 2013 5:28 am |
|
|
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 |
|
|
|