Help with DT's 16-bit averaging subroutine?


Closed Thread
Results 1 to 4 of 4
  1. #1
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378

    Default Help with DT's 16-bit averaging subroutine?

    I am trying to get DT's 16-bit averaging subroutine to work correctly. I created the attached code as a way to test it. As you can see from the code, it writes values at various locations in the code to EEPROM so that after each execution I can read the data from the EEPROM as a way to see what values are being created.
    What I don't undestand and am asking for help from anyone on this forum is why the variable VALUE is always showing up as zero (EEPROM addresses 19 and 36). By the way I set up this test routine, starting with a decimal value of 35260 and incrementing it 6 times, the average stored in VALUE should be 35263...not zero.
    Any help is appreciated on this.
    Code:
    '*****************************************************************
    '*  Name    : TEST_AVERAGE2.BAS                                  *
    '*  Author  : John R. Ellis                                      *
    '*  Notes   : Adapted from code by Darrel Taylor                 *  
    '* "This routine will keep a "Running Average.                   *
    '* Instead of adding a bunch of values together and then dividing*
    '* by the number of samples, it averages each sample into the    *
    '* final result immediately. This eliminates the need for 32 bit *
    '* math.                                                         *
    '* To allow it to "Catch up" to large changes, set the FAspread  *
    '* to an acceptable range. Simply place the new number in VALUE  *
    '* and GoSub AVERAGE  The Average will be returned into the same *
    '* variable VALUE."                                              *
    '*  Memory  : 546 Words of program memory required               *
    '*****************************************************************
    ADavg    VAR  WORD
    AvgCount CON  16		' = Number of samples to average
    FAspread CON  1000	' = Fast Average threshold +/-
    i        VAR Byte        ' Index for measurment loop
    pw       VAR WORD        ' Stores each pw measurment
    pw0      Var pw.BYTE0    ' LSB of pw value
    PW1      var PW.BYTE1    ' MSB of pw value
    range    VAR WORD        ' Stores calculated range value
    range0   VAR range.Byte0 ' LSB of range value
    range1   VAR range.Byte1 ' MSB of range value
    us_inch  con 147         ' Scale factor converts sensor 147 microsecs to inches
    VALUE    VAR WORD        ' Stores average of measurements
    value0   VAR value.byte0 ' LSB of value
    value1   VAR value.byte1 ' MSB of value 
    
    GOTO Main               ' Jump over Subroutines
     
    ' -----------------{ Subroutines }----------------------------------------
    Average_Single:
        'Embedded use of Darrel Taylor's 16 bit averaging routine
        ' USE INTRUCTIONS: First, Select the sensor. ie.  Sensor = Temperature
        ' then place the new number in VALUE and then GoSub AVERAGE_SINGLE.
        ' The Average will be returned into the same variable VALUE.
            
        IF Value = ADavg Then NoChange
        IF ABS (Value - ADavg) > FAspread OR Value < AvgCount Then FastAvg
        IF ABS (Value - ADavg) < AvgCount Then RealClose
        ADavg = ADavg - (ADavg/AvgCount)
        ADavg = ADavg + (Value/AvgCount)
        GoTo AVGok
     
      FastAvg:
        ADavg = Value
        GoTo AVGok
     
      RealClose:
      'If averaging less than 8 samples, change AvgCount/4 to AvgCount/2.
        ADavg = ADavg - (ADavg/(AvgCount/2))
        ADavg = ADavg + (Value/(AvgCount/2))
     
      AVGok:
        Value = ADavg   ' Put Average back into Value
     
      NoChange:
    Return
    
    '--------------------------------------
    Main:
       'DEFINE WRITE_USED 1 'Required if only writing WORD variables in version 2.6
        pw = 35260
        WRITE 32,pw                ' Comment out for test only
        For i = 0 to 5
            'PULSIN PORTA.4,1,pw   ' Make 5 measurements from PW pin 
                                   ' of transceiver into array pw(i)
                                   ' with running average in value
            pw = pw +1                 ' Simulates pw measurement
            WRITE 34,pw            ' Comment out for test only
            Value = pw
            WRITE 36,VALUE         ' Comment out for test only
            'Running average in value...Max pw = 20' = 240" = 35280 usec. Therefore
                                       'pw, value, & range are 16 bit WORDs.
            GOSUB Average_Single
        NEXT
        WRITE 17,i                 ' Comment out for test only
        WRITE 19,VALUE             ' Comment out for test only
        range = (Value / us_inch) +1   ' Convert value to range in inches (max 240)
                                       ' add 1 to account for division rounding.
        WRITE 21,range      ' Store day's range in EEPROM location
    END

  2. #2
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    If you want to write WORD variables to EEPROM, you need to either add the WORD modifier to the WRITE statement, or WRITE the lowbyte and highbyte seperately in 2 WRITE statements.

    Code:
    WRITE 36,WORD VALUE
    DT

  3. #3
    Join Date
    Mar 2009
    Location
    Colorado
    Posts
    378


    Did you find this post helpful? Yes | No

    Default Re: Help with DT's 16-bit averaging subroutine?

    OK, Darrel,...that is one stupid mistake on my part. But I fixed the WRITE statements per the attached code, and VALUE is still coming out of the subroutine with a value of zero, as evidenced in the EEPROM WRITE address 19. Yet when I WRITE to EEPROM address 36 within the loop where the subroutine is called, the values in VALUE are correct going into the averaging subroutine.
    I still can't figure out why the averaging isn't working?? Any ideas?
    Code:
    '*****************************************************************
    '*  Name    : TEST_AVERAGE2.BAS                                  *
    '*  Author  : John R. Ellis                                      *
    '*  Notes   : Adapted from code by Darrel Taylor                 *  
    '* This routine will keep a "Running Average".                   *
    '* Instead of adding a bunch of values together and then dividing*
    '* by the number of samples, it averages each sample into the    *
    '* final result immediately. This eliminates the need for 32 bit *
    '* math.                                                         *
    '* To allow it to "Catch up" to large changes, set the FAspread  *
    '* to an acceptable range. Simply place the new number in VALUE  *
    '* and GoSub AVERAGE  The Average will be returned into the same *
    '* variable VALUE.                                               *
    '*  Memory  : 546 Words of program memory required               *
    '*****************************************************************
    ADavg    VAR  WORD
    AvgCount CON  16		' = Number of samples to average
    FAspread CON  1000	' = Fast Average threshold +/-
    i        VAR Byte        ' Index for measurment loop
    pw       VAR WORD        ' Stores each pw measurment
    pw0      Var pw.BYTE0    ' LSB of pw value
    PW1      var PW.BYTE1    ' MSB of pw value
    range    VAR WORD        ' Stores calculated range value
    range0   VAR range.Byte0 ' LSB of range value
    range1   VAR range.Byte1 ' MSB of range value
    us_inch  con 147         ' Scale factor converts sensor 147 microsecs to inches
    VALUE    VAR WORD        ' Stores average of measurements
    value0   VAR value.byte0 ' LSB of value
    value1   VAR value.byte1 ' MSB of value 
    
    GOTO Main               ' Jump over Subroutines
     
    ' -----------------{ Subroutines }----------------------------------------
    Average_Single:
        'Embedded use of Darrel Taylor's 16 bit averaging routine
        ' USE INTRUCTIONS: First, Select the sensor. ie.  Sensor = Temperature
        ' then place the new number in VALUE and then GoSub AVERAGE_SINGLE.
        ' The Average will be returned into the same variable VALUE.
            
        IF Value = ADavg Then NoChange
        IF ABS (Value - ADavg) > FAspread OR Value < AvgCount Then FastAvg
        IF ABS (Value - ADavg) < AvgCount Then RealClose
        ADavg = ADavg - (ADavg/AvgCount)
        ADavg = ADavg + (Value/AvgCount)
        GoTo AVGok
     
      FastAvg:
        ADavg = Value
        GoTo AVGok
     
      RealClose:
      'If averaging less than 8 samples, change AvgCount/4 to AvgCount/2.
        ADavg = ADavg - (ADavg/(AvgCount/2))
        ADavg = ADavg + (Value/(AvgCount/2))
     
      AVGok:
        Value = ADavg   ' Put Average back into Value
     
      NoChange:
    Return
    
    '--------------------------------------
    Main:
       'DEFINE WRITE_USED 1 'Required if only writing WORD variables in version 2.6
        pw = 35260
        WRITE 32,WORD pw           ' Comment out for test only
        For i = 0 to 5
            'PULSIN PORTA.4,1,pw   ' Make 5 measurements from PW pin 
                                   ' of transceiver into array pw(i)
                                   ' with running average in value
            pw = pw +1                 ' Simulates pw measurement
            WRITE 34,WORD pw       ' Comment out for test only
            Value = pw
            WRITE 36,WORD VALUE    ' Comment out for test only
            'Running average in value...Max pw = 20' = 240" = 35280 usec. Therefore
                                       'pw, value, & range are 16 bit WORDs.
            GOSUB Average_Single
        NEXT
        WRITE 17,i                 ' Comment out for test only
        WRITE 19,WORD VALUE        ' Comment out for test only
        range = (Value / us_inch) +1   ' Convert value to range in inches (max 240)
                                       ' add 1 to account for division rounding.
        WRITE 21,WORD range        ' Store day's range in EEPROM location
    END
    Last edited by jellis00; - 21st March 2011 at 23:44. Reason: correct statement

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: Help with DT's 16-bit averaging subroutine?

    Maybe you've worn out your EEPROM.
    I never liked that debugging method.

    I've run it here and it works fine on a 16F887.

    Here's a run in Proteus.

    Name:  EE_SIM.jpg
Views: 714
Size:  101.2 KB

    And here's a readback from a real chip running the same program.

    Name:  EE_Real.jpg
Views: 726
Size:  103.4 KB
    DT

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts