View previous topic :: View next topic |
Author |
Message |
snooer
Joined: 22 Apr 2009 Posts: 14
|
Wind speed counter |
Posted: Fri Apr 24, 2009 11:18 am |
|
|
So I'm using IR and phototransistor and writing a program to count the wind speed. Counting process is simple detecting first low input and then second. Then getting result and of the time distance is known so we know and the speed.
So maybe anyone can help figure out how to make cycle like this and how the pic16f877a timer1 get second value?
Code so far:
Code: | #include <16F877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <stdlib.h>
#include <lcd.c>
#include <ctype.h>
void wait_for_low1() {
while(input(PIN_C1)); /* if it's high, wait for a low */
delay_us(3); /* account for fall time */
while(!input(PIN_C1 )); /* wait for signal to go high */
}
void wait_for_low2() {
delay_us(3); /* account for rise time */
while(input(PIN_C1)); /* wait for signal to go low */
lcd_init();
}
//int16 time;
float distance,mph,time;
void main() {
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
distance = 500;
lcd_init();
do {
wait_for_low1();
set_timer1(0);
wait_for_low2();
time = get_timer1();
mph = 0.0000016*(float)time/3600.0; // calculate the time in hours
mph = distance/(63360.0*mph);
printf(lcd_putc "value: %3.1fn\n\r",(float) time);
} while (TRUE);
} |
|
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Fri Apr 24, 2009 11:36 am |
|
|
This would be a good one to use an interrupt on. Tie your input to a pin with an interrupt. The first time the interrupt is entered, zero a variable that is incremented by a timer (that way you know the frequency the counter is incremented at). The next time the interrupt is entered, see how high the counter variable is and you can calculate your speed from that. Zero your counter again and it's ready for the next pulse. This will free up your program to do other things.
Ronald |
|
|
snooer
Joined: 22 Apr 2009 Posts: 14
|
|
Posted: Fri Apr 24, 2009 11:48 am |
|
|
I'am new in C so maby can you show in code? Ore some example |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 24, 2009 11:52 am |
|
|
Quote: | void wait_for_low1() {
while(input(PIN_C1)); /* if it's high, wait for a low */
delay_us(3); /* account for fall time */
while(!input(PIN_C1 )); /* wait for signal to go high */
}
|
You have modified the CCS routine "wait_for_low_to_high()" from the
Ex_Pulse.c example file. The new name you have given it is not very
good. You should use the CCS function name, or maybe call it
"wait_for_rising_edge()"
Quote: | void wait_for_low2() {
delay_us(3); /* account for rise time */
while(input(PIN_C1)); /* wait for signal to go low */
lcd_init();
} |
This routine also comes from the Ex_Pulse.c example. CCS calls it
"wait_for_low()". You have added a call to the lcd_init() routine.
That's not necessary. You should only call lcd_init() one time, at the
start of main(). If you need to clear the lcd, then do this:
or this:
Code: | printf(lcd_putc, "\f"); |
Quote: |
Counting process is simple detecting first low input and then second. |
So you want to count negative-going (falling) edges on the signal.
You can do this by modifying the CCS "wait_for_low_to_high()" routine
and make a wait_for_high_to_low() routine. Then call it 2 times, in a
similar way as the code at the start of your do-while loop. Set the timer
to 0 after the first call. Then read the timer after the 2nd call. |
|
|
snooer
Joined: 22 Apr 2009 Posts: 14
|
|
Posted: Fri Apr 24, 2009 11:59 am |
|
|
I was thinking about that and yes it's redone code from examples because i need to count from low to low input.
Code: | void wait_for_low1() {
while(input(PIN_C1)); /* if it's high, wait for a low */
delay_us(3); /* account for fall time */
while(!input(PIN_C1 )); /* wait for signal to go high */
}
void wait_for_low2() {
delay_us(3); /* account for rise time */
while(input(PIN_C1)); /* wait for signal to go low */
delay_us(3);
while(!input(PIN_C1));
} |
But in this case the phototransistor has to be trigered two times. It's not a big problem the bigest problem is that i dont know how to timer1 reult convert to S in diferent osilator |
|
|
snooer
Joined: 22 Apr 2009 Posts: 14
|
|
Posted: Fri Apr 24, 2009 1:55 pm |
|
|
Can anyone tell me why can't I get seconds in LCD getting numbers from 500 to 11000?
Code: | do {
wait_for_low1();
set_timer1(0);
wait_for_low2();
time = get_timer1();
time_s = 0.0000016*(float)time*63360.0; // calculate the time in hours
// mph = distance/(63360.0*mph);
printf(lcd_putc "value: %3.2f s\r\n", time_s);
} while (TRUE); |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 24, 2009 2:26 pm |
|
|
1. Use a printf statement after you get the Timer1 value, and display it.
Use "%ld" or "%lx" to display an int16 value. What values do you see ?
2. Also post the frequency of the input signal. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: Wind speed counter |
Posted: Sat Apr 25, 2009 5:42 pm |
|
|
snooer wrote: | So I'm using IR and phototransistor... |
Your job in software will be made much easier if you put some hysteresis in hardware when detecting the phototransistor. A little noise in the phototransistor can make several logic transitions which you may incorrectly count as separate pulses unless you ensure each pulse of light produces one clean on transition and one clean off transition. Look for comparator circuits with hysteresis.
If you are unable to add hardware hysteresis, then you can do some software debouncing. Look up debouncing algorithms, many of which have been discussed in this and the Microchip forum. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
snooer
Joined: 22 Apr 2009 Posts: 14
|
|
Posted: Sun Apr 26, 2009 5:53 am |
|
|
Yes I was thinking about this but so far the problem is not in hardware design. The problem is all about timer1. I still can't find the problem why I can't get 1 second when I'm using 1 Hz in input signal. Using Comparator difference will be converted logical 1 and more clear signal but so far I'm testing on virtual mode so. |
|
|
snooer
Joined: 22 Apr 2009 Posts: 14
|
|
Posted: Sun Apr 26, 2009 8:18 am |
|
|
So is it possible to count how much time passed between timer start and stop? Converting result in seconds? Or counting frequency? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 26, 2009 11:49 am |
|
|
Quote: |
#use delay(clock=20000000)
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
I still can't find the problem why I can't get 1 second when I'm using 1 Hz in input signal. |
Read the data sheet for the 16F877A.
Timer1 is clocked by Fosc/4, divided by the Timer1 Prescaler.
With your 20 MHz clock, this becomes 5 MHz / 8, which is 625 KHz.
This means in one second, there are 625000 clocks applied to the Timer.
Timer1 is a 16-bit counter, which can count up to 65535. So, it will count
up to its maximum value in about 1/10 of a second. It can't possibly
count up to 1 second. The clock is too fast.
You could add a Timer1 interrupt routine and increment a global byte
variable inside the interrupt routine to extend Timer1 to 24-bits. Then
you would have enough resolution to count a 1 Hz input signal. |
|
|
|