Has anyone tried ultrasonic distance measurement by PICAXE alone, not using SRF005 etc ?

Buzby

Senior Member
Hi All,

I'm tempted to try building a location system, a sort of cut down version of the one I linked to a couple of years ago ...

https://picaxeforum.co.uk/threads/erco-another-toy-for-you-you-will-need-to-sweet-talk-the-wife-though.30120/

The basic idea is that two devices at fixed locations can be used to determine the location of a third device, if the distances to it from each fixed device are known.

My first attempt would be a master PICAXE with two independant US transmitters ( A & B ) about 20m apart, and a third mobile PICAXE would have a US reciever.

The idea is that the master sends a sync signal to the mobile, via RF or IR, at the start of a US pulse from A or B, which enables the mobile device to determine the distance to the relevant transmitter.

The maths is not complex, but will still need a lot of coercion to run in PICAXE BASIC. My main concern is the sync signal and US timing.

Could a PICAXE measure the time between the sync pulse and the reception of the US in a reliable and repeatable manner ?

Has anyone tried anything like this, or have a better idea of how to solve it ?

Cheers,

Buzby
 

hippy

Senior Member
I recall there has been discussion on the forum about creating an SRF004 with just a PICAXE.

The theory is simply enough; put a burst of 40kHz pulses into the transmitting piezo, then start timing until the first pulse comes back. That time can be adjusted to how long it took for the first sent to arrive, and distance can be calculated from that -
Code:
Output ___||||||__________________
          
Input  __________________||||||___

          |    |<-- t -->|
          |              |
          |<------------>|
As the signal is 40kHz, that's a period of 25us, 12.5us on, 12.5us off.

In theory one can even do it with just a single (10us) pulse which is easier to do with a PICAXE.-
Code:
Do
  w0 = 0
  PulseOut TX, 1
  Do
    w0 = w0 + 1
  Loop Until PinRX = 1
  SerTxd( #w0 )
Loop
The three problems are; 'ringing', that the initial TX feeds-back to the RX so one needs a short delay after sending the pulse, 'pulse shaping', having to amplify and clean-up what is received, and 'calculating', determining how whatever is returned represents a distance. That isn't so important if one is only after "is something closer than some distance"; just determine what the value read for that distance is, and then compare against that value without any regard to how the two relate.

I believe the conclusion is it could be done, but it wasn't as reliable or consistent as an SRF004 designed for the job. But I guess one could replicate all that an SRF004 has.

What you suggest for triangulation does appear to be possible, but I think turning it into reality could be challenging. A and B could be normal SRF004, A gives a pulse, ignores the echo, M, also an SRF004, receives the pulse then sends its own pulse some fixed time later, A receives that and can determine a distance between A and M. Tells B to fire and can see what that elicits.
Code:
A sends    ___|__________ ______________________

B sends    ______________ ___|__________________

                A   M         B       M
A receives _____|___|____ ____|_______|_________


               A     M         B      M
M receives ____|_____|___ _____|______|_________

M sends    _______|______ ________|_____________
You would probably need to tap into each SRF004 RX to see pulses other than those emitted from the same sensor.

I think it's one of those things you are going to have to try to see if it can work. I would not want to try it without a DSO or logic analyser so you can see exactly what's going on with the hardware.
 

Buzby

Senior Member
Hi hippy,

I toyed with the idea of hacking some SRF004 devices to utilise just their analogue bits, and after reading the .pdf it looks like it would be a solution to the hardware side of things.

https://www.robot-electronics.co.uk/files/srf1.pdf

My first experiment will be to see if one SRF004 can detect the other at 20m. ( I might need to change the TX side to use +- 12v )

A gives a pulse, ignores the echo, M, also an SRF004, receives the pulse then sends its own pulse some fixed time later, A receives that and can determine a distance between A and M. Tells B to fire and can see what that elicits.
This is where two heads are better than one !.

I envisaged M as measuring the time between an RF sync pulse and the US pulse.

Your solution effectively turns the M device into a 'reflector', and the fixed devices measure the round trip time, just like RADAR.

Time for a dig in my bits box to see if I've got any SFR004s, if not I'll buy a few.

Further updates will be forthcoming, maybe in a week or two.

Cheers,

Buzby
.
 

erco

Senior Member
Good call on using two existing sensors, Buzby. Using one to transmit the pulse and the other to receive sounds like a plan. I wonder if you could use IR to trigger the process without running wires everywhere. Could be as simple as the master unit initiates ranging by sending a Sony IR code. When the remote slave detects the IR, it sends an ultrasonic burst back to the master. Sound/ultrasonic is glacially slow in comparison to lightspeed IR, which can be ignored. Plenty of latency timing issues to work out (IR receivers have built-in lag), but the concept is sound. I'll leave it to you and Alleycat to suss out the technical details. :)
 

techElder

Well-known member
Ultrasonics is fraught with real world problems that get masked in normal use because folks using them are generally in a controlled environment.

"Time-of-flight" changes with temperature, humidity and even the surfaces the echo is reflected from (not to mention the signal reflection degradation based on the surfaces involved.) Challenging to say the least.

Look up the details on the old Texas Instruments / Polaroid instant camera electronics for good information. They even used a 300 volt power supply for pulsing the piezo element to get the range.
 

Buzby

Senior Member
Hi Tex,

Yes, it is going to be a challenge to get reliable results, but it will be helped greatly by the fact that I will be using an 'active reflector'.

The variations due to temperature and humidity can be corrected for, but initially I'll ignore them. During a short time period they won't change much. ( Unless it starts raining ! )

The SRF04s have been ordered, so while I'm waiting for delivery I'll start on the software. The triangulation code is . . .
Code:
' Calc angles for triangle ABC
' Angle C = Arccos ((a^2 + b^2 - c^2) / 2ab)
' Angle B = Arccos ((a^2 + c^2 - b^2) / 2ac)
' Angle A = (Pi - C - B )

Where a,b,c are the lengths of the sides opposite each of the angles A,B,C.
As you can see, there are squared values in the equations. If I aim for 5cm resolution over 20m, then I'll need to square scaled values of upto 4000.

4000^2 = 16,000,000 which is well out of the PICAXE maths capabilities, so I'll need some 32 bit maths, including an Arccos function.

I'm hoping there are some in 'Code Snippets' :)

Cheers,

Buzby
 

AllyCat

Senior Member
Hi,
I'm hoping there are some in 'Code Snippets' :)
Yes, but a forum search might not find the relevant thread. ;)

