Searching \ for '[PIC] CCP range and limiting' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/ios.htm?key=rang
Search entire site for: 'CCP range and limiting'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] CCP range and limiting'
2008\08\29@200143 by Jinx

face picon face
I'd like to have some thoughts about the range of CCP please. I've
not used CCP for a long time and the only other time I did it was
with a quite narrow input range

I'm making up a test-bench version of a frequency switch for a wind
turbine. The final implementation will be a simplified version of this

At some frequency the coils need to be switched from star to delta or
back. The unit I'm making now is for the turbine prototyper, and will
include pot-settable switch frequency, +/- window, +/- time period,
time in delta configuration, time in star configuration, etc

The estimated switch-over frequency is about 300Hz (from the coils,
not the blades)

I'm using a 16F88 running at 16MHz, TMR1 increments are 250ns

I calculated 61Hz as the lowest frequency measurable with 16-bit
TMR1, (ie 4,000,000/65536), and that seems to be verified on the
LCD. Below 61Hz, TMR1 overflows before the next input edge
and so the LCD display of the division is meaningless. At the other
end of the scale, due to LCD processing time, the upper limit is
about 2100Hz, but as the turbine should be governed, I'm not too
worried about that

I'm not particularly interested in displaying the actual frequency below
61Hz, but maybe display "<061" or "Slow" or something like that

So far I'm simply polling PIR1,CCP1IF and then jumping off to the
division/LCD routine

