View previous topic :: View next topic |
Author |
Message |
Chubbs
Joined: 02 May 2005 Posts: 14
|
ADC Trouble |
Posted: Mon May 02, 2005 11:41 pm |
|
|
Hi, this is the first time using a PIC so any help you can give will be appreciated.
I'm using the 16F872 and all I want to do at this stage is get an analog input from a smoke sensor and display it on an LCD.
I've got the LCD working ok, and am able to write to it.
Here is the code I am using.
Code: | #include "C:\My Documents\smoke project\Code\Detector.h"
#fuses NOWDT,HS, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
#include <LCD.C>
#include <stdlib.h>
#include <math.h>
void LCD_disp(void);
void get_val(void);
int16 value;
void main()
{
set_tris_a(0xFF);
setup_adc_ports( ALL_ANALOG );
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
lcd_init();
LCD_disp();
// Loop to constantly read the values and display to LCD //
while(TRUE)
{
delay_ms(100);
get_val();
}
}
void LCD_disp(void)
{
// display text on LCD //
lcd_gotoxy(1,1);
lcd_putc("Smoke:");
}
void get_val(void)
{
delay_us(10);
value = Read_ADC();
lcd_gotoxy(8,1);
printf(lcd_putc,"%Ld",value);
} |
The output I get displayed on the LCD from the conversion is 255 a short pause then it goes down to a low number(say 30) pauses a little then rushes back to 255 and keeps going. The output of the sensor constantly changes but basically stays around the same level.
I don't know what I'm doing wrong, I've tried changing the delays but nothing seems to work.
Also how would you get it to display the actual voltage readings?
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon May 02, 2005 11:57 pm |
|
|
I'd suggest that you first get it working with a trimpot (1K or 5K will work)
as the voltage source. Once you have that working, then try it with
your sensor. If, at that time, you can't get it to work, then post a
link to the data sheet for your smoke sensor. |
|
|
Chubbs
Joined: 02 May 2005 Posts: 14
|
|
Posted: Tue May 03, 2005 5:42 pm |
|
|
Using the same code, I put in a 5k trimpot and it worked fine no problems. I guess then the problem is with the input not the PIC. The following is the sensor URL:
http://www.nemoto.co.jp/product/02_sensor/f/nis-05a_e.html
It doesn't contain a datasheet but I am using it with the Allegro 5367:
http://www.allegromicro.com/datafile/5367.pdf
and the input to the PIC comes from pin 16 of this chip not the actual sensor as the sensor has a very high impedance. I have also tried to put the output through an op-amp to reduce the impedance but I don't think this is the problem. The output goes through a voltage divider anyway as it is originally above 5v.
The PIC can handle up to 10K can't it?
Also how would you calculate the actual voltage after the ADC?
Will keep trying I guess. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 03, 2005 8:19 pm |
|
|
Quote: | I am using it with the Allegro 5367,
and the input to the PIC comes from pin 16 of this chip not the
actual sensor as the sensor has a very high impedance. |
Pin 16 of the Allegro chip is a Guard pin. It's not an output.
It looks like you should be using the I/O pin, which is pin 2.
When no smoke is detected, the I/O pin appears to be a high-Z
input pin, based on my reading of the data sheet. When smoke
is present, the I/O pin goes to a 7.0v level after a short delay.
When the smoke goes away, the I/O pin goes to a 1.0v level
for about 2 seconds. Then it goes back to the high-Z state.
So this means that it's a digital output. However, because its
Voh level is always equal to Vdd - 2.0v, the Voh will start out
as 7.0v with a new battery and decay to about 5.0v with an
old battery.
Because the I/O pin is in a high-Z state when there's no alarm,
you need a pull-down resistor to bring it down to ground level
so your PIC can see that as a Logic zero. You'll also need
a series resistor that comes before the pull-down resistor,
because you need a voltage divider to reduce the 7.0v down
to 5.0v max, so you don't violate the PICs Vih spec.
So one way to do this, would be to use a 1K series resistor
coming out of the Allegro's I/O pin. Then after that, put
a 1K resistor to ground. Then connect the junction of
those two resistors to pin RB1 on your PIC. That pin has
TTL input levels. ie., Vil = 0.8v, and Vih = 2.0v.
The voltage divider reduces the voltage coming out of the I/O
pin by a factor of 0.5, so with a fresh 9v battery you'd get:
7v x 0.5 = 3.5v
With a weak battery (7.0v), you'd get:
5v x 0.5 = 2.5v
Both those levels (and anything in-between) will work as a Logic High
level for a TTL input, such as pin RB1, because its Vih is 2.0v.
When there's no smoke and the I/O pin on the Allegro is at a High-Z
level, the voltage divider simply becomes a 1K pull-down, as far
as the PIC is concerned.
During the 2 second "charge dump" period which occurs just after
smoke disappears, the Allegro puts out 1.0v. This will be reduced
to 0.5v by the voltage divider, which is below the 0.8v threshold
of the PIC's input pin.
According to the Allegro data sheet, it can source a minimum of 7.5ma
during an alarm condition (ie., when there is smoke present).
We want to make sure that our voltage divider is not going to load
down the output of the I/O pin and reduce its voltage. So with a
weak battery I/O voltage of 5.0v, the current used by the voltage
divider is:
5v / (1K + 1K) = 2.5ma
That's no problem. It's way below the 7.5ma available from the I/O pin.
There shouldn't be a problem in charge-dump mode either.
One more thought -- Looking at the data sheet, it shows an internal
pull-down resistor on the I/O pin. They don't say what the value is.
It doesn't really matter to us, because we've got have a voltage divider
(or some other method) in order to reduce the 7.0v I/O pin down to
TTL levels anyway.
There might be other methods of doing this, but making a voltage
divider with two 1K resistors and connecting it to a TTL-compatible
input on the PIC seems the simplest way to do it. |
|
|
Chubbs
Joined: 02 May 2005 Posts: 14
|
|
Posted: Tue May 03, 2005 9:29 pm |
|
|
I should have stated why I'm using pin 16. I want to display the output of the actual sensor, but I can't connect that directly as it has a very high impedance and will be greatly affected. The sensor input on the chip is a high impedance pin and can accept it without problems, however you still cannot take a connection from this pin to the PIC.
If you happened to see it on page 4 of the datasheet(under detector circuitry) the gaurd pins, both 14 and 16, are within 100mV of the input and basically the only way to measure the sensor voltage without overloading it. Pin 2 only changes when there is a transition from no alarm to an alarm stage and viceversa. I want to display the result at all times.
When I tried the sensor again I got the same result as last time the output would go from 0 to 255 and back to 0 and so forth, but when I removed the battery from the sensor circuit the output on the LCD continued to do this despite the fact that there was no voltage on the ADC input pin.
I know there is something wrong with the input I just don't know what. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 03, 2005 10:28 pm |
|
|
If that's what you want to do, then you should be using pin 14 of
the Allegro chip. The chip has two guard pins. Pin 16 has a 500K
output impedance. Pin 14 has a 10K output impedance (Typ).
These specs are on page 3 of the data sheet. |
|
|
Chubbs
Joined: 02 May 2005 Posts: 14
|
|
Posted: Tue May 03, 2005 11:04 pm |
|
|
Sounded like a good idea and i gave it a try but it also gave the same result. All I'm doing is going from pin 14 through a voltage divider then to the PIC, I can't figure it out. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 03, 2005 11:20 pm |
|
|
What are the resistor values in your voltage divider ? |
|
|
Chubbs
Joined: 02 May 2005 Posts: 14
|
|
Posted: Tue May 03, 2005 11:30 pm |
|
|
I used small values all under 1k.
910ohm and 390ohm. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 04, 2005 12:05 am |
|
|
At this point, I would try buffering the signal. I would use a single-supply
rail-to-rail opamp, such as the TLC2272, and wire it in voltage follower
configuration. This would tell you pretty quickly if the output impedance
of the Allegro chip and the voltage divider is the problem. |
|
|
JohnKennedy
Joined: 12 May 2004 Posts: 38
|
|
Posted: Wed May 04, 2005 2:25 am |
|
|
I tried to open the link to the sensor but for some reason it won't , anyway just one thought I had from previous experience of working with smoke detectors, is the output a DC level or not as the last one I worked with had a square wave output, this might explain the variance of the voltages measured. |
|
|
Chubbs
Joined: 02 May 2005 Posts: 14
|
|
Posted: Wed May 04, 2005 7:03 am |
|
|
I have already tried using an opamp in the voltage follower configuration. I am using the LMC6042, taking the output from the Allegro pin 14 through the buffer then through the voltage divider before connecting it to the PIC.
The sensor output is a DC voltage, the Allegro chip compares this voltage to a preset threshold. As the amount of smoke increases the sensor DC output decreases, when it becomes lower then the threshold the alarm souds.
The result I get goes from one extreme to another(0v-5v) constantly, regardless of the voltage going into the PIC.
By pressing the test button on the detector this forces the DC level that is being compared to the threshold to decrese until an alarm is sounded, thus checking if the detector is working.
Doing this has no effect on the ADC output it just continues as is.
The mystery continues................. |
|
|
Chubbs
Joined: 02 May 2005 Posts: 14
|
|
Posted: Wed May 04, 2005 8:52 pm |
|
|
Guess what the problem was??
I was running the PIC off a 5v power supply and was running the detector circuit off a 9v battery, so I had a ground from the battery and one from the supply. The voltage divider was grounded via the battery and input to the PIC that had ground from the power supply...floating ground...Not Good.
Anyway thanks for all your input and ideas, eventhough it was a stupid mistake on my behalf your thoughts opened my eyes to some other issues.
One last thing the output from the detector circuit jumps around a fair bit after the ADC. So if it is say 4v it may keep changing from 3v to 5v even if the actual output is rather steady. Any ideas on how I could settle the ADC output, I thought perhaps taking the average of say 20 samples and displyaing that.
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 04, 2005 9:52 pm |
|
|
Quote: |
One last thing the output from the detector circuit jumps around a fair bit
after the ADC. So if it is say 4v it may keep changing from 3v to 5v even
if the actual output is rather steady. Any ideas on how I could settle the
ADC output, I thought perhaps taking the average of say 20 samples and
displaying that. |
How are you determining that the Allegro chip puts out a steady value ?
Are you looking at it with an oscilloscope, or with a voltmeter ?
If you're using a voltmeter, you may not see a problem if there is one.
I think two things could be causing the problem. If you're not using
the opamp buffer anymore, then the output impedance of the Allegro
chip could cause problems. It's rated at 10K typical. That's right at
the limit of the recommended value. It might be higher.
I would try re-inserting the opamp voltage follower.
The 2nd thing is the A/D clock. You didn't say what your crystal
frequency is. I notice the PCW now hides the #fuses and the
#use delay() statement in a special little .H file. There's no good
reason for CCS to do this, in my opinion. Anyway, the data sheet
says that for best performance, you should not use the internal RC
clock for the A/D at crystal frequencies above 1 MHz, unless you
take the A/D reading while in Sleep mode. So it's much easier
to use one of the clock divider settings.
If your crystal frequency is in the range of 5.1 MHz to 20 MHz,
then use this:
setup_adc( ADC_CLOCK_DIV_32 );
If you're running at 4 MHz, then use:
setup_adc( ADC_CLOCK_DIV_8 );
There is a chart in the data sheet that shows the above settings. |
|
|
Guest
|
|
Posted: Sun May 08, 2005 5:54 pm |
|
|
I looked at the output through the oscilliscope and found a steady output.
I am using a 20 MHz frequency, I put in the:
setup_adc( ADC_CLOCK_DIV_32 );
The output now looks ok and is as expected.
Thanks for all your help. |
|
|
|