PDA

View Full Version : ADCIN giving inconsistent results



triton99
- 24th September 2011, 19:29
A friend of mine had an issue with the cooling fans on one of his cars. He originally asked if I could just wire up a switch so he could turn the fans on/off with a switch. I thought this would work but what if he forgot to turn them on and the car would then overheat. So I decided to look into creating a circuit for him that would monitor the temperature of the coolant and turn the fans on/off respectively.

The coolant sensor on his car is just a thermistor that increases in resistance as the temperature rises. The car ECU provides a voltage divider circuit that then measures the voltage at the sensor. While gathering information about thermistors i concluded that there measured resistance on a graph is non-linear. When using the thermistor in a voltage-divider circuit the graph of the measured voltage becomes more linear. There are different reasons why car cooling fans do not turn on; faulty relay's, ECU's, sensor's, fan's, wiring, etc. The particular model of car he has [2000 Chevy Malibu] is notorious for having this problem. As far as I can see no one has solved the problem directly; it seems to be a problem of the manufacturer.

When connecting a OBDII scanner to the car I am still able to read the coolant sensors temperature. Using a voltmeter, we read the value at the sensor and noted what the temperature was on the OBDII scanner. He told me what temps he wanted the fans high/low to turn on/off. This initially seemed simple enough....so I thought.

Back at my home I decided I would use a PIC12F675 for the project; it was small and had ADC features. I remembered a long time ago I built a circuit for a very simple voltmeter, but it was using a BS2 module. After a little more research, I found a similar example on these forums for reading the voltage on a ADC pin. After a few tests everything seemed to work as it should. The values fluctuated initially, but after I set the VREF to VDD it seemed to stop. Next I etched circuit onto a copper-clad PCB. Now the fluctuation returned.

What I was wanting to know, is there a better way of reading the voltage using an ADC on the 16F675. Here is my code, and I also attached a picture of the schematic. The SEROUT portions will eventually be removed once develpment was complete. They were just used so I could test the circuit while at the car. The fan-relays on the car also have flyback-protection diodes.

Also when I inserted the PICBASIC code it changed the formatting, so everything that was supposed to be capitalized is not anymore.

Thanks, and sorry for the long-winded story.


@ DEVICE pic12F675, INTRC_OSC_NOCLKOUT ' Internal Oscillator
Define OSCCAL_1K 1 ' Calibrate internal oscillator

ADCON0.7 = 1 ' Right justify result
ADCON0.6 = 0 ' set Vref to VDD
ANSEL = 001000 ' Set AN3 analog, rest digital
CMCON = 7 ' disable analog comparator

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


sample_size var byte
i var byte
V_in Var Word
V_total var word
TX Var GPIO.5
mode VAR byte
low_fan var GPIO.2
high_fan var GPIO.1


mode = 2 '// 2=T9600, 6=N9600
sample_size = 50
v_total = 0
V_in = 0


LOW low_fan
LOW high_fan


pause 500


serout TX, mode, [10,10]
serout tx, mode, [10,13,"------------------", 10, 13]
serout tx, mode, [ "ECT Fan-Controller", 10, 13]
serout tx, mode, [ "------------------", 10, 13]


main:
gosub read_v
gosub check_v
gosub update_display
goto main


