PICs: ADC is a "Tad" difficult - Page 1
Forum section: electronics / general

author: PerranOak
author_rank: Frequent Contributor
timestamp: May 31, 2018, 03:51:26 pm
content: In the 16F1827 datasheet it says:"The time to complete one bit conversion is defined as TAD."It talks about the time the PIC needs to make the conversion and that you must give it this time to work properly: it tells you how to calculate this.However, it also gives a piece of sample code to get you started (extract):BSF ADCON0,GOBTFSC ADCON0,GOGOTO $-1Surely, this code will not be exited until the "GO" bit that tells you the conversion has ended has been cleared. Therefore, why do you need to know what the TADis?Also, someone told me that the capacitor in the ADC unit needs time to charge so you need code like this:CALL chrgtime ;a delay of a few micro-secondsBSF ADCON0,GOI can't really see why as the PIC will be doingsomethingbefore the ADC is "GO" so what difference does it make if it's engaged in a delay routine?Thank you.

author: mikerj
author_rank: Super Contributor
timestamp: May 31, 2018, 05:09:01 pm
content: You need to know TADbecause the ADC conversion clock is derived from the main system oscillator Fosc via a programmable divider (or the internal RC oscillator can be used). You therefore need to set the divider correctly to ensure TADlies within a suitable range. If you get this wrong, performance of the ADC will be degraded.By the way you are posting in the wrong forum for microcontroller related topics, use the "Microcontroller and FPGA" sub-forum.

author: Simon
author_rank: Unknown
timestamp: May 31, 2018, 06:05:20 pm
content: I have moved the topic.The ADC typically works at a lower frequency than the CPU, as stated above you need to get the divider right. It may interest you to know how long the conversion will take. No I'm not sure why you need "cap charge" code. The cap will not see the input until you start a conversion. I am not familiar with PIC but on AVR the first 1.5 clock cycles is spent charging the cap.Given that the CPU may be executing code at a much higher frequency than the ADC it is feasible to tell the ADC to get goinc and then go do something else and an interrupt tells you the conversion is over so you can go back to collect your result.On AVR the ADC runs between 50 and 200KHz far slower than the 16+MHz of the CPU.

author: fourtytwo42
author_rank: Super Contributor
timestamp: May 31, 2018, 06:12:55 pm
content: Quote from: PerranOak on May 31, 2018, 03:51:26 pmThat is called the acquisition time and it depends on the source impedance (ensure its in specification). You only need to worry about this if you are using multiple channels as it applies from the time of changing the channel to when you start the conversion. The PIC has a means of programming this so that it happens automagically

author: PerranOak
author_rank: Frequent Contributor
timestamp: May 31, 2018, 07:15:06 pm
content: Thank you for the replies.Sorry, I posted it in “Beginners” as I am a beginner (this is literally my first project not "out-of-a-book") and I thought it was probably a “numpty” question.Mikerj:By “suitable range” you mean for the parameters of a particular project, e.g. that you are not trying to convert it too quickly?Simon:I may have misunderstood the cap charge situation.I see, the “do something else” scenario means you need to know the conversion time, thanks.Fourtytwo42:Do you mean that you never need to have a built-in delay because the PIC does it “automagically”? (I like that word)

author: Simon
author_rank: Unknown
timestamp: May 31, 2018, 07:23:09 pm
content: The ADC runs at KHz, the main clock can be a few hundred KHz up to 10's of MHz. You need to divide down the main clock frequency to the frequency required by the ADC. The pin could be a digital I/O and then be switched to analogue. The ADC has nothing to do with the pin until you start a conversion, the first clock or two is spent charging the sample and hold cap. So if you clock the ADC too fast it might not charge the cap to the full input value. If you run too slow the cap starts to discharge due to natural leakage so the conversion can be incorrect.

