![]() |
Forum Index : Microcontroller and PC projects : Basic Averaging Routine
Author | Message | ||||
OA47 Guru ![]() Joined: 11/04/2012 Location: AustraliaPosts: 986 |
Does anyone have an example of a Basic averaging routine where a series of samples are sorted and the highest and lowest removed so the rest can be averaged? OA47 |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Is it a running average or a stand-alone block of values? How many in the set and are you using a version of Basic with a SORT command? Jim VK7JH MMedit |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Here is a quicky that doesn't use SORT OPTION EXPLICIT OPTION DEFAULT NONE DIM FLOAT rdgs(10) DIM INTEGER n DIM FLOAT x FOR n = 1 TO 10 rdgs(n) = RND()*30 PRINT rdgs(n) NEXT n PRINT filtered() FUNCTION filtered() AS FLOAT LOCAL FLOAT n, largest=0, least=50, av FOR n = 1 TO 10 av = av + rdgs(n) IF rdgs(n) > largest THEN largest = rdgs(n) IF rdgs(n) < least THEN least = rdgs(n) NEXT n PRINT "Ignoring ";largest;" and ";least av = (av - largest-least)/8 filtered = av END FUNCTION Jim VK7JH MMedit |
||||
OA47 Guru ![]() Joined: 11/04/2012 Location: AustraliaPosts: 986 |
Here is some of the code I am currently running but I am not removing the highest and lowest values. Dim Integer Rt Dim Float CoreTemp(5),AvTemp ' This Sub Called every second Rt=Rt+1 If Rt=6 Then Rt=1 CoreTemp(Rt)=Pin(TEMP) AvTemp=(CoreTemp(1)+CoreTemp(2)+CoreTemp(3)+CoreTemp(4)+CoreTemp(5))/5 Text 240,30,Str$(AvTemp,2,1) + Chr$(96),LB,4,1,C.Blue OA47 |
||||
OA47 Guru ![]() Joined: 11/04/2012 Location: AustraliaPosts: 986 |
Thanks Jim I will investigate more. OA47 |
||||
paceman Guru ![]() Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Here's a different one showing it running a rolling average (temp & %RH data as ASCII strings, coming in), flagging and logging outsiders (noise - see the DEBUG statements in the 'noisecheck routine) and displaying/plotting data as it comes in. The full caboodle is on the forum somewhere - search for Digoo and member 'paceman'. Greg sub plotdata 'another Digoo oC/%RH data set coming in. local float flT,flRH flT =val(temp$): flRH =val(relhumid$) 'convert to integer for noisecheck & plot. if flRH > 99.0 then flRH = 99.0 'DEBUG stops any over-scale RH stuffing up display. if flRH = 99.0 then relhumid$ = "99" 'DEBUG stops any over-scale RH stuffing up display. 'Noisecheck data then display & plot on grid. Scroll at grid end. xposn = plotstart + (timer/60000) 'start posn + elapsed mins since grid draw or scroll. if xposn => mm.hres-30 then scroll 'if reached end of grid, start scrolling. If cn1=6 Then cn1=5 'Reset rolling average noisecheck data array counters to 5 If cn2=6 Then cn2=5 'after first 6 have been built up. After that, number 6 is If cnP=6 Then cnP=5 'then always the current result. if channel$ ="1" then 'this is Ch1 data. cn1 = cn1+1 'array element counter for Ch1 noisecheck arrays. Tch1(cn1)= flT: Rch1(cn1)= flRH 'build up Ch1 noisecheck array elements. if cn1 =6 then 'when six Ch1 array elements have been filled. text 8,20,dattime$ +" Out ",,2 'display date/time of current Ch1 data. Ch1=Outside noisecheck(Tch1(),5) 'check if Ch1 temp. is noise. Limits +/- 5oC. if noise then Ch1TN = Ch1TN +1 'Update Ch1 temperature noise count. text 398,20,Str$(Ch1TN,2,0),,2,,yellow 'display it in textbox. else text 218,20,temp$,,2,,yellow 'display temperature in TCh1 textbox Pixel xposn,308-(5*(flT+5.0)),yellow 'and plot using base & slope of temp. scale. endif noisecheck(Rch1(),15) 'check if Ch1 %RH is noise. Limits +/- 10%. if noise then Ch1RN = Ch1RN +1 'Update Ch1 %RH noise count. text 438,20,Str$(Ch1RN,2,0),,2,,GREEN 'display it in textbox else text 282,20,relhumid$,,2,,green 'display %RH in RCh1 textbox & then plot Pixel xposn,308-(2.5*flRH),green 'using base, slope and offset of %RH scale. endif endif else ...... goes on to Channel 2 data. -------------------------- sub noisecheck(param() As float,limit As float) As integer 'Simple rolling average. Local integer i,m Local float sum,rollave noise =0 'reset flag. For i = 1 To 5 sum = sum + param(i) Next i rollave = sum/5 'calc. rolling average of first 5 array elements. If param(6)> rollave+limit Or param(6)< rollave-limit Then noise =1 'test current result. if noise then 'DEBUG line xposn,134,xposn,142 'DEBUG mark display when noise occurred. text xposn,150,Str$(param(6),2,2),ctv,,,red 'DEBUG display param(6)vertically. text xposn,65,Str$(rollave,2,2),ctv,,,cyan 'DEBUG display rollave vertically. endif 'DEBUG If noise Then Exit Sub 'if noise, exit with flag set. For m = 1 To 6 'if not noise, shuffle array back one. This drops 1st array param(m) = param(m+1) 'element thus the current data, param(6), is now param(5). Next m End Sub |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
This is a classic merge sort application. Attached is Geoff's code from the analog input routine on the Micromite - just convert the syntax and away you go |
||||
OA47 Guru ![]() Joined: 11/04/2012 Location: AustraliaPosts: 986 |
Thank you for your contribution. I could not fully understand the code enough to convert it to basic (must be your English accent Peter or maybe my lack of practice with C) Could the code be simply converted to MMBasic retaining its simplicity or would I need to implement a C routine in my MMBasic program? OA47 |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
Hi OA47, should be something like this: CONST ANA_DISCARD = 1, pin = 1 'ANA_DISCARD is the amount of samples to be discarded top and bottom DIM INTEGER i, j, ANA_AVERAGE = 100 'ANA_AVERAGE is amount of samples DIM FLOAT b[ANA_AVERAGE-1], t, avg, sum FOR i = 0 TO ANA_AVERAGE-1 b[i] = ExtInp(pin) 'here is the sample read FOR j = i TO 1 STEP -1 IF b[j-1] < b[j] THEN t = b[j-1] b[j-1] = b[j] b[j] = t ELSE EXIT FOR ENDIF NEXT j NEXT i sum = 0 FOR i = ANA_DISCARD TO ANA_AVERAGE-ANA_DISCARD-1 INC sum, b[i] NEXT i avg = sum / (ANA_AVERAGE - 2*ANA_DISCARD) Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
lizby Guru ![]() Joined: 17/05/2016 Location: United StatesPosts: 3378 |
Except with "(" instead of "[" and ")" instead of "]". PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
For a small array like you are using, we don't need to do a sort etc. ' This Sub Called every second Rt=Rt+1 If Rt=6 Then Rt=1 CoreTemp(Rt)=Pin(TEMP) AvTemp = AvT() Text 240,30,Str$(AvTemp,2,1) + Chr$(96),LB,4,1,C.Blue FUNCTION AvT() AS FLOAT LOCAL FLOAT n, largest=-10, least=100 ' set largest and least to ridiculous extremes FOR n = 1 TO 5 AvT = AvT + CoreTemp(n) IF CoreTemp(n) > largest THEN largest = CoreTemp(n) ELSEIF CoreTemp(n) < least THEN least = CoreTemp(n) ENDIF NEXT n 'PRINT "Ignoring ";largest;" and ";least AvT = (AvT - largest-least)/3 END FUNCTION My original suggestion changed to fit your variables. Jim VK7JH MMedit |
||||
OA47 Guru ![]() Joined: 11/04/2012 Location: AustraliaPosts: 986 |
Thanks Jim, but I was taking the average over 5 seconds where I think your code will take sequential samples, am I right? OA47 |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
My code is almost the same as yours. You take an average of the last 5 readings. I take the same last 5 readings and drop the highest and lowest before averaging. Jim VK7JH MMedit |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
Yes, of course. It was too late night... thanks lizby. Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
Ingotron Newbie ![]() Joined: 17/03/2021 Location: GermanyPosts: 1 |
Hello, a very simple and fast way of averaging data is the following (I use it for a data logger for noisy signals): a ... current measured signal b ... former stored signal f ... filter constant The new signal to store is calculated by: b=(1-f)*b+f*a For f=1 there is no filtering, for f=0 there is no signal information in b. I use f=0.3 ... f=0.8 depending on the maximum frequency of information in the signal. The advantage of this filter is, that it is very fast und does not need much memory space. The disadvantage is that the output signal is delayed. Greetings Ingo. Edited 2021-03-17 20:48 by Ingotron |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |