oversampling adc

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
be80be
Registered User
Registered User
Posts: 90
Joined: Mon Feb 23, 2009 2:15 am
Location: tn

oversampling adc

Post by be80be » Thu Aug 20, 2015 12:32 am

Any one have a sample of how to oversample the adc
Thanks Burt

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: oversampling adc

Post by Jerry Messina » Thu Aug 20, 2015 2:59 pm

Here's a module that should do it.

To use it, set the '#option ADC_BITS' to match the ADC of your device (ie 10, 12, etc)
and set '#option OVERSAMPLE_BITS' to the number of bits you want to increase it by.

Code: Select all

module adc_oversample

// note: you need to setup the ADC before calling oversample()
// make sure it's set to "right-justify"
include "adc.bas"
include "math.bas"

// current number of ADC bits (device-dependent)
#option ADC_BITS = 10
const _adc_bits = ADC_BITS

// number of bits to increase resolution by
#option OVERSAMPLE_BITS = 4
const _num_bits = OVERSAMPLE_BITS

// set a type for the sample count based on how many oversample bits (saves some code)
#if (OVERSAMPLE_BITS < 4)
  type sample_count_t = byte
#elseif (OVERSAMPLE_BITS < 8)
  type sample_count_t = word
#else
  type sample_count_t = longword
#endif

// number of sample averages
dim num_samples as sample_count_t

// this returns the "max ADC reading" accounting for the number of increased bits
// you can use this to scale the oversample() result
public function max_oversample() as longword
    result = pow(2, _adc_bits + _num_bits) - pow(2, _num_bits)
end function

// this function returns a single adc reading
function read_adc(chan as byte) as word
    result = ADC.Read(chan)
    'result = pow(2, _adc_bits)-1    // just return max adc reading (useful for debugging)
end function
    
// read adc with oversampling
public function oversample(chan as byte) as longword
    dim acc as longword,
        i as sample_count_t

    // first time through we need to compute the number of samples
    //  to average, which is 4^OVERSAMPLE_BITS
    if (num_samples = 1) then
        num_samples = pow(4, _num_bits)
    endif

    // accumulate samples
    acc = 0
    for i = 1 to num_samples
        acc = acc + read_adc(chan)
    next
    
    // divide the sum by 2^OVERSAMPLE_BITS (by shifting right)
    acc = acc >> _num_bits
    
    result = acc
end function

// init
num_samples = 1

end module
example test code:

Code: Select all

#option ADC_BITS = 10           // set exisiting ADC resolution (check your device)
#option OVERSAMPLE_BITS = 2     // desired number of bits to increase resolution by 
include "oversample.bas"
include "adc.bas"

dim adc_max as longword,
    adc_result as longword

//setup adc as appropriate (make sure it's set to right-justify)
adc.setconvtime(FOSC_16)
adc.setacqtime(10)

// get new "ADC max reading" so we can scale result
adc_max = max_oversample()

// read ADC chan 1 with oversampling
adc_result = oversample(1)


be80be
Registered User
Registered User
Posts: 90
Joined: Mon Feb 23, 2009 2:15 am
Location: tn

Re: oversampling adc

Post by be80be » Thu Aug 20, 2015 5:54 pm

I got a problem I think windows 10 changed something when I complie it doesn't use any of the library's
Got to maybe reinstall swordfish. The asm doesn't have the adc code set at all in it. I tried the sample from swordfish it gives no LCD output

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: oversampling adc

Post by Jerry Messina » Thu Aug 20, 2015 7:18 pm

Can't help you there, Burt.

I'll be installing Windows 10 Real Soon Now. Honest. Really...

be80be
Registered User
Registered User
Posts: 90
Joined: Mon Feb 23, 2009 2:15 am
Location: tn

Re: oversampling adc

Post by be80be » Thu Aug 20, 2015 9:50 pm

I've tried a sample like this

Code: Select all

Device = 18F2550
Clock = 20 
#option LCD_DATA = PORTB.4
#option LCD_RS = PORTB.1
#option LCD_EN = PORTB.2

// uses LCD and AD libraries...
Include "LCD.bas"
Include "ADC.bas"
Include "convert.bas"
          
// read the AD port and scale for 0 - 5 volts...
Function ADInAsVolt() As Word
   result = (ADC.Read(0) + 1) * 500 / 1024
End Function

// sampled AD value...
Dim ADVal As Word

// initialise and clear LCD...
ADCON1 = $07       // PORTE as digital (LCD)
TRISA.0 = 1        // configure AN0 as an input 
ADCON1.7 = 1       // set analogue input on PORTA.0 
DelayMS (500)
LCD.Cls

// main program loop...
While true
   ADVal = ADInAsVolt
   LCD.MoveCursor (1,1)
   LCD.Write("DC Volts = ", DecToStr(ADVal / 100), ".", DecToStr(ADVal, 2), " ")
   DelayMS(250)
Wend
Theres No ADC ouput at all.
But If I just send text the LCD works fine as long as I leave the ADC stuff out.
I don't understand what's happening there I looked at ths ASM code and it's like it's never running it.
I simulated it and the ADC pins never change to read ADC on pin AN0

Post Reply