View previous topic :: View next topic |
Author |
Message |
dxdxdx
Joined: 05 Jan 2011 Posts: 10
|
pic16f877a adc help |
Posted: Wed Jan 05, 2011 9:48 am |
|
|
hi all, I'm new to pic. Currently I'm having an assignment to read an analog input (0~5V) at pin A0, so that different led light will be on for different case.
I need to separate the input into 5 case:
case 1: 0-1V = pin B0 on
case 2: 1-2V = pin B1 on
case 3: 2-3V = pin B2 on
case 4: 3-4V = pin B3 on
case 5: 4-5V = pin B4 on
I have tested with a simulator, but it is only pin B0 on, no matter what value I set as A0 input voltage. Please help me out with this, please point out my mistake I have made and make correction. Thanks alot.
Below is my code:
Code: |
#include <16F877.h>
#device adc=8
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=2000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)
void main(void)
{
long value;
set_tris_b(0b00000000);
setup_adc_ports( RA0_ANALOG );
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel( 0 );
delay_us(10);
while( TRUE )
{
value=read_adc();
read_adc(ADC_START_ONLY);
value=read_adc(ADC_READ_ONLY);
if(0<value<=1)
{
output_high(PIN_B0);
}
else
{
if(1<value<=2)
{
output_high(PIN_B1);
}
else
{
if(2<value<=3)
{
output_high(PIN_B2);
}
else
{
if(3<value<=4)
{
output_high(PIN_B3);
}
else
{
output_high(PIN_B4);
}
}
}
}
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Wed Jan 05, 2011 10:15 am |
|
|
Couple of things. The A/D converter returns a number, not a voltage. Since your converter is set to 8 bits, there are 256 different numbers possible from the A/D converter, which are in the range 0 - 255. The number you get depends on "how far up the ladder" your input voltage falls compared to the high and low reference voltages that the A/D converter uses. [Read more about the references and how to set up the A/D converter by the way.]
For an A/D converter that's been set up with a low reference voltage of Vss (0V) and a high reference of Vcc (I'll assume is 5V), and is in 8 bit mode, a 1V input will result in an A/D output number of:
Code: | 1V (input to A/D) / (5V - 0V) = 0.2 (5V - 0V) is the difference between the high and low reference voltages
0.2 * 255 (max number the A/D will output) = 51. |
Second, your tests aren't valid C. Do this instead:
Code: | if (value < 51) {
output_high(PIN_B0);
// you'll also have to output_low all the other pins to turn them off here
}
else if (value < 102) {
output_high(PIN_B1);
// see comment above about turning every other pin off
}
else if ... // hopefully you get the point |
|
|
![](templates/subSilver/images/spacer.gif) |
dxdxdx
Joined: 05 Jan 2011 Posts: 10
|
|
Posted: Wed Jan 05, 2011 10:44 am |
|
|
Hello newguy, thanks for replying. Now I have changed my code into this.
But it is still the same, the led is not on even if I set different input value.
Here is the print screen of my simulator:
Code: |
#include <16F877.h>
#device adc=8
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=2000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)
void main(void)
{
long value;
set_tris_b(0b00000000);
setup_adc_ports( RA0_ANALOG );
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel( 0 );
delay_us(10);
while( TRUE )
{
value=read_adc();
read_adc(ADC_START_ONLY);
value=read_adc(ADC_READ_ONLY);
if(0<value<=51)
{
output_high(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_B3);
output_low(PIN_B4);
}
else
{
if(value<=102)
{
output_high(PIN_B1);
output_low(PIN_B0);
output_low(PIN_B2);
output_low(PIN_B3);
output_low(PIN_B4);
}
else
{
if(value<=153)
{
output_high(PIN_B2);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B3);
output_low(PIN_B4);
}
else
{
if(value<=204)
{
output_high(PIN_B3);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_B4);
}
else
{
output_high(PIN_B4);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_B3);
}
}
}
}
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Wed Jan 05, 2011 11:17 am |
|
|
Once again - read the manual entry for "setup_adc()" and "setup_adc_ports()". Open "16F877.h" and look for the A/D converter section. Read it. Consult the datasheet for the 16F877 too.
And again,
Code: | if (0 < value <= 51) {
...
} |
isn't valid C syntax.
Finally, don't trust a simulator. Ever |
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Wed Jan 05, 2011 11:51 am |
|
|
One of the first things to learn to do troubleshooting things is to have "test points" in the middle so you can check the intermediate results and figure out where things went wrong. In this case, try watching the output from the ADC and verify it is changing as the input changes as expected. Make sure it is in the range you expect - trying to fix the following code won't work if the input to the code is not valid. Make sure you have the ADC set up correctly and the values read by it are correct first then move on to the next part of the code.
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
demonspells
Joined: 06 Jan 2011 Posts: 26
|
|
Posted: Thu Jan 06, 2011 8:10 am |
|
|
Check your clock delay, it says 2000000, if you're using a 20MHz crystal, you have to fix it. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9172 Location: Greensville,Ontario
|
|
Posted: Thu Jan 06, 2011 8:16 am |
|
|
Also, whenever you include 'use rs232(...) be sure to add the 'errors' option ! |
|
![](templates/subSilver/images/spacer.gif) |
Rosmaninho
Joined: 16 Jan 2011 Posts: 23
|
|
Posted: Sun Jan 16, 2011 4:08 pm |
|
|
Hi, I'm new here, I have two questions, can you help me?
- In this code, at the beginning have #use rs232, we only need this if we use serial communications? It's correct?
- I'm using a 16F876. I have one bug in my configuration, I define Rb has output, but I can't set pin Rb3 high. I read the manual. I have to do something, but I don't know what.
Basic, my project is, had temperature in LM35, connect to ADC port. Then had the result to a display, or 2 Seven Segments LEDs or LCD. I want to control an extra output relay to control an heater.
Regards |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 16, 2011 9:03 pm |
|
|
Quote: | but I can't set pin Rb3 high.
|
Then make a test program where you only try to do one thing:
Set pin B3 high. Example:
Code: |
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
//==========================================
void main()
{
output_high(PIN_B3);
while(1);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Rosmaninho
Joined: 16 Jan 2011 Posts: 23
|
|
Posted: Mon Jan 17, 2011 4:54 am |
|
|
I will try later, but i guess it don't work...
The pin RB3, Also have the function PGM, the manual says:
"Low Voltage ICSP Programming (LVP) is enabled by default, which disables the RB3 I/O function. LVP
must be disabled to enable RB3 as an I/O pin and allow maximum compatibility to the other 28-pin and
40-pin mid-range devices."
so, i have to disable LVP, but I don't know how to do.... |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19365
|
|
Posted: Mon Jan 17, 2011 9:02 am |
|
|
You already are.
NOLVP in the fuses....
What you need to check is that your programmer is actually writing these. read back the fuses from a chip you have programmed.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Rosmaninho
Joined: 16 Jan 2011 Posts: 23
|
|
Posted: Mon Jan 17, 2011 9:54 am |
|
|
Sorry... i'm new in pic programmer
In my program i don't have the order.... NOLVP
I'll try again, nut, i guess it works properly
Later i tell you ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Mon Jan 17, 2011 11:36 am |
|
|
What programmer are you using to program your parts?
Does it verify the "burned" part after programming ?
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
Rosmaninho
Joined: 16 Jan 2011 Posts: 23
|
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Mon Jan 17, 2011 12:38 pm |
|
|
OK, it looks like it will verify the programming as well as allow you to view the fuses (with the "Fuses" button in the screenshot).
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
|