Sorting and finding the middle number is the median, not the mean. > > --- Dave Mucha <> wrote: >> --- In , "burt0072003" <burt007@i...> wrote: >> > A 16bit word from externel adc and sample may be 10 times and >> average >> > it to get a stable value. Then display the final results on the >> > character LCD. I know how to control the LCD, I have routines for >> > that. Only need the code to average a 16 bit word 10 times. The >> > results from external adc could be stored in 20 ram locations >> > initialy. These are for pic 16fxx series. >> > Thanks >> >> Op's I just re-read... you have a 16 bit value. >> >> Another way to look at the data would be to find the mean value. >> This requires a SORT of the data and finding the middle number. That >> >> would allow you to use only 16 bit math with 16 bit numbers as you >> are just comparing to see if one is higher than another. >> >> Since you are mostly ignoring numbers, a fast way to eleminate the >> extreems would be to take 10% of each number and sum them. (Still 16 >> >> bit) and average that number, then multiply by 10. That is a poor >> average, but with that you can quickly lose the min and max values >> prior to sorting. >> >> >> I haven't run that process to it's simplicity, but one could take a >> pass thru all the stored values to get the max and then delete that. >> take another pass to get the MIN and delete that and just repeat >> until the extreems have been deleted and you are left with the middle >> >> number. >> >> Since I'm rambling, one could take the lowest number and find the >> differences between that and all the others and average those >> differences and then add that back to the lowest number.... >> >> Dave >> (just lost the whole 'simple' thing) > > This will give you the median, not the mean. > > The answer is, set up a circular buffer of 8 or 16. Add all the > numbers and save the total. On each sample, subtract the last buffer > value from the total, replace it in the buffer with the new value, and > add it to the total. Increment the pointer and shift the total by 3 or > 4. > > Chad > ===== > My software has no bugs. Only undocumented features. > > __________________________________ > ------------------------ Yahoo! Groups Sponsor > ---------------------~--> Buy Ink Cartridges or Refill Kits for your > HP, Epson, Canon or Lexmark Printer at MyInks.com. Free s/h on orders > $50 or more to the US & Canada. > http://www.c1tracking.com/l.asp?cidU11 > http://us.click.yahoo.com/mOAaAA/3exGAA/qnsNAA/dN_tlB/TM > ---------------------------------~-> > > to unsubscribe, go to http://www.yahoogroups.com and follow the > instructions Yahoo! Groups Links > > |
Re: Looking for codes to average adc results
Started by ●February 20, 2004
Reply by ●February 20, 20042004-02-20
A 16bit word from externel adc and sample may be 10 times and average it to get a stable value. Then display the final results on the character LCD. I know how to control the LCD, I have routines for that. Only need the code to average a 16 bit word 10 times. The results from external adc could be stored in 20 ram locations initialy. These are for pic 16fxx series. Thanks |
|
Reply by ●February 20, 20042004-02-20
--- In , "burt0072003" <burt007@i...> wrote: > A 16bit word from externel adc and sample may be 10 times and average > it to get a stable value. Then display the final results on the > character LCD. I know how to control the LCD, I have routines for > that. Only need the code to average a 16 bit word 10 times. The > results from external adc could be stored in 20 ram locations > initialy. These are for pic 16fxx series. > Thanks There are a few ways to handle averaging and retrieving data. Personally, I preferr to scan the input each cycle. Others like to get 10 readings at one shot and then average them. ( for loop ) Here is a clue to one way to average. Assuming you can read your ADC into "RAW" RAW = external ADC value MID = MID AVG MID = MID + RAW AVG = MID / 10 MID is just a holder for the interim calculations. Initally, MID equals zero and the first read will do nothing unless you had assigned values. So, on the first pass, MID minus zero is zero. Then it adds the RAW ADC input value. Then divides by 10 to report the average. Say, your ADC was reading 100 MID(0) = MID (0) - AVG(0) = zero MID(0) - AVG(0) = zero MID(0) + 100 = 100 AVG then equals 10 on the first loop At the end of the first, MID = 100 and AVG = 10 end of second MID = 190, AVG = 19 end of thrid ; MID = 281, AVG = 28 it will take a hundred or so loops to get the average to equal the input, and the average will lag behind the real value, but this offers a very simple method using little RAM. There ARE better ways and there ARE much more accurate and faster ways, but this is really simple. Dave (likes simple) |
Reply by ●February 20, 20042004-02-20
--- In , "burt0072003" <burt007@i...> wrote: > A 16bit word from externel adc and sample may be 10 times and average > it to get a stable value. Then display the final results on the > character LCD. I know how to control the LCD, I have routines for > that. Only need the code to average a 16 bit word 10 times. The > results from external adc could be stored in 20 ram locations > initialy. These are for pic 16fxx series. > Thanks Op's I just re-read... you have a 16 bit value. Another way to look at the data would be to find the mean value. This requires a SORT of the data and finding the middle number. That would allow you to use only 16 bit math with 16 bit numbers as you are just comparing to see if one is higher than another. Since you are mostly ignoring numbers, a fast way to eleminate the extreems would be to take 10% of each number and sum them. (Still 16 bit) and average that number, then multiply by 10. That is a poor average, but with that you can quickly lose the min and max values prior to sorting. I haven't run that process to it's simplicity, but one could take a pass thru all the stored values to get the max and then delete that. take another pass to get the MIN and delete that and just repeat until the extreems have been deleted and you are left with the middle number. Since I'm rambling, one could take the lowest number and find the differences between that and all the others and average those differences and then add that back to the lowest number.... Dave (just lost the whole 'simple' thing) |
|
Reply by ●February 20, 20042004-02-20
Dave Mucha wrote: > --- In , "burt0072003" <burt007@i...> wrote: > > A 16bit word from externel adc and sample may be 10 times and > average > > it to get a stable value. Then display the final results on the > > character LCD. I know how to control the LCD, I have routines for > > that. Only need the code to average a 16 bit word 10 times. The > > results from external adc could be stored in 20 ram locations > > initialy. These are for pic 16fxx series. > > Thanks > There are a few ways to handle averaging and retrieving data. > > Personally, I preferr to scan the input each cycle. Others like to > get 10 readings at one shot and then average them. ( for loop ) > > Here is a clue to one way to average. > > Assuming you can read your ADC into "RAW" > RAW = external ADC value > > MID = MID - AVG > MID = MID + RAW > AVG = MID / 10 > > MID is just a holder for the interim calculations. > > Initally, MID equals zero and the first read will do nothing unless > you had assigned values. > > So, on the first pass, MID minus zero is zero. > > Then it adds the RAW ADC input value. > Then divides by 10 to report the average. > > Say, your ADC was reading 100 > > MID(0) = MID (0) - AVG(0) = zero > MID(0) - AVG(0) = zero > MID(0) + 100 = 100 > AVG then equals 10 on the first loop > > At the end of the first, MID = 100 and AVG = 10 > end of second MID = 190, AVG = 19 > end of thrid ; MID = 281, AVG = 28 > > it will take a hundred or so loops to get the average to equal the > input, and the average will lag behind the real value, but this > offers a very simple method using little RAM. > > There ARE better ways and there ARE much more accurate and faster > ways, but this is really simple. > > Dave > (likes simple) Instead how about MID = AVG * 10 MID = MID - AVG MID = MID + RAW AVG = MID / 10 which is the same as AVG = ((AVG * 10 - AVG) + RAW) / 10 which is the same as AVG = ((AVG * 9) + RAW) / 10 If you substitute 8 in place of 10 your division becomes much simpler (simply shift right 3 places) e.g. AVG = ((AVG * 7) + RAW) >> 3 or 16 in place of 10 (shift right 4 places) AVG = ((AVG * 15) + RAW) >> 4 If you keep a seperate total you will not need to multiply AVG_ACC = AVG_ACC - AVG + RAW AVG = AVG_ACC >> 4 Regards Sergio Masci http://www.xcprod.com/titan/XCSB - optimising structured PIC BASIC compiler |
Reply by ●February 20, 20042004-02-20
--- Dave Mucha <> wrote: > --- In , "burt0072003" <burt007@i...> wrote: > > A 16bit word from externel adc and sample may be 10 times and > average > > it to get a stable value. Then display the final results on the > > character LCD. I know how to control the LCD, I have routines for > > that. Only need the code to average a 16 bit word 10 times. The > > results from external adc could be stored in 20 ram locations > > initialy. These are for pic 16fxx series. > > Thanks > > Op's I just re-read... you have a 16 bit value. > > Another way to look at the data would be to find the mean value. > This requires a SORT of the data and finding the middle number. That > > would allow you to use only 16 bit math with 16 bit numbers as you > are just comparing to see if one is higher than another. > > Since you are mostly ignoring numbers, a fast way to eleminate the > extreems would be to take 10% of each number and sum them. (Still 16 > > bit) and average that number, then multiply by 10. That is a poor > average, but with that you can quickly lose the min and max values > prior to sorting. > I haven't run that process to it's simplicity, but one could take a > pass thru all the stored values to get the max and then delete that. > take another pass to get the MIN and delete that and just repeat > until the extreems have been deleted and you are left with the middle > > number. > > Since I'm rambling, one could take the lowest number and find the > differences between that and all the others and average those > differences and then add that back to the lowest number.... > > Dave > (just lost the whole 'simple' thing) This will give you the median, not the mean. The answer is, set up a circular buffer of 8 or 16. Add all the numbers and save the total. On each sample, subtract the last buffer value from the total, replace it in the buffer with the new value, and add it to the total. Increment the pointer and shift the total by 3 or 4. Chad ===== My software has no bugs. Only undocumented features. __________________________________ |
|
Reply by ●February 20, 20042004-02-20
--- In , Chad Russel <chadrussel@y...> wrote: > The answer is, set up a circular buffer of 8 or 16. Add all the > numbers and save the total. On each sample, subtract the last buffer > value from the total, replace it in the buffer with the new value, and > add it to the total. Increment the pointer and shift the total by 3 or > 4. Don't forget to add 4 (if you have 8 values) or 8 (if you have 16 values) before dividing in order to properly round the result. If you don't your result will always be truncated. For example, if you had the set {2,2,2,2,2,2,2,1} the sum is 15 and if you do the shift (15 >> 3) you get 1. However, if you add half the divisor to the sum before dividing you would get 15 + 4 = 19 and after dividing (19 >> 3) you get the proper result of 2. The worst part about this is you must use 24 bit math since you have 16 bit values. But that is not terribly difficult to deal with. --Scott |
|
Reply by ●February 20, 20042004-02-20
----- Original Message ----- From: "Paul James E." <> To: <> Cc: <> Sent: Friday, February 20, 2004 6:24 AM Subject: Re: [piclist] Re: Looking for codes to average adc results > > Sorting and finding the middle number is the median, not the mean. The median can sometimes be more 'meaningful' than the mean; it depends on how the data are distributed. It is another type of average. Leon -- Leon Heller, G1HSM Email: My low-cost Philips LPC210x ARM development system: http://webspace.webring.com/people/jl/leon_heller//lpc2104.html |
|
Reply by ●February 20, 20042004-02-20
----- Original Message ----- From: Scott Lee <> To: <> Sent: Friday, February 20, 2004 6:13 PM Subject: [piclist] Re: Looking for codes to average adc results > --- In , Chad Russel <chadrussel@y...> wrote: > > > The answer is, set up a circular buffer of 8 or 16. Add all the > > numbers and save the total. On each sample, subtract the last > buffer > > value from the total, replace it in the buffer with the new value, > and > > add it to the total. Increment the pointer and shift the total by > 3 or > > 4. > > Don't forget to add 4 (if you have 8 values) or 8 (if you have 16 > values) before dividing in order to properly round the result. If > you don't your result will always be truncated. > > For example, if you had the set {2,2,2,2,2,2,2,1} the sum is 15 and > if you do the shift (15 >> 3) you get 1. However, if you add half > the divisor to the sum before dividing you would get 15 + 4 = 19 and > after dividing (19 >> 3) you get the proper result of 2. > > The worst part about this is you must use 24 bit math since you have > 16 bit values. But that is not terribly difficult to deal with. > > --Scott Hi Scott, Actually if it's a 10 bit ADC reading the calculation will fit in a 16 bit int (10+3, only 3 bits needed for all possible carries since only 7 adds present with bit 9 possibly set to 1). Regards Sergio Masci http://www.xcprod.com/titan/XCSB - optimising structured PIC BASIC compiler |
|
Reply by ●February 20, 20042004-02-20
--- In , "sergio masci" <smypl@x> wrote: > > ----- Original Message ----- > From: Scott Lee <midl_man@y...> > To: <> > Sent: Friday, February 20, 2004 6:13 PM > Subject: [piclist] Re: Looking for codes to average adc results > > --- In , Chad Russel <chadrussel@y...> wrote: > > > > > The answer is, set up a circular buffer of 8 or 16. Add all the > > > numbers and save the total. On each sample, subtract the last > > buffer > > > value from the total, replace it in the buffer with the new value, > > and > > > add it to the total. Increment the pointer and shift the total by > > 3 or > > > 4. > > > > Don't forget to add 4 (if you have 8 values) or 8 (if you have 16 > > values) before dividing in order to properly round the result. If > > you don't your result will always be truncated. > > > > For example, if you had the set {2,2,2,2,2,2,2,1} the sum is 15 and > > if you do the shift (15 >> 3) you get 1. However, if you add half > > the divisor to the sum before dividing you would get 15 + 4 = 19 and > > after dividing (19 >> 3) you get the proper result of 2. > > > > The worst part about this is you must use 24 bit math since you have > > 16 bit values. But that is not terribly difficult to deal with. > > > > --Scott > > Hi Scott, > > Actually if it's a 10 bit ADC reading the calculation will fit in a 16 bit > int (10+3, only 3 bits needed for all possible carries since only 7 adds > present with bit 9 possibly set to 1). That would be correct if using the internal DAC but he already stated he is using an external DAC and getting 16 bit data. |