update_display:
serout TX, mode, [#V_total,13]
pause 1000 '// slight delay to lower flickering
Return


check_v:
if V_total <= 201 then high low_fan '/ car test value 201
if V_total <= 181 then high high_fan '/ car test value 191
if V_total >= 211 then gosub fans_off '/ turn both fans off
Return

fans_off:
low low_fan
low high_fan
return

read_v:
for i = 1 to sample_size
pauseus 50
ADCIN 3, v_in ' Read channel 3 to V_in (0-1023)
V_Total = (V_In + V_total)
next i

V_total = V_total/sample_size ' average the values
V_Total = (V_total */ 500)>>2 ' Equates to: (V_in * 500)/1024
Return


end



6004

mister_e
- 24th September 2011, 19:55
I would insert a low-pass filter and buffer between the sensor and the PIC. This way, you cut the noise, avoid some spikes (if designed accordingly) and make sure you also have the maximum input impedance on the ADC. (2Kohm if my memory serves me well)

Side note, if your unit is mounted on a breadboard... you may/will experiment all sort of behaviours, Car noise can be really nasty sometimes.

Charles Linquis
- 24th September 2011, 21:30
It doesn't look like you are clearing V_total every time before you go into your A/D routine.

mister_e
- 24th September 2011, 21:31
:eek: True!

triton99
- 24th September 2011, 21:51
I changed the code to reset V_total variable at the start of the V_read routine. I am not able to test until I get home. But i was under the assumption that if I did not reset V_Total it would then the last value would be reused in the next readings average.

Also when implementing the low-pass filter on the voltage in what values do you think would work for the resistor and capacitor??
What is a good cut-off frequency??

6005

Thanks again for all the help.

mister_e
- 24th September 2011, 22:04
as-is: It really depend of the source....
assuming you want to use an opamp in between: it's a totally different thing.

You already use some averaging thing, Try the code modification, I'm pretty confident it will solve the problem.

You could also use the ADC in 8 bit mode instead of 10...

Anyways, have a look at this document
http://ww1.microchip.com/downloads/en/DeviceDoc/adn007.pdf

Charles Linquis
- 24th September 2011, 23:15
My guess is that if you clear V_total, you won't need anything else.

Consider:

If the A/D returns a value of 410

1st time through the loop

V_Total = 200

Second time through the loop

V_Total = 202

Third time through the loop

V_Total = 204

....

And it goes through those loops pretty fast. I can see how the results would look inconsistent

HankMcSpank
- 25th September 2011, 00:43
What I was wanting to know, is there a better way of reading the voltage using an ADC on the 16F675.


fwiw I've come to the conclusion that using the picbasic 'ADCIN' command = much badness (unstable ADC readings for me at least)

Nowadays, if I've a spare CCP module going free, I always use the PIC's special event trigger - it's a very tidy effiicient way of collecting ADC samples in the background - Once it's setup (it's not hard to do this), whenever you want a sample - it's already therefore you ...just go and grab the contents of ADRESH. Job done, eg...



v_in = ADRESH
'now go do cool stuff with v_in



The 16f675 has a special event trigger option ...it uses CCP4 for it, so...if you're not intending utilising CCP4, then seriously consider dedicating it to the special event trigger....

Charles Linquis
- 25th September 2011, 02:22
Add one line and most of your problems will go away.




fans_off:
low low_fan
low high_fan
return

read_v:

V_Total = 0 <--------------------------------------------------------------

for i = 1 to sample_size
pauseus 50
ADCIN 3, v_in ' Read channel 3 to V_in (0-1023)
V_Total = (V_In + V_total)
next i

V_total = V_total/sample

triton99
- 25th September 2011, 13:38
mister-e: Thanks for the document on reducing system noise. I dont know how I missed that one.

Charles Linquist: Thanks for pointing out reseting the V_Total variable. My brain sometimes gives me flawed logic...:confused:

HankMcSpank: I orginally tried to use the ADC directly using ADRESH. For some reason I could not get it to work. Once I get back home I will mess with it again. It seemed like a better approach.

Thanks again everyone, and I will be testing this again today on the car, so I will post the results when finished.

triton99
- 23rd October 2011, 00:55
After a few weeks of work and family things, I finally found the time to complete the project. The ACDIN results were inconsistent at first, but I etched a new board and instead of SMD components I used thru-hole. The new board worked perfect on the bench but failed on the car...until I realized I had used a NPN transistor instead of an PNP. Before I realized this I made a small relay board that the transistor would switch, which would then turn on the cooling fans. I salvaged the relay from an old TRS-80 motherboard that was ruined. Once the transistor was swapped out and the relay board added, everything worked perfect. We took some test runs, and the cooling fans turned on/off as expected. When the transistors were switched I also had to reverse the high/low settings on the relay outputs on my board. My personal blog (http://triton9.wordpress.com/) has a little more info. http://triton9.wordpress.com/
Thanks again to everyone for all the help!!
6079608060786081

Dave
- 23rd October 2011, 14:47
I specialy like the custom MicroChip enclosure.....

triton99
- 23rd October 2011, 19:52
Yeah...cant beat free!! I have a few of those sitting around gathering dust so it seemed like a perfect reason to get rid of one. First we cut a small rectangle in the top for the relay, then my friend drilled some holes for airflow.

Dave
- 24th October 2011, 11:39
It's even antistatic.....