CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Olympic average - 8bit ADC

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
PrinceNai



Joined: 31 Oct 2016
Posts: 446
Location: Montenegro

View user's profile Send private message

Olympic average - 8bit ADC
PostPosted: Mon Mar 27, 2023 3:45 am     Reply with quote

Below is the routine to calculate olympic average for 8 bit ADC readings (or any other 8 bit values, of course). Thanks to Asmboy, all the hard work was done by him and posted in this thread: https://www.ccsinfo.com/forum/viewtopic.php?t=50320&highlight=olympic

This is a simple adaptation of his code for 8 bit values. If you want to use it in its original form for 10 or 12 bit values, all you have to do is comment and uncomment a few lines as described in the code.

For production use remove the settings for a debugger.

Code:

#include <18F46K22.h>
#device ADC = 8
//#device ADC = 10

#FUSES NOWDT, NOPUT , DEBUG                                    //No Watch Dog Timer, noput for ICD compatibility

#device ICD=TRUE
#use delay(internal=32000000)
#use rs232(baud=19200, parity=N, UART2, bits=8, stream=DEBUG, errors)

//int16 MyADC = 0;                                             // for 10 bit or 12bit ADC
int8 MyADC = 0;                                                // for 8 bit ADC

// ****************************************************************************
// olympic++  adc de-noising routine for 8, 10 or 12 bit ADC values           *
// NOTE: you must have selected the desired ADC channel before calling        *
// reads 16x , sorts and tosses low 6 (or 4) && high 6 (or 4) readings        *
// then averages the middle 4 or 8                                            *
// You must set  #device ADC = 8 or #device ADC = 10 according to your needs  *
// This code is only an 8 bit adaptation from the thread asmboy posted here:  *
// https://www.ccsinfo.com/forum/viewtopic.php?t=50320&highlight=olympic      *
// ****************************************************************************

//unsigned int16 adchlx(void){      // read ADC 16x - sort, keep middle 4, average, uncomment for 8 bit ADC
unsigned int8 adchlx(void){     // read ADC 16x - sort, keep middle 4, average, comment for 10 bit ADC

   unsigned int8 i; unsigned int16 accum=0;
   char b[16]; int1 didswap=1;
   
//   unsigned int16 s;                                         // un-comment for 10 bit ADC
   unsigned int8 s;                                            // comment for 10 bit ADC
   
   unsigned int8 result;                                       // comment out for 10 bit, not needed

// read ADC 16 times
   for ( i = 0 ; i < 16;  i++ ) {
      b[i]= read_adc();                                        // ADC set for 8, 10 or 12 bits
      delay_us(2);                                             // optional, can be whatever, even commented out
     }                                                         // end of for loop for multi sample   
// now sort the readings lowest to highest   
   while(didswap){                                             // bubble sort
      didswap=0;
      for (i=0; i<15; i++){                                    // i 0-15
         if(b[(i)]>b[(i+1)]){                                  // if low element greater than next  -do  swap
            s=b[i];                                            // hold upper
            b[i]=b[(1+i)];
            b[(1+i)]=s;
            didswap=1;
      }  // ~if
     }   // ~for
    }    // ~while
   
// It is up to you how many values you keep for averaging.
// This keeps only the middle 4 values. I've found it more stable than keeping 8 samples because the integer division
// defaults to the first lower whole integer value (for example, if you had 5 values of 57 and eleven of 58, it returned 57).
// For a pot reading it is rock stable. 8 bytes averaging code is commented out.
   for (i=6; i<10; i++){                                       // sum middle 4 values
//   for (i=4; i<12; i++){                                     // sum middle 8 values
      accum +=b[i];                                           
   }     
   accum = accum >> 2;                                         // divide by 4 for 4 values
// accum = accum >> 3;                                         // divide by 8 for 8 values
   result = make8(accum,0);                                    // for 8 bit ADC discard upper 8 bits, return 8bit value. Comment this out for 10 bit ADC.
//   return(accum);                                            // uncomment for 10 bit, returns 16 bit value.
   return(result);                                             // 8 bit return value, comment for 10 bit ADC
}

// ************************************************************
void main()
{
   setup_adc_ports(sAN0, VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_32 | ADC_TAD_MUL_20);
   set_adc_channel(0);                                         //read from ADC channel 0

   while(TRUE)
   {
      MyADC =  adchlx();
      fprintf(DEBUG,"ADC value = %u \r\n", MyADC);             // send the result out on UART2, debug info
      delay_ms(500);                                           // delay to prevent flooding the serial monitor
   }
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group