I'm trying to measure a frequency with the PIC16F627 RA4/TOCKI/CMP2 - Pin 3. I want to measure/count the frequency input, WRITE it into EPROM, READ the EPROM, then PRINT the value on the LCD.
I included some extra PRINT commands in the code for troubleshooting purposes. When I run the program, the LCD randomly PRINTS a 1 or 0 for FreqOne, 255 for DataLoc, and 0 for DataStor. This occurs with and without a signal generator attached to pin 3. I've tried frequencies as low as 1 Hz and as high as 10 MHz but the results are the same.
Anyone know what I'm doing wrong? I should mention I'm new to PIC programming.
Your program is doing what you are telling it to do.
"EPWrite DataLoc, FreqOne" - FreqOne is only the input pin that you told it to be. It can only be on or off, 0 or 1
You should be reading the timer0 register.
Many other things need attention:
EPwrite/read are byte wide
DataLoc needs to be initialized
Timer0 needs to be setup for counting
Frequency units are counts per time, you need a better timer than ' wait '. It might work for experiment?
Down load the microchip 40044D.book for the 16F627 and read relevant sections.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks mmotte for your quick response. I downloaded and read the appropriate sections in 40044D as you suggested. I've also read DS33023. My problem is that these documents use assembly language terms and I don't know how to make GCBASIC do them. Your first suggestion was:
"You should be reading the timer0 register" - The document uses terms like TOCS, TOSE bits, and TMRO register. How do I do this in GCBASIC?
Another suggestion was "Timer0 needs to be set up for counting." - In my above software I have the GCBASIC code-
InitTimer0 Osc, PS0_1/2
Is there some other GCBASIC code I should include?
"DataLoc needs to be initialized" - I assume DataLoc is a location in EEPROM. The documents discuss EECON1, ECCON2, EEDATA, and EEADR. In Section 13.4, it states "The write will not initiate if the above sequence (example 13.2) is not followed exactly (write 55h to EECON2, write AAh to EECON2, then set WR bit) for each byte. We strongly recommend that interrupts be disabled during this code segment. Any number that is not equal to the required cycles to execute the required sequence will cause the data not to be written into the EEPROM….." Same question, How do I do this in GCBASIC?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Can you provide more information about exactly what you're trying to do? For instance, what is the range of frequencies you're trying to count? How much resolution is required? How much accuracy is required?
There are several ways you might accomplish this with various combinations of the internal timer/counters. Basically, you need to set up one of the timer/counters as a sampling gate (eg, 10 hz or 1 hz, depending on the resolution required) and use the output of that timer to start/stop another counter that actually measures the frequency. However, it's probably not going to be possible for you to do this unless you study the datasheet sections on the PIC's internal timer/counters.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
there is some help in http://gcbasic.sourceforge.net/help/
timer0 is only a byte wide so it can only count 0 -255
Timer1 is two bytes wide so it can count to 65535
Syntax:
InitTimer0 source, prescaler
source can be Osc or Ext Osc would be internal osc/4 , you want to count so use 'Ext'
prescaler would be "PS0_1/2 to PS0_1/256"
Same for timer1 except it don't have as many prescaler options.
TMR0 is the count value
TMR1H ,TMR1L is counter 1 values
************************
That was detail but first you need to define what you are doing and how you will do it (algorithm).
what frequency would you want to count?
How many digits resolution?
because PIC's count binary you may have to do scaling to get something meaningful
Hardware frequency counters have two parts: a counter and a gate timer counts/time
Timer0 can't stop running so you can load it with 0 and then "wait" a time period and then read the TMR0 just as you were trying to do.
A more complicated solution would be to make use timer0 as a 1 sec interrupt and use timer 1 as a counter. During the interrupt you read timer1to temp variables(2) and reset both timer1 to 0 and timer0 to it's initial value , finally reset timer0 interrupt bit.
GL
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the response!
Since I'm new to PIC programming, I'm just trying to get whatever frequency I measure to be displayed on the LCD display. At this time I'm not looking for a great deal of accuracy. If I could get some semi-reasonable measurement of frequencies between 10 Hz and 1 MHz, I'd be happy.
Reference was made to using timer 0 and 1. The PIC16F627 uses pin 12 for the Timer1 Osc output and Timer1 clock input. Pin 13 has the Timer1 osc input. Unfortunately, I'm using pins 6 - 13 for the DB0 - DB7 inputs of the LCD. Are the Timer1 pins still usable?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Set up timer0 and its prescalers to run on the main system clock oscillator with interrupts enabled. Every time timer0 overflows, it will generate an interrupt. These interrupts ill occur at regular intervals, determined by the clock oscillator frequency and the timer0 prescaler value.
Connect the signal to be measured to the timer1 input pin. When a timer0 interrupt occurs, read the contents of timer 1, then reset timer1 and wait for the next interrupt. If the input frequency is so high that a timer1 overflow occurs during the timer0 gating interval, then you'll have to keep track of the number of overflows. The rest is all math.
There are many variations on this theme, using different timers in the PIC, different prescaler values, different timer value presets, and totalizing counts over a variable number of timer overflows. You should only need one PIC pin for the input to be measured.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
2011-04-03 05:35:37 EDT
Basically, here's what you do:
More on this…
If interrupts are a little too advanced for you right now and all you want to do is prove the frequency counting concepts, try this:
After setting up timer0 and timer1 as in my previous, go into a tight loop where you just keep looking at the timer0 interrupt flag. This flag will go high every time timer0 overflows, even if interrupts are off. As soon as the timer0 interrupt flag goes high, read the contents of timer1, then reset timer1 (load it with zeros) and go back yo your tight timer0 monitoring loop. Keep in mind that you have to get back to monitoring timer0 before it overflows again, so you can't spend too much time reading timer1 and processing the data.
This method will completely tie up the PIC just measuring frequency, but it's probably the simplest way to get someting going. Once you learn how to use interrupts, it will be like you walked through a door to a whole new dimension, allowing you to manage several processes simultaneously.
Joe
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
" Unfortunately, I'm using pins 6 - 13 for the DB0 - DB7 inputs of the LCD. Are the Timer1 pins still usable? "
You could go to a 4 bit wide data bus to the lcd, this would require DB4-7 to be rewired. This would free up the timer1 input.
LCD_IO The I/O mode. Can be 2, 4 or 8.
In my previous reply I suggested timer0 could cause a 1sec interrupt but after looking it over, it can't count high enough for 1 sec. But it could do a 1 tenth sec interrupt or something smaller yet. Then just accumulate the interrupts(sometimes called ticks) until you reach the desired timebase or gate time.
Meanwhile timer1 is accumulating your frequency count. If it overflows, that needs to be kept track of.
back in ? january of 2010 I used the timer1 as a timebase with external 32khz crystal for 1sec timing and used the timer0 for the counter. the application was for a very low frequency counter ?7-128 hz
Sunday I was trying to get the first part of your original code to work.
I could not get timer0 to count externally, even with the Ext in the timer0 Init command.
I should have checked the forum sooner. There was an error in the timer.h functionSInitTimer0 (line152)
Turns out it was always on internal Osc.
73
mike
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
whatpic,
last night I got the frequency counter to work .Like you had first imagined.
' Timer0 frequency counter
' can only count 0to 255
'but with prescaler divider scaled outputs up into the 65000 are possible
#chip 16F887, 8
#config INTOSC
Dir PORTA.4 in 'counter input pin is PORTA.4
Dir PortD out ' my proto board has 8 leds on this port so the value can be shown
InitTimer0 Ext , PS0_1/2 ' read portA.4 and divide it by 1/2 on the prescaler
bsf OPTION_REG,PSA ' reset prescaler assignment so it does not divide by prescaler
' comment out if you want to use the prescaler
Start:
TMR0 = 0 ' this zeroes timer0 because ClearTimer 0 resets it to '8'
wait 1 sec ' timebase
mydata = TMR0 ' read Timer0 register in case you need to use it somewhere else
PortD = mydata ' display the value
Goto Start
This code runs on my protoboard which has a 16F887 PIC. The InitTimer0 was a struggle because of the mistake in timer.h file and because making the prescaler 1/1. ( Search forum for timer0 fix) I hope your version this problem is fixed.
My portD has 8 Leds on. When I touch the PortA.4 to Gnd no LEDs light up. When I touch PortA.4 with my finger(i am a 60hz antenna) the leds light up lsb-msb xx****xx 4+8+16+32 = 60. I can tickle the lead and get other readings.
When I used ClearTimer 0 it reset it to 8 not 0 for some reason? I will explore that later.
73
Mike
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm trying to measure a frequency with the PIC16F627 RA4/TOCKI/CMP2 - Pin 3. I want to measure/count the frequency input, WRITE it into EPROM, READ the EPROM, then PRINT the value on the LCD.
I included some extra PRINT commands in the code for troubleshooting purposes. When I run the program, the LCD randomly PRINTS a 1 or 0 for FreqOne, 255 for DataLoc, and 0 for DataStor. This occurs with and without a signal generator attached to pin 3. I've tried frequencies as low as 1 Hz and as high as 10 MHz but the results are the same.
Anyone know what I'm doing wrong? I should mention I'm new to PIC programming.
;Chip Settings
#chip 16F627,4
#config MCLRE=ON, OSC=INTRC_OSC_CLKOUT
;Defines (Constants)
#define LCD_IO 8
#define LCD_DATA_PORT PORTB
#define LCD_RS PORTA.2
#define LCD_RW PORTA.1
#define LCD_Enable PORTA.3
#define FreqOne PORTA.4
;Variables
Dim DataLoc As byte
Dim TempStor As word
'A program to count a Frequency.
Dir PORTA.4 In
Loop:
InitTimer0 Osc, PS0_1/2
Wait 200 ms
'
EPWrite DataLoc, FreqOne
Wait 200 ms
'
EPRead DataLoc, TempStor
Wait 200 ms
'
Print "FreqOne"
Locate 1, 1
Print FreqOne
Wait 1 s
CLS
'
Print "Data Loc"
Locate 1, 1
Print DataLoc
Wait 1 s
CLS
'
Print "TempStor"
Locate 1, 1
Print TempStor
Wait 1 s
CLS
goto loop
End
Your program is doing what you are telling it to do.
"EPWrite DataLoc, FreqOne" - FreqOne is only the input pin that you told it to be. It can only be on or off, 0 or 1
You should be reading the timer0 register.
Many other things need attention:
EPwrite/read are byte wide
DataLoc needs to be initialized
Timer0 needs to be setup for counting
Frequency units are counts per time, you need a better timer than ' wait '. It might work for experiment?
Down load the microchip 40044D.book for the 16F627 and read relevant sections.
Thanks mmotte for your quick response. I downloaded and read the appropriate sections in 40044D as you suggested. I've also read DS33023. My problem is that these documents use assembly language terms and I don't know how to make GCBASIC do them. Your first suggestion was:
"You should be reading the timer0 register" - The document uses terms like TOCS, TOSE bits, and TMRO register. How do I do this in GCBASIC?
Another suggestion was "Timer0 needs to be set up for counting." - In my above software I have the GCBASIC code-
InitTimer0 Osc, PS0_1/2
Is there some other GCBASIC code I should include?
"DataLoc needs to be initialized" - I assume DataLoc is a location in EEPROM. The documents discuss EECON1, ECCON2, EEDATA, and EEADR. In Section 13.4, it states "The write will not initiate if the above sequence (example 13.2) is not followed exactly (write 55h to EECON2, write AAh to EECON2, then set WR bit) for each byte. We strongly recommend that interrupts be disabled during this code segment. Any number that is not equal to the required cycles to execute the required sequence will cause the data not to be written into the EEPROM….." Same question, How do I do this in GCBASIC?
Can you provide more information about exactly what you're trying to do? For instance, what is the range of frequencies you're trying to count? How much resolution is required? How much accuracy is required?
There are several ways you might accomplish this with various combinations of the internal timer/counters. Basically, you need to set up one of the timer/counters as a sampling gate (eg, 10 hz or 1 hz, depending on the resolution required) and use the output of that timer to start/stop another counter that actually measures the frequency. However, it's probably not going to be possible for you to do this unless you study the datasheet sections on the PIC's internal timer/counters.
there is some help in http://gcbasic.sourceforge.net/help/
timer0 is only a byte wide so it can only count 0 -255
Timer1 is two bytes wide so it can count to 65535
Syntax:
InitTimer0 source, prescaler
source can be Osc or Ext Osc would be internal osc/4 , you want to count so use 'Ext'
prescaler would be "PS0_1/2 to PS0_1/256"
Same for timer1 except it don't have as many prescaler options.
TMR0 is the count value
TMR1H ,TMR1L is counter 1 values
************************
That was detail but first you need to define what you are doing and how you will do it (algorithm).
what frequency would you want to count?
How many digits resolution?
because PIC's count binary you may have to do scaling to get something meaningful
Hardware frequency counters have two parts: a counter and a gate timer counts/time
Timer0 can't stop running so you can load it with 0 and then "wait" a time period and then read the TMR0 just as you were trying to do.
A more complicated solution would be to make use timer0 as a 1 sec interrupt and use timer 1 as a counter. During the interrupt you read timer1to temp variables(2) and reset both timer1 to 0 and timer0 to it's initial value , finally reset timer0 interrupt bit.
GL
Thanks for the response!
Since I'm new to PIC programming, I'm just trying to get whatever frequency I measure to be displayed on the LCD display. At this time I'm not looking for a great deal of accuracy. If I could get some semi-reasonable measurement of frequencies between 10 Hz and 1 MHz, I'd be happy.
Reference was made to using timer 0 and 1. The PIC16F627 uses pin 12 for the Timer1 Osc output and Timer1 clock input. Pin 13 has the Timer1 osc input. Unfortunately, I'm using pins 6 - 13 for the DB0 - DB7 inputs of the LCD. Are the Timer1 pins still usable?
Basically, here's what you do:
Set up timer0 and its prescalers to run on the main system clock oscillator with interrupts enabled. Every time timer0 overflows, it will generate an interrupt. These interrupts ill occur at regular intervals, determined by the clock oscillator frequency and the timer0 prescaler value.
Connect the signal to be measured to the timer1 input pin. When a timer0 interrupt occurs, read the contents of timer 1, then reset timer1 and wait for the next interrupt. If the input frequency is so high that a timer1 overflow occurs during the timer0 gating interval, then you'll have to keep track of the number of overflows. The rest is all math.
There are many variations on this theme, using different timers in the PIC, different prescaler values, different timer value presets, and totalizing counts over a variable number of timer overflows. You should only need one PIC pin for the input to be measured.
More on this…
If interrupts are a little too advanced for you right now and all you want to do is prove the frequency counting concepts, try this:
After setting up timer0 and timer1 as in my previous, go into a tight loop where you just keep looking at the timer0 interrupt flag. This flag will go high every time timer0 overflows, even if interrupts are off. As soon as the timer0 interrupt flag goes high, read the contents of timer1, then reset timer1 (load it with zeros) and go back yo your tight timer0 monitoring loop. Keep in mind that you have to get back to monitoring timer0 before it overflows again, so you can't spend too much time reading timer1 and processing the data.
This method will completely tie up the PIC just measuring frequency, but it's probably the simplest way to get someting going. Once you learn how to use interrupts, it will be like you walked through a door to a whole new dimension, allowing you to manage several processes simultaneously.
Joe
" Unfortunately, I'm using pins 6 - 13 for the DB0 - DB7 inputs of the LCD. Are the Timer1 pins still usable? "
You could go to a 4 bit wide data bus to the lcd, this would require DB4-7 to be rewired. This would free up the timer1 input.
LCD_IO The I/O mode. Can be 2, 4 or 8.
In my previous reply I suggested timer0 could cause a 1sec interrupt but after looking it over, it can't count high enough for 1 sec. But it could do a 1 tenth sec interrupt or something smaller yet. Then just accumulate the interrupts(sometimes called ticks) until you reach the desired timebase or gate time.
Meanwhile timer1 is accumulating your frequency count. If it overflows, that needs to be kept track of.
back in ? january of 2010 I used the timer1 as a timebase with external 32khz crystal for 1sec timing and used the timer0 for the counter. the application was for a very low frequency counter ?7-128 hz
look on thread https://sourceforge.net/projects/gcbasic/forums/forum/579126/topic/353031
73
mike
Thanks!
What GCBasic command do I use to count/accumulate the Interrupts? The GCB help pages don't seem to mention Interrupts.
Mike, the thread you provided did not work.
n=n+1
https://sourceforge.net/projects/gcbasic/forums/forum/579126/topic/3530317
the 7 got dropped in the link
Sunday I was trying to get the first part of your original code to work.
I could not get timer0 to count externally, even with the Ext in the timer0 Init command.
I should have checked the forum sooner. There was an error in the timer.h functionSInitTimer0 (line152)
Turns out it was always on internal Osc.
73
mike
Thanks Mike.
whatpic,
last night I got the frequency counter to work .Like you had first imagined.
This code runs on my protoboard which has a 16F887 PIC. The InitTimer0 was a struggle because of the mistake in timer.h file and because making the prescaler 1/1. ( Search forum for timer0 fix) I hope your version this problem is fixed.
My portD has 8 Leds on. When I touch the PortA.4 to Gnd no LEDs light up. When I touch PortA.4 with my finger(i am a 60hz antenna) the leds light up lsb-msb xx****xx 4+8+16+32 = 60. I can tickle the lead and get other readings.
When I used ClearTimer 0 it reset it to 8 not 0 for some reason? I will explore that later.
73
Mike