PDA

View Full Version : A/D IO pins changing function while running?



TerdRatchett
- 4th June 2013, 17:21
Hi Friends!

I am experiencing some strange activity with the A/D converter on my project. The design uses a

PIC16F876A.

I have a tight loop which monitors the voltage from an output circuit and either turns on or off PWM. Essentially a closed loop, special purpose power supply. The design works great, however, after about three minutes the A/D stops reading the data correctly and the power supply runs away as a result.

I have monitored the input voltage to the A/D on either side of its 10K series resistor. While operating normally I have approx. .328 volts on both sides. When the anomoly occurs the voltage on the processor side of the input resistor goes to 0, while the actual input voltage is still correct. At that point the firmware, seeing no voltage, starts increasing the PWM until the supply maxes out. Of course my output voltage is dangerously high at that time!

The only thing I can relate this too is as if the processor has somehow changed the port A pin from an input to an output and set it low? My firmware is a very tight loop however and I don't see how this could happen. In fact the program is continued and is not resetting.

I switched the input from AN4 to AN0 and the problem follows.

Here is the source:

'INCLUDES
Include "Modedefs.bas" 'for serial out routine

'DEFINES
DEFINE OSC 20 'use 20MHz crystal

'Define ADCIN parameters
Define ADC_BITS 10 ' Set number of bits in result
'Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_CLOCK 0 ' Set clock source (0=clock / 2)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

'set WDT for 2.3 sec time out and no R pullups on portB
OPTION_REG = %10001111

'PORT DIRECTION, NAME ASSIGNMENTS
trisA = %11111111 'All inputs on Port A
ADCON1 = %00000000 'Set PORTA analog inputs
trisB = %00000011 'Set PortB outputs except 0 and 1
trisC = %10010000 'All outputs except Serial and Microwire data in

wKVset = 3000 ' 15300 actual = 14,500

gosub setup_PWM


Main001:
'GOSUB PWM_Off
GOSUB Get_HV

if wHVvolts > wKVset then
GOSUB PWM_Off
Else
gosub PWM_ON
ENDIF

goto Main001

Subs -

Get_HV:
'pause 1 ' don't delay, enough time spent in main
ADCIN 0, AdData[0] ' Read HV channel 4 to adval
'ADCIN 2, AdData[2] ' Read area pot for test sim

' For test purposes
'SEROUT pTXD, T9600, ["Raw HV AD: ", #AdData[0], 10,13]

' wHVvolts = (AdData[0] */ 82) >> 2 ' equates to: (adval * 82)/1024
' wHVvolts = wHVvolts * 10

wHVvolts = (AdData[0] /132)
wHVvolts = wHVvolts * 100
' wHVvolts now contains actual HV in volts
' For test purposes
'SEROUT pTXD, T9600, ["Actual HV: ", #wHVvolts, " Volts DC", 10,13]

Return


Setup_PWM:

TRISC.2 = 1 ' Set PORTC.2 (CCP1) to disable
PR2 = %00001000 ' Set PWM Period to 34 KHz
CCP1CON = %00001100 ' Set CCP1 to PWM, ACTIVE HIGH
CCPR1L = 0 'Set PWM Duty-Cycle to 0%
CCP1CON.4 = 0 ' Ten bits, set
CCP1CON.5 = 0
PIR1.1=0
T2CON = %00000111 ' Timer2 ON, Prescale 1:16
While PIR1.1=0 ' Wait for Timer 2 Overflow
wend
TRISC.2 = 0 'Set port C as output to enable

return


PWM_ON:
PWM_Duty = 500
CCP1CON.4 = PWM_Duty.1 ' Ten bits, set
CCP1CON.5 = PWM_Duty.0
CCPR1L = 4 'PWM_Duty >> 2 'Set PWM Duty-Cycle to 50%
return

PWM_OFF:
PWM_Duty = 0
CCP1CON.4 = PWM_Duty.0 ' Ten bits, set
CCP1CON.5 = PWM_Duty.0
CCPR1L = 0 'PWM_Duty >> 2 'Set PWM Duty-Cycle to 0%
return

Any advice would be appreciated.

Thanks in advance,
TR

aerostar
- 4th June 2013, 18:16
DEFINES should be in UPPERCASE.

TerdRatchett
- 4th June 2013, 19:16
Thanks aerostar! They are uppercase in the MicroCode Studio editor. I get no errors.

TerdRatchett
- 4th June 2013, 19:37
Update: I wrote a value of $FF to the porta register on initialization and had the same failure.

Art
- 6th June 2013, 13:39
So which is it?


ADCON1 = %00000000 'Set PORTA analog inputs
^
|
set 8 bit ADC


DEFINE ADC_BITS 10 ' Set number of bits in result

Not sure it is your problem if you've done all your testing with an 8bit range,
but doesn't look good to tell PBP you're doing something you're not.

Art
- 6th June 2013, 16:41
I found this interesting so looked a bit more...
I've done a couple of projects with analogue in that worked great :)

I think your program is resetting bits in ADCON1 register and resetting ports back digital
depending on the value read from the port that starts out analogue.

For an 8 bit result, setting ADCON1:7 to zero sets the 10 bit result left justified so you
only see the high 8 bits in the word which are most significant because you access the
high byte of a word with the 10 bit result shifted into place.
How much of this is handled by PBP I don't remember, but that's what's happening.
Otherwise the 10 bit result is right justified, and you see a 16 bit word who's leading
6 bits are always zero, and that's the 10 bit result.

I'll bet that you're making PBP access a 16 bit word comprised of the ADCON1 register,
and the lower end result register, and that's somehow enough to wreck the contents
of ADCON1, and leave your program running with a digital port.

I was thinking asm when doing this,
it would be nice if someone else has any thoughts on what PBP is doing.
I suspect the DEFINE would set the ADCON1 bit 7 without touching the other bits,
and setting it again directly might only override it.

peterdeco1
- 6th June 2013, 17:32
I had some issues in the past similar to this. Try putting your main001: label under your DEFINEs so it essentially reboots each time it goes there.

TerdRatchett
- 12th June 2013, 17:00
Thanks Art, I corrected that error but the problem persists. What I have found is that while in a tight loop reading any A/D input the input impedance becomes much lower and causes A/D readings that are way out of whack. For example; I have a 10k input resistor and there is .212 volts on the input and .108 on the processor side while continuously reading. If I comment out the line that reads the A/D I get .212 volts on both sides of the resistor.

TerdRatchett
- 12th June 2013, 17:51
In addition if I comment out the line that turns on PWM I get no voltage drop across the input resistor and the A/D reads the voltage correctly. It almost appears as if the PWM is affecting the A/D.

peterdeco1
- 12th June 2013, 19:06
If you connect your PWM output to a scope or even an LED, does it behave correctly?

TerdRatchett
- 13th June 2013, 19:16
Thanks to everyone for their help! I found the actual problem yesterday. As it turns out there was a transient coming in on an A/D pin other than the one I was using to measure the high voltage. I removed that input and the product regulates precisely. Lesson learned: transient voltages on any A/D input can effect the operation of other inputs of the A/D input multiplexer.

TR

Art
- 14th June 2013, 03:58
It's hair pulling stuff when your programming problem was really an electronics problem,
or vice versa.