View previous topic :: View next topic |
Author |
Message |
Ruby
Joined: 04 Jul 2014 Posts: 44
|
Tachometer |
Posted: Tue Sep 02, 2014 4:53 pm |
|
|
Hi guys. I am trying to build a tachometer by pic16f877a with IR sensor.
I think i have trouble with interrupts. Timer stops in the middle...
This is the code i wrote.
Thanks.
Code: |
#include <16f877a.h>
#fuses hs,nowrt,nowdt,nodebug,brownout,nolvp,nocpd,put,noprotect
#use delay (clock=20000000)
#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, errors)
#define LCD_ENABLE_PIN PIN_B0 //#define use_portb_lcd TRUE
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B5
#define LCD_DATA6 PIN_B6
#define LCD_DATA7 PIN_B7
#include <lcd.c> // For LCD and has to be after #use delay()
unsigned int16 i=0,t1=0,t2=0;
unsigned int x=0,y=0,t=0;
float32 pulse_width=0;
#int_TIMER1
void one_minute()
{
++i;
if (i==600) // 60 sec.
{
output_toggle(PIN_D1);
t=0.1*i;
x=1;
}
set_timer1(3035);
}
void main ()
{
set_tris_a(0xff);
set_tris_d(0x00);
output_d(0x00);
lcd_init();
delay_ms(100);
printf(lcd_putc,"\fREADY");
delay_ms(500);
printf(lcd_putc,"\nWAITING...");
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
set_timer1(3035); //========> 1/(20.000.000)*8*4(65535-3035)=0.1 sec.
enable_interrupts(int_timer1);
enable_interrupts(GLOBAL);
output_toggle(PIN_D1);
while (TRUE)
{
if (input (pin_A4) && y==0 )
{
while (input (pin_A4));
t1=get_timer1();
while (!input (pin_A4));
t2=get_timer1();
setup_timer_1(T1_DISABLED);
printf(lcd_putc,"\fCalculating...");
delay_ms(100);
pulse_width=(0.1*(t1-t2)/(65535-3035))+t;
printf(lcd_putc,"\fPulse width \n%f seconds",pulse_width);
delay_ms(500);
y=1;
}
if (x==1)
{
setup_timer_1(T1_DISABLED);
printf(lcd_putc,"\fTimer Stopped in \n%u seconds",t);
x=0;
}
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Wed Sep 03, 2014 12:49 am |
|
|
Without even looking at the main:
1) i==600 - what then sets i back to 0?.
2) float maths in the interrupt - don't do this. Multiple problems:
First interrupts will be disabled in float multiplies in the main.
Second it takes an age.
Third it is large.
Avoid float maths in anything if you can.
Think about it. Just have an int16 or int32, that is in 0.1 sec 'counts'. Then use %l5.1w in the printf, which will display this as xxx.x seconds. No need to ever involve float. Code will be smaller, faster, and more reliable (fp suffers from routing errors, which integers don't have...).
I didn't look further. |
|
|
Ruby
Joined: 04 Jul 2014 Posts: 44
|
|
Posted: Wed Sep 03, 2014 2:23 am |
|
|
Thanks for reply.
I have changed the code but now counter goes up not only high to low but also low to high.
Code: |
#include <16f877a.h>
#fuses hs,nowrt,nowdt,nodebug,brownout,nolvp,nocpd,put,noprotect
#use delay (clock=20000000)
#use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, errors)
#define LCD_ENABLE_PIN PIN_B0 //#define use_portb_lcd TRUE
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B5
#define LCD_DATA6 PIN_B6
#define LCD_DATA7 PIN_B7
#include <lcd.c> // For LCD and has to be after #use delay()
unsigned int16 i=0;
unsigned int x=0;
#int_TIMER0
void one_minute()
{
output_toggle(PIN_D1);
++i;
x=1;
set_timer0(255);
}
void main ()
{
set_tris_a(0xff);
set_tris_d(0x00);
output_d(0x00);
lcd_init();
delay_ms(100);
printf(lcd_putc,"\fREADY");
delay_ms(500);
printf(lcd_putc,"\nWAITING...");
setup_timer_0 (RTCC_DIV_2|RTCC_EXT_H_TO_L);
set_timer0(255);
enable_interrupts(int_timer0);
enable_interrupts(GLOBAL);
output_toggle(PIN_D1);
while (TRUE)
{
if (x==1 )
{
printf(lcd_putc,"\fRPM %Lu",i);
set_timer0(255);
enable_interrupts(int_timer0);
enable_interrupts(GLOBAL);
x=0;
}
}}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Wed Sep 03, 2014 2:48 am |
|
|
It'll trigger almost instantly....
Timer0, is an 8bit timer. Counts to 256. You are setting it to 255, so it'll trigger just two edges later..... |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Sep 03, 2014 10:34 am |
|
|
Please explain EXACTLY how you are trying to achieve a display of RPM.
I can't understand your code at all.
Mike |
|
|
Ruby
Joined: 04 Jul 2014 Posts: 44
|
|
Posted: Wed Sep 03, 2014 1:02 pm |
|
|
Hi. This is only the first part i wrote. I want to calculate time between two pulses. But the problem is timer interrupts also when it goes low to high. |
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Wed Sep 03, 2014 1:24 pm |
|
|
While not your current problem, I would give serious consideration to looking at at least 10 pulses (and then applying some form of averaging) or you are more than likely to get numbers that jump all over the place and not be readable. If you are looking at a fan for example with IR and the blades are not symmetrically placed, you will get strange results.
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: Wed Sep 03, 2014 3:54 pm |
|
|
Ruby wrote: | Hi. This is only the first part i wrote. I want to calculate time between two pulses. But the problem is timer interrupts also when it goes low to high. |
So, what EXACTLY were you trying to do.
To me, your code bears no relation to any of your explanations.
We can better help when you provide more information.
Mike |
|
|
Ruby
Joined: 04 Jul 2014 Posts: 44
|
|
Posted: Thu Sep 04, 2014 12:11 pm |
|
|
Ok. I have two options for diy tachometer.
1) Calculate time between two pulses
2) Calculate how many pulses in a minute.
I tried the first one. Without calculating time.
Ps: Do I have to use ccp? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Sep 04, 2014 1:45 pm |
|
|
OK. Let's be serious.
Tell us:-
1) What kind of pulses you are trying to measure.
2) The expected frequency range of your pulses.
Maybe then we can start to do sensible design.
Mike |
|
|
Ruby
Joined: 04 Jul 2014 Posts: 44
|
|
Posted: Sat Sep 06, 2014 9:30 am |
|
|
Poblem solved.
I change two things.
1)setup_timer_0 (RTCC_DIV_2|RTCC_EXT_H_TO_L); ==> DIV_1
2)The most important ; my sensor has two outputs. Analog and digital. Pic was connected to digital so I swaped it , it works perfect.
Now I did counter but when motor runs fast sensor can't catch the black spot.
And how can I calculate the time between two pulses? |
|
|
|