Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] 12c508 frequency switch

Status
Not open for further replies.

dom87

Newbie level 6
Joined
Jul 27, 2011
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,358
Hi,

I was wondering if anyone was able to help me with some code.
I'm building a frequency activated relay using a 12C508, which triggers when the input frequency is between 4-15KHz (square wave).

Any suggestions or guidance would be greatly appreciated. :)

I was given this code as an example, but I'm not quite sure how to tailor it to my requirements.

Code:
test 
clrwdt 
clrf TMR0 
clrf pulse_count 
 
wait3 
movlw d'200' 
subwf TMR0, W 
btfsc STATUS, C 
goto time_up 
btfsc GPIO, 3 
goto wait3 
 
wait4 
movlw d'200' 
subwf TMR0, W 
btfsc STATUS, C 
goto time_up 
btfss GPIO, 3 
goto wait4 
incf pulse_count, F 
goto wait3 
 
 
time_up 
movlw d'3' 
subwf pulse_count, W 
btfss STATUS, C 
goto test 
 
movlw d'9' 
subwf pulse_count, W 
btfsc STATUS, C 
goto test

So I would like the relay to come on to a signal like this....
signal forum.jpg
 
Last edited:

4 kHz is a period of 250 uSec. 15 kHz is a period of 67 uSec.

You need two loops.
The first counts the amount of time the signal is high (above, say 3 V).
Continue until the signal goes low, or you count to 251 uSec.
Store the time in variable A. End loop 1.

The second loop counts the time the signal is low (below, say 2 V).
Continue until the signal goes high, or you count to 251 uSec.
Store the time in variable B. End loop 2.

Add A and B.
If the total is <66 uSec or >250 uSec, then you turn off the relay. Otherwise turn on the relay.

Repeat from the beginning.
 
  • Like
Reactions: dom87

    dom87

    Points: 2
    Helpful Answer Positive Rating
Thanks for getting back to me. What would be the best way to time it?

Could one way be to reset the watchdog timer when both loops have been met, thereby allowing the code to proceed to the "output on" statement?
 

Thanks for getting back to me. What would be the best way to time it?

I believe others have said there is a time counter in microcontrollers. I am not familiar with them.

Could one way be to reset the watchdog timer when both loops have been met, thereby allowing the code to proceed to the "output on" statement?

Yes, there is more than one way to manage the loops. I believe there needs to be a way to exit loops in cases where the incoming signal is unchanging high or unchanging low. That is why I set a time limit for a loop.

You don't have to set the tick-count to zero at the beginning of each loop. You can add 250 uS to the current tick-counter, and call it targetTime. Check the tick-count through each iteration of the loop. If at some point the tick-count exceeds targetTime, exit the loop.

The code in your OP is a beginning. Your own ingenuity will be called on to revise and test the code until it suits your purpose.
 

thanks.....

I tried doing something similar with the 16f628a in Mikrobasic, just so I could understand what was going on a little better.

It works but for some strange reason, it turns on at 1KHz, then off at 3KHz and the back on again at 5KHz. Same thing happens at certain other frequencies too.

I have no idea why it's doing that.....


Code:
program charge_pump_controller

' Declarations section 

' Header******************************************************
symbol RELAY = PORTB.0 ' Pin PORTD.3 is named RELAY
dim LOWFREQ as byte       ' Variable TEST is of byte type
dim HIGHFREQ as byte


main:                  ' Start of program
LOWFREQ = 90               ' Constant TEST = 5
HIGHFREQ = 180
TRISB = 0
OPTION_REG = 0x0E ' Prescaler is assigned to timer


PORTA = 0              ' Reset PORTA
TRISA = 0xFF           ' All portA pins are configured as inputs
PORTB = 0              ' Reset PORTB
'TRISA = %11110111      ' Pin RD3 is configured as an output, while other pins are
                       ' configured as inputs
OPTION_REG.5 = 1       ' Counter TMR0 receives pulses through the RA4 pin
OPTION_REG.3 = 1       ' Prescaler rate is 1:1
TMR0 = 0               ' Reset timer/counter TMR0

while 1
TMR0 = 0
delay_ms(200)


