Sigh... from datasheet ..
page 113These steps should be followed for doing an A/D Conversion:
1. Configure the A/D module:
• Configure analog pins/voltage reference and digital I/O (ADCON1)
• Select A/D input channel (ADCON0)
• Select A/D conversion clock (ADCON0)
• Turn on A/D module (ADCON0)
^ this you do at the start of the program, before reading values, once it's initialized you don't have to turn it off and on again and mess with it
2. Configure A/D interrupt (if desired):
• Clear ADIF bit
• Set ADIE bit
• Set PEIE bit
• Set GIE bit
^ This you don't care about because you won't use interrupts3. Wait the required acquisition time.
^ The datasheet lists a formula a page or so below this text where it says the acquisition time is about 20 uS. So after initializing the adc and before first conversion, and then between every conversion, your program needs to wait about 20 us for the controller to be "ready" to do the actual conversion4. Start conversion:
• Set GO/DONE bit (ADCON0)
^ Self explanatory 5. Wait for A/D conversion to complete, by either:
• Polling for the GO/DONE bit to be cleared (with interrupts enabled); OR
• Waiting for the A/D interrupt
^ Instead of waiting with that while loop, you can do some math here, this is going to take just a few uS. The conversion goes separately and you know it's done when that bit is cleared so even if you do some math the result is going to be in those ADRESH and ADRESL after a few moments when you're done6. Read A/D result register pair (ADRESH:ADRESL), clear bit ADIF if required.
^ put the value in a variable 7. For the next conversion, go to step 1 or step 2, as required. The A/D conversion time
per bit is defined as Tad.
A minimum wait of 2Tad is required before the next acquisition starts.
This basically says you can't just do something like this for ( i =1; i<=100; i++) { results=read_adc(); }
The adc becomes "unavailable" for a few us after the conversion is done and the bit is cleared and the result is stored and waiting for you. Then you also have the acquisition time of about 20us.
One Tad for this pic16 controller is at least 1.6us, but it depends on how you set the AD clock - in your case it will actually be more like 2us.
page 114, note 4
4: After a conversion has completed, a 2.0TAD delay must complete before acquisition can begin again.
During this time, the holding capacitor is not connected to the selected A/D input channel.
Further on the next pages it says (page 115):
11.2 Selecting the A/D Conversion Clock
The A/D conversion time per bit is defined as TAD. The A/D conversion requires a minimum 12TAD per 10-bit conversion. The source of the A/D conversion clock is software selected. The four possible options for TAD are:
• 2TOSC
• 8TOSC
• 32TOSC
• Internal A/D module RC oscillator (2-6 ?s)
For correct A/D conversions, the A/D conversion clock (TAD) must be selected to ensure a minimum TAD time of 1.6 us.
and I'm going to quote something I saved a while ago:
Due to the settling times and bandwidths of the analog components involved, each comparison step takes a certain minimum amount of time and the operation is controlled by the A/D clock and it is important that this time per bit (Tad) not be less than a critical minimum otherwise these steps will fail to settle correctly and the A/D resolution will be impaired.
In the case of the 16F877, Tad is a minimum of 1.6us and although it is a 10 bit A/D, it actually takes 12 of these bit times as a couple of additional clocks are used for set up and data transfer.
Theoretically the A/D clock source could come from anywhere but since the PIC already has a master clock oscillator for the processor, it is convenient to use a submultiple of that or an onboard RC clock and the choices provided in the ADCON0 register are 2Tosc, 8Tosc, 32Tosc or RC.
If you are operating with an 8MHz clock, then Tosc = 0.125us so you will need a multiple of at least 12.8 ( the minimum 1.6us / 0.125us). If you wish to use the processor clock, you would have to choose the 32Tosc option as 8Tosc & 2Tosc would be too fast. 32Tosc will result in a Tad of 32x0.125 = 4us and a total A/D conversion time (the time from starting the A/D to getting a result) of 12 x 4 = 48us.
You could also choose the internal RC clock, but at 4uS typical, it would be about the same 48us conversion time.
In addition to the A/D conversion time, there is an analog input settling time (referred to in the data sheet as acquisition time). It is controlled by the source resistance and the A/D input capacitance (see Example 11-1 in the data sheet) and can easily add another 12-20us to the conversion time.
The two times (acquisition + conversion) would then be the total time required after applying a new analog input voltage, waiting for the input to settle, commanding the A/D to start, waiting for it to convert and ending up with a 10 bit result (possibly 60-70us total).
He did the math for a 8 Mhz clock. At 16 Mhz, you're still going to have to set the ADC for 32Tosc but Tad will actually be half of that, 2us, which is ok because it's higher than 1.6us. And since the conversion needs 12 x Tad to convert, you're looking at 24us instead of the 48us he determined.
So for 16 Mhz, you have:
Tad = ~ 2 us
Taquisition = ~ 20 us
Tconversion = 12 Tad = ~ 24 us
pause between conversions = 2 Tad = ~ 4 us
and you have in the loop :
wait ~ 20 uS for aquisition or so something in this time
set the bit to go so that conversion will start ... from this point, the conversion takes about 12 Tad = 24 us so in the meantime you can do something. Results will go automatically in those registers and bit cleared when done
wait 2Tad (about 4 us) between conversions because the adc is not available
go back to waiting 20us before you can request another conversion, first line in loop
If however you treat the first conversion as a "special case", you can change the loop to something like this:
// initialize adc here, set the clock to 32 Tosc, turn it on
value = -1; // this stores the adc result
i = 0;
delay_us(25); // wait at least 25 us, the aquisition time
while (1=1) {
adc.go = 1; // start the conversion process, this is gonna run separately for at least 24us or so, then it's gonna need 2xTad to be ready for next conversion so do some stuffstuff
if (value!==-1) {
v_square = value * value; // this is gonna take about 150-200 cycles, at 16 Mhz that's about 4 cycles per us so about 40 us (varies from compiler to compiler how it optimizes it). by the time this multiplication is done the conversion should be ready
v_sum = v_sum + v_square; // about half a us
i++ ; increment the number of readings
}
while (adc.go==1) { }; // just in case we finished faster than the conversion or it's the first time in loop so the if never executed, wait until conversion is done
value = 0 to 1023; // adresshi (two bits ) + addresslo (8 bits ) <- this is not correct but you get the point, put the value from those 2 registers in the variable "value", to be used in next iteration
// now you're ready to do another reading but you need to give it time, those 2Tad and the aquisition so try to do more stuff here instead of just freezing the controller with a delay_us().
// between the moment the adc generated result and next measurement, the adc needs that 2 x Tad + Tacquisition, about 20us + 2xTad (2x2us) .. about 24us
// the multiplication alone above in the if may have taken 40us or more but we can't be sure it was more than this Tacquisition + 2xTad + 12 Tad (actual conversion time) = 20 + 4 + 24 = 68us that's required for the whole process. If you do your own multiplication routing, you'd no exactly how many cycles would be used, therefore how many us would take to multiply, then use a lower delay value.
// so wait some more
delay_us(30); // 30 us should be a safe value
if (i>1000) { // or whatever amount of values you think it's suitable
// divide the v_sum to i
// print to lcd
i = 0;
} // this if should take about 100us but it's only done when sending to lcd, not every time, you don't update the lcd 1000 times a second, the lcd is not that fast.. maybe 10 times a second is even too much
}
This will get a reading every 60-80us or so, or about 8-10 readings a ms ... that should be enough.