# 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
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.

#### 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.

#### Benjie

##### Senior Member
The project can change to a 5 IC's system: 08M2, I2C Sensor, 16bit DAC, VF IC, TX with only 4 resistors.

#### hippy

##### Technical Support
Staff member
The project can change to a 5 IC's system: 08M2, I2C Sensor, 16bit DAC, VF IC, TX with only 4 resistors.
It could probably also be a three IC system using just the sensor and two PICAXE.

#### 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

#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
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
SignedWord:
If Negative(w0) Then ; this line gives syntax error
w0 = -w0
SerTxd( "-", #w0 )

#### 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.

#### hippy

##### Technical Support
Staff member
I am using the Mac editor because it is much faster than the Windows one
To keep you going; you can change the "If Negative(w0) Then" line to -

If w0 >= \$8000 Then

And just comment out the two #DEFINE commands

#### 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
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
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 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
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 # 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

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
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

• 74 KB Views: 8
• 23.5 KB Views: 8
• 23.5 KB Views: 6

#### 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.