if TMR0 > LOWFREQ then
   if TMR0 < HIGHFREQ then 
      RELAY = 1      ' Numbers match. Set the RD3 bit (output RELAY)
	
      else
          RELAY = 0
   end if
else
  RELAY = 0

  
end if



wend                   ' Remain in endless loop

end.                   ' End of program
 

Nevermind, got it working now.... :)

Code:
program charge_pump_controller

' Declarations section 

' Header******************************************************
symbol RELAY = PORTB.0 ' Pin PORTD.3 is named RELAY
dim LOWFREQ as byte       ' Variable TEST is of byte type
dim HIGHFREQ as byte
dim COUNTREP as integer


main:                  ' Start of program
LOWFREQ = 10              ' Constant TEST = 5
HIGHFREQ = 70
TRISB = 0
OPTION_REG = 128 ' Prescaler is assigned to timer WDT (1:64)


PORTA = 0              ' Reset PORTA
TRISA = 0xFF           ' All portA pins are configured as inputs
PORTB = 0              ' Reset PORTD
'TRISA = %11110111      ' Pin RD3 is configured as an output, while other pins are
                       ' configured as inputs
OPTION_REG.5 = 1       ' Counter TMR0 receives pulses through the RA4 pin
OPTION_REG.3 = 1       ' Prescaler rate is 1:1
TMR0 = 0               ' Reset timer/counter TMR0

while 1
    TMR0 = 0
    delay_ms(18)




    if TMR0 > LOWFREQ then
       if TMR0 < HIGHFREQ then
          COUNTREP = COUNTREP + 1
          
          
            if COUNTREP > 2 then
               RELAY = 1      ' Numbers match. Set the RD3 bit (output RELAY)
            end if
          
          
          else
          
              COUNTREP = 0


       end if
    else
      RELAY = 0
      COUNTREP = 0

    end if



wend                   ' Remain in endless loop

end.                   ' End of program


Now I just need to get the code to work for the 12c508. There is one slight problem, Mikrobasic doesn't support the 12c508..... bugger! So I need to take the exported Assembly code and tweak it.
 

Yes, the code was not so hard to write, was it?

I see that you used a single loop. This is possible because the hardware counts high and low pulses, then calculates the frequency for you.
 

actually it was quite tricky for someone who codes pics once in a blue moon, to get working and in the right frequency range. hey-ho.
 

Now I just need to get the code to work for the 12c508. There is one slight problem, Mikrobasic doesn't support the 12c508..... bugger! So I need to take the exported Assembly code and tweak it.

Is there any particular reason why you are using an OTP rather than a flash based PIC?

I believe the MikroC supports the PIC12F609, I don't have MikroBasic available, and offers another 1KB of FLASH program memory and three times the RAM for another 10 cents or less.

Besides, the additional FLASH and RAM might come in handy for any future developments with an HLL like MikroBasic.

Just a thought.

BigDog
 

well it was mainly because I have so many of them, so thought I'd put them to good use. But for all the hassle their worth, i might just sell them on ebay as apparently the playstation modders love them.

I've gone for the 12f675 as that's all the local electronics shop had. So i've adjusted the code, to try and make it work on the 12f675 but it's acting very strange. The output comes on above 8KHz and stays on.:???:

Any suggestions as to what is causing the issue?

Code:
program Charge_Pump_PIC12F675

 ' Processor speed @ 1MHz
 ' All additional off (Watchdog off, brownout off, etc)
' Header******************************************************
'GP0 and GP1 cannot be digital outputs
symbol RELAY = GPIO.5 ' Pin GP5 is named RELAY
dim LOWFREQ as byte       ' Variable TEST is of byte type
dim HIGHFREQ as byte
dim COUNTREP as boolean



main:
'   Main program

    ADCON0.0 = 0
    ANSEL = 0             ' Turn off Analog to Digital converter  GP2
       
    LOWFREQ = 14              ' 3.5KHz switch on
    HIGHFREQ = 70             ' 16.3 KHz Switch off
    TRISIO = 0              ' Set as output
    OPTION_REG = 128        ' Prescaler is assigned to timer WDT (1:64)


    TRISIO.2 = 1          ' GP2 pin is configured as input
    RELAY = 0            ' Reset Relay Pin

                          ' configured as inputs
