PDA

View Full Version : Frequency Counter



Asmith
- 14th June 2007, 16:54
Hello Everyone,

I'm new to this forum and PIC BASIC PRO. I do although have some background in PICs and other forms of programming for them.

I have a question about a PIC12F683 program I'm writing. I believe the internal clock is 4MHz, typically you set it a different way, but the guy before me said what's in the "Define PIC Internals" will do it. What I'm trying to do is count the number of pulses coming into an input on the PIC from a hall effect sensor. The frequency should be nothing faster than 2kHz. Basically the hall effect will be like giving a position based off of counts, and I will be outputting a 2kHz PWM wave with the number of counts determining the duty cycle.

I would do a COUNT function but the only problem is I need to be looking at the pulses coming in all the time while changing the duty cycle based on the counts I have. I don't want to miss any of the counts and I'm worried if I make the processor sit and just count pulses I will have to update the duty cycle and while I'm doing so miss a couple counts. I might be thinking way to hard about this and missing a very easy way to complete it. The PWM signal does not take many cycles to update so I might be able to use the COUNT function but I'm unsure.

Below is the code I have. All this is suppose to do is count the pulses and store them into EEPROM. I only add 1 to position every 10 pulses because of overflow of variable. When I run this I get 00 00 stored into EEPROM. I have gpio.2 tied directly to +5V and a function generator on gpio.3 at 500 Hz. I usually run the system for 10 seconds as well.

Any help on this would be appreciated, or just any feedback and ideas. Thank guys, and hopefully I can be a good addition to this forum.

Anthony Smith

************************************************** ***
' Define PIC Internals

@ DEVICE PIC12F683, INTRC_OSC_NOCLKOUT
' System Clock options
@ DEVICE PIC12F683, WDT_ON
' Watchdog timer
@ DEVICE PIC12F683, PWRT_ON
' Power-On Timer
@ DEVICE PIC12F683, MCLR_OFF
' Master Clear Options
@ DEVICE PIC12F683, BOD_ON
' Brown-Out Detect
@ DEVICE PIC12F683, CPD_OFF
' Data Memory Code Protect
@ DEVICE PIC12F683, PROTECT_OFF
' Program Code Protection

' Define Hardware Variables


' Define Software Variables
Position VAR WORD

Shrink VAR BYTE

WasLow VAR BIT

' Initialize PIC Configuration
CMCON0 = 7

TRISIO = %00011110
'WPU = %00011111


Position = 0
WasLow = 0
Shrink = 0
PAUSE 50

MainLoop:
IF gpio.3 = 1 AND WasLow = 0 THEN
IF gpio.2 = 1 THEN
Shrink = Shrink + 1
ELSE
Shrink = Shrink - 1
ENDIF
WasLow = 1
ENDIF

IF Shrink = 10 THEN
Position = Position + 1
Shrink = 0
ENDIF

IF gpio.3 = 0 THEN
WasLow = 0
ENDIF

IF Shrink = -10 THEN
Position = Position - 1
Shrink = 0
ENDIF

WRITE 0, Position.Byte1
WRITE 1, Position.Byte0


GOTO MainLoop

************************************************** ****

skimask
- 14th June 2007, 17:26
Break it down, make it simple, build it back up.
Erase the chip, Blank check it, make sure both program and eeprom space reads back as $ff, then try this:


@ DEVICE PIC12F683, INTRC_OSC_NOCLKOUT
@ DEVICE PIC12F683, WDT_ON
@ DEVICE PIC12F683, PWRT_ON
@ DEVICE PIC12F683, MCLR_OFF
@ DEVICE PIC12F683, BOD_ON
@ DEVICE PIC12F683, CPD_OFF
@ DEVICE PIC12F683, PROTECT_OFF

temp var byte
temp2 var byte
ledpin var gpio.(pick a pin)
output ledpin

main:
'show a heartbeat for the program on an LED to make sure something is happening
temp2 = temp2 + 1 : ledpin = temp2.0

