• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Strange behaviour from PIC16F18856 pin

Status
Not open for further replies.

Flyback

Well-Known Member
Hello,

We are using the PIC16F18856 in 4x4mm UQFN package.

Port RA5 works when we program it as digital input…..reads it fine whether input is high or low. Port RA5 also works when we program it as digital output….gives a square wave output fine.

However, when we program the pin as an analog (ADC) input..it reads it but the 9th bit (dec 256) of the ADRES register is strangely always set high)….so for example even when we have a grounded input to the pin as an ADC, it reads 0x0100 instead of zero.

PIC16F18856 datasheet
https://www.microchip.com/wwwproducts/en/PIC16F18856
 

Flyback

Well-Known Member
Thanks, thing is, on most of our boards, the ADC works fine. Its just around 30% of boards that are bad like this. Three out of ten...so we stopped production till we solve this.
The code is writen by a remote softy, but it looks bona fide.
Also, when we read ADC on RA4 pin it also has the same error on the bad boards.
We can shift the "bad bit" to the left with the left justify command, but its always in there.

I dont know what you mean by "stopping" it......the bad boards didnt work properly and the mal-operation corresponds to the ADC fault described. We tracked it down using the pickit3 debugger. We just set the debugger running, and set a breakpoint in the loop, and we run it repeatedly back to the breakpoint, then read the ADRES value off the screen.....this is where we see the "stuck" bit.

The fact that 70% of the boards worked fine suggests an ADC fault, do you agree?

The below is our code...its just bog-standard ADC code, so i can post it here....

//******************************************************************************
// Measure Light
//******************************************************************************
uint16_t MeasureLight(void)
{
uint16_t x;

Init_Normal_ADC();
ADC_StartConversion(0x05); // Port A.5
while (!ADC_IsConversionDone());
x = ADC_GetConversionResult();
return x;
}


//******************************************************************************
// The random.c DALI library changed the ADC settings, so we need to restore them
// after a random command. Also this function initialize ADC the first time
//******************************************************************************

void Init_Normal_ADC()
{

// ADGO stop; ADFM right; ADON enabled; ADCONT disabled; ADCS FOSC;
ADCON0 = 0x84;

ADCON1 = 0x00;
ADCON2 = 0x00;
ADCON3 = 0x00;

ADSTAT = 0x00;

// ADCCS FOSC/2;
ADCLK = 0x00;
// ADNREF VSS; ADPREF VDD;
ADREF = 0x00;

// CHANNEL --> ANA0;
ADPCH = 0x00;

// PRECHARGE TIME --> 0;
ADPRE = 0x00;

// ACQUISITION TIME --> 0;
ADACQ = 0x00;

// ADDITIONAL CAPACITOR --> 0
ADCAP = 0x00;

// AUTO conversion disabled;
ADACT = 0x00;


// ADRPT 0;
ADRPT = 0x00;
// ADLTHL 0;
ADLTHL = 0x00;
// ADLTHH 0;
ADLTHH = 0x00;
// ADUTHL 0;
ADUTHL = 0x00;
// ADUTHH 0;
ADUTHH = 0x00;
// ADSTPTL 0;
ADSTPTL = 0x00;
// ADSTPTH 0;
ADSTPTH = 0x00;


// ADC VALUE REGISTER L
ADRESL = 0x00;
// ADC VALUE REGISTER H
ADRESH = 0x00;
}



//******************************************************************************
// Start ADC conversion
//******************************************************************************
void ADC_StartConversion(uint8_t channel)
{
// Set CHANNEL
ADPCH = channel;
// ADRESL 0x0;
ADRESL = 0x00;

// ADRESH 0x0;
ADRESH = 0x00;

// Acquisition time delay
__delay_us(ACQ_US_DELAY);

// Turn on the ADC module
ADCON0bits.ADON = 1;

// Start the conversion
ADCON0bits.ADGO = 1;
}


//******************************************************************************
// Conversion DONE
//******************************************************************************
uint8_t ADC_IsConversionDone()
{
// Start the conversion
return (!ADCON0bits.ADGO);
}

//******************************************************************************
// Get result
//******************************************************************************
uint16_t ADC_GetConversionResult(void)
{
// Conversion finished, return the result
return ((ADRESH << 8) + ADRESL);
}
 
Last edited:

Pommie

Well-Known Member
Most Helpful Member
By "stopping it" I was referring to the errata sheet where it explains that the GO/DONE bit can be read too early and give incorrect readings. This isn't the case in your code.
Have you measured the actual voltage on the pins of the faulty board? Could RA4/5 be bridged? It does seem very unlikely it's a board fault that gives an error so precise.

It does sound like a batch of faulty chips.

Mike.
 

Flyback

Well-Known Member
Have you measured the actual voltage on the pins of the faulty board?
Thanks, the pins of the UQFN PIC16F18856 are too small to get a probe on to measure the voltage.

Could RA4/5 be bridged?
Thanks, The pin next to RA5 is GND, so if it was bridged, then it would still be ground. The pin the other side is the temperature measurement ADC input.....it also has the same problem.
...right, now youve got me wondering, could the RA5 and RA4 be bridged.....just maybe....because 0x0100 correponds to the temperature being 25degC....hmmm.
I best get back to the baords and check this.
...ahhh..no, we removed the mcp9700 temp sensor and grounded the input to RA4 and it still read 0x0100 in the ADRES register, so that cant be the problem.
 
Last edited:

Flyback

Well-Known Member
By the way, if I may add, the offending ADC reading is being taken from an SFH5711 light sensor IC which is also on the PCB. This has an 82k resistor to ground at its output which develops the requisite voltage in response to the SFH5711’s current source output. (the current source magnitude corresponds to the light level sensed by the SFH5711). There is also an 100pF capacitor at the SFH5711 output, as in the attached schematic.

I am just realising that the actual impedance presented to the PIC ADC channel by the light sensor might be too high for the PIC to get an accurate ADC reading?


---------------------------------------------------------------------------------------------------------
Hello,
Please assist us, because I have just realised from page 346 of the PIC16F18856 datasheet that the ADC module requires the input impedance of the external circuit to be less than 10 kiloOhms, and this because of the leakage current that can come out of the micro pin.
(page 346 of the PIC16F18856 datasheet tells us this)
The SFH5711 light sensor circuit has an impedance equal to the 82k resistor that we placed at its output.
In other words, we have seriously violated the input impedance level required by the ADC input of the PIC16F18856 microcontroller.
Do you have any thoughts on this?
I presume the reason that 70% of the boards worked was because the microcontrollers on those boards just happened to have lower leakage current at their ADC pins?

Also, i presume we can solve this mess by changing the resistor at the output of the SFH5711 light sensor to 10k (instead of the 82k that it already is)........and then just settling for a lower resolution light reading?
We don't have any room on the PCB to add an opamp buffer.

SFH5711 light sensor..
https://dammedia.osram.info/media/resource/hires/osram-dam-2496447/SFH 5711.pdf

PIC16F18856 datasheet:
https://www.microchip.com/wwwproducts/en/PIC16F18856
 

Attachments

Last edited:

Pommie

Well-Known Member
Most Helpful Member
The impedance of the external circuit just changes the acquisition time - the time taken to charge the internal sample and hold (SAH) capacitor. If the signal is slow moving then a simple capacitor will buffer the signal or you can leave the ADC permanently connected to the circuit so the SAH cap will follow the voltage. If you increase the value of the 100pF capacitor it will act as a buffer for the 10pF SAH capacitor. You will have some error due to the leakage current but I think this will be minimal.

Mike.
Edit, do you realise that Vpp (12V) can power your sensors via R36? It is normal to include a diode in the reset circuitry to eliminate this. The light sensor has max Vcc of 6V.
Also, what are the resistors for on C2,3?
 
Last edited:

Flyback

Well-Known Member
The impedance of the external circuit just changes the acquisition time - the time taken to charge the internal sample and hold (SAH) capacitor.
…Thanks, well yes OK, the series resistance leading into the ADC pin does indeed set the charge time for the S&H capacitor in the micro’s ADC unit..Granted that much, yes…however….

….thePIC16F18856 datasheet , on page 346, states, as you allure, that the impedance seen looking out from the PIC ADC module must be less than 10K, and this because of the leakage current. We have clearly violated this by having an 82k resistor there. So our resistance is 82k, because the SFH5711 light sensor has a current source output which is extremely high impedance. So for us, 10uA of pin leakage current would put a voltage of 820mV at the ADC pin, which makes it way too inaccurate.

The PIC16F18856 datasheet doesn’t actually state for sure what the leakage current is, but since its not a tightly controlled variable, its likely to be poorly toleranced. Page 610 appears to state that it’s a maximum of 1uA. This gives an inaccuracy of 82mV to our measurement setup.
 

Nigel Goodwin

Super Moderator
Most Helpful Member
As has already been suggested, it's not particularly the leakage, which will be very small anyway, but more the charge time for the S&H capacitor - by increasing the time between selecting the analogue input and taking the reading (possibly quite substantially), it makes readings MUCH more accurate then a fast reading. If you're only using a single A2D input, and you leave it permanently selected, then it's not usually a problem.

If you've got the time, and the inclination, do a simple test - get two 10K pots, wired across the supply, feed each slider via a 100K resistor to different analogue inputs, then write a program that reads each input in turn and displays the values, write it to read the ports as fast as possible. Now run the program and adjust the pots, each pot will change the voltage reading on BOTH inputs, to varying degrees. Now add delays to the program, between selecting the input and taking the reading, increase the delay until the pot's no longer interact with each other.

You'll be amazed at the result.
 

Flyback

Well-Known Member
If you've got the time, and the inclination, do a simple test - get two 10K pots, wired across the supply, feed each slider via a 100K resistor to different analogue inputs, then write a program that reads each input in turn and displays the values, write it to read the ports as fast as possible. Now run the program and adjust the pots, each pot will change the voltage reading on BOTH inputs, to varying degrees. Now add delays to the program, between selecting the input and taking the reading, increase the delay until the pot's no longer interact with each other.
….Thankyou, in fact, a very big ThankYou…..because I did not realise that if you have two separate ADC inputs, then ultimately both of them end up having to feed into the same S&H capacitor in the ADC of PIC16F18856

