VARIOMETER using GY63/MS5611 barometer

Benjie

Senior Member
Now I went a step further: I reduced the pause between loops down to 10 ms and I added a little piece of code to detect the difference between previous and actual average.
Code:
 ; Show the 24-bit hex averages
    'SerTxd( "Avg(", #SAMPLES, ")", TAB )
    w0 = m.average     : Gosub HexWord
    b0 = l.average.msb : Gosub HexByte
    ; Show the 16-bit decimal average
    b1 = m.average.lsb
    b0 = l.average.msb
    'SerTxd( TAB, #w0, CR,LF )
    
 if w0 < w8 then
     diff = w8 - w0 : b14 = 2
 elseif w0 > w8 then
     diff = w0 - w8 : b14 = 1
 endif
 'debug
 sertxd(#b14,tab,#diff,cr,lf)
 w8=w0

    pause 10
  loop
The sertxd in static conditions is:
1 31
1 2
2 17
2 17
1 18
1 7
2 26
1 8
2 1
1 32
2 3
2 27
2 3
2 17
In moving it fast up and down by 50cm:
1 65
1 41
1 35
1 47
2 95
2 107
2 67
1 83
1 320
1 288
1 12
2 126
1 21
2 24
1 29
1 65
1 39
by moving fast down and then up:
2 4
1 20
2 78
2 55
1 330
1 254
1 25
2 71
2 312
2 126
1 4
2 80
2 116
2 98
2 95
2 178
2 150
2 137
2 85
2 67
2 82
2 53
2 114

All this means that with a threshold of about 100 the required sensitivity is achieved.
I will continue modulating a sound with the diff and it sign.
 

hippy

Technical Support
Staff member
The average of the average is 43220, and variances from that average are -
Code:
85A91B 43291 +71
85A929 43305 +85
85A930 43312 +92
85A935 43317 +97
85A909 43273 +53
85A8F8 43256 +36
85A8E5 43237 +17
85A8E4 43236 +16
85A8B7 43191 -29
85A8A1 43169 -51
85A89C 43164 -56
85A8A2 43170 -50
85A8A1 43169 -51
85A893 43155 -65
85A8AE 43182 -38
85A8C4 43204 -16
85A8B5 43189 -31
85A8C6 43206 -14
85A8C3 43203 -17
85A8AD 43181 -39
That seems to be rather cyclical but considering 1 bit represents 1.2 mm if the earlier calculations were correct then it seems it's accurate to within +/-10 cm.

Next step would be to do various height tests to see if results are repeatable, consistent with themselves and what would be expected.

Measure on desk, 1 metre below, on desk, 1 metre above, then on desk again.
 

hippy

Technical Support
Staff member
Change your reporting code to the following and the differences will be much easier to comprehend -
Code:
    Symbol diff          = w7 ; b15:b14
    Symbol last          = w8 ; b17:b16

    ; Show the 24-bit hex averages
    SerTxd( "Avg(", #SAMPLES, ")", TAB )
    w0 = m.average     : Gosub HexWord
    b0 = l.average.msb : Gosub HexByte
    ; Show the 16-bit decimal average
    b1 = m.average.lsb
    b0 = l.average.msb
    SerTxd( TAB, #w0, " " )
    Select Case w0
      Case > last : diff = w0 - last : SerTxd( "+", #diff )
      Case < last : diff = last - w0 : SerTxd( "-", #diff )
      Else        :                    SerTxd( "=" )
    End Select
    SerTxd( CR, LF )
    last = w0
 

Benjie

Senior Member
Here the result for 60cm changes up and down:

Avg(16) 22316 +50
Avg(16) 22273 -43
Avg(16) 22301 +28
Avg(16) 22863 +562
Avg(16) 23941 +1078
Avg(16) 24124 +183
Avg(16) 24156 +32
Avg(16) 24163 +7
Avg(16) 24126 -37
Avg(16) 24128 +2
Avg(16) 24157 +29
Avg(16) 24025 -132
Avg(16) 22764 -1261
Avg(16) 22894 +130
Avg(16) 22877 -17
Avg(16) 22770 -107
Avg(16) 22727 -43
Avg(16) 22678 -49
Avg(16) 22614 -64
Avg(16) 22531 -83
Avg(16) 22490 -41
Avg(16) 22482 -8

Very nice indeed!
 

hippy

Technical Support
Staff member
That does look encouraging, but we need to take care not to fall into the earlier traps ( which I inadvertently have ) of not using signed numbers. And, as we are not doing full 24-bit maths when it comes to crossing boundaries, it means the difference between current and last may jump around wildly and be incorrect.

We have proved that we can get fairly stable and repeatable readings from the sensor. We now need to consider how best to turn that into a usable audible indication of ascent or descent.

The good news is that simply comparing current to last reading does seem to serve the purpose, so just a matter of determining the difference, the rise or fall, taking into account it is 24-bit data, then mapping that to some audible frequency for output.

Getting a pot to produce a signed 'diff' signal and something which can generate the desired frequencies within a loop would seem to be the next step.

It would be interesting to see what effect putting a "Start0:" at the beginning of the sampling code and a "Start1: Do : Loop" at the end has on operations. Using multi-tasking may be one way to generate the audible tones.
 

premelec

Senior Member
I'm wondering if it wouldn't make sense to transfer the serial data directly to a 16 bit digital to analog converter and use the analog output [possibly averaged] to make the tone... there are a few 24bit DAs but that might be getting too fine. Sorry if I'm off the mark - I'm interested in a different possible app than sailplane use.
 

hippy

Technical Support
Staff member
I'm wondering if it wouldn't make sense to transfer the serial data directly to a 16 bit digital to analog converter and use the analog output [possibly averaged] to make the tone...
It is a possibility; have that drive a VCO. A second PICAXE could act similarly and would mean we can avoid all the problems of integrating sound generation into the sampling regime.

I suppose we need to determine how a tone could be generated and then test how they work.

Writing to DAC or another PICAXE is easy enough.
SOUND might work but blocks and will have gaps between each execution.
Some sort of DDS could work but requires high speeds.
PWMOUT might work but only has limited period values which can be used.

Also, if we are still using an 08M2; the only PWMOUT pin is used by the I2C bus.

I guess that means SOUND is the only simple candidate.
 

premelec

Senior Member
My electronics history goes back to VF chips - and biasing one of those to a tone and driving DA output [amplified] into VF converter bias point through a capacitor would give simple up/down sound indication - not sure if that's what's wanted here but is what I've heard in sailplane use... All of this can be done with micros with more programming complexity. Didn't Jeremy have some 24 bit math?
 

Benjie

Senior Member
Nice large horizon!
It is possible to consider a DAC operating on the least 16 bits while to avoid jumps the value of the first 8 can be divided by 2 to allow a sufficient span.
Have no idea on how small can be a 16 bit DAC nor its consumption and availability. Being myself analog educated, I appreciate Premelec idea.
 

Benjie

Senior Member
I found a serial 16 bit DAC the AD5660. The 08M2 can read the least 16 bits of the sensor, serial them out to the AD5660 and drive a VF converter.
All this in two tasks which will provide the pulsed audio output.
Any advise?
 

hippy

Technical Support
Staff member
It is possible to consider a DAC operating on the least 16 bits while to avoid jumps the value of the first 8 can be divided by 2 to allow a sufficient span.
No, the difference determination has to be achieved by subtracting two 24-bit averages, but that will be a signed 16-bit value, can be capped to be that, and the audio result will be determined from that after scaling, which should be easy because the full range of PICAXE maths can easily be applied to those signed 16-bit values.
 

hippy

Technical Support
Staff member
This code will calculate a 24-bit average, do a 24-bit subtraction of last from current average, and deliver a signed 16-bit result in 'diff' -

Edited: Code updated from original posted. Fixed subtraction borrow bug, tidied code up, added extra comments.
Code:
#Picaxe 08M2
#Terminal 4800
#No_Data

; Comment the line below to disable SERTXD output
;#Define USE_SERTXD

Symbol reserveW0     = w0
Symbol reserveW1     = w1

Symbol h.average     = w2 ; b5:b4
Symbol m.average     = w3 ; b7:b6
Symbol l.average     = w4 ; b9:b8

Symbol h.average.lsb = b4
Symbol m.average.lsb = b6
Symbol l.average.lsb = b8

Symbol h.average.msb = b5
Symbol m.average.msb = b7
Symbol l.average.msb = b9

Symbol m.last        = w5 ; b11:b10
Symbol l.last        = w6 ; b13:b12

Symbol diff          = w7 ; b15:b14

Symbol h.byte        = b16
Symbol m.byte        = b17
Symbol l.byte        = b18

Symbol counter       = b19

Symbol SAMPLES       = 16

Symbol CMD_RESET     = $1E
Symbol CMD_D1_4096   = $48
Symbol CMD_ADC       = $00

#Define Negative(wVar) wVar >= $8000
#Define Positive(wVar) wVar <  $8000

PowerOnReset:

  HI2cSetup I2CMASTER, %11101110, I2CSLOW, I2CBYTE

MainLoop:

  Do
    h.average = 0
    m.average = 0
    l.average = 0
    For counter = 1 To SAMPLES
      HI2cOut ( CMD_D1_4096 )
      Pause 10
      HI2cOut ( CMD_ADC )
      Pause 10
      HI2cIn ( h.byte, m.byte, l.byte )
      #IfDef SIMULATING
        Random diff
        h.byte = $AB
        m.byte = $CD ^ diff
        l.byte = $EF + diff
      #EndIf
      h.average = h.average + h.byte
      m.average = m.average + m.byte
      l.average = l.average + l.byte
      #IfDef USE_SERTXD
        SerTxd( #counter, TAB, "  " )
        b0 = h.byte : Gosub HexByte
        b0 = m.byte : Gosub HexByte
        b0 = l.byte : Gosub HexByte
        SerTxd( CR, LF )
      #EndIf
    Next

    #IfDef USE_SERTXD
      ; Show the raw averages
      SerTxd( "h", TAB )
      w0 = h.average : Gosub HexWord
      SerTxd( CR,LF, "m", TAB, "  " )
      w0 = m.average : Gosub HexWord
      SerTxd( CR,LF, "l", TAB, "    " )
      w0 = l.average : Gosub HexWord
      SerTxd( CR,LF )
    #EndIf

    ; Combine the numbers
    m.average = m.average + l.average.msb 
    h.average = h.average + m.average.msb

    ; Create m:l sum
    l.average.msb = m.average.lsb
    m.average     = h.average
 
    #IfDef USE_SERTXD
      ; show the sum
      SerTxd( "Sum", TAB )
      w0 = m.average : Gosub HexWord
      w0 = l.average : Gosub HexWord
      SerTxd( CR,LF )
    #EndIf

    ; Find the average
    m.average = $100 / SAMPLES * m.average
    m.average = l.average / SAMPLES / 256 + m.average 
    l.average = $100 / SAMPLES * l.average 

    ; At this point the integer 24-bit average
    ; held in the m.average and l.average pair
    ; as -
    ;       m.average               l.average
    ;.---------------------. .---------------------.
    ;| xwvutsrq | ponmlkji | | hgfedcba | 00000000 |
    ;`---------------------' `---------------------'
    ;  m.avg.msb  m.avg.lsb    l.avg.msb  l.avg.lsb

    ; Now make the numbers lsb aligned -
    ;
    ;       m.average               l.average
    ;.---------------------. .---------------------.
    ;| 00000000 | xwvutsrq | | ponmlkji | hgfedcba |
    ;`---------------------' `---------------------'
    ;  m.avg.msb  m.avg.lsb    l.avg.msb  l.avg.lsb

    l.average.lsb = l.average.msb
    l.average.msb = m.average.lsb
    m.average.lsb = m.average.msb
    m.average.msb = 0

    ; Determine which is highest, this average or last

    If m.average > m.last Then ThisIsHigher
    If m.average < m.last Then LastIsHigher
    If l.average > l.last Then ThisIsHigher
    If l.average < l.last Then LastIsHigher

    BothTheSame:
      diff = 0
      Goto CalculatedDifference

    ThisIsHigher:
      ; Calculate diff = average - last
      m.last = m.average - m.last
      diff   = l.average - l.last
      ; Handle subtraction borrow
      If l.average < l.last Then
        m.last = m.last - 1
      End If
      ; Limit to maximum positive value
      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If
      ; Reult is correctly positive
      Goto CalculatedDifference

    LastIsHigher:
      ; Calculate diff = last - average
      m.last = m.last - m.average
      diff   = l.last - l.average
      ; Handle subtraction borrow
      If l.last < l.average Then
        m.last = m.last - 1
      End If
      ; Limit to maximum positive value
      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If
      ; Make negative, because average - last is
      diff = -diff
      Goto CalculatedDifference

    CalculatedDifference:
      ; last becomes latest average
      m.last = m.average
      l.last = l.average

    ; Show the 24-bit hex averages
    SerTxd( "Avg(", #SAMPLES, ")", TAB )
    b0 = m.average.lsb : Gosub HexByte
    w0 = l.average     : Gosub HexWord
    ; Show the 16-bit decimal average
    SerTxd( TAB, #l.average, TAB )
    ; Show the signed difference
    If diff = 0 Then
      SerTxd( "=")
    Else
      w0 = diff : Gosub SignedWord
    End If
    SerTxd( CR, LF )

    #IfDef USE_SERTXD
      SerTxd( "===", TAB, "========", CR,LF )
    #EndIf

    Pause 1000
  Loop

HexWord:
  b2 = b1 / 16 : Gosub HexNibble
  b2 = b1      : Gosub HexNibble
HexByte:
  b2 = b0 / 16 : Gosub HexNibble
  b2 = b0
HexNibble:
  b2 = b2 & $0F + "0"
  If b2 > "9" Then : b2 = b2 + 7 : End If
  SerTxd( b2 )
  Return

SignedWord:
  If Negative(w0) Then
    w0 = -w0
    SerTxd( "-", #w0 )
  Else
    SerTxd( "+", #w0 )
  End If
  Return
So, assuming instantaneous difference from last to current is a good enough measure to determine what sound to generate, all that needs to be done is convert the signed 16-bit 'diff' value to an appropriate audio tone.
 
Last edited:

Benjie

Senior Member
I’ll test your code to assess if, once all sertxd’s are omitted, final pause reduced to minimum and the setfreq increased to m8, the execution speed is acceptable.
 

Benjie

Senior Member
in some instances you use the minus sign on words and bytes:
; Make negative, because average - last is
diff = -diff
as far as I know variables cannot have a minus sign. Am I wrong?
 

Benjie

Senior Member
About diff calculation wasn't simpler the previous code:
Code:
  Select Case w0
       
    Case > last : diff = w0 - last : SerTxd( "+", #diff )
    Case < last : diff = last - w0 : SerTxd( "-", #diff )          
    Else :  SerTxd( "=" )

    End Select
 

hippy

Technical Support
Staff member
If Negative(w0) Then ; this line gives syntax error
That's probably because the pre-processor isn't enabled. Use the Options menu, select the Compilers page, and tick the Use Pre-Processor option at the top.

in some instances you use the minus sign on words and bytes: ... as far as I know variables cannot have a minus sign. Am I wrong?
PICAXE numbers can be negated as is being done. PICAXE numbers are generally considered positive only, but it's simply a convention. Two's Complement representation allows a positive number to represent either a positive or negative number. When the msb is set it's negative, when clear it's positive, so a PICAXE word can hold a positive number which ranges from 0 to 65535, or a signed number which ranges from -32768 to +32767. For example, with 3-bit numbers -
Code:
111  7
110  6
101  5
100  4
011  3 ... 011 +3
010  2     010 +2
001  1     001 +1
000  0 ... 000  0
           111 -1
           110 -2
           101 -3
           100 -4    Note adding 1 takes it to -3, and so on to 0, and beyond
What any particular number means depends on how it's being used and how one is displaying it.

010 will always be 2 or +2, but 101 is either 5 or -3 depending if considered unsigned or signed.
About diff calculation wasn't simpler the previous code:
It was simpler earlier, but that wasn't subtracting the last from the average. It wasn't doing the appropriate 24-bit maths, and won't work in the real world, or if we scale things to get the maximum accuracy for our calculations.

The 24-bit calculations will deliver the same results as earlier but won't have any problems when last and average span across 16-bit boundaries.

For example, if your 24-bit average went from AAFE89 to AB012A the 16-bit calculations would consider that a fall of 64863 ...
Code:
Avg(16)  AAFE89  65161
Avg(16)  AB012A  298     -64863
Using 24-bit calculations that is correctly determined to be an increase of 673.
Code:
Avg(16)  AAFE89  65161
Avg(16)  AB012A  298     +673
Like a car oddometerr seen at 99997 then 00002, you've gone forwards 5 miles, not back 99995 miles.
 
Last edited:

Benjie

Senior Member
I still have a lot to learn. At my age (78) sometime is difficult.
I am using the Mac editor because it is much faster than the Windows one. The option menu does not have the preprocessor. I'll move the set to a portable pc and will tick the Use preprocessor option.
 

Benjie

Senior Member
Your code works nicely and fast enough for the final use.
I have however a problem which appeared already in the past codes:
anytime I attempt to use the "diff" to generate a sound, the diff start moving up and down by large amount also in stating conditions. I tried if....then and gosub with same problem in all cases.
Initially I supposed an interference of the 433MHz transmitter but removing it the problem remained.

The sequence of diff in these cases is:
+25
-340
+320
-10
-220
+250
+30
and so on. Removing the if... then : sound 4,(70,30) .....the diff moves up and down steadily by less than 50.

Any idea of what happens?
 

Benjie

Senior Member
To generate a two tone sound I will try to use “diff” at the end of “ThisIsHigher” and “ThisIsLower” just before “GotoCalculateTheDifference”.
Will see if a sound generation sat that level will repeat the diff large change.
 

hippy

Technical Support
Staff member
have however a problem which appeared already in the past codes:
anytime I attempt to use the "diff" to generate a sound, the diff start moving up and down by large amount also in stating conditions.
I seem to recall in previous code you were blocking code execution for a considerable time. So you are probably seeing larger jumps because you are taking longer before taking another reading or, as documented, the sensor really doesn't like being read at an inconsistent rate.

Perhaps post your full code and show what you have.

To generate a two tone sound I will try to use “diff” at the end of “ThisIsHigher” and “ThisIsLower” just before “GotoCalculateTheDifference”.
It shouldn't make one jot of difference; there's no logical reason it should.
 

Benjie

Senior Member
To easy the code reading I omitted most of comments.
The actual code is modified to maximize the speed; it works.
I added two sound codes one on ThisIsHigher and one on ThisIsLower. They execute correctly: see the code.
Code:
PowerOnReset:

  HI2cSetup I2CMASTER, %11101110, I2CSLOW, I2CBYTE

MainLoop:

  Do
    h.average = 0
    m.average = 0
    l.average = 0
    For counter = 1 To SAMPLES
      HI2cOut ( CMD_D1_4096 )
      Pause 20
      HI2cOut ( CMD_ADC )
      Pause 20
      HI2cIn ( h.byte, m.byte, l.byte )
    
      h.average = h.average + h.byte
      m.average = m.average + m.byte
      l.average = l.average + l.byte
    Next

    ; Combine the numbers
    m.average = m.average + l.average.msb 
    h.average = h.average + m.average.msb

    ; Create m:l sum
    l.average.msb = m.average.lsb
    m.average     = h.average


    ; Find the average
    m.average = $100 / SAMPLES * m.average
    m.average = l.average / SAMPLES / 256 + m.average 
    l.average = $100 / SAMPLES * l.average 

    l.average.lsb = l.average.msb
    l.average.msb = m.average.lsb
    m.average.lsb = m.average.msb
    m.average.msb = 0

    ; Determine which is highest, this average or last

    If m.average > m.last Then ThisIsHigher
    If m.average < m.last Then LastIsHigher
    If l.average > l.last Then ThisIsHigher
    If l.average < l.last Then LastIsHigher

    BothTheSame:
      diff = 0
      Goto CalculatedDifference

    ThisIsHigher:
      ; Calculate diff = average - last
      m.last = m.average - m.last
      diff   = l.average - l.last
   
      sound 4,(60,20)
      pause 10

      ; Handle subtraction borrow
      If l.average < l.last Then
        m.last = m.last - 1
      End If
      ; Limit to maximum positive value
      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If
      ; Reult is correctly positive
      Goto CalculatedDifference

    LastIsHigher:
      ; Calculate diff = last - average
      m.last = m.last - m.average
      diff   = l.last - l.average

       sound 4,(100,20)
       pause 10

      ; Handle subtraction borrow
      If l.last < l.average Then
        m.last = m.last - 1
      End If
      ; Limit to maximum positive value
      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If
      ; Make negative, because average - last is
      diff = -diff
      Goto CalculatedDifference

    CalculatedDifference:
      ; last becomes latest average
      m.last = m.average
      l.last = l.average

    ; Show the 24-bit hex averages
    'SerTxd( "Avg(", #SAMPLES, ")", TAB )
    b0 = m.average.lsb ': Gosub HexByte
    w0 = l.average     ': Gosub HexWord
    ; Show the 16-bit decimal average
    'SerTxd( TAB, #l.average, TAB )
    ; Show the signed difference
    'If diff = 0 Then
      'SerTxd( "=")
    'Else
      w0 = diff : Gosub SignedWord
    'End If
    SerTxd( CR, LF )

    Pause 50
  Loop

HexWord:
  b2 = b1 / 16 : Gosub HexNibble
  b2 = b1      : Gosub HexNibble
HexByte:
  b2 = b0 / 16 : Gosub HexNibble
  b2 = b0
HexNibble:
  b2 = b2 & $0F + "0"
  If b2 > "9" Then : b2 = b2 + 7 : End If
  SerTxd( b2 )
  Return

SignedWord:
  If w0>= $8000  Then
    w0 = -w0
    SerTxd( "-", #w0 )
  Else
    SerTxd( "+", #w0 )
  End If
  Return
The "diff" result is:
-39
+34
-18
-12
+35
+1
-44
-1
+80

If I add a if..then...else code to "diff" to establish a threshold to diff to have no sounds for a "diff" value lower than 100:
Code:
   if diff > 100 then
      sound 4,(60,20)
   else
       low 4
   endif
      pause 10
I get:

+297
+146
+6
-445
+315
+99
-448
+303
+151
+59
-432
+321
This test is made with just a pull-up 4.7K resistor on C.4.

Do you see a reason for that?
 

hippy

Technical Support
Staff member
Do you see a reason for that?
I would guess it does come down to consistency of read rates. The more consistent the read rate the more stable the readings are.

Your "play a sound for some time otherwise set the pin low" does not however have consistent timing; playing a sound takes far longer than setting the pin low. A "Sound(note,20)" will play for around 200ms, so you have a loop time of about 250 ms when a tone is produced, just 50ms when it isn't.

You need to make the timing consistent.

That is fairly easy to do. First remove the tone generating code you added within the "ThisIsHigher" and "LastIsHigher" parts. Replace your 'Pause 50' at the end of the loop with 'Gosub GenerateTone'.

Now we need a GenerateTone routine, like that below. Add that at the end of the program or after the main loop 'Loop' command -
Code:
Symbol TONE_PERIOD = 5   ; 50ms
Symbol MIN_DIFF    = 100

GenerateTone:
  ; Negate diff because a rising pressure means
  ; a falling height
  diff = -diff
  If Negative(diff) Then
    ; We are falling (negative)
    w0 = -diff
    If w0 > MIN_DIFF Then
      Sound C.4, ( 60, TONE_PERIOD )
      Return
    End If
  Else
    ; We are rising (positive)
    w0 = diff
    If w0 > MIN_DIFF Then
      Sound C.4, ( 100, TONE_PERIOD )
      Return
    End If
  End If
  ; We haven't returned, so haven't issued a tone so
  ; far. Issue silence so we have consistent timing.
  Sound C.4, ( 0, TONE_PERIOD )
  Return
 

Benjie

Senior Member
Excellent! You spotted the issue. Now it responds correctly with no sound in static conditions and beeps with the correct tone moving as little as 30 cm up and down. I connected a hearphone on C.4 instead of the transmitter to avoid RF interference. I have two options for it: a 433MHz data unit or a 100 MHz FM audio transmitter. I will evaluate the best.
Here the full code:
Code:
#Picaxe 08M2
#Terminal 9600
#No_Data
setfreq m8

Symbol reserveW0     = w0
Symbol reserveW1     = w1

Symbol h.average     = w2 ; b5:b4
Symbol m.average     = w3 ; b7:b6
Symbol l.average     = w4 ; b9:b8

Symbol h.average.lsb = b4
Symbol m.average.lsb = b6
Symbol l.average.lsb = b8

Symbol h.average.msb = b5
Symbol m.average.msb = b7
Symbol l.average.msb = b9

Symbol m.last        = w5 ; b11:b10
Symbol l.last        = w6 ; b13:b12

Symbol diff          = w7 ; b15:b14

Symbol h.byte        = b16
Symbol m.byte        = b17
Symbol l.byte        = b18

Symbol counter       = b19

Symbol SAMPLES       = 4

Symbol CMD_RESET     = $1E
Symbol CMD_D1_4096   = $48
Symbol CMD_ADC       = $00

Symbol TONE_PERIOD = 5   ; 50ms
Symbol MIN_DIFF    = 100

#Define Negative(wVar) wVar >= $8000
#Define Positive(wVar) wVar <  $8000

PowerOnReset:

  HI2cSetup I2CMASTER, %11101110, I2CSLOW, I2CBYTE

MainLoop:

  Do
    h.average = 0
    m.average = 0
    l.average = 0
    For counter = 1 To SAMPLES
      HI2cOut ( CMD_D1_4096 )
      Pause 20
      HI2cOut ( CMD_ADC )
      Pause 20
      HI2cIn ( h.byte, m.byte, l.byte )

      h.average = h.average + h.byte
      m.average = m.average + m.byte
      l.average = l.average + l.byte
    Next

    m.average = m.average + l.average.msb 
    h.average = h.average + m.average.msb

    l.average.msb = m.average.lsb
    m.average     = h.average

    m.average = $100 / SAMPLES * m.average
    m.average = l.average / SAMPLES / 256 + m.average 
    l.average = $100 / SAMPLES * l.average 
 
    l.average.lsb = l.average.msb
    l.average.msb = m.average.lsb
    m.average.lsb = m.average.msb
    m.average.msb = 0

    If m.average > m.last Then ThisIsHigher
    If m.average < m.last Then LastIsHigher
    If l.average > l.last Then ThisIsHigher
    If l.average < l.last Then LastIsHigher

    BothTheSame:
      diff = 0
      Goto CalculatedDifference

    ThisIsHigher:
      m.last = m.average - m.last
      diff   = l.average - l.last
      If l.average < l.last Then
        m.last = m.last - 1
      End If
      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If

      Goto CalculatedDifference

    LastIsHigher:
      m.last = m.last - m.average
      diff   = l.last - l.average

      If l.last < l.average Then
        m.last = m.last - 1
      End If

      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If
      diff = -diff

      Goto CalculatedDifference

    CalculatedDifference:
      m.last = m.average
      l.last = l.average

    b0 = m.average.lsb ': Gosub HexByte
    w0 = l.average     ': Gosub HexWord
      w0 = diff : Gosub SignedWord

    SerTxd( CR, LF )

    Pause 50

    Gosub GenerateTone
  Loop

HexWord:
  b2 = b1 / 16 : Gosub HexNibble
  b2 = b1      : Gosub HexNibble
HexByte:
  b2 = b0 / 16 : Gosub HexNibble
  b2 = b0
HexNibble:
  b2 = b2 & $0F + "0"
  If b2 > "9" Then : b2 = b2 + 7 : End If
  SerTxd( b2 )
  Return
 
 GenerateTone:
  diff = -diff
  If diff >= 8000 Then
    w0 = -diff
    If w0 > MIN_DIFF Then
      Sound C.4, ( 60, TONE_PERIOD )
      Return
    End If
  Else
    w0 = diff
    If w0 > MIN_DIFF Then
      Sound C.4, ( 100, TONE_PERIOD )
      Return
    End If
  End If
  Sound C.4, ( 0, TONE_PERIOD )
  Return
 

hippy

Technical Support
Staff member
Code:
 GenerateTone:
  diff = -diff
  If diff >= 8000 Then
That last line should be "If diff >= $8000 Then" but, other than that, it is good to know it's working.

With the tone generation moved to its own routine it will be easier to adjust the tone so it reflects how much it's rising or falling.
 

Benjie

Senior Member
I didn’t find in the manuals the meaning of the $ sign. I bet it means hexadecimal value while no sign is decimal. Additionally I am confused about # and %. Can you enlight me?
 

hippy

Technical Support
Staff member
The $ sign indicates the number which follows is hexadecimal, % indicates it is binary.

The # is used within commands to indicate that a number should be output ( or received ) as a string of characters which represent a decimal value.
 

Benjie

Senior Member
Hippy, I think the project can be considered completed. Now the users may decide to add a RF transmitter or just a loudspeaker if used for paragliding or delta flights.
The code is:
Code:
#Picaxe 08M2
#Terminal 4800
#No_Data

setfreq m8
Symbol reserveW0     = w0
Symbol reserveW1     = w1

Symbol h.average     = w2 ; b5:b4
Symbol m.average     = w3 ; b7:b6
Symbol l.average     = w4 ; b9:b8

Symbol h.average.lsb = b4
Symbol m.average.lsb = b6
Symbol l.average.lsb = b8

Symbol h.average.msb = b5
Symbol m.average.msb = b7
Symbol l.average.msb = b9

Symbol m.last        = w5 ; b11:b10
Symbol l.last        = w6 ; b13:b12

Symbol diff          = w7 ; b15:b14

Symbol h.byte        = b16
Symbol m.byte        = b17
Symbol l.byte        = b18

Symbol counter       = b19

Symbol TONE_PERIOD = 5   ; 50ms
Symbol MIN_DIFF    = 100

Symbol SAMPLES       = 8

Symbol CMD_RESET     = $1E
Symbol CMD_D1_4096   = $48
Symbol CMD_ADC       = $00

PowerOnReset:

  HI2cSetup I2CMASTER, %11101110, I2CSLOW, I2CBYTE

MainLoop:

  Do
    h.average = 0
    m.average = 0
    l.average = 0
    For counter = 1 To SAMPLES
      HI2cOut ( CMD_D1_4096 )
      Pause 20
      HI2cOut ( CMD_ADC )
      Pause 20
      HI2cIn ( h.byte, m.byte, l.byte )

      h.average = h.average + h.byte
      m.average = m.average + m.byte
      l.average = l.average + l.byte

    Next

    ; Combine the numbers
    m.average = m.average + l.average.msb 
    h.average = h.average + m.average.msb

    ; Create m:l sum
    l.average.msb = m.average.lsb
    m.average     = h.average

    ; Find the average
    m.average = $100 / SAMPLES * m.average
    m.average = l.average / SAMPLES / 256 + m.average 
    l.average = $100 / SAMPLES * l.average 

    ; At this point the integer 24-bit average
    ; held in the m.average and l.average pair
    ; as -
    ;       m.average               l.average
    ;.---------------------. .---------------------.
    ;| xwvutsrq | ponmlkji | | hgfedcba | 00000000 |
    ;`---------------------' `---------------------'
    ;  m.avg.msb  m.avg.lsb    l.avg.msb  l.avg.lsb

    ; Now make the numbers lsb aligned -
    ;
    ;       m.average               l.average
    ;.---------------------. .---------------------.
    ;| 00000000 | xwvutsrq | | ponmlkji | hgfedcba |
    ;`---------------------' `---------------------'
    ;  m.avg.msb  m.avg.lsb    l.avg.msb  l.avg.lsb

    l.average.lsb = l.average.msb
    l.average.msb = m.average.lsb
    m.average.lsb = m.average.msb
    m.average.msb = 0

    ; Determine which is highest, this average or last

    If m.average > m.last Then ThisIsHigher
    If m.average < m.last Then LastIsHigher
    If l.average > l.last Then ThisIsHigher
    If l.average < l.last Then LastIsHigher

    BothTheSame:
      diff = 0
      Goto CalculatedDifference

    ThisIsHigher:
      ; Calculate diff = average - last
      m.last = m.average - m.last
      diff   = l.average - l.last
      ; Handle subtraction borrow
      If l.average < l.last Then
        m.last = m.last - 1
      End If
      ; Limit to maximum positive value
      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If
      ; Reult is correctly positive
      Goto CalculatedDifference

    LastIsHigher:
      ; Calculate diff = last - average
      m.last = m.last - m.average
      diff   = l.last - l.average
      ; Handle subtraction borrow
      If l.last < l.average Then
        m.last = m.last - 1
      End If
      ; Limit to maximum positive value
      If m.last > 0 Then
        diff = $7FFF
      Else
        diff = diff max $7FFF
      End If
      ; Make negative, because average - last is
      diff = -diff
      Goto CalculatedDifference

    CalculatedDifference:
      ; last becomes latest average
      m.last = m.average
      l.last = l.average

    'If diff = 0 Then
      'SerTxd( "=")
    'Else
      w0 = diff ': Gosub SignedWord
    'End If
    'SerTxd( CR, LF )
Gosub GenerateTone
  Loop
  
  GenerateTone:

  ; Negate diff because a rising pressure means
  ; a falling height
  diff = -diff
  If diff >= $8000  Then
    ; We are falling (negative)
    w0 = -diff
    If w0 > MIN_DIFF Then
      Sound C.4, ( 50, TONE_PERIOD )
      Return
    End If
  Else
    ; We are rising (positive)
    w0 = diff
    If w0 > MIN_DIFF Then
      Sound C.4, ( 110, TONE_PERIOD )
      Return
    End If
  End If
  ; We haven't returned, so haven't issued a tone so
  ; far. Issue silence so we have consistent timing.
  Sound C.4, ( 0, TONE_PERIOD )
  Return

SignedWord:
  If w0 >= $8000  Then
    w0 = -w0
    SerTxd( "-", #w0 )
  Else
    SerTxd( "+", #w0 )
  End If
  Return
The photo and circuit diagram are attached.
A big THANK YOU HIPPY is largely deserved!
 

Attachments

Benjie

Senior Member
Additional information for remote audio: two types of transmitter can be used depending upon the receiver.
If a handheld UHF receiver is used, like the Baufeng R5, it is better to use a 433 MHz FSK transmitter.
In the other cases the use of a ASK transmitter demands an ASK receiver.
Note that the photos do not include the transmitter.
Enjoy the experimenting.
 
Top