for temp = 0 to 255 : write temp, temp : next temp : goto main
end


Hook an LED to a pin, let it blink a few times, then do a readback on the PIC. That should tell you if your eeprom statement is working in the first place. Then build it back up...

mister_e
- 14th June 2007, 20:19
The internal oscillator is set @4MHz by default, you can set OSCCON register to go to 8MHz.

As usual i'll suggest you to use a internal Timer (TMR0 or TMR1) as counter. Yes you'll have to use the dedicated pins for that... no harm at all, you have tons of benefits.
1. it runs in background
2. it's more accurate
3. use less code space
4. more flexible

This PIC have this cute and handy CCP module, so you'll be able to generate the PWM signal really easy using HPWM or by setting the according register manually. This also run in background.

HTH

Asmith
- 14th June 2007, 22:12
To Skimask:
I tried out the code you gave me and it did write through the EEPROM like it was suppose to. I re-wrote the code I had and it gives me 00 00 when I do not move any of the inputs around at all if I pull the Pulse Wire in and out of ground it seems to give me random values not how many time I pull it in and out, it does seem kind of close though. The code is posted below if you see a problem with it. Thanks for your help btw. I've been working on this all day now and can't seem to get any repeatability.

*************************************************
@ DEVICE PIC12F683, INTRC_OSC_NOCLKOUT
@ DEVICE PIC12F683, WDT_ON
@ DEVICE PIC12F683, PWRT_ON
@ DEVICE PIC12F683, MCLR_OFF
@ DEVICE PIC12F683, BOD_ON
@ DEVICE PIC12F683, CPD_OFF
@ DEVICE PIC12F683, PROTECT_OFF

TRISIO = %11111111

Location var WORD

Mult_Count VAR BYTE

Was_Low VAR BIT

Pulse var gpio.3
Direction VAR gpio.5

Mult_Count = 0
Location = 0
Was_Low = 0

PAUSE 500

main:

IF Pulse = 1 AND Was_Low = 0 THEN
IF Direction = 1 THEN
Mult_Count = Mult_Count + 1
ELSE
Mult_Count = Mult_Count - 1
ENDIF
Was_Low = 1
ENDIF

IF Pulse = 0 THEN
Was_Low = 0
ENDIF

IF Mult_Count = 10 THEN
Location = Location + 1
Mult_Count = 0
ENDIF

IF Mult_Count = -10 THEN
Location = Location - 1
Mult_Count = 0
ENDIF

WRITE 0, Location.Byte1
WRITE 1, Location.Byte0
GOTO main
end

*********************************************

To mister_e:

I can easily change the clock to 8MHz, I should have done that in the first place. The PWM signal I have done as well, using C code on this chip, and it works pretty nicely. I haven't used the timers before though, although I would really like to go this route with this. My only concern would be I need to be able to count up and down and I'm unsure if can I do so with these Timers. Maybe one way to do so would be to call a interrupt when a direction change is seen and save the timer value before resetting it to 0. Then do the math to another variable with the true position value. I'm gonna start reading on it while I'm still at work. Thanks for the idea it sounds like the best way to go. If you have any advice for going about it let me know. Thanks again.

Anthony

Bruce
- 15th June 2007, 01:40
See if this helps;

CMCON0 = 7
ANSEL = 0

Comparators & A/D are enabled by default on power-up. To use some pins for
digital I/O, you need to disable these.

Archangel
- 15th June 2007, 03:11
To Skimask:
I tried out the code you gave me and it did write through the EEPROM like it was suppose to. I re-wrote the code I had and it gives me 00 00 when I do not move any of the inputs around at all if I pull the Pulse Wire in and out of ground it seems to give me random values not how many time I pull it in and out, it does seem kind of close though.
Anthony
It might be working and counting multiple switch closures due to bouncing switch contacts (noise).