They use lookup tables (with interpolation) which could be accurate to around 0.01 degree (the number of reference points is flexible). However, ATAN2 is often the most useful function for "navigation" because it gives a unique solution for each "bearing" (i.e. revolution 0 - 360 degrees). A problem with ASIN and ACOS is that they can give two solutions for most input values, e.g. COS 60 degrees = COS 300 degrees (= 0.5).

It's a very long time since I worked with "raw" Ultrasonic transducers, but in those days there were two distinct types: Transmitters and Receivers. The Transmitters had a relatively high Q so virtually set the resonant (transmitting) frequency. The Receivers were more like "microphones" with a wide bandwidth, so could work with any Transmitter. In my "Time of Flight" project I needed to repeatedly Reverse the acoustic path direction, so found that using two Receivers was necessary/optimum. But my range was quite short, so your needs may be different. You haven't said much about your application, but don't forget that (a normal advantage of ultrasonics is that ) the transducers do not emit or respond in narrow beams, so "echoes" (from off-axis objects) can have a considerable influence.

Cheers, Alan.
 

Buzby

Senior Member
... It's a very long time since I worked with "raw" Ultrasonic transducers, but in those days there were two distinct types: Transmitters and Receivers.
Yes, I gathered that by looking at the SRF04 circuit, it uses two different devices for TX and RX, N1076 and N1081. My plan is to remove the CPU chip from the SRF04, then wire some 28X2 I/O pins in its place.

Regarding echoes, I expect an echo to arrive some time later than the direct signal, so I should be able to filter it out.

I'm confident that all this can be done, because the MarvelMind system does it already. However, it could be that the software will let me down, both in speed and capabilities, but pushing the PICAXE envelope is what I like to do !.

Cheers,

Buzby
 

hippy

Senior Member
My plan is to remove the CPU chip from the SRF04, then wire some 28X2 I/O pins in its place.
My initial plan would be to keep the SRF04 as it is, use the normal trigger mechanism to generate the pulse, and then just split the incoming signal back to the PICAXE -
Code:
       .--------.      |\    _|
