![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
engrmunir786
Joined: 25 Jul 2012 Posts: 20
|
PIC16F877 ADC value is fluctuating on lcd. |
Posted: Wed Jul 25, 2012 10:56 pm |
|
|
Dear experts
My adc value is fluctuating on lcd. Flex_lcd.c is sub function file, if you want this file then I also send this file. This program is working fine in Proteus but when I compile it with real hardware then the adc value is not stable on lcd.
I can also share hardware. It is so simple. I have connected a 10k variable resistor with one side is +5v and other side is ground and center pin is connected with analog input. I also connect 104pf and 10uf/16v capacitor at that pin and i also connect 10pf and 100uf/16v capacitor at main +5v supply. I am using computer power supply for +5v.
I have changed different code tricks but result is not stable on lcd. I have also changed adc clock to internal but result is same. Can anybody tell me that there is error in my code or the error in hardware ? Is there any concept that adc must be read after a specific time ? I mean that must I read adc after 10ms exact interval, or can I read adc at any time ? Please help me out to solve this problem.
Code: |
#include <16f877.h>
#device adc=8
#fuses HS, NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,PUT
#use delay(clock = 16000000)
#byte PORTA = 0x05
#byte PORTB = 0x06
#byte PORTC = 0x07
#byte PORTD = 0x06
#byte TRISA = 0x85
#byte TRISB = 0x86
#byte TRISC = 0x87
#byte TRISD = 0x88
#include <flex_lcd.c>
void CPU_SETUP(void);
void read_bvolt(void);
unsigned int adc_value;
unsigned int volts;
void main()
{
CPU_SETUP();
lcd_init();
delay_ms(100);
while(1)
{
read_bvolt();
delay_us(128);
delay_ms(9); //total 10ms delay
delay_ms(490);
}
}
void CPU_SETUP()
{
setup_ccp1(CCP_OFF); // not use comparator module
setup_ccp2(CCP_OFF); // not use comparator module
setup_adc_ports( All_ANALOG );
setup_adc(ADC_CLOCK_32);
TRISA=0b00111111;
TRISB=0b00000000;
TRISC=0b11111111;
TRISD=0b00000000;
}
void read_bvolt()
{
set_adc_channel(0);
delay_us(30);
adc_value=read_adc();
lcd_gotoxy(1,2);
Printf(lcd_putC,"%u.%uV ",adc_value/10,adc_value%10);
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Thu Jul 26, 2012 1:53 am |
|
|
ADC_CLOCK_INTERNAL, is _not_ legal if your clock rate is above 1MHz, unless you put the processor to sleep for the reading. Will make things _worse_.
Your problem is noise.
I'd say your computer supply, has not got enough load, and is oscillating. Generally the main supplies on computers have a _minimum_ load required of something perhaps around 5% of their maximum. So a 500W PC supply, will _require_ a load of perhaps 25W, before it can regulate.....
On timings, _read the data sheet_...
There is no 10mSec figure _anywhere_ associated with the ADC.
There is a 10_u_Sec requirement, between selecting a signal, and reading it, or between successive readings.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
engrmunir786
Joined: 25 Jul 2012 Posts: 20
|
|
Posted: Thu Jul 26, 2012 2:10 am |
|
|
Thanks Ttelmah
Today I will change power supply with battery. And I will checked my circuit with battery power and then reply you. In your opinion my code is ok there is no error. Thanks for your reply. |
|
![](templates/subSilver/images/spacer.gif) |
engrmunir786
Joined: 25 Jul 2012 Posts: 20
|
|
Posted: Thu Jul 26, 2012 9:46 pm |
|
|
Dear Ttelmah
I have replaced my computer power supply with battery source and now my program is working 100% fine. Now adc value is not fluctuating even after decimal point. Can you tell me is it necessary to read every channel at after same time. I mean, I read channel (0) and it takes total processing time including delays are 10 Mili Second. Is this necessary to read this channel every time after 10 Mili Second ? What is the best programming approach to start any new program and what are the things which must be considered to start a new program and what are the recommended fuse settings for efficient running of a program in real hardware? Means no hanging problem appear in program etc. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Fri Jul 27, 2012 2:21 am |
|
|
As I said before, there is no '10mSec' figure anywhere associated with the ADC. 10_u_Sec.
The basic sequence is:
1) Select a channel
2) Wait for Tacq. This varies between chips, typically 10uSec on older chips (though there are a couple where it is nearly 20uSec), and can be as little at 2.5uSec on some of the newer chips. This basically allows the internal capacitor to charge up through the resistances of the input multiplexer etc.. For your chip, it is actually just under 5uSec.
3) Trigger the conversion.
4) Wait for conversion to complete.
5) Take a reading. - read_adc, if used in it's 'default' mode, performs 3,4,5 automatically one after the other
Total time for this is 11*Tad. With your 16MHz clock, and clock/32 selected, this takes 22uSec.
Then loop back to '1' to read another channel, or '2' to read the same channel.
It takes perhaps 10 processor clock cycles to actually transfer the reading from the ADC, so at your 16MHz, perhaps 2.5uSec, and allow the same again for other slight delays (takes a moment to 'see' that the conversion has finished for example). So you could potentially read every 5+22+2.5+2.5 = 32uSec = about 31250 times per second.
Now, you don't need to reselect the ADC channel each time you read it. If you are only reading one channel, select this early on in the code, and leave it selected.
Then note that you need 5uSec, between successive readings, but this doesn't have to be a 'delay'. If it takes 30uSec (say) to display your value to the ADC, then the Tacq delay has already been met.
The LCD is your slowest thing here. Most only update about 50* per second, so sending values to it faster than this won't gain anything.
Then use the inbuilt display functions:
printf(lcd_putc,"%2.1w ",adc_value);
will output the value with the decimal point added, without fiddling around using the modulus operator (which is a slow function...).
You can read the ADC as infrequently or frequently (within the limitations of Tacq), as you want. You would take one reading per minute, or 20000 per second if you wish.
On fuses, if there was a magic setting, these wouldn't exist. They depend totally on your hardware, allowing you to change the chip's behaviour to suit different clocks, different code designs, etc. etc... As you have seen already, little things _will_ 'creep out of the woodwork' with any design to catch you (minimum PSU load requirement), but this is where data is your friend. PC supplies are designed to run PC's, so don't bother to list minimum load requirements, provided they are less than the likely minimum for any PC. However industrial versions of similar supplies will all have a data sheet specifying load limits etc. etc..
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9176 Location: Greensville,Ontario
|
|
Posted: Fri Jul 27, 2012 5:54 am |
|
|
When and how often you read the ADC is dependent on the application. Consider a 'battery test' program. Simple coin cell battery hooked up to a 'dummy load' and read the battery voltage. Under a light load it'll take hours(or days) to drain the battery so reading the ADC once every second is not required as thousands of readings will be the same. However if the application is a 'solar cell tracking' device, then sampling at a faster rate is important to gain useful information.
These sampling rates are either learned from hands on experience, R&D, or a 'gut' feeling.
As for 'fuses'...when I use a new PIC, I create a project_name_fuses.h header file with all the fuses in it, grouped according to purpose (clock, memory, startup, etc.). First, it's a 'common' file with a known good set of fuses for that type of PIC and simple to insert into future projects that have the same PIC. Second, it gets rid of a page full of 'fuses' from the main program! Newer PICs like the 18F4550 have dozens of fuses and 'main' gets 'cluttered' with them. Having one line (the include...fuses.h) makes it simpler and easier to follow.
I do the same for the I/O pin functions as well. A project_PICtype_pin_defines.h header file. Every I/O pin of the PIC is #defined..allowing for rapid 'copy/paste/redefine' for different projects.
Again it 'cleans up' the main program. Also, you can easily printout the 'pin_defines' page to check the hardware wiring.
hth
jay |
|
![](templates/subSilver/images/spacer.gif) |
engrmunir786
Joined: 25 Jul 2012 Posts: 20
|
|
Posted: Sun Jul 29, 2012 11:57 pm |
|
|
Dear Ttelmah
Thank you so much for your detailed response. Can you tell me what is the best programming sequence in which any program never hangs up ? I mean program run continuously without any error. What is the best programming techniques to start a new project ? |
|
![](templates/subSilver/images/spacer.gif) |
bkamen
Joined: 07 Jan 2004 Posts: 1611 Location: Central Illinois, USA
|
|
Posted: Mon Jul 30, 2012 11:21 am |
|
|
temtronic wrote: |
As for 'fuses'...when I use a new PIC, I create a project_name_fuses.h header file with all the fuses in it, grouped according to purpose (clock, memory, startup, etc.). First, it's a 'common' file with a known good set of fuses for that type of PIC and simple to insert into future projects that have the same PIC. Second, it gets rid of a page full of 'fuses' from the main program! Newer PICs like the 18F4550 have dozens of fuses and 'main' gets 'cluttered' with them. Having one line (the include...fuses.h) makes it simpler and easier to follow.
I do the same for the I/O pin functions as well. A project_PICtype_pin_defines.h header file. Every I/O pin of the PIC is #defined..allowing for rapid 'copy/paste/redefine' for different projects.
Again it 'cleans up' the main program. Also, you can easily printout the 'pin_defines' page to check the hardware wiring.
|
I do something similar. I usually have a "projectname.h" that accompanies the top project 'C' file.
In it - I have
All the #fuses
Definitions for all IO ports (*ALL* of them so I can take care of pins that aren't used to make them outputs and set them to 0)
And any other items I don't want to clutter up the main .C file.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19375
|
|
Posted: Mon Jul 30, 2012 1:22 pm |
|
|
No program will ever run 100% without error.
For high reliability applications, you use special processors, where every possible state has been tested. These are perhaps four generations 'behind' the processors in general use, because of the difficulty of such testing.
Even with this, they can still fail, if an atomic particle or a cosmic ray hits a memory cell, so you then add physical shielding, checksum's on data, and watchdog protection to verify that code is going where it is meant to go.
Then you triplicate the code, with the three sets working from the same design brief, but each written by different teams, and implement 'voting' between the three results.
At this point you get to something like 99.9999999% reliability possible.
However the first step, using conventional processors, is just careful checking of every possible data source and target, so you implement bounds checking on every write, and limit checking on all incoming data. Again checksum the stored values, etc. etc.. Working like this you can get systems that perform reliably for years. I still have some stuff built using the very first PIC16C84, that have 100% date records - no 'off-time' at all in twenty years. Funny thing is that some of these were built a year before Microchip say they made the chip, and they involved a real time clock, which didn't have any 'year 2000' problems at all!.....
A system I designed using FPGA's, and the latest Zilog chip at about the same time, was just retired last year, and it's replacement had problems within a week (another grin.....). This even had hamming code on the data storage, implemented in hardware.
Real reliability means thinking about _every_ step in the hardware and software. Unfortunately, though PIC's are very cheap, I'd not rate most of the newer chip's in particular as being suitable for a high reliability application, if their function was critical....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
engrmunir786
Joined: 25 Jul 2012 Posts: 20
|
|
Posted: Tue Jul 31, 2012 10:07 pm |
|
|
Dear Ttelmah
Thanks again for your detail response. Can you tell me your skype id. I want to add you on skype, if you have no problem. Do you have any sample program of PIC MICROCONTROLLER in which all these things are considered in programming then I can get idea that what is the best programming approach. I will send you my recent lcd program. If you have time then check my program and tell me that is it ok programming technique or not. Can you tell me your email address. I will send it on your email address. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|