PDA

View Full Version : Weird problem with logic level on pin.



HenrikOlsson
- 3rd June 2011, 15:13
Hi,
I just had weird problem that I can't really explain, hopefully someone else here can.

Basically I have an 18F2431 device. One of it's pin is used as an fault-input normally pulled high thru 4.7k and then two active LOW signal are OR'd thru diodes to this pin.

In my Main loop I had this (basically):


Main:
If Fault_Input = 0 THEN
Fault_Flag = 1
GOSUB Abort
EndIf

If FaultFlag = 0 THEN
If RunServo = 1 THEN GOSUB DoServo
ENDIF

Goto Main
RunServo is a flag that gets set by a timer interrupt, currently at 1.5kHz.

This has worked fine for a very long time but a user has a problem where I suspect electrical noice is tripping the fault input. Therefor I thought I'd implement a simple filter and did this:

Main:
If RunServo = 1 THEN

If FaultInput = 0 THEN
Accumumlator = Accumulator + 1
If Accumulator = Limit THEN
FaultFlag = 1
GOSUB Abort
EndIf

ELSE
Accumulator = 0

EndIf

If FaultFlag = 0 THEN GOSUB DoServo

ENDIF
Goto Main

Again, this is not exactly how it's done but the principle is the same.

To my surprise this didn't work. Well, it worked when the fault was triggered by one of the two OR'd signals but not by the other. The one that worked has a simple switch to GND making the voltage at the pin one diode drop (~0.6V). But the other input have a transistor (optoisolator output) as its "switch" to GND and there was about 0.55V voltage drop across that for a total "low" voltage at the pin of 1.15V.

This 1.15V is above the logic low thershold of the input which at Vdd=5V is about 0.75V. I fixed the problem by changing the diode to a schotky type with lower forward voltage drop and it now seems to be OK.

The big question I can't find the answer to is how and why it has worked before adding the filter code (there's been ano problem at all that I know of...). It doesn't matter if I set Limit to 1 which should make it trip the first time it sees the signal. The only difference with that is that it won't get checked untill the RunServo flag is set which happens 1500 times/second.

Anyone's got any ideas on what is happening here, it's clear that I was operating outside the electical specs but why does it matter WHERE in the code I actually check the input?

Thanks guys!
/Henrik.

mackrackit
- 4th June 2011, 05:28
Probably not...
But what if the flow is changed a bit?


Main:
IF RunServo = 1 THEN CONTINUE
CONTINUE:
IF FaultInput = 0 THEN
Accumumlator = Accumulator + 1
IF Accumulator = Limit THEN
FaultFlag = 1
GOSUB Abort
'ENDIF
ELSE
Accumulator = 0
ENDIF

IF FaultFlag = 0 THEN GOSUB DoServo

ENDIF
GOTO Main

HenrikOlsson
- 4th June 2011, 08:21
Thanks Dave, I see now that I made a terrible mistake when typing in the example, the Accumulator gets reset when RunServo is 0 and not when FaultInput is 1, this is of course wrong. That, however, is not the case in my real system. Here's the exact code, cut and pasted from my program:

If ServoFault = 1 then Goto OverRunPID 'General fault flag set - don't run servo loop.
'-------------------------------------------------------------------------------
If RunPID then 'Time to run the servo-loop?

'----------------------------- Added 2011-06-03 -----------------------------------
If ip_Fault_Input = 0 THEN 'External fault input is "active"
FaultFilterAccumulator = FaultFilterAccumulator + 1 'If so we increment the accumulator for the filter

If FaultFilterAccumulator = FaultFilterConstant THEN 'Have we reached the filter limit?
ExternalFault = 1 'Set the FAULT Flag
BlinkPattern = Pattern_Ext_Fault 'Change the pattern for the status LED
GOSUB AbortServo 'Abort the servo loop.
ENDIF
ELSE
FaultFilterAccumulator = 0
ENDIF
'----------------------------------------------------------------------------------

op_LED = 1 'Drive LED on the module.
GOSUB DoServo 'Rune the servo loop
RunPid = 0 'Clear flag
op_LED = 0 'Turn off LED on the module.
ENDIF

OverRunPid:
This works fine now that I've changed the diode so the voltage at the pin is within specs. If I change it back to the 1N4148 it does not work, the input is not seen. But WHY does it see it before, when the checking of the input was outside the IF RunPID THEN construct? Here's how it looked before which has worked fine for years:

If ip_Fault_Input = 0 THEN 'External fault input is "active"
ExternalFault = 1 'Set software flag indicating fault
BlinkPattern = Pattern_Ext_Fault 'Select the "blink pattern" for the FW-LED
GOSUB AbortServo 'Abort servo operation.
ENDIF

