Menu

Read a Frequency

Help
MBB
2011-04-01
2013-05-30
  • MBB

    MBB - 2011-04-01

    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

     
  • mmotte

    mmotte - 2011-04-02

    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.

     
  • MBB

    MBB - 2011-04-02

    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?

     
  • Nobody/Anonymous

    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.

     
  • mmotte

    mmotte - 2011-04-02

    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

     
  • MBB

    MBB - 2011-04-03

    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?

     
  • Nobody/Anonymous

    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.

     
  • joe rocci

    joe rocci - 2011-04-03

    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

     
  • mmotte

    mmotte - 2011-04-03

    " 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

     
  • MBB

    MBB - 2011-04-04

    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.

     
  • joe rocci

    joe rocci - 2011-04-04

    n=n+1

     
  • mmotte

    mmotte - 2011-04-04

    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

     
  • MBB

    MBB - 2011-04-04

    Thanks Mike.

     
  • mmotte

    mmotte - 2011-04-05

    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

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.