Shop OBEX P1 Docs P2 Docs Learn Events
summation question — Parallax Forums

summation question

cplattcplatt Posts: 55
edited 2011-07-03 20:38 in General Discussion
I do not understand how to use numbers over a Word's 16-bit size limit. I want to poll a sensor every 10th of a second, get a number like 3,000, and average the readings over lets say 5 minutes. The total of the averages exceeds a Word's size very quickly. Can someone help or give me a good link??? Thank you!!

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-07-03 13:24
    You can create a 32-bit sum, as follows:

    1. Add your reading to the lower 16-bit word. If the result is lower than it was before the add, that means there was a carry out of the high bit, so increment the high-order 16-bit word by one.
    2. Do this 16384 times (a power of two, or about 5.46 minutes worth of data.)

    Your average will be the lower 14 bits of the high word, concatenated with the upper 2 bits of the low word. You can shift the high word left by two bits and the low word right by 14 bits, then bitwise "or" the two together to get the average in one 16-bit word.

    -Phil
  • kwinnkwinn Posts: 8,697
    edited 2011-07-03 13:26
    I take it that you are not using a prop but some uC that is limited to 16 bit math. 50 samples per second times 300 seconds is 15,000 samples. At readings around 3000 that would come to a sum of about 45,000,000. I suspect the readings are probably 12 bits so the worst case would be 61,425,000.

    Simplest would be to use two words for double precision math. When word one has a carry increment word 2 by 1.

    It would also be simpler if you use a power of two for the number of samples to average so you can use a shift instead of a divide to do the averaging.

    What uC and language are you using?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-07-03 13:30
    I assumed he was using a BASIC Stamp, due to the way he capitalized "Word", but I could be wrong.

    -Phil
  • kwinnkwinn Posts: 8,697
    edited 2011-07-03 13:41
    I assumed he was using a BASIC Stamp, due to the way he capitalized "Word", but I could be wrong.

    -Phil

    That was my guess as well. Looks like our responses crossed in the ether.
  • cplattcplatt Posts: 55
    edited 2011-07-03 16:00
    Thank you kind Sirs. Yes I am using a Basic Stamp...if you could slightly dumb down your answer it would help me, I am a beginner, or if you could send me a link to a primer I would so appreciate it!!!
  • cplattcplatt Posts: 55
    edited 2011-07-03 16:53
    Here is my best try so far...do not understand the or command yet

    FOR x= 1 TO 16384
    sensor=3000
    IF lowword < sensor + lowword THEN highword = highword + 1
    ELSE lowword=lowword + sensor
    ENDIF
    PAUSE 100
    DEBUG, highword << 2 (OR???) lowword >> 14
    NEXT x
    END
  • kwinnkwinn Posts: 8,697
    edited 2011-07-03 18:42
    Try this:
    sensor=3000
    FOR x= 1 TO 16384
    IF sensor + lowword < lowword THEN highword = highword + 1
    ENDIF
    lowword=lowword + sensor
    PAUSE 100
    NEXT x
    DEBUG, highword = highword << 2 + lowword >> 14
    END
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-07-03 18:52
    Here's some code that summarizes the principle:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    i         VAR Word
    high_sum  VAR Word
    low_sum   VAR Word
    sensor    VAR Word
    average   VAR Word
    
    high_sum = 0
    low_sum = 0
    FOR i = 1 TO 16384
      GOSUB read_sensor
      IF (low_sum + sensor < low_sum) THEN high_sum = high_sum + 1
      low_sum = low_sum + sensor
    NEXT
    
    average = (HIGH_sum << 2) | (low_sum >> 14)
    DEBUG DEC average
    
    read_sensor:
      'Read sensor value.
      RETURN
    
    BTW, guys:

    attachment.php?attachmentid=78421&d=1297987572

    -Phil
  • kwinnkwinn Posts: 8,697
    edited 2011-07-03 19:11
    Shouldn't "IF (low_sum < low_sum + sensor) THEN high_sum = high_sum + 1" be "IF ( low_sum + sensor < low_sum) THEN high_sum = high_sum + 1"
  • Tracy AllenTracy Allen Posts: 6,667
    edited 2011-07-03 19:13
    cplatt,

    There is something of a tutorial on double precision math with the Stamp at http://emesystems.com/BS2math6.htm.

    It shows methods for using non-power-of-two divisors like 3000 (5 minutes worth of samples at 0.1 sec spacing).
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-07-03 19:30
    kwinn,

    Yes, of course you're right. 'Fixed.

    Tracey,

    Thanks for chiming in. It's always a relief to have your input on BASIC Stamp math questions! :)

    -Phil
  • Tracy AllenTracy Allen Posts: 6,667
    edited 2011-07-03 20:23
    I usually have the following subroutine for double precision averaging in my Stamp programs. The input at each step is from, say, a 12 bit ADC. The output is the current average value, times 10. I usually do it times 10 or more in order to take advantage of interpolation, if possible. The final step is division of the double precision accumulator by the number of samples. This uses the scratchpad RAM in the BS2pe, which is very convenient in an otherwise memory starved system.
    Average4:
    ' -- entry:
    '    wx =  current sample
    '    wj = current number of samples
    '   wpe1=address of 2 contiguous words (32 bits) allocated in scram for accumulator
    ' -- exit:
    '    wx = current average value of wx * 10
    '  -- uses for computation:
    '     wy, wz
      wx=wx*10        ' average computed on wx*10 for possible interpolation
      GET wpe1,WORD wy   ' low word of accumulation
      wy=wy+wx
      PUT wpe1,WORD wy
      GET wpe1+2, WORD wz    ' high word of accumulation
      IF wy<wx THEN
        wz=wz+1
        PUT wpe1+2,WORD wz
      ENDIF
     ' compute double precision division, wz:wy / wj       
      wx=65535//wj*wz//wj+wz+(wy//wj)
      wx=65535/wj*wz+(65535//wj*wz/wj)+(wy/wj)+(wx/wj)
      RETURN
    
  • cplattcplatt Posts: 55
    edited 2011-07-03 20:38
    You guys are fantastic!!! Thank you so much...I think I got it!!!
Sign In or Register to comment.