This could explain everything…because we do have a second ADC input, and this comes from an MCP9700 temperature sensor IC……this temperature sensor IC has a buffered output, so it can drive the S&H capacitor to the required value in very quick time.

What I now suspect, is that in our software our softy has inadvertently left the temperature channel connected to the S&H capacitor for too long, and then when we take the light reading, it simply reads what the temperature monitor had left in there. This would make kind of sense because the dreaded residual reading that we are getting in the ADRES register is 0x0100…this is what we would expect to see from the temperature sensor at 25degC….room temperature…hmmmmmm….much head-scratching to do now for us.

MCP9700 temperature sensor IC datasheet..
http://www.microchip.com/wwwproducts/en/en022289
 
Last edited:

Nigel Goodwin

Super Moderator
Most Helpful Member
What I now suspect, is that in our software our softy has inadvertently left the temperature channel connected to the S&H capacitor for too long.
You can't do it for 'too long' - once the capacitor is charged to the input voltage (which it needs to be for an accurate reading), it won't charge any more. When you then switch channels, that capacitor has to be charged (if the new voltage is higher) or discharged (if the new voltage is lower) until it stabilises at the new reading. As you're reading sensors there's presumably no need or reason for fast reads?, so try adding delays between selecting the input and taking the reading - it's probably worth trying my two pot technique to find what kind of delay you're looking for (and then make it 50% longer) - one pot at zero, and one at full voltage, are the worst points as the capacitor has to fully charge/discharge each switch.
 

Flyback

Well-Known Member
When you then switch channels, that capacitor has to be charged (if the new voltage is higher) or discharged (if the new voltage is lower) until it stabilises at the new reading.
Thanks, the problem is, that one of the sensors is a SH5711, which is a current source, so it isn’t really capable of discharging the S&H capacitor down from what it was at for the temperature adc reading. The only thing available to discharge the s&h cap down from the temperature reading is the 82k resistor that we have added at the output of the sfh5711. –Maybe this is not enough to discharge the s&h capacitor down in time…especially since it seems that our software engineer has not put in any acquisition time before the conversion is done.

---------------------------------------
Also, the PIC16F18856 osc is set to 16MHz, so one thing we can definetely say is that the software engineer has set the conversion clock wrongly. He has set it to FOSC/2, and page 340 of the datasheet clearly says that this is not acceptable for a micro set to 16MHz.

Also, the softy has set ADACQ to 0x00...which means no acquisition time, so thats not good for us either.

Also, our softy has put in an acquisition delay, but he does this before the ADC module is actually turned ON...so this is absolutely useless.

Also, our softy is setting the ADLTHL, ADLTHH, ADUTHL, ADUTHH, ADSTPTL and ADSTPTH registers. These all pertain to the ADC module. There is no need for this. This might be having unwanted effects on our ADC reading?
 
Last edited:

Nigel Goodwin

Super Moderator
Most Helpful Member
Thanks, the problem is, that one of the sensors is a SH5711, which is a current source, so it isn’t really capable of discharging the S&H capacitor down from what it was at for the temperature adc reading. The only thing available to discharge the s&h cap down from the temperature reading is the 82k resistor that we have added at the output of the sfh5711. –Maybe this is not enough to discharge the s&h capacitor down in time…especially since it seems that our software engineer has not put in any acquisition time before the conversion is done.
Was the software engineer asked to include long acquisition times in the routines?, if you're expecting the software to correct for hardware deficiencies then you need to let them know. However, it's asking for trouble with different people designing the hardware from the software, as neither knows what the other is up to.

As I said above, try the two pot technique (or get the software guy to), and see what delays you need - I suggested 100K series resistors to be slightly more pessimistic than your 82K, so as to cover component spreads.

Why didn't this problem come to light during design and breadboarding stages, rather than (presumably) after you've had boards made?.
 

Flyback

Well-Known Member
Thanks, we'll look into it....we need to be able to control the time between the sampling switch being turned on, and the actual conversion happening...at the monment we are not sure how to adjust the software to get this?
I note your points, -We are on stop, and soon, if we dont get sorted , sackings will commence.
---------------------------------------------------------------------
Sorry but does anyone know what is it that turns the sampling switch ON so that the C(HOLD) can be charged up?....does the sampling switch get turned on when the analog channel is enabled?
..or is it after the go/done bit is set?
Because our software engineer has set a variable and called it "acquisition delay".......but how does he make this happen at the right time..surely the acquisition delay is what happens after the go/done bit is set?...you cannot start this yourself.....it can surely only be started by setting the go/done bit?...and the actual value of acquisition delay can only be set in the ADACQ register, and it is up to 255* TAD?
So why has our softy made a variable called "acquisition delay"?...surely this is of no use whatsoever?
 

Nigel Goodwin

Super Moderator
Most Helpful Member
As far as I remember the capacitor starts charging/discharging after the analogue channel is enabled, you then add the delay, and only then start the actual conversion. Starting the conversion freezes the charging, that's the actual 'hold' part of the sample and hold, this is to prevent the voltage changing during the conversion.
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top