Using 12c629 as smart flip-flop

Status
Not open for further replies.

jimg

Member
I've been working on a replacement wall switch using a qprox touch switch. The basic circuit works fine, but I found that all normal flip-flops I used to toggle the output were sensitive to noise, and I needed to remember the state between power outages. So I bought a pickit2 and some 12c629 chips (they were the cheapest 8-pin dip with eeprom). After a couple of weeks working through several tutorials, I thought I was ready to tackle something as simple as emulating a flip-flop.

The qprox chip outputs a 95 millisecond pulse when triggered. I will have the output of several of these connected together by diodes to a common wire, pulled down with a 50k resistor. So I wrote a program to ignore any pulse less than about 90 ms, wait until the pulse was done, check for a lack of pulse for an additional ms, and then toggle an output pin. The problem is that when I introduce noise into the system, it still toggles my new software flipflop, even though the noise spikes are less than 90 ms. I introduce noise by plugging a transformer into the same ac circuit. It makes enough of a spike to make the speaker click on my pc.

I'm using gp2 as the input as it looks like it is a schmitt trigger when used as a general input pin. I'm using gp0 as an output. (I was using gp5 as an output, but for some reason the circuit quits working after using it a few times on this output?). So to trace the problem, I turn on gp1 to drive an led whenever I get a pulse bigger than 90ms, wait for the pulse to disappear for at least 1ms, and then toggle the output gp0, in the process turning off the test gp1 led.

The circuit works very well under normal circumstances.
The very strange thing is that when I introduce noise spikes into the system as above, I can see the gp1 led turn on and stay on, but it never gets to the code to switch the output gp0 pin high. I can't see how this can possibly happen looking at the code. I disable interupts every time through the loop.

So I need another set of eyes to find the problem. Any additional suggestions for this newbie would also be appreciated.

-Jim

Here's the code:

Code:
 include p12F629.inc
 __config _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT

;** note, case sensitivity turned off ( /c option)


; ra2 = gp2 = input   (schmitt trigger)
; ra0 = gp0 = output

	cblock 20

State	; state output should be at.  1h = gp0 on
wait1	; wait amount (for 1 millisec)
wait2	; number of millisecs to wait

	endc
	
	org 0
Start
	bcf	status,rp0	; bank 0
	clrf	gpio		; initialize gpio (PORTA)
	movlw	7h
	movwf	cmcon		; comparator off (gp2=schmitt input)
	bsf	status,rp0	; bank 1
	movlw	4h
	movwf	trisio		; Make gp2=input, all else output
	bcf	status,rp0	; back to bank 0 
	clrf	State	
ww1
	clrf	intcon	; disable all interupts, just in case
	btfss	gpio,2	; wait for leading edge of pulse	
	goto	ww1

	movlw	.90	; want at least a 90ms pulse
	movwf	wait2
ww2
	movlw	.200	; set up for 1 ms delay
	movwf	wait1
ww3
	btfss	gpio,2	;1
	goto	ww1	; short noise pulse, ignore and start over 
			;1
 	decfsz	wait1,f	;1
	goto	ww3	;2
			;total=200*(5)=1000us=1ms
	decfsz	wait2,f	; count off millisecs
	goto	ww2
	
 bsf gpio,1  ;***  for debug, found >90ms pulse, turn on led
	nop
	nop
ww4
	btfsc	gpio,2 ; ok, long enough, wait for pulse to end	
	goto	ww4

	movlw	.200	; minimum width between pulses, 1ms
	movwf	wait1
ww5	
	btfsc	gpio,2 
	goto 	ww4	; must have been ringing, start over

	decfsz	wait1,f
	goto	ww5	; wait a bit
 
	movlw	1	; gp0 (ra0) output
	xorwf	State,f	; toggle the output bit
	movf	State,w	; state of light, 1 = on
	movwf	gpio	; (porta)
	goto	ww1
		
	end
 
Last edited:
As you state, if the led on gp1 lights then it must carry on and toggle the led on gp0. I think the spike must be crashing the Pic. I'd look at power supply decoupling and input pin spike handling. Or, you have a pulse that last forever and your code never gets past the ww4 loop.

Mike.
 
Last edited:
Looking at the input with a scope, none of the spikes are anywhere near 90ms wide, but they are rather large and very ugly. If the pic crashes, shouldn't it start over at the beginning of the program, which would immediately reset the outputs turning off the leds?

When it gets in this impossible condition, all I have to do is send a valid input and everything works properly, so it's not getting hung up anywhere, it just didn't reset the led. And of course, it shouldn't have set the led in the first place.

Is there some maximum rate at which you can check inputs? Much of the code I have seen checks an input, delays a bit, and checks again for debouncing. Is there some minimum delay after setting outputs before you can check inputs again?

The whole reason for going to a pic for a flipflop was to handle this noise problem, as normal IC's weren't able to, but the pic is showing the exact same problem. I was sure I could handle this in software.

I put the pic on a breadboard with nothing else on the board but two leds on the outputs and a 47k resistor from the input to ground. Powered it from a small lamda power supply set to 3 volts, the voltage of the target circuit. I connected the VSS to the AC neutral line also, since this will be it's normal environment, and is probably the source of the noise. I got the same glitch when creating the noise spikes. So this eliminates any problems with the qprox or any of the other circuitry.