author: JPortici
author_rank: Super Contributor
timestamp: May 31, 2018, 08:45:06 pm
content: Quote from: PerranOak on May 31, 2018, 07:15:06 pmNo.When you are not converting, the sampling capacitor is connected to the analog input selected by [...] (i don't remember which register is in your particular pic that selects the current analog input)when you set the "GO" bit the sampling capacitor is disconnected from the selected analog input and is connected to the rest of the ADC circuitry, for the number of TAD that it takes to complete the conversion.The number of TADs that it takes to convert a value is fixed, while the value of TAD is not. TAD can be derived from the system clock (and must not exceed some value, tipically 1us in PIC16) or can be derived from a dedicated oscillator.The sampling capacitor is a capacitor, so it needs to be charged to the input voltage. The best way to do so is by connecting a low impedance source to the analog pin (for example an opamp used as buffer with a small resistor in series).The datasheet specifies a maximum recommended source impedance. if you exceed this two things may/will happen: The time to charge the capacitor is too big, you need to spend a lot of time on sampling the input, or the source impedance is too high and the parasitic currents inside the ADC input will affect the voltage, this is what he means by degradating the performance of the ADC.knowing the source impedance, you can use the ADC input model to calculate an estimate of how much time you have to spend on sampling an input. And that's why you call the sampling delay, to charge the sampling capacitor.On more recent and more evolved PICs you have the possibility to perform auto-sampling/auto converting (by using one timer to initiate the conversion, or by a dedicated timer in the ADC.. in which case the sampling time is STILL expressed as a number of TADs so Tsample + Tconvert = Tconversion -> then you have the sampling frequency of your ADC.On more recent and more evolved PICs you can even have the possibility to SCAN the analog inputs, that's it: when channels are enabled for scan, the ADC acquire from channel A, then converts channel A and puts the result in the first location of a buffer. Then samples/convert channel B and puts it in the second location of the buffer. Then channel C and so on, then it restarts from channel A. The only thing you need to do is to take the data from the buffer before it gets overwritten

author: cv007
author_rank: Frequent Contributor
timestamp: June 01, 2018, 12:19:14 am
content: a simple summary-Datasheet-table 16.1find your Fosc columnchoose a Fosc/x row that is in white, which is what you use for your adc clock source(or just use Frc as adc clock source if speed not needed)16.2.6 a/d conversion procedurestep 2a-> adc conversion clock -> see table 16.1step 4-> see 16.416.4 a/d acquisition requirementsneeded after input channel selected or changedexample shows about 4-5usnew adc channel = need acquisition time to get charge cap happyadc conversion = need conversion clock selected that gets tad >= 1us (choosing frc as adc clock always ok)

author: mikerj
author_rank: Super Contributor
timestamp: June 01, 2018, 08:20:34 am
content: Quote from: PerranOak on May 31, 2018, 07:15:06 pmNo, I mean the range specified in the datasheet. Tad is determined by the ADC design, it is the same whatever your project. The issue here is that the ADC doesn't know what your main clock frequency is, since you this is by selection of crystal/resonator or internal RC. You therefore need to select the correct divider for your clock frequency to ensure that Tad meets the datasheet specifications.

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 01, 2018, 02:12:52 pm
content: Thank you all so very much, this is great!I think that I was confusing and conflating some of the principles. Let me try to summarise my understanding.The capacitor is disconnected from the analogue input when theGObit is set and this is when it takes (in my case, using the 16F1827) 11.5 * TADto make the conversion. At the end, presumably, the capacitor is reconnected to the analogue input and sits there waiting for the nextGOsetting?The value of TADis given in the datasheet based on FOSCand the “conversion clock select” bits (ADCS). In my case this is FOSCof 4MHz,ADCSof FOSC/8 so the table in the datasheet gives TADof 2.0us. This means that conversion will take 23us. I can vary this within the parameters set in the datasheet but if I go outside the recommendations then the conversion could be unpredictable. It seems that, in my case, 1us<= TAD<=8us.I need this figure of 23us if I intend to “do other stuff” while the conversion is happening and I must not try to use the reading until the 23us is up. However, if I simply wait in a simple loop for theGObit the be cleared by the ADC then I can safely proceed. FRCcan be used as a catchall that will always work (in relation to TADrequirements) but is this an external oscillator: I only use the internal one just now?The sampling delay (acquisition time TACQ) is entirely separate from the TADand is to do with the sampling capacitor having the correct amount of time to charge to the analogue input voltage. If the analogue input impedance is too high then the capacitor may not charge/discharge entirely to the analogue input voltage (classic RC circuit situation?); there is no lower limit? The datasheet has an equation to derive the TACQand in the example given TACQis 4.42us: I assume that this is a “typical” sort of time?A delay of at least TACQis needed on changing channels before taking a reading. Even when using only one channel, presumably, the delay is needed after setting theADONbit and before starting the first conversion? As the capacitor is reconnected to the analogue input immediately after a conversion, presumably, a delay of at least TACQmust be observed before the next reading for the capacitor to charge to the “new” voltage? This delay may be a “delay routine” or it may simply happen as part of the main programme?My “analogue input voltage” is from an LM35 and so I think that its impedance is not an applicable concept here. How can I determine the TACQrequired for such a device?Thank you all again.

author: JPortici
author_rank: Super Contributor
timestamp: June 01, 2018, 03:25:37 pm
content: Quote from: PerranOak on June 01, 2018, 02:12:52 pmCorrect.QuoteCorrectQuoteWell, the FRC is a dedicated oscillator for the ADC and as you can probably see from the datasheet it doesn't have a well defined period, since it can span a range of several microseconds (1 to 6 in your case). I would say use it if you don't have requirements for the sample rate.Quotecorrect, except for the last bit. TACQ is calculated using the analog input model. Did you take a look at EQUATION 16-1 and FIGURE 16-4 (datasheet DS41391D) ? i think they are almost self explanatory. The quation is commented and explain on HOW to calculate TACQ, the figure is the analog input model with typical values and curves for the various elements (switches resistance, parasitics, sample capacitor)Quoteas you are acquiring from only one channel, you don't need to care about that.How to calculate TACQ: you have to know the output impedance of the LM35, then apply equation 16-1.Or go by trial and error..Or maybe you could use a timer interrupt: if you implement a systick of some sort (like, a timer that fires an interrupt at a fixed rate such as 1ms-10ms) you could set a flag "checkADC", in the main loop if the checkADC flag is set, get the value from the ADC and start a new conversion.The idea is that this flag is set at a rate so that the sampling and converting requirets are met. You start the conversion, the converter converts and then start sampling until the next cycle.

author: StillTrying
author_rank: Super Contributor
timestamp: June 01, 2018, 05:20:53 pm
content: Quote from: PerranOak on June 01, 2018, 02:12:52 pmAssuming the LM35's output impedance is 0 compared with all the other junk already in the formula, I make the TACQ 2.5us. Page 149http://ww1.microchip.com/downloads/en/DeviceDoc/41391D.pdfOne other thing you can do while waiting for an ADC conversion to complete is to read and save the previous ADC result!

author: mikerj
author_rank: Super Contributor
timestamp: June 04, 2018, 09:13:07 am
content: Quote from: StillTrying on June 01, 2018, 05:20:53 pm:yes: This facility is often ignored, and CPU cycles wasted whilst the ADC completes. At the higher clock rates there can be enough cycles to perform filtering functions between samples (if multiplies and divides are avoided).

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 04, 2018, 04:46:31 pm
content: Fantastic. Thank you for taking the time to reply in such great detail JPortici.StillTrying: Right, thank you.mikerj: I see, the ADC is completely separate and so doing other things will not affect it … unless you're silly and alter its parameter.

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 05, 2018, 01:40:46 pm
content: Now the problem is the first reading!The programme sets up the registers then goes on to the ADC reading (temperature from the LM35). It the puts these into tens, units decimals and then displays the result on three 7-seg LEDs in a closed loop. The Timer1 interrupt then comes in and triggers a new ADC reading. This goes on every second forever. Now that I am using the interrupt properly, the accuracy has gone up! It is now only about 0.2 – 0.3degC out, so all was well.The problem is every time I start the PIC the first reading is random. After that, the readings are always fine. I have tried “everything” to stop this. It doesn’t matter whether it is a power supply switch start or an MCLR. I disabled interrupts and obviously it only gives the first figure and waits but this first figure is random as before. I’ve fiddled with the code and put delays in here and there, nothing. I’ve cleared ADRESH/L and TMR1H/L ... maddening!Is the ADC like pancakes: the first one is a “throw away”? If not, then could you please give me a few pointers as to how I might investigate the issue or any insight into likely causes?Thank you.

author: StillTrying
author_rank: Super Contributor
timestamp: June 05, 2018, 02:45:02 pm
content: As long as you're allowing some time for the power supply to stabilize 200ms ?, and the ADC is ON before the first TACQ and then GO, the first reading should be fine.Are you doing it all in ASM.

author: mikerj
author_rank: Super Contributor
timestamp: June 05, 2018, 02:55:55 pm
content: Post your initialisation code and your interrupt code. Does your interrupt set the ADC channel each time, or is that done just once in your init code?

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 05, 2018, 03:54:14 pm
content: StillTrying:I put a 5s delay at the start and it did just the same. Yes, I can only do assembly at the moment.mikerj: (sorry for the formatting, I can't seem to do it without <tab> !start:banksel TRISA ;Select bank1movlw b'00000001' ;Set RA0 as inputmovwf TRISA ;as input rest as outputs.clrf TRISB ;Configure all port B as outputs.movlw b'00000001' ;AN0 = RA0 i/p, GO low, ADC on.movwf ADCON0bsf PIE1,TMR1IE ;enable timer1 overflow interruptmovlw b'10010011' ;Right just, Fosc/8, Vss, FVR.movwf ADCON1movlw b'01101000' ;sets int osc to 4MHzmovwf OSCCONbanksel ANSELA ;Select bank3movlw b'00000001' ;Configure RA0 as analoguemovwf ANSELA ;input.clrf ANSELB ;Config all port B as digital i/o.banksel FVRCON ;Select bank2.movlw b'11000001' ;FVR enable, 1.024V.movwf FVRCONbanksel PORTB ;Select bank0movlw b'00110101' ;Fosc/4, 1:8 pre-scale, ... timer onmovwf T1CONbcf PIR1,TMR1IF ;clear timer1 interrupt flagbsf INTCON,PEIE ;enable peripheral interruptsbsf INTCON,GIE ;enable global interruptsmain:call chrgtime ;Tacq 8us (my assumption)banksel ADCON0bsf ADCON0,GO ;Set GO bit to start conversion.wait:btfsc ADCON0,GOgoto wait ;Wait for GO bit to clear.... rest of main loop ...INTERRUPTintrpt:bcf PIR1,TMR1IF ;clear timer1 interrupt flagdecfsz counti,Fretfie ;return to normal ops if counter not donebsf flag,0 ;set flag bit to trigger new readingmovlw .4movwf counti ;reset interrupt counter to 4.RetfieADC channel set just once. Thank you for taking a look.

author: StillTrying
author_rank: Super Contributor
timestamp: June 05, 2018, 05:00:44 pm
content: "I can only do assembly at the moment."Assembly is fine.When the FVR is enabled it requires time for the reference and amplifier to stablize, unfortunately it doesn't tell how long this time is.With no ORGs visible, have you got gotos to the right bits of code.Something like0000 goto start0001000200030004 goto isr0005 start

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 05, 2018, 05:30:10 pm
content: I have this before the "start:" label:#include p16f1827.inc ;Register and bit definitions.centig equ 0x20tens equ 0x21ones equ 0x22decs equ 0x23org 0x0000goto startorg 0x0004goto intrptorg 0x0005dispdata: addwf PCL,Fretlw .126 ;digit 0retlw .12 ;digit 1retlw .182 ;digit 2This is how I was shown.Cheers.

author: StillTrying
author_rank: Super Contributor
timestamp: June 05, 2018, 06:48:46 pm
content: Other than adding a few ms delay aftermovwf FVRCONI can't think of anything else.banksel FVRCON ;Select bank2.movlw b'10000001' ;FVR enable, 1.024V.movwf FVRCONbtfss FVRCON, FVRRDYgoto $-1should work. - in theory.

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 06, 2018, 12:02:30 pm
content: Thank you, I'll try that.In the meantime, I wondered if it was an artifact of the LM35. So, I used a resistor divider to apply the voltage to the input instead of the LM35. I took 100k, 220k and 470k resistors in turn and used a series of resistors from 1k to 100k in the "pin-to-ground" section of the divider. I then noted the "temperature" difference between first and second readings for each pair. The accuracy of the "proper" reading from the PIC was the same as the voltage measured by the Fluke87V across the "pin-to-ground" resistor, i.e. the voltage at the input pin.The results were that while the differences did vary somewhat by resistance (pin-to-ground side) the change looks like it depends most strongly on the actual voltage at the pin rather than the resistance. The difference was a reasonably consistent 0.8%.I thought that the resistance would matter more at it should affect the charge time of the sampling capacitor.I'll try StillTrying's solution now.

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 06, 2018, 12:26:23 pm
content: Tried that and it is still doing it but now the difference is higher on the second reading where is used to be lower!I notice in the datasheet it says:When the Fixed Voltage Reference module is enabled, itrequires time for the reference and amplifier circuits tostabilize. Once the circuits stabilize and are ready for use,the FVRRDY bit of the FVRCON register will be set. SeeSection 30.0 “Electrical Specifications” for theminimum delay requirement.However, there is no mention of the requirement in that section!Also, it says:Note 1: FVRRDY is always ‘1’ on devices with LDO (PIC16F1826/27).and mine is an 1827. Does this mean it's always ready?

author: StillTrying
author_rank: Super Contributor
timestamp: June 06, 2018, 02:57:56 pm
content: I looked at the LM35 data sheet, with its 0.1R impedance and 25us start up time I don't think it could be that. And searching for FVR, FVRCON, and Fixed Voltage, I never did find the FVR stabilization time, so dunno.But I've thought of a possible something else.As I understand it in the code above you seem to be turning the ADC ON and setting it up while Fosc is only 500kHz, Page57. I suppose it's possible the very slow CLK and TAD could be putting the ADC into a strange state for a while. It might be an idea to set the Fosc to 4MHz and TAD time first, before turning the ADC ON, I've done that reversing below! Good luck.Code:;OSCCON: OSCILLATOR CONTROL REGISTER P65;SPLLEN IRCF<3:0> --- SCS<1:0>movlw b'01101000';sets int osc to 4MHzmovwf OSCCON;ADCON1: A/D CONTROL REGISTER1 P146;ADFM ADCS<2:0> --- ADNREF ADPREF<1:0>movlw b'10010011';RightJust, Fosc/8, --- ref=Vss, ref=FVR.movwf ADCON1;ADCON0: A/D CONTROL REGISTER0 P145; --- CHS<4:0> GO/DONE ADONmovlw b'00000001';AN0 = RA0 i/p, GO low, ADC on.movwf ADCON0

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 06, 2018, 08:08:39 pm
content: That was well spotted!I tried it but there was no discernible change. Thank you for trying.

author: StillTrying
author_rank: Super Contributor
timestamp: June 06, 2018, 08:34:52 pm
content: Oh dear, scope time?

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 07, 2018, 10:09:32 am
content: Yippee! I think I have it!To check that the readings from the PIC were accurate, I permanently had myFluke 87VDMM connected to theLM35. Today, I unplugged the DMM and hey presto! The "first reading error" vanished. I plugged it back and the error returned even when the DMM was turned off!When I measured the DMM it came up as "infinite" resistance (though it's about 11MOhms when on) but 60pF capacitance, again even when off. As an aside, I have a memory of inaccuracies creeping in when I changed the range from Volts to mV.Could it be that this extra capacitance caused the error? 60pF doesn't sound a lot.BTW I'm intrigued by "scope time"? Pray tell.

author: JPortici
author_rank: Super Contributor
timestamp: June 07, 2018, 03:58:32 pm
content: hm.. was having a problem with erroneous readings, reading a potentiometerit was like the pot was logarithmic, while it was marked and measured as a linear one.Connected the scope, i saw a pulse wave with fast rise time and slow/exponential curve fall time at a divisor of the sample rate (SR/n of channels)duh moment, i forgot to set the channel as an analog input, so when it was its turn to be converted the peripheral priority on the input would override the pin settings for the time of conversion, giving obviously wrong errors

author: StillTrying
author_rank: Super Contributor
timestamp: June 07, 2018, 04:26:44 pm
content: Quote from: PerranOak on June 07, 2018, 10:09:32 amYes, that is it, I didn't know you were leaving the DVM permanently connected, I wouldn't have known it was 60pF, but it's quite normal for the outputs of small devices to not be able to drive even small caps or cables.QuoteWell page 14 of the LM35 says:"Like most micropower circuits, the LM35 device has a limited ability to drive heavy capacitive loads. Alone, theLM35 device is able to drive 50 pF without special precautions. If heavier loads are anticipated, isolating ordecoupling the load with a resistor is easy"QuoteTime to do checks with a scope, you'd hopefully have seen the LM35's slight oscillations at power up, and quite a few more checks.In theory, the ADC should be ready for GO in just a couple of us from turn ON, just the ACQ time would be enough. Don't know about the FVR start time.

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 08, 2018, 10:54:13 am
content: I have learned something here. I have always assumed that meters had no effect at all on a circuit - lesson learned.Why do all my problems stem from not reading the datasheet properly! Will I ever learn that lesson. I assumed that that section was for when you wanted to attach the LM35 to a long cable - still, if I'd read it properly …I hadn't used the scope yet as I got caught-up in this error but I will now.BTW capacitance in my "Kryptonite" I've never really got to grips with the subtler effects of it. It seems that the experts are like wizards who sprinkle capacitors throughout a circuit like magic dust and then, "whoosh!" everything works! It seems like magic because I don't get it. Sure I know what capacitors are and can "do all the calculations" (mostly!) but things like capacitative loading and such do throw me. I don't suppose you know of a good book that will help at all?Thank you for your help and forbearance.

author: StillTrying
author_rank: Super Contributor
timestamp: June 08, 2018, 10:43:25 pm
content: "I have always assumed that meters had no effect at all on a circuit - lesson learned."There are small invisible components all over the place, and once you add a test probe a few more are added, which ones are going to have a noticeable, usually bad! effect depends on impedances, current, speeds."BTW capacitance in my "Kryptonite" I've never really got to grips with the subtler effects of it."Maybe think of it as a flat battery, when a voltage is first applied across it a high current flows while it charges, and stops flowing when it's fully charged, the larger the battery or the faster the voltage rises the higher the charging current will be.Which method did you use to do binary to decimal in 8 bit ?

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 11, 2018, 12:07:15 pm
content: Thank you for the continued help.In fact, I wanted to use the full 10-bits from the ADC but wasn’t sure what the best way was. I set it to make theLSBthe 8-bit part with theMSBas the 2-bit. I then took theLSBand subtracted 100 until it went negative: this gives the number of hundreds (put into a variable) and similarly for the tens, the ones being what’s left. I assume that this is the “normal” way? As for theMSBI then realised that this figure can only be 0, 1, 2 or 3. So, I used it as a loop counter to add 256 (2 to the hundreds, five to the tens, 6 to the ones) the“MSB-number-of-times”. I reasoned that because the temperatures that I am using (room temp) it will be looping mostly zero or one time and never 2 or 3 whereas if I’d done it the other way (MSBas 8-bit andLSBas 2-bit) it would loop more frequently than just once much more often - presumably, an average of 1.5 times?

author: StillTrying
author_rank: Super Contributor
timestamp: June 13, 2018, 11:49:39 pm
content: Subtracting 1000 until you've gone to far, then subtracting 100 until you've gone to far, is the obvious way to do it but needs quite a bit of 2 byte math.I tried to finda best waya few years ago, the best I came up with is looking at the first few binary bits one at a time. For a 12 bit binary, if bit 11 (2048) is set, you set the value 2 bit in the decimal 1000s, nothing in the 100s, value 4 bit in the 10s and value 8 bit in the 1s, the same can be done for the next binary bit 10(1024), before you have to start adding values into the decimal bytes. The last 5 binary bits can all be added into the decimal 1s. The decimal bytes then look something like 1,5,22,34 but fixing the few over tens is easy in 1 byte math.The 12 bit (0-4095) version is 67 bytes and 80 CLKs, I don't think it can be done much faster.

author: PerranOak
author_rank: Frequent Contributor
timestamp: June 15, 2018, 08:04:23 am
content: Yes I see. It is adding with carry that causes the most difficulty so anything that minimises this is a boon.