>----->| Trig   |------| >--|_|
       |        |      |/     |
       |        |
       |        |       /|   _|
     <-| Echo   |<--.--< |--|_|
       `--------'   |   \|    |
                    |
<-------------------'
That way you still have usable SRF04 if it doesn't work out.
 

Buzby

Senior Member
Great, that's a less intrusive method !.

I might need to chop the board about a bit if more voltage is needed for the TX, but let's see how it behaves 'en naturel'.

The maths is giving me a lot of headaches. Last night I enlisted the help of an expert in maths to advise about the Arccos, and even he couldn't see how a PICAXE could do it without using a lookup method.

So, if the hardware tests come out OK, I might have to jump ship and use something else, ( but it won't be an A*** ).

Cheers,

Buzby
 

hippy

Senior Member
The maths is giving me a lot of headaches. Last night I enlisted the help of an expert in maths to advise about the Arccos, and even he couldn't see how a PICAXE could do it without using a lookup method.
Maybe you don't need ACOS, just help from Pythagoras -
Code:
    M
   /|\
  / | \
 /__|__\
A   X   B
AM2 = AX2 + MX2
BM2 = BX2 + MX2

Given we know AB, AM and BM, if I'm remembering correctly, it should be possible to determine MX, AX and BX. Simultaneous equations ?
 

Buzby

Senior Member
Not sure about this idea.

X is only known ( as 1/2 AB ) if AM = BM, ie. an isosceles triangle.

If AM <> BM then the triangle is scalene, and X is not known, so no help there from Pythagoras.

However, there might be some mileage in exploring this idea further, maybe seeing if it's possible to determine X just with SIN and COS.

Cheers,

Buzby
 

AllyCat

Senior Member
Hi,
... even he couldn't see how a PICAXE could do it without using a lookup method.
What's wrong with a Lookup method? ;) The SIN, COS and TAN (<45 degrees) transfer characteristics are not too "sharp", so piecewise linear (interpolation) is fine. My PICaxe sunrise/sunset calculator (using pure Trigonometry) is good to a minute (of time) per day, even at quite high latitudes.

What coordinate system do you want for the results, R-Theta (Distance-Bearing) or X-Y (Long.-Lat.)?

My concern about using Pythagoras is how to calculate the Square Root? That isn't easy with a lookup table, particularly if you need a 32-bit input. Again, I did write some 32-bit maths code snippets (particularly for the BMP280 sensor) , but they didn't include a Square Root function. :(

Cheers, Alan.
 

Buzby

Senior Member
Hi Alan,

Thanks for your input. The 32 bit stuff you've written is what I am looking to use as the basis for the code, but wasn't certain if Arccos was feasable.

My first objective is to generate the X/Y coordinates of the mobile unit relative to the baseline through AB. This just needs 32 bit maths and the Arccos function.

Once I'm happy that this works then I can move onto more complex arrangements with multiple base units, but I don't think I will need any new functions after Arccos, the rest will be just more of the same.

If I do eventually need a square root, I might just have to resort to calculating it on-the-fly ( https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method )

But, easy steps first !.

Cheers,

Buzby
 

hippy

Senior Member
X is only known ( as 1/2 AB ) if AM = BM, ie. an isosceles triangle.
True, I should have drawn a more slopey triangle, and perhaps labelled it differently ...
Code:
   /|`.
 a/ |  `.b
 /  |h   `.
'___|______`.
  A      B
`-----D-----'
a2 = A2 + h2
b2 = B2 + h2

h2 = a2 - A2
h2 = b2 - B2

a2 - A2 = b2 - B2

a2 - A2 = b2 - (D-A)2

A2 - (D-A)2 = a2 - b2

A is the single unknown so I'm pretty sure it could be shaken out without reverting to trig. But I can't remember how to and I accept I might be wrong.
 

hippy

Senior Member
If I do eventually need a square root, I might just have to resort to calculating it on-the-fly ( https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method )
Seems quite easy, apart from an error with SQRT(1) = 0 ...
Code:
Symbol test   = w0
Symbol number = w1
Symbol root   = w2
Symbol last   = w3

For test = 0 To 255
  number = test * test
  Gosub FindSquareRoot
  SerTxd( "SQRT(", #number, ") = ", #root, " ", #test, CR, LF )
Next
End

FindSquareRoot:
  root = number / 2
  Do
    last = root
    root = number / last + last / 2
  Loop until last = root
  Return
That should be quite easy to extend to larger than 16-bit, but one could go round that loop quite a few times. There are some tricks in choosing a better starting guess which can limit the number of iterations. I am sure there are also faster algorithms which aren't overly complicated.
 
Last edited:

Buzby

Senior Member
Hippy, on that Wikipedia page, under digit-by-digit, is a binary version, all shifts and ORs.

Much more suited to your bit twiddling skills !.

( I'm not trying it, I've not got the hardware working yet ! )
 

Buzby

Senior Member
True, I should have drawn a more slopey triangle, and perhaps labelled it differently ...
Code:
   /|`.