I'm trying to break this down logically. If TMR1IF goes off before
CCP1IF, then the frequency is below 61Hz and should be ignored.
However, the next input edge may come in shortly after TMR1IF,
and CCP would be a small value of TMR1 (which is what happens
now and the frequency displayed is in the 1000's of Hz)

Should I be timing input edges with another timer and using that
measurement to indicate whether CCP is > 61Hz ? Bearing in mind
that at some times the turbine will be stopped or moving very slowly,
leading to huge counts in a timer. Or is there another method ?

Any ideas, links to similar projects etc, welcome and appreciated

TIA

2008\08\29@215000 by Jon Baker

picon face
2008/8/30 Jinx <spam_OUTjoecolquittTakeThisOuTspamclear.net.nz>:
> I'm making up a test-bench version of a frequency switch for a wind
> turbine. The final implementation will be a simplified version of this

> Any ideas, links to similar projects etc, welcome and appreciated

Perhaps you're using the wrong tool for the job. A Frequency to
Voltage convertor like LM2917 is designed for this type of
application. The 10 bit ADC would give you good enough resolution to
provide an accurate display of frequency,


--
Jon Baker

2008\08\29@221759 by Jinx

face picon face
> Perhaps you're using the wrong tool for the job. A Frequency to
> Voltage convertor like LM2917 is designed for this type of application.
> The 10 bit ADC would give you good enough resolution to provide
> an accurate display of frequency

Jon, thanks, you're quite right to suggest the LM2917. The originator
of the project used Jaycar's KC5378 kit (http://www.jaycar.com.au)
which has an LM2917 as the front end. He's got the kit somewhere
else but I've a couple of LM2917 around here that could be used
with the PIC if it comes to that. Which it may

The CCP approach is as much a learn-your-PIC exercise for myself
as getting the job done. As this will be a tool for the people he's sold
the idea to, there's no real need for minor cost-savings and I'm on slack
time anyway, so for my own curiosity I'd like to see how CCP can be
made to work

2008\08\29@223909 by Jinx

face picon face
> LM2917 is designed for this type of application. The 10 bit ADC
> would give you good enough resolution to provide an accurate
> display of frequency

Looking through the LM2917 d/s, it seems there's some dependency
on temperature, Z, C, R and Vcc. If I did use one, I think what I might
do is use it to get a rough idea of frequency, and enable CCP only
when say > 100Hz (according to the voltage from the LM2917) to
then measure the frequency more accurately against the PIC's crystal

Not given up on the CCP idea, but the above seems a fair compromise

2008\08\29@231155 by Marcel Duchamp

picon face
You seem to have a good handle on using the capture function.  I would
continue with it until either you get success or decide that other
factors dictate another path.

Out of curiosity, why don't you run your capture business through an
interrupt as well as the TMR1?  Then you don't have to worry about
missing pulses or whatnot.  A software loop (or another timer) can warn
you about times when the turbine is going way slow or stopped.

One thing you did not mention (but probably know about) is adding
hysteresis for the actual switch over from star to delta.  As the wind
will speed up/slow down continually, you probably won't want it
switching  back and forth when it's just at the threshold...



Jinx wrote:

I'd like to have some thoughts about the range of CCP please. I've
not used CCP for a long time and the only other time I did it was
with a quite narrow input range

I'm making up a test-bench version of a frequency switch for a wind
turbine. The final implementation will be a simplified version of this

At some frequency the coils need to be switched from star to delta or
back. The unit I'm making now is for the turbine prototyper, and will
include pot-settable switch frequency, +/- window, +/- time period,
time in delta configuration, time in star configuration, etc

The estimated switch-over frequency is about 300Hz (from the coils,
not the blades)

I'm using a 16F88 running at 16MHz, TMR1 increments are 250ns

I calculated 61Hz as the lowest frequency measurable with 16-bit
TMR1, (ie 4,000,000/65536), and that seems to be verified on the
LCD. Below 61Hz, TMR1 overflows before the next input edge
and so the LCD display of the division is meaningless. At the other
end of the scale, due to LCD processing time, the upper limit is
about 2100Hz, but as the turbine should be governed, I'm not too
worried about that

I'm not particularly interested in displaying the actual frequency below
61Hz, but maybe display "<061" or "Slow" or something like that

So far I'm simply polling PIR1,CCP1IF and then jumping off to the
division/LCD routine

I'm trying to break this down logically. If TMR1IF goes off before
CCP1IF, then the frequency is below 61Hz and should be ignored.
However, the next input edge may come in shortly after TMR1IF,
and CCP would be a small value of TMR1 (which is what happens
now and the frequency displayed is in the 1000's of Hz)

Should I be timing input edges with another timer and using that
measurement to indicate whether CCP is > 61Hz ? Bearing in mind
that at some times the turbine will be stopped or moving very slowly,
leading to huge counts in a timer. Or is there another method ?

Any ideas, links to similar projects etc, welcome and appreciated

TIA

2008\08\29@231339 by Jinx

face picon face
I wrote

> enable CCP only when say > 100Hz

which doesn't need an LM2917. An RC integrator could provide
an indicator voltage


2008\08\29@231558 by Harold Hallikainen

face
flavicon
face
It looks like you're measuring period instead of frequency. You could stay
with that method if you have the timer interrupt increment a RAM location,
just making the timer longer (more bits).

Another approach would be to actually measure the frequency. Use one timer
running off the processor clock. Use another timer as a counter counting
the inputs signal. When the first timer generates an interrupt, copy the
second timer value over to RAM (that's the frequency), reset the second
timer (counter), and reinitialize the counter.

Frequency counters are relatively slow compared to period counters, so it
depends on how fast you need to be and what resolution. If you need to be
fast and have high resolution, you can do the "stack ram on timer"
approach above.

I don't recall which chip you were using, but some have 16 bit counters or
prescalers that also extend the range of a period counter.

I did the second "frequency counter method" driven by a TAOS light to
frequency converter to measure the mw/cm^2 coming out of a dental
composite curing lamp.

Good luck!

Harold

Harold

--
FCC Rules Updated Daily at http://www.hallikainen.com - Advertising
opportunities available!

2008\08\30@001855 by Jinx

face picon face
> You seem to have a good handle on using the capture function.  I
> would continue with it until either you get success or decide that
> other factors dictate another path

Jon's response does have me considering an analogue input as a fairly
easy and workable solution. CCP is just a bit of a logic exercise

> Out of curiosity, why don't you run your capture business through
> an interrupt as well as the TMR1?  Then you don't have to worry
> about missing pulses or whatnot.  A software loop (or another timer)
> can warn you about times when the turbine is going way slow or
> stopped

That's right. There has to be a lower limit for measuring. And there's
a bottom speed limit for useful power output anyway. I don't think
there's any chance of missing pulses because of the long gap between
them. It seems to work fine with a signal generator to > 2100Hz

> One thing you did not mention (but probably know about) is
> adding hysteresis for the actual switch over from star to delta

One of the settables I did mention was the +/- window and a +/-
time. So you might set the centre frequency to 300Hz, with a +/-
30Hz window, and perhaps 5s outside the window before a
state change. Although both of those settables are hysteresis and
one may be dropped. We'll have to see what filtering is necessary
or works in gusty conditions. I've not been to the fabricator yet
to judge the blades' inertia for example

2008\08\30@001950 by Jinx

face picon face
> It looks like you're measuring period instead of frequency

I am. Division of TMR1 into 4,000,000 (the number of 250ns in
1 second) returns a hertz result directly

eg if TMR1 capture is 0x3918 (ie d14616 * 250ns = 3654us), then
dividing 4,000,000 by 14616 = 273Hz

> Another approach would be to actually measure the frequency
>
> Frequency counters are relatively slow compared to period counters

That's what I've done on another project (variable-pitch propellor
controller for light planes)

Calculations are made on a running average of the propellor rpm and
the result determines the direction and duration of the blade motor to
meet the set rpm target


2008\08\30@081503 by olin piclist

face picon face
Jinx wrote:
> Should I be timing input edges with another timer and using that
> measurement to indicate whether CCP is > 61Hz ? Bearing in mind
> that at some times the turbine will be stopped or moving very slowly,
> leading to huge counts in a timer. Or is there another method ?
>
> Any ideas, links to similar projects etc, welcome and appreciated

I did some flow meters a long time ago that had to cover a large dynamic
range.  I used a CCP module in capture mode to get the period between
pulses, but had to deal with timer 1 overflow issues.

I essentially extended the timer in software to 24 bits, which happened to
be enough for this application.  This technique can be used to extend it any
number of bytes you want.

Your timer 1 overflow period is 16.4mS.  All you need is some code that is
guaranteed to run a little more often than that.  This code grabs the timer
0 high byte, finds the delta from the last time it did that, then adds that
delta into a software accumulator.  The software accumulator must be more
than 8 bits to be useful.  Any bits past the first 8 essentially extend the
timer.

The procedure above makes the software accumulator up to date with the
latest high byte of timer 1.  In the capture interrupt, the total period is
the period indicated by the timer 1 low byte difference, plus the timer 1
high byte difference from its last updated value, plus the software
accumulator.  You then clear the software accumulator, update the timer 1
old low byte, and update the timer 1 old high byte used by the software
accumulator update routine.

Yes, you have to wake up to make sure you are thinking thru all the boundary
cases properly, but it can definitely be done.  I probably still have the
code on a dusty archive disk somewhere.  These flow meters were some of the
first PIC projects I ever did, so the code probably isn't that pretty.  I
can try to find it if you really want to see it.  It runs on a 16C923 if I
remember right.  The PIC measured the period, inverted it to make flow, then
displayed that on the LCD.  I think this is the project I originally wrote
the 32 bit fixed point multiply and divide routines for.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\08\30@204802 by Jinx

face picon face
Olin, using the example below, can you expand/clarify please

> Your timer 1 overflow period is 16.4mS.  All you need is some code
> that is guaranteed to run a little more often than that

Say its period is 0xFF00 (16.320ms), and the frequency being measured
is ~59.4Hz, ie a period of 16.832ms, or 0x10700 * 250ns. So that's (1
rollover + 0x0700) of TMR1 between rising edges

> This code grabs the timer 0 [1 ? typo ?] high byte, finds the delta from
> the last time it did that, then adds that delta into a software
accumulator
>
> The procedure above makes the software accumulator up to date with
> the latest high byte of timer 1

Assuming the previous sample left 0x00 in the s/w acc, which was loaded
into TMR1H (as per paragraph below)

This sample of TMR1H is 0xFF

delta = 0x01 -> into s/w acc (*** did you mean absolute delta ?)

Now, next edge comes along when TMR1H is 0x07 (rolled through 00).
So total increments since last edge is 0x010700

> In the capture interrupt, the total period is the period indicated by the
> timer 1 low byte difference, plus the timer 1 high byte difference from
> its last updated value, plus the software accumulator

TMR1H difference = 0x07 (last update) + 0x01 (s/w acc)

> You then clear the software accumulator, update the timer 1 old low
> byte, and update the timer 1 old high byte used by the software
> accumulator update routine

2008\08\30@235209 by Jinx

face picon face
> LM2917

Jon, I've tried the LM2917 as a frequency indicator and it works
well. It's set for about 1.5V per 100Hz, so unless there's at least
1.5V input the PIC doesn't use CCP to measure the frequency,
which it can do more accurately as a timed digital event rather than
an analogue voltage. Quite a neat combination I think. It's a good
Plan B for extended-range CCP Plan A. I'm assuming the output
of the turbine is sinusoidal

I also tried an RC filter and a 4001 as a re-triggerable monostable,
they were OK-ish

Trying to remember where I got so many LM2917 from. Sure they
were from old floppy drives

2008\08\31@093102 by olin piclist

face picon face
Jinx wrote:
> Say its period is 0xFF00 (16.320ms), and the frequency being measured
> is ~59.4Hz, ie a period of 16.832ms, or 0x10700 * 250ns. So that's (1
> rollover + 0x0700) of TMR1 between rising edges
>
>> This code grabs the timer 0 [1 ? typo ?]

Oops, yes.  Everything we are talking about is with timer 1.

{Quote hidden}

I think so.  This is a lot more complicated to explain than to do, so here
is a example.  This example will extend the capture timer to 24 bits, so the
sofware accumulator will be 16 bits wide.  All numbers are in HEX:

Starting out

 Timer 1:        0000
 old timer1l:      00
 old timer1h:    00
 SW acc:       0000

then 1234h counts in the accumulator update routine is run:

 Timer 1:        1234
 old timer1l:      00
 old timer1h:    12
 SW acc:       0012

The new timer1h was subtracted from the old timer1h: 12 - 00 = 12.  This
increment is added into the software accumulator: 0000 + 12 = 0012.  The
timer1h value found this time is saved as the old value for next time.

Now let's say the timer 1 update routine was run again, this time at 8765h
counts from the start:

 Timer 1:        8765
 old timer1l:      00
 old timer1h:    87
 SW acc:       0087

The new timer1h is 87, and the old is 12.  87 - 12 = 75.  This increment is
added to the software accumulator:  0012 + 75 = 0087.  The new timer1h (87)
is then saved as the old timer1h for next time.

Note that since so far there has been less than one total timer 1 wrap time,
the result is the same whether the first iteration of the update code was
run or not.  It needs to get run at least a little more often than every
10000h timer 1 counts else a wrap will get lost.  It's a good idea to run it
more often than that to allow for slop.  Every 10mS, for example, would be
fine.

So far this hasnt done much useful since the timer didn't wrap.  So now
let's say the update routine got run at 14567 ticks from the start.  This is
where it earns it's keep:

 Timer 1:        4567
 old timer1l:      00
 old timer1h:    45
 SW acc:       0145

45 - 87 = BE (remember, this is unsigned math with the carry tossed).  The
software accumulator is updated:  0087 + BE = 0145.  Then the old timer1h is
updated to 45.  Since we started at 0, the software accumulator directly
shows the high 2 bytes of the 3 byte total elapsed ticks.  If the original
timer 1 value wasn't 0, this wouldn't be the case.

Now there is a CCP capture event at 18592 total ticks from the start.  The
state on entry to the capture handler is:

 Timer1 capture: 8592
 old timer1l:      00
 old timer1h:    45
 SW acc:       0145

The period since the last capture is assembled in pieces.  The *signed*
subtract of captured timer1l minus the old timer1l is 92 - 00 = 000092.  The
captured high byte minus the old high byte is 85 - 45 = 40.  These plus the
SW accumulator are added together to yield the complete 24 bit period since
the last capture:

    000092
  +   40
  + 0145
  --------
    018592  <-- Don't you love it when it all works out!

Then the state is reset to start accumulating the time delta to the next
capture:

 old timer1l:      92
 old timer1h:    85
 SW acc:       0000

The captured timer 1 bytes are saved as the old bytes for the next time, and
the software accumulator is cleared.

Then you do it all again.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\08\31@120142 by Scott Dattalo

face
flavicon
face
> I think so.  This is a lot more complicated to explain than to do, so here
> is a example.  This example will extend the capture timer to 24 bits, so
> the
> sofware accumulator will be 16 bits wide.  All numbers are in HEX:


Depending on the application, it might be simpler to just monitor the
change in the MSB of TMR1H:

; 24-bit software timer that shadows TMR1
;
; Copy TMR1H:L to the low 16 bits of the software timer.
; If TMR1 rolled over since the last update, then increment
; high byte of the software timer
;
;   Software timer
; SWTmrHigh  ; bits 23-16
; SWTmrMid   ; bits 15-8
; SWTmrLow   ; bits 7-0

   MOVF   TMR1L,W     ;Read the HW timer (latches TMR1H too)
   MOVWF  SWTmrLow

   INCF   SWTmrHigh,F ;Assume that there was a roll over

   BTFSS  TMR1H,7     ;If the MSB of the HW timer is set
    BTFSS SWTmrMid,7  ;or bit 15 of the SW timer is clear
     DECF SWTmrHigh,F ;then there was no roll over

   MOVF   TMR1H,W     ;Update the middle byte.
   MOVWF  SWTmrMid

This assumes that the software timer is updated at a rate faster then one
half of the period of time for a hardware timer roll over.

Note, this has not been tested!

Scott

2008\08\31@183057 by Jinx

face picon face
> This is a lot more complicated to explain than to do

Olin, understood. I'll work through it

> Depending on the application, it might be simpler to just monitor
> the change in the MSB of TMR1H:

Scott, logging TMR1 rollovers did occur to me and it does seem
applicable here



2008\08\31@190139 by cdb

flavicon
face


:: ;   Software timer
:: ; SWTmrHigh  ; bits 23-16
:: ; SWTmrMid   ; bits 15-8
:: ; SWTmrLow   ; bits 7-0

This looks similar to Roman Black's/Bob Ammerman's Bresenham Algorithm, which I borrowed (copied?) in my water flow meter project

void Interrupt()
{
 

if(PIR1&(1<<TMR2IF))
 {
   #asmline bcf PIR1,TMR2IF            ;Timer 2 Flag
   SysFlag.Tmr2=1;
 }
 
if(INTCON&(1<<T0IF))                        // Test TMR0 interrupt flag
 {
   #asmline bcf INTCON,T0IF           ;  Clear TMR0 interrupt flag
   SysFlag.Tmr0=1;                    
     
   if(TickMid!=0)                        //Has TickMid reached zero
     {
           if(--TickMid!=0)        
       return;                              //if not decrease and check for zero
     }
   else                                //Tickmid was zero so decrease TickHigh
     {
            --TickHigh;
            if(--TickMid!=0);                //Has Tickmid reached zero now?        
            return;
     }        
   
    if(TickHigh==0)                        //TickMid is zero so check TickHigh if
      {                                //zero reload counter
         TickHigh=COUNTH;
         TickMid=COUNTM;
         TickLow+=COUNTL;                //Load counter with initial+ remainder
         #asmline btfsc STATUS,C        ;Has a carry occurred from low to mid
         TickMid++;                        //yes so increase TickMid
         sec++;
      }    
    }
  if(PIR1&(1<<CCP1IF))
  {
     #asmline bcf PIR1,CCP1IF
     SysFlag.Tmr1E=1;
  }    
   
}

void setup()
{
<snip>
TickHigh=COUNTH;                        //2,500,000
  TickMid=COUNTM+1;                        //add 256 to initial count        
  TickLow=COUNTL;                        //Total 24 bit number = 2500256
  PIE1=PIR1=0;                         //Make sure interrupts are off
  TMR1H=TMR1L=0;                       //Ensure Timer1 is cleared
  T1CON=(1<<TMR1CS);                    //Put Timer1 in counter mode
  CCPR1H=SENSH;                        //Load MSB of Compare Register, 0x04B0
  CCPR1L=SENSL;                        //Load LSB of Compare Register=1200 pulses
  CCP1CON=(1<<CCP1M3)|(1<<CCP1M1)|(1<<CCP1M0); //Compare Mode/Trigger Interrupt
  PR2=250;                   //TMR2 preload with 250. 1/(2.5MHz/16/16/250)=25.6mS
  //Post scale *16 prescale *16
  T2CON=0x7B;                          //TOUTPS3/2/1/0=1 T2CKPS1/2=1  
<snip>
}
--
cdb, .....colinKILLspamspam@spam@btech-online.co.uk on 1/09/2008

Web presence: http://www.btech-online.co.uk  

Hosted by:  http://www.1and1.co.uk/?k_id=7988359

Friendship multiplies the good of life and divides the evil.
Baltasar Gracian





More... (looser matching)
- Last day of these posts
- In 2008 , 2009 only
- Today
- New search...