Ioannis
- 15th June 2007, 06:54
IF Mult_Count = -10 THEN
Location = Location - 1
Mult_Count = 0
ENDIF



Are you sure that PBP can do negatives???

Ioannis

Asmith
- 15th June 2007, 19:59
Bruce:
Thank you I did forget to set up those two registers. I will fix that.

Joe:
I'm using a function generator on the input with a scope on it as well and there is no bouncing on the pin. In the end it will be from a hall effect switch which also should not have any bouncing.

Ioannis:
I believe PBP will do negative numbers, Location should never be a negative number anyways as 0 would be the lowest number of counts you can have it will be zero we it is set up.

I think I'm going to try and use the internal timer which I haven't been able to work on it much as work has me burried. I did have some time to write out some code. I will post is below, if you guys would like to comment on it I would appreciate it. It might be a little chopy at the moment though.

************************************************** *****
@ DEVICE PIC12F683, INTRC_OSC_NOCLKOUT
@ DEVICE PIC12F683, WDT_ON
@ DEVICE PIC12F683, PWRT_ON
@ DEVICE PIC12F683, MCLR_OFF
@ DEVICE PIC12F683, BOD_ON
@ DEVICE PIC12F683, CPD_OFF
@ DEVICE PIC12F683, PROTECT_OFF

'* Hardware Setups *

INTCON = %10001000
PIE1 = %00000000
PIR1 = %00000000
OSCCON = %01110000

'* I/O Pin Descriptions Below *
'* PIN 1 - VDD - 5V *
'* PIN 2 - T1CK1 - Input - Pulses from Hall Effect *
'* PIN 3 -
'* PIN 4 - GP3 - Input for the direction of the Hall Effect *
'* PIN 5 - CCP1 - PWM Output to the Analog converter *
'* PIN 6 -
'* PIN 7 -
'* PIN 8 - VSS - Ground *

TRISIO = %00101000
WPU = %00000000
IOC = %00001000

'* Timer Setup *
T1CON = %00100111



Location var WORD

Mult_Count VAR BYTE

Was_Low VAR BIT

Pulse var gpio.3
Direction VAR gpio.5

Mult_Count = 0
Location = 0
Was_Low = 0

PAUSE 500

main:


GOTO main
end

************************************************** ***

skimask
- 15th June 2007, 21:15
Ioannis:
I believe PBP will do negative numbers, Location should never be a negative number anyways as 0 would be the lowest number of counts you can have it will be zero we it is set up.

Sure, PBP and assembly both will do negative numbers, but they won't show up the way you want them to...i.e.:

5 - 6 = -1, but PBP will show 255 (for a byte variable), 65535 (for a word variable).

You're going to want to add something like this to your program in post #4:

main:
IF Pulse = 1 AND Was_Low = 0 THEN
IF Direction = 1 THEN
Mult_Count = Mult_Count + 1
ELSE
if mult_count > 0 then mult_count = mult_count - 1
ENDIF
Was_Low = 1
ENDIF
...............

