# Porting MikroC code to MPLAB for PIC16F1508 adding extra noise to ADC

I decided to start using MPLAB with XC8 after I started reaching the 2k code size limit in MikroC. The problem is that since all the Mikroc libraries are proprietary and there are no libraries available for the PIC16F series in MPLAB, I had to write my own ADC functions.

These are the two functions I wrote to set up my ADC using the datasheet:

void ADC_Init(){
PIR1bits.ADIF = 0; // Clear interrupt flag
INTCONbits.PEIE = 0; // Disable perriferal interrupts

}

ADCON0bits.CHS = channel; // Set channel, must be between 0 and 11
__delay_us(5); // Wait some arbitrary acquisiton time

PIR1bits.ADIF = 0; // Clear interrupt flag
ADCON0bits.GO_nDONE = 1; // Start acquisioin

while(ADCON0bits.GO_nDONE) {} // Wait for the conversion to finish

}


The input signal that I'm reading in is pretty noisy to begin with. In my MikroC program with the library ADC functions, the noise floor on the samples ranged between 60 and 100 (10-bit ADC). By noise floor, I mean the range of values the ADC was reading with no input. Noise from the rest of the system I suppose.

In MPLAB with the above functions, the noise floor has shot up 200 to 300. On a 10-bit ADC, this much noise is unacceptable. I run the ADC_Init() function once outside my main program loop, then use the ADC_Read(..) function in my program loop.

Any ideas on why the noise is so much more? Or any ideas on how MikroC get this performance? I suspect it has something to do with the way I configured the ADC.

## EDIT

In response to Olin's answer, I believe the 5us "acquisition time" might be a misnomer, that delay is there to allow the holding capacitor to charge after changing ADC channels. The datasheet shows an example for a 10kohm signal impedance needing 7.4us charge time. My signal impedance is only 700ohms, so I figured 5us should be more than enough. As for the circuit, it has not changed, only the software has. And the signal I'm measuring is a slightly noisy digital signal coming out of a MSGEQ7 filter IC.

This is a good illustration of the trouble you run into when using canned libraries.

If you originally had 10% noise on the signal, then maybe the problem is with the circuit. What kind of signal are you measuring? What is its upper frequency? How often are you sampling? It would be useful to show the schematic.

You seem to be allowing 5 µs for acquisition, but how do you know that is enough? What impedance is the signal being fed to the A/D? One possible explanation of your symptoms is that the signal impedance is too high, and the previous code used a longer acquisition time, which allowed the sample and hold to settle more closely to the correct value.

However, a better answer is probably to re-think the whole A/D strategy in the first place. Don't base it on what library routines happen to be available or some similar nonsense. Read the datasheet section on the A/D and think about how best to use it, possibly in conjunction with other hardware, like timers, to solve the overall measurement problem.

A strategy I often use is to take A/D readings in a periodic interrupt. You run this as fast as the A/D will let you acquire and convert the signal, and within limits of leaving enough foreground cycles for the rest of the system. This A/D interrupt samples the A/D much faster than you really need, then low pass filters the results. When the main code wants the latest reading, it doesn't go out and take a single A/D reading. It just uses the current value of the low pass filter output. I have done this sort of thing many times. In fact, it's my normal way to take A/D readings unless there is a specific reason to do it differently.

In a small microcontroller, there is no substitute for actually understanding the hardware and being aware of how exactly it is being used, whether it is thru your own code or "library" routines.