a/ |  `.b
/  |h   `.
'___|______`.
  A      B
`-----D-----'
a2 = A2 + h2
b2 = B2 + h2

h2 = a2 - A2
h2 = b2 - B2

a2 - A2 = b2 - B2

a2 - A2 = b2 - (D-A)2

A2 - (D-A)2 = a2 - b2

A is the single unknown so I'm pretty sure it could be shaken out without reverting to trig. But I can't remember how to and I accept I might be wrong.
Expanding (D - A)2 gives ...

(D - A)2 = D2 - 2AD - A2 , I think

Putting this into your last equation gives ....

A2 - D2 + 2AD + A2 = a2 - b2

rearranged ...

A2 = ( a2 - b2 + D2 + 2AD ) / 2

Assuming I've not made a mistake, it does look like A or B can be calculated without trig.
If h can be done as easily, which I think it can be once A or B are found, then the XY coords are A,h

Does this make sense, or have I got a sign wrong somewhere ?

Cheers,

Buzby
 

AllyCat

Senior Member
Hi,
. If I aim for 5cm resolution over 20m, then I'll need to square scaled values of up to 4000.
I make that 400, so 16 bits might be sufficient. :)

(D - A)^2 = D^2 - 2AD - A^2 , I think
[ Aside: How did you superscript the 2s ? ;) ]

No, it should be (D - A)^2 = D^2 - 2AD + (plus) A^2

Yes, as hippy said, it should be possible to do it all with Pythagoras (only) and I quite like the idea of a Square Root function using "digit-by-digit" in pure binary. But I'm not sure I can see if 32 bits can be done within my (self-imposed) constraint of using a maximum of 7 bytes of RAM (variables), as I did with my 32 bit divison and interpolated Trig functions, etc..

EDIT:
rearranged ...
A^2 = ( a^2 - b^2 + D^2 + 2AD ) / 2
There's still an "A" on the right-hand-side, so maybe not that easy to solve. :(

Cheers, Alan.
 
Last edited:

Buzby

Senior Member
Hi Alan,

It's good to see someone spotted my mistake. I was so busy getting a single A on the left I didn't notice the one on the right !.

I think your right about the 400 v 4000 as well. Feet and inches at least had different powers for everything, whereas SI lengths seem to choose 100 or 1000 on a whim.

Superscripting is done like this ( omit the obvious spaces ) .... [ s u p ] number [ / s u p ]

On the web somewhere is an explanation of a bit-by-bit binary squaring algorithm, as well as the square root algorithm found earlier.

I'll have another look tonight, still at work now.

Cheers,

Buzby
 

hippy

Senior Member
Expanding (D - A)2 gives ...

(D - A)2 = D2 - 2AD - A2 , I think
Walks to face corner, having forgotten the basics. I'll blame it on being late in the day. But that's why teamwork's great.

Aside: How did you superscript the 2s ?
Superscripting is done like this ( omit the obvious spaces ) .... [ s u p ] number [ / s u p ]
As said n[sup]2[/sup] = n2

Though a slighter smaller superscript is probably better, n[sup][size=1]2[/size][/sup] = n2

And to display the [sup]..[/sup], that's [plain][sup]..[/sup][/plain]

And to display that is [plain][plain][sup]..[/sup][/plain][/plain] !

There's also [sub]...[/sub] for subscripts.

Our list of 'BB Codes' is under Help at the bottom of the page -

https://picaxeforum.co.uk/help/bb-codes

[size=7] gets an instant ban.

Only joking, but it probably will get mod edited unless there's a really good excuse for using it :)
 

hippy

Senior Member
Hippy, on that Wikipedia page, under digit-by-digit, is a binary version, all shifts and ORs
Thanks for that. That looked familiar, but still can't find my own code which I am sure I created some time ago, but easy enough to convert what Wikipedia has -
Code:
Symbol reserveW0 = w0
Symbol test      = w1
Symbol number    = w2
Symbol root      = w3
Symbol bits      = w4

For test = 0 To 255
  number = test * test
  Gosub FindSquareRoot
  number = test * test
  SerTxd( "SQRT(", #number, ") = ", #root, " ", #test, CR, LF )
Next
End

FindSquareRoot:
  root = 0
  bits = $4000
  Do While bits > number
    bits = bits / 4
  Loop
  Do While bits <> 0
    w0 = root + bits
    If number >= w0 Then
      number = number - w0
      root = root / 2 + bits
    Else
      root = root / 2
    End If
    bits = bits / 4
  Loop
  Return
 

Buzby

Senior Member
Well, it looks like the maths is certainly possible on the PICAXE. Now I just need to wait for my ultrasonics to arrive.

Thanks all for your help !

Cheers,

Buzby
 

hippy

Senior Member
Yay; A = ( a2 - b2 + D2 ) / 2D

Not a single square root or trig function in sight, only squares and they are easy enough to calculate. The division shouldn't be too hard and there is only one.

Though we haven't asked whether finding A, or B, is even useful for what you are doing :)
 

Buzby

Senior Member
Either A or B will do, that's the X coordinate. Then find h, that's the Y coordinate. Job done !.
 

AllyCat

Senior Member
Hi,

Yay; A = ( a2 - b2 + D2 ) / 2D
Yes, I found that one; BTW I've swapped the case of D and h (to d and H) so that the Lower Case characters are "knowns" and the Upper Case "unknowns" (the other way around would be better but it could get confusing swapping A with a, etc.).

Unfortunately, I think "H" is also required, which I can't see how to calculate without a (32-bit) Square Root function. :(

My preference* is for a "Trig" solution, but I haven't managed to solve the simultaneous equations yet. ;)

Cheers, Alan.

*EDIT: To qualify that statement: Even a 1 : 400 input resolution will probably require 32-bit maths (or at least >16 bits) for a Pythagorean solution, whilst my interpolated Trig. lookup table can handle a 1 : 4,000 input, even in the "Forward Lookup" direction (16 line segments of 256 points). That only needs a 17-point ACOS table to be created, or a "Reverse Lookup" version (more accurate but slower) is already written !

So I already have a fully-coded "hybrid" solution, using the 32-bit maths subroutines for "A" and then a Trig. calculation for "H", but would prefer something rather more "elegant". ;)
 
Last edited:

Buzby

Senior Member
Hi Alan,

Hippy's solution worked by dropping a perpendicular and then finding where it bisected the base line.

If the bisection points of the other two perpendiculars were calculated, could the length of 'h' be found somehow ?

I'm not able to calculate it, so I'll leave it to the experts !.

If we don't come up with a solution by the time my ultrasonics arrive, then we might just have to go with your hybrid version.

Thanks again for your help,

Buzby
 

AllyCat

Senior Member
Hi,
[....Babylonian_method...] Seems quite easy, apart from an error with SQRT(1) = 0 ...
Just for future reference, the code in #18 doesn't appear to work for SQRT (2400) either (and probably others). It hangs (in the simulator), oscillating between 48 and 49, so perhaps a minor rounding issue in the code? But that in #24 (which I'm attempting to adapt) is probably fine. BTW, thanks both, for the tips on [sup]...etc. :) .

I forgot to mention above that the solution in #27 (etc.) also works if A or B > "d" (i.e. B or A can be negative) so it can work "outside the box". Mathematically, there are two solutions, with H positive or negative (i.e. each side of the AB baseline) which is probably a clue that a Square Root is involved in the calculation of H. :)

We "know" the values of "A" and "a" (or B and b) so it's possible to calculate H using Pythagoras - it just needs that annoying SQRT function. I'm looking at a few ideas how to code it "economically", since I'm not very confident that I can work out how to solve the Trig. equation(s). ;)

Cheers, Alan.
 

AllyCat

Senior Member
Hi,

Do you know what "field of view" you'll get from the transducers? The commercial items linked via post #1 appear to use multiple "ports" (or are they Transmit+Receive, or just "styling" ?), but some of the "Ultrasonic Time of Flight" Wind sensors mount the transducers pointing vertically, with a conical reflector to distribute the sound horizontally around 360 degrees.

I've successfully coded a Square Root function using the "32 bit ALU" software that I wrote for the BMP280, etc., but I think shown that it's NOT the best approach. Currently, I'm looking at cobbling together a few of the separate 32-bit Code Snippets which I've contributed over the years (Add, Subtract, Divide, etc.), using a minimum number of register variables (remember 4 bytes are needed for every variable).

Rearranging the formula above (again) as follows may be useful :
A = a2 - b2 / d + d / 2 (working Left to Right as normal PICaxe)

Only the "-" and first division need to work at 32-bits resolution. The divisions may need to be signed, but that's easily done by stripping out any negative values (by complementing) and re-inserting when needed. I think I should have a firm(er) proposal by the time you have any range measurements. ;)

Cheers, Alan.
 
Last edited:

Buzby

Senior Member
Hi Alan,
... Do you know what "field of view" you'll get from the transducers?
No idea at all !.

I was hoping to start work on this tonight, but family stuff getting in the way.

I think I should have a firm(er) proposal by the time you have any range measurements. ;)
Give me till next weekend.

I'm working away, and might attract some unwanted attention if I walk round Heathrow pointing electronic thingies this way and that.

Cheers,

Buzby
 

Buzby

Senior Member
First results ...

DS0005.png

The yellow trace shows the analogue signal received by the 'mobile' SR04, brought out from pin 10 on the SR04 CPU.

The transmitter is about 8m away, the furthest I can get in my hotel room.

The first lobe is the direct signal, and the second is an echo from a wall. ( The source of the echo was determined by using a thick towel to muffle it, but I don't think the hotel will let me nail laundry to the wall.)

The blue trace is the trigger to the 'mobile' transmitter. This is set 15ms after the reception to give time for any reflections to settle, but I may reduce this if it's too much.

The next step is to transfer the 'mobile' from the breadboard to a bit of stripboard, and power it from a USB powerbank.

Then I'll start work on the first base station.

Cheers,

Buzby

Code:
#picaxe 28x2
#no_data
#no_table
       
symbol trig = a.3
symbol echo = b.0
symbol LED0 = a.0

' Interrupt on b.0      
hintsetup %00000001
setintflags %00000001, %00000001

main:            

goto main  

interrupt:
    pause 15
      pulsout trig,8 
    high LED0
    pause 100
    low LED0

      hint0flag = 0
      setintflags %00000001, %00000001        
return     

[\code]
 

AllyCat

Senior Member
Hi,

That's a good start; you're not ready for the navigation calculation code yet, but here's some food for thought. I've devised several Square Root routines, but I hope the one posted below is consistent with the first part of the code.

Firstly, a verification that we do need 32-bit maths: Even without Pythagoras, the basic formula above contains a2 and b2 terms, so 16-bit (Word) calculations will limit a and b to a single byte each. Thus 10 cms would be the best resolution if the maximum range is to be 20 metres. Furthermore, a2 - b2 can easily generate a negative result (and so can the original equation, if the "target" can move outside the length of the baseline), which potentially limits rhe resolution to a sign plus 7 bits (1: 127).

There's no point in going up to less than 32-bits (i.e. Double Words) but this is rather "overkill" - The maths can then resolve to 1 mm units, which keeps the scaling simple, but gives you quite a challenge for the hardware. ;)

The Program/Calculation for A and B (i.e. along the "Y" axis of the two transducers) actually proved quite easy, since I had already documented code snippets for 32-bit subtraction and division (down to a 16-bit word result). Here it is,, with a few extra "hooks", in preparation for adding a Pythagorean calculation for "X". It should be easily fast enough; the simulator produces a result after around 5 seconds.

Code:
; Ultrasonic Triangulation ; AllyCat June 2019
#picaxe 08m2 ;        And most others
#no_data
symbol AL = w1                         ; Low word of Range A
symbol AH = w2                         ; High word of Range A
symbol BL = w3                         ; Low word of Range B
symbol BH = w4                         ; High word of Range B
symbol DL = w5                        ; Baseline spacing
symbol DH = w6                      ; Auxiliary register
symbol rangeA = w1                    ; Input values
symbol rangeB = w3                    ; 
symbol rangeD = w5                    ; Transducer spacing
symbol sign = w4                    ; Sign (flag) used for division subroutine (Overlays BH)

init:
    rangeA = 13000                        ; Test values
    rangeB = 5000
    rangeD = 12000                        ; Transmitter spacing (baseline)
;*  A = a2 - b2 + d2 {s / 2d s}     ; Base formula (s = Signed functions)
;*  A = a2 - b2 [s / d s] + d / 2   ; Revised formula
Yaxis:
    DH = AL                         ; Store for X-Axis Pythagoras calculation
    AH = rangeA ** rangeA            ; High word of A squared
    AL = rangeA * rangeA            ; Low word of A squared
    BH = rangeB ** rangeB                ; High word of B squared
    BL = rangeB * rangeB                ; Low word of B squared
     call subAB:                      ; Calculate AH:AL = AH:AL minus BH:BL   
div32:
    BL = rangeD                     ; Divisor
    call sdiv                                ; Signed division 32 bits / 16 bits := 16 bits
result:
    AL = AL + rangeD
    if AL > 32767 then                ; Negative value
        AL = -AL / 2
        AL = -AL
    else
        AL = AL / 2
    endif   
    sertxd("Y= ",#AL,cr,lf)          ;  Result
     DL = AL                                    ; Store for later

Xaxis:         ; ** Insert Pythagoras program and Additional subroutine here **  
end

; SUBROUTINES:
sdiv:                                     ; 32 bit Signed division
    sign = 0                             ; Use BH for loop counter and sign flag
    if AH > 32767 then                 ; Negative input
        sign = 1
negateA:                               ; Twos complement of AH:AL
        AL = not AL + 1
        AH = not AH
        if AL = 0 then
         inc AH
        endif
    endif           
div31:                                   ; Divide numerator (AH:AL) by divisor (BL)
   for BH = sign to 63  step 4          ; Repeat for 16 bit positions
       AH = AL / 32768 + AH + AH        ; Add carry and shift numerator left (top bit lost)
       AL = AL + AL                    ; Shift done
       if AH >= BL then                ; Skip if can't subtract
          AH = AH - BL                  ; Subtract divisor, then..
          AL = AL + 1                   ; Add the flag into result (in low word)
        endif     
   next BH                                        ; Result in AL, remainder in AH
    if sign = 65 then                  ; Negative result
       AL = -AL
   endif   
return

subAB:                           ; Calculate AH:AL = AH:AL minus BH:BL   
    AH = AH - BH                 ; Subtract high words    :
    if AL < BL then              ; Borrow if minuend < subtrahend
       dec AH                     ; Borrow for low word
    endif      
    AL = AL - BL                 ; Calculate low word
return
Of course we still need a solution for "X", which, notably cannot be "unique" because of symmetry about the baseline (mathematically, remember the square root of a real, positive number can be either positive or negative). Therefore, perhaps the "best" solution is to introduce a third (or more) transducer(s) at right angles to the first two. That can be solved in exactly the same way as for the first two transducers, to give a complete and unique solution. Or four transducers in a square or rectangular pattern permit up to six calculations (four sides and two diagonals) which could be averaged for improved accuracy.

However, here is some additional program code to calculate "X", using Pythagoras. It requires more variable space and takes longer to compute, typically 15 seconds in the simulator.

Code:
Xaxis:                                        ; Pythagoras
symbol rootL = w3                            ; Low word for square root
symbol rootH = w4                            ; High word for square root calculation
symbol bitsL = w5                            ; Low word of bits for square root calc
symbol bitsH = w6                            ; High word of bits for root calculation

    BH = AL ** AL                    ; Square of Y-offset
    BL = AL * AL
    AH = DH ** DH                    ; High word of Hypotenuse
    AL = DH * DH                     ; Low word
     call subAB                         ; Calculate AH:AL = AH:AL minus BH:BL   
squareroot:
    rootH = 0 : rootL = 0       ; Initialise
    bitsH = $4000 : bitsL = 0
;#  Do While bits > number
     do
         if bitsH > AH then shiftbits
        if bitsH < AH then bitsdone
        if bitsL <= AL then bitsdone
shiftbits:                          ; Shift Right by two bits
         call shiftbits2
    loop
bitsdone:
    do while bitsH <> bitsL            ; Loop until both are zero (only 1 bit is ever set)
;#  number = number - root - bits
subroot:                            ; Calculate AH:AL = AH:AL minus rootH:rootL
        AH = AH - rootH             ; Subtract high word
        if AL < rootL then          ; Borrow if minuend < subtrahend
            dec AH                  ; Borrow for low word
        endif      
        AL = AL - rootL             ; Calculate low word
        if AH > 32767 then addroot    ; Already negative so skip to restore      
subbits:                                  ; Calculate AH:AL = AH:AL minus bitsH:bitsL   
        AH = AH - bitsH             ; Subtract high words    :
        if AL < bitsL then          ; Borrow if minuend < subtrahend
            dec AH                  ; Borrow for low word
        endif      
        AL = AL - bitsL             ; Calculate low word
;#  If number is negative then Restore subtraction        
        if AH > 32767 then          ; Negative so restore number
addbits:                                       ; Calculate A = A + bits
            AL = AL + bitsL
            AH = AH + bitsH
            if AL < bitsL then                ; Carry from low word
                inc AH  
            endif
addroot:                                    ; Calculate A = A + root
            AL = rootL + AL
            AH = rootH + AH
            if AL < rootL then             ; Carry from low word
                inc AH
            endif 
;#  root = root / 2
shiftroot:
            rootL = rootL / 2
            rootL = 32768 * rootH + rootL
            rootH = rootH / 2
        else
;#  root = root / 2 + bits
            rootL = rootL / 2
            rootL = 32768 * rootH + rootL
            rootH = rootH / 2   
addbitsR:   ; Calculate root = root + bits
            rootL = bitsL + rootL
            rootH = bitsH + rootH
            if rootL < bitsL then                ; Carry from low word
                inc rootH
            endif                            ; Carry from low word
        endif
;#  bits = bits / 4
          call shiftbits2             ; Shift Right by two bits
    loop
    sertxd("X= ",#rootL," Rem= ",#AL,cr,lf)       
     end

;  ADDITIONAL SUBROUTINE:
shiftbits2:                         ; Shift bits Right by two bits
    bitsL = bitsL / 4
    bitsL = 16384 * bitsH + bitsL
    bitsH = bitsH / 4 
return
I won't clutter up this thread with details and options for the Square Root function, but maybe will start a new "Snippets" thread in due course.

Cheers, Alan.
 

erco

Senior Member
"Hotel room", Buzby? You're taking the development of this "mobile transmitter" quite literally! :)
 

Buzby

Senior Member
"Hotel room", Buzby? You're taking the development of this "mobile transmitter" quite literally! :)
I did try across the hotel car park, but after 5m my old eyes couldn't see the LED flashes which show it's receiving. It would be better in the dark, but I attracted enough attention in daylight, so I don't really want to try wandering round the car park at night.

And for Alan,

I'm not ready for the calculation stuff yet, but I agree it will need a 32 bit 'front end'. However, I'm not sure how accurate the distance measuring will be. The trigger pulse seems to be jittering a little, maybe 200uS, which ( using the audio engineer's rule of thumb, 1ft per mS ) is getting on for 3"

This jitter I think is because the received signal has a slow rise-time, combined with the variable ( upto 250uS ) response time of the PICAXE. It's either that, or I'm not interpreting the scope properly. This jitter will be doubled when the 'base station' code runs, because then there will be one at each end. When I move to the stripboad I'll also change to a 'new style' 28X2 which can run at 64MHz. That should help reduce the jitter, if it's due to PICAXE response time.

Regarding the maths, the mobile will never cross the baseline, so no need for -ve roots of +ve squares. It's too late tonight for me to run your code in the simulator, but I'll give it a try tomorrow.

Cheers,

Buzby
 

techElder

Well-known member
Regarding resolution in your project, have you developed a minimum resolution based on the frequency of the transducer? Remember that the transmitted "direct signal" is actually a burst of ultrasound. This burst is a wave front of several cycles of increasing and decreasing amplitude. The receiver detects these cycles by setting a threshold level (most likely) that a cycle's amplitude has to pass to be the first detected cycle. If the threshold is too high, nothing will be detected (perhaps due to deterioration of the burst over distance), and if too low then everything will be detected.

The point is that there is a finite distance between each cycle that can be detected by a receiver's amplitude-based threshold. You'll never get your desired resolution without controlling the amplitude of the received signal over time. (This was how the Texas Instruments / Polaroid camera focusing mechanism worked, too.)

Your received time will always jump by the distance between a cycle of the burst and that's being generous with the description of the process, too.

PS. Nice job getting that trace within the confines of your travel. +1
 

Buzby

Senior Member
Regarding resolution in your project, have you developed a minimum resolution based on the frequency of the transducer?
Hi Tex,

There will be a few known sources of error that will limit resolution.

1 - As you say, the abolute limit of resolution will be determined by the wavelength of the ultrasonic.

2 - The variable response time of the PICAXE will add to the error

3 - Both the above will happen twice, once at each end of the range.

Some maths will give the resolution possible, but I've not done it yet.

Once I get all the hardware running ( and enough space to test in ) then we will have plenty new information to work on.

Thanks for your interest,

Cheers,

Buzby
 
Top