OPTION_REG.5 = 1          '  Counter TMR0 receives pulses
OPTION_REG.3 = 1          ' Prescaler rate is 1:1
TMR0 = 0                  ' Reset timer/counter TMR0
     
     
     COUNTREP = false


    while 1
        TMR0 = 0
        delay_ms(18)


        if TMR0 > LOWFREQ then
           if TMR0 < HIGHFREQ then


                if COUNTREP = true then
                   RELAY = 1      ' Numbers match. Set the RD3 bit (output RELAY)
                end if

                COUNTREP = true

              else

                  COUNTREP = false


           end if
        else
          RELAY = 0
          COUNTREP = false

        end if



    wend                   ' Remain in endless loop

end.
 

Have you double checked the Configuration Register settings?

It's been a while since I've used any PIC12F series in designs, so I'd need to compare the datasheets.

Also the PIC12F675 has several peripheral modules which your PIC12C508 does not, which maybe the source of issues.

BigDog

- - - Updated - - -

One major difference is the PIC12F675 has both ADC and Comparator which are enabled by default and need to be disabled to use those pins as digital I/O.

Reference: PIC12F629/675 Datasheet, Section: 3.0 GPIO PORT, Page: 21
Note: The ANSEL (9Fh) and CMCON (19h)
registers (9Fh) must be initialized to
configure an analog channel as a digital
input. Pins configured as analog inputs will
read ‘0’. The ANSEL register is defined for
the PIC12F675.


Disable Both Peripherals in C
Code:
CMCON = 0x07;
ANSEL  = 0x00;


After reviewing your code it looks like you've disable the ADC but left the comparator enabled which may have some effect.

Also be aware there are a few oscillator configuration settings, in the Configuration Register, which output an Fosc/4 clock on GP4 and a clock input on GP5.


BigDog
 

I got this working now... :-D

Thanks for all your help guys.

It turned out to be a combination of things.

The working code....
Code:
program Charge_Pump_PIC12F675

 ' Processor speed @ 1MHz
 ' All additional off (Watchdog off, brownout off, etc)
' Header******************************************************
'GP0 and GP1 cannot be digital outputs



symbol RELAY = GPIO.5          ' Pin GP5 is named RELAY
dim LOWFREQ as byte            ' Variable used to store the lower frequency threshold
dim HIGHFREQ as byte           ' Variable used to store the higher frequency theshold
dim COUNTREP as boolean        ' Used to count two repetitions of successful frequency ranges



main:
'   Main program

    ADCON0.0 = 0              ' Turn off analog settings
    ANSEL = 0                 ' Turn off Analog to Digital converter  GP2
    CMCON = 7                 ' Turn off comparators
    
    LOWFREQ = 5               ' 3.5KHz switch on
    HIGHFREQ = 29             ' 16.3 KHz Switch off
    
    TRISIO = 0                ' Set as output
    OPTION_REG = 128          ' Prescaler is assigned to timer

    TRISIO.2 = 1              ' GP2 pin is configured as input
    RELAY = 0                 ' Reset Relay Pin


    OPTION_REG.5 = 1          '  Counter TMR0 receives pulses
    OPTION_REG.3 = 0          ' Prescaler rate is 1:1
    TMR0 = 0                  ' Reset timer/counter TMR0
     
     
     COUNTREP = false         ' Initialise the successful frequency count


    while 1
        TMR0 = 0
        delay_ms(18)


        if TMR0 > LOWFREQ then
           if TMR0 < HIGHFREQ then

                 ' If there are two successful repetitions, then turn on relay
                  if COUNTREP = true then
                     RELAY = 1      ' Numbers match. Set the RD3 bit (output RELAY)
                  end if

                  COUNTREP = true

              else
                  
                  ' If the frequency exceeds the upper threshold, 
                  ' turn off the RELAY and reset the successful frequency count
                  RELAY = 0
                  COUNTREP = false

           end if
           
           
        else
        
            ' If the frequency is less than the lower frequency threshold, turn off and reset count
            RELAY = 0
            COUNTREP = false

        end if



    wend                   ' Remain in endless loop

end.

I'm still not entirely sure why the frequency variables are so much lower than when I had the program working on a 16f628a despite both being set at 1MHz.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top