Eventually, I was going to run this off a 32768 hz crystal to cut down on the current demands. Do you think this would have any effect on this problem?

Anyone else have any suggestions?
 
Last edited:
Hi Jim,

You got a .1-ufd bypass capacitor across and located as close as possible to the VDD and VSS pins?

Mike
 
Yes, see attached picture of entire circuit. Notice that there is nothing attached to input gp2. This is because it is no longer an input. I started stripping down the program until I got to this:
Code:
 include p12F629.inc
 __config _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
	org 0

	bcf	status,rp0	; bank 0
	clrf	gpio		; initialize gpio
	movlw	7h
	movwf	cmcon		; comparator off
	bsf	status,rp0	; bank 1
	clrf	trisio		; make all output
	bcf	status,rp0	; back to bank 0 
	clrf	gpio		; turn everything off
	clrf	intcon		; disable all interupts
	
lp	goto	lp

	end

so there is nothing left to the program. No inputs, the only write to output clears everything. I get the same action when I generate the noise by plugging and unplugging the transformer. The led's light up randomly. Obviously, the pic is not resetting to the beginning when there is a problem, but how do I stop this random behavior?
 

Attachments

  • IMG_0893.jpg
    139.8 KB · Views: 259
This might be a shot in the dark but you can try turning the Brownout detection ON to see if situation improves. This would stop the PIC running wild if there are voltage dips on the supply.

__config _BODEN_ON
 
I agree with the BrownOut Detect

Here's a little something i did awhile back. The code is in PICBAsic Pro but you should be able to understand it
https://www.picbasic.co.uk/forum/showthread.php?t=2671

you can increase/decrease the sensitivity of the sensor by playing with the resistors value. Higher value=higher sensitivity.

22K seems fine and problem free... 'till now.
 
I'll give the brownout a try.

For some reason, I'm having much more difficulty recreating the problem this afternoon. Perhaps because of the humidity? I'll try in the morning.

I love your touch switch application. I'll have to play around a bit with it.
 
Well, the brownout had no effect. I went back and tried more capacitors however. After 4 .1uf caps, it started to settle down. I think I'll just use 1uf for insurance. I guess the regulator I'm using isn't as good as the specs indicate. And I'm sure it will be less of a problem when soldered to a small circuit board rather than being plugged into a breadboard. Perhaps a transient voltage suppressor would help.

Thanks everyone for your help.
 
A good power supply is ESSENTIAL, just throwing an IC regulator at it doesn't make a good power supply!.

The capacitor on the output of the regulator in the datasheet is just to prevent it oscillating, and needs to be as close as possible to the regulator - you still need proper supply decoupling as well.
 
Ok, I finally found the problem. It was an intermittant connection in the breadboard I was using. Everything is solid now.

So I've finalized my design except one thing keeps nagging at me. If there is a power outage, do I want all the lights that were on to come on in the middle of the night? I don't think so. But if it's only a few minutes, I would like them to return to their last state.

What is the easiest/cheapest way to give the pic some indication of the time elapsed since the last time it was on? Just a simple go/nogo value of about 5 minutes should be good enough.

I was thinking just a capacitor self discharging, but this was not as easy as I thought it would be. Since I have about 35 light switches, I like to keep this under a buck or so. Since these will be sealed behind wall plates, I'd also like to avoid batteries or any other part that might need replaceing for 30 or 40 years Anyone have any ideas?
 
Last edited:
One quick thought! - how about a battery backed RTC (real time clock), the PIC could read it every minute and store the time in it's data EEPROM memory. Then if there's a power cut, when it resets, your PIC can compare the current time (read from the RTC) to the value stored in the EEPROM, if the difference is more than 5 minutes then elsure everything is switched off.

Another quick thought! - you could also use the RTC to give timing functions, such as turning lights on when you're out.
 
jimg said:
I was thinking just a capacitor self discharging, but this was not as easy as I thought it would be.

This is the proper method to go. You need some circuit to isolate the PIC pin from the capacitor when the main power is off, otherwise the protection diode of the PIC input pin will discharge the capacitor quickly upon supply failure.

So you'll need at least two pins. One to compare the voltage on the cap and the other to detect the main supply has failed. Upon detected mains failure and before the DC supply has completely gone, the current state of the switch is stored in EEPROM during this critical moment.

I'll look at using a super capacitor, which I think would provide a discharge time long enough of several minutes with a 10~20K series resistor and still maintains a certain voltage.

The idea is to program the port pin as output and charges the capacitor via a diode across the 10-20K resistor when the mains is normal. Upon PIC reset on power up, you use the pin as analogue comparator mode and checks the voltage on the capacitor. If it is higher than the comparator reference, then you know the last supply outage happens not long ago and restore the switch state stored inside the EEPROM, otherwise put the switch into the default state and clear the EEPROM content.

Added: I have just done a test using a 0.1F super cap. with a 10K discharge resistor across. Starting voltage=3.30V, after 5 minutes, voltage=2.43V.
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…