If ServoFault = 1 then Goto OverRunPID 'General fault flag set - don't run servo loop.
'-------------------------------------------------------------------------------

If RunPID then 'Time to run the servo-loop?
PortA.0 = 1 'Drive LED on the module.
GOSUB DoServo 'Rune the servo loop
RunPid = 0 'Clear flag
PortA.0 = 0 'Turn off LED on the module.
ENDIF

'-------------------------------------------------------------------------------
OverRunPID:
If I run this version, with the original diode in place it works just fine and both versions above works now that the voltage level on the pin is within specs. But why does one work and not the other when the voltage is slightly out of spec? I wouldn't be surprised if neither worked but the original code have worked, with the original hardware, "for years".

The only thing I can think of is that previously the input could get checked tens of thousand of times per second depending on what else was done thru the main loop. Perhaps some capacitive coupling or whatever made the voltage go down to within specs for a short time making the PIC pick it up. But now, when it's "only" checked 1500 times per second that isn't working any more....I don't know...

/Henrik.

Archangel
- 12th June 2011, 11:23
Depending upon which port you are using . . . some Schmidt trigger inputs there.

mister_e
- 12th June 2011, 11:32
...Never mind.....

HenrikOlsson
- 12th June 2011, 11:33
As the code shows I'm using PortA.0. Schmidt trigger or not why would that make a difference in this case, care to elaborate a bit? Same pin, same signal, same voltage on input. One program sees the input it, the other doesn't.

I'm still pretty much stumped on this one.

mister_e
- 12th June 2011, 11:37
By any chance... is there still any ADC or Comparator enabled on those specific pins...

HenrikOlsson
- 12th June 2011, 12:00
Hi,
Aahrgh, sorry can't read my own code...The input pin in question is PortB.3 not PortA.0, sorry about that - and it IS set to an input.

No, the 18F2431 doesn't have any comparators and all pins are set to digital with ANSEL0 = 0.

Here's what the hardware looks like (again, that should read PortB.3, not A.0):

5663

As I've said, the hardware has been this way "for ever" and it has been working just fine "for ever". I changed the code and all of a sudden it didn't see the input. I could go back and forth between working and not working by basically changing where in the code I polled the input.


Again, the voltage at the pin WAS indeed outside the electrical specs but I still don't understand how it can see the input in one version of the code and not the other. The diode in series with the opto-isolator is NOW a shotky type and it's back up and running with the new code. I'm still looking for an explanation though.

mister_e
- 12th June 2011, 15:23
Does the code modification also add/modify what happen to the adjacent "offending" input pins?!?

Or you've been lucky OR...well... let's apply this rule


Sometimes, you don't wanna know why... and stay happy

Keep it simple... Look forward ;)

Darrel Taylor
- 12th June 2011, 18:41
Have you looked at the transitions with a scope?
Is there any undershoot?

The non-filtered version would be more likely to catch short lived pulses just under the threshold.

HenrikOlsson
- 12th June 2011, 19:33
No I have not scoped it but it's got to be something like that. I'm just a bit surprised that it "never" (that I know of) missed it before and now it didn't see it at all. I spent quite some time staring at the code before I even bothered to put the meter on it since I "was sure" that the hardware was OK.

I'll scope it next time I work on that project.

Thanks!

/Henrik.

Archangel
- 12th June 2011, 20:26
Hello Henrik,
Here is my thoughts, for better or worse . . . Schmidt Trigger is more particular as to threshold voltage as to when it switches, both high and low. TTL switches around 1/2 way between VSS - VDD, if your diodes are different in terms of their switching voltage, as I see it, 1 will work and the other will not, and your VOM might not be high enough impedance to see the difference.
In any event, as I said, those are my thoughts . . .

HenrikOlsson
- 13th June 2011, 06:31
Yes, but I didn't switch inputs or diodes or did anything else to the hardware. It was working just fine with the old code but stopped working with the new code. I took a working board and downloaded the revised code. Nothing changed hardware wise, just the code. Reverted to the old version - everything OK. New code, nope.

It's got to be something in line with Darell's thinking. Previously it checked the input in a very tight loop except when it ran the servo loop which is around 350us 1500 times per second. Now it checks it a single time each time it enters the servo loop.

But if this is the case I would expect it to have missed it on ocations even with the old code. After all, it's busy ~50% of the time thus not checking the input so if an undershoot event on the signal was what caused it to work I must have been seriosult lucky since I haven't had it miss a single time.

Thanks!
/Henrik.