IF Mult_Count = -10 THEN(statement won't work the way you want it to in PBP)
Location = Location - 1
Mult_Count = 0
ENDIF

Archangel
- 16th June 2007, 00:10
Bruce:

Joe:
I'm using a function generator on the input with a scope on it as well and there is no bouncing on the pin. In the end it will be from a hall effect switch which also should not have any bouncing.




************************************************** ***

It was worth checking.
JS

Asmith
- 19th June 2007, 22:48
Hello again everyone. I've been trying to complete my task using the timer option that mister_e informed me about. I'm not sure what I'm doing wrong, for some reason I get half the number of pulses counted as the frequency I'm running at. It's this way at every frequency. Maybe it's just been a long day, or I'm misunderstanding something in the book. I tried to mess with the prescale, but it only adds that extra to the already multiplier. The Code is posted below. Thank you everyone who has helped me out.

Anthony



@ DEVICE PIC12F683, INTRC_OSC_NOCLKOUT
@ DEVICE PIC12F683, WDT_ON
@ DEVICE PIC12F683, PWRT_ON
@ DEVICE PIC12F683, MCLR_OFF
@ DEVICE PIC12F683, BOD_ON
@ DEVICE PIC12F683, CPD_OFF
@ DEVICE PIC12F683, PROTECT_OFF

'* Hardware Setups *

INTCON = %10001000
OSCCON = %01110000

'* I/O Pin Descriptions Below *
'* PIN 1 - VDD - 5V *
'* PIN 2 - T1CK1 - Input - Pulses from Hall Effect *
'* PIN 3 -
'* PIN 4 - GP3 - Input for the direction of the Hall Effect *
'* PIN 5 - CCP1 - PWM Output to the Analog converter *
'* PIN 6 -
'* PIN 7 -
'* PIN 8 - VSS - Ground *

TRISIO = %00111000
'IOC = %00001000

'* Timer Setup *
T1CON = %00000110
TMR1H = 0
TMR1L = 0

PAUSE 500


T1CON.0 = 1
PAUSE 1000
T1CON.0 = 0
WRITE 0, TMR1H

WRITE 1, TMR1L

end

Darrel Taylor
- 20th June 2007, 00:32
With OSCCON = %01110000, the internal oscillator will be running at 8Mhz.

But the default setting for PBP is 4Mhz.
So the PAUSE 1000 is only pausing for 1/2 second instead of a whole second.
Which then only allows it to count half of the pulses.

ADD
DEFINE OSC 8
<br>

Asmith
- 20th June 2007, 14:20
Darrel,

Thank you, I didn't even think of that while I was doing this code. It makes a lot more sense now. Thank you again.


I have one more question, well it's more of something going on with PBP. I have about 30 PCB board designs and Software for each of them. I have all the file to each board in a dedicated folder including the sch, pcb layout, and PBP files. In this one folder the board has 2 PICs onboard and when I try to compile one it overwrites all the files of the other ones, except for the pbp file. Also, what is stranger is that it takes my sch file and renames it after the file I just compiled, and the sch file has nothing to do with pbp. Has anyone ever seen this occur. It's only on this one folder so it's not a big deal I just made a seperate folder for each PIC inside the main folder.

Again thank you for all the help everyone. I appreciate the support. Hopefully this new project of mine will continue smoothly for a while.

Anthony Smith

Darrel Taylor
- 20th June 2007, 23:30
Yeah, isn't that annoying?
I lost several files before realizing what was going on.

When PBP does a compile, it first deletes all the files generated on the last compile.
But, instead of being Smart about it and verifiying the filenames it needs to delete, it just deletes everything with the same Name.

But here's the problem ... it uses the old DOS style names when it does it. So everything with the same 8 characters in the beginning of the filename also get deleted.

Let's say you have the following files ...

TestProg.PBP
TestProg.ASM
TestProg.LST
TestProg.XRF
TestProg.HEX
TestProg.XLS
TestProg.BRD

When you compile TestProg.PBP, you will lose the Excel and PC board files (.XLS and .BRD) because they have the same Name.

You would also lose these files, if they were there.

TestProg_Try2.HEX
TestProgram.ASM
TestProgram3.INC

or any other file with the same first 8 characters, that isn't a .BAS or .PBP.

So, you're right. It's best to have each program in it's own folder.
And, be sure to name anything else in that folder something different than the main program.


HTH,

Ioannis
- 21st June 2007, 07:31
Yeah, it is easy to do a:

del testprog.*

than check each file with its own extension.

Now I understand why I lost a project sometime ago and never knew why... pitty.

Thanks Darrel.

Ioannis

Asmith
- 22nd June 2007, 15:54
Thank you for the insight on this issue Darrel. I understand what is going on now. I will be sure to keep everything seperated, or maybe just start the file name with the specific file task instead of end with it. Thanks again.

Anthony