# Line/magnet follower

#### edmunds

##### Senior Member
Dear all,

I have an idea following up my little line follower projects from earlier. I would like to achieve similar functionality using hall sensors and small magnets. I have tested the physical feasibility and I'm now thinking about the algorithms. I have built a 'sensor' from three DRV5053 hall sensors. The advantage of those is they are bidirectional i.e. they are able to measure S and N pole of magnets. They produce a voltage of 1.0V when there is no magnetic field present and deviate up for S pole and down for N pole magnet. For my situation this is important, as I need to maintain 'magnet line' following capability while decoding 'messages' coded with N and S pole magnets. Assume S = 1 and N = 0. Most magnets are N. Then, S magnet is a 'start condition' followed by 4 bit code encoded with the following magnets. Gives me 16 possible messages encoded in the road.

I have been sketching on napkins and various other surfaces ideas for calculating where the line is from this for a few days now, but every time I come up with something, I discover it not to work for both polarities of magnets at the same time. Intuitively, it feels this should be a simple task, but somehow I cannot come up with a solution. [I used completely different idea for the optical line follower back then, so this is of no use.]

The ADC_8 value of no magnetic field is about 55 with the supply of 4.5V. It will be around 100 in the final application or 125 if I use FRV2048. My best solution, albeit working with one pole only, is as follows.

Assume LEFT sensor is 0, CENTRE sensor is 1 and RIGHT sensor is 2. Read all sensors and multiply the results with 0 for LEFT, 1000 for CENTRE and 2000 for RIGHT. Add up the result and divide with the sum of direct ADC results. This is working and with very good resolution, but is quite math intensive and falls apart if you reverse the field, because now the LEFT sensor should be 2 and the RIGHT sensor should be 1. There are obvious ways of accounting for this, like running ADC twice and then determining if what we are seeing is N or S magnet, but this will take way too much time for the final implementation. Need to find something more efficient.

Maybe you have some time to think about this and come up with a hint to something I'm obviously missing .

Edmunds

#### AllyCat

##### Senior Member
Hi,
multiply the results with 0 for LEFT,
Multiplication by 0 is simply "throwing away" the data. But actually you only need two sensors, one to the left and the other to the right of the "line". Then "compare" the strength of the two channels to tell which is nearer to the line and steer accordingly. This might be done mathematically in the software, or by (external, analogue) hardware (mixing resistors or a comparator) if computational speed is an issue.

It might be easier to visualise the system in an optical form, i.e. a "grey" road with a line of white dots, with some black ones. That's obviously much more difficult to analyse and process than a simple white (or black) line. You can consider grey as "zero" with black (S) and white (N) as signed numbers, or grey to have a "bias" level with lower and higher ADC values for black and white; whichever you are more comfortable with.

In theory, when the sensors are exactly half-way between a white (N) and black (S) dot (magnet), the sensors should both indicate "zero" (grey) and the software could interpret this as an "invert" signal, i.e. from then on the L-R processing is reversed. But in practice this probably won't work, because a single "missed" transition would change from "negative feedback" (a control loop) to "positive feedback" (instability). So I think you need at least one more sensor along the path of the line. That might be one more sensor at the centre in the front (or behind) the L/R sensors (i.e. a triangle), or four sensors in a square.

Cheers, Alan.

#### hippy

##### Technical Support
Staff member
It's an interesting problem. If we had signed maths and a perfect world I am guessing you would expect to see something like ...
Code:
``````    .-----------.   .-----------.   .-----------.   .-----------.
| s       N |   | s       N |   | N       S |   | N       S |
`-----------'   `-----------'   `-----------'   `-----------'
|   |   |           |   |   |       |   |   |           |   |   |
+25 +50  0          +50  0  -50     -50  0  +50          0  +50 +25``````
The challenge then is which side is greater, towards the left or towards the right.

I'll have to think about that but I don't think you can do it merely by multiplying. You will have to take into account some sort of sign indicator.

Signed maths isn't that hard so I would work out how to do it while assuming you will be able to with some help rather than try and implement something and make it work.

It would be useful if you could give some raw ADC readings of your sensor for when the magnet is positioned as in the above diagram.

#### techElder

##### Well-known member
Be sure to consider the value of magnetic field concentration instead of just dropping magnets on a "road" like daisies in a field.

You can make a magnet look much more "digital" with a little soft iron director.

#### AllyCat

##### Senior Member
Hi,

If these are the readily available Neodimium button magnets (typically 4+mm in diameter and 1+mm thick, then they are usually magnetised across their thickness, so one face is "North" and the other "South". They will try very hard to stack themselves automatically to form a stronger "rod" magnet. Thus, your "inverted" magnets will need to be very securely glued to a base board, or they will just flip themselves over and join up.

Viewed from the top, the magnetic field of a single magnet and two, will probably look something like this where N , n = strong and weaker "North" fields, S , s = strong and weaker South fields and o a weak (reversing) field:

Code:
``````o o o s S S s o o o      o o s S S S S s s s S S S S s o o
o s S o o o o S s o      o s S o o o o s S s o o o o S s o      Left sensor     ---->
s s S o N N o S s s      s s S o N N n n n n n N N o S s s
s s S o N N o S s s      s s S o N N n n n n n N N o S s s
o s S o o o o S s o      o s S o o o o s S s o o o o S s o      Right sensor   ---->
o o o s S S s o o o      o o s S S S S s s s S S S S s o o
One magnet                      Two magnets``````
Locate the two Hall sensors as near as possible to the two "lines" where the field is reversing. This will have to be a compromise because you are trying to create a line with almost "point sources". Then, when the car deviates from a symmetrical position the (signed) field strength will increase in one sensor and decrease in the other i.e. one becomes more N and the other becomes less N (or more S). Thus the steering (control) signal is simply obtained by "comparing" the two sensor signals, i.e. by subtracting one from the other. Or if the control signals are already signed (e.g. S = negative) then you might simply add the two signals, perhaps externally with a couple of resistors into a single ADC input.

IMHO, trying to invert some of the magnets for "signalling" is making things really hard for yourself. If you do want to try that, consider the optical equivalent of a "black" road marked with dots of "white" and "grey". Then the binary data is indicated by grey/white levels, whilst the steering uses black versus "not black" (i.e. grey or white).

Cheers, Alan.

#### edmunds

##### Senior Member
Thank you all for your time and ideas. I, too, have been continuing to think.

I think I should first elaborate that the physical side of the idea is to build a road of consecutive magnets drilled into the road surface at some distance in the direction of the road. I assume, the distance between two magnets could be more for straight sections and less for curves, but no testing has been done. The diameter of neodymium magnets I'm looking at is about 2mm and thickness could be between 2 and 4 millimetres. The magnets sticking to each other is not a problem for the size of magnets in relation to imagined distance between them.

As for the actual readings, the hall sensors I'm working with are quite 'vertical'. I have TO92 packaged devices side by side and if I put a 2mm magnet vertically on top of the centre sensor (would be below in real life) 3mm apart (which is the proposed sensor height above the road, I read about 4 for N pole and 100 for S pole. The outer sensors (left and right) would show 55 to say there is no magnet nearby. I only have to move the magnet a few tenths of a millimetre to the right or to the left, when the respective sensor starts to 'feel' something and the centre one starts to loose. With the 3D positioning jig I have created for this out of UNIMAT lathe/mill , I can quite easily position the magnet right between two sensors and get an equal reading of about 24 on two adjacent sensors. I hope this makes sense.

The problem with the 'sign read' is I cannot place anything in front of the main sensor as even that, pushed as far forward as chassis allow, is just a few millimetres ahead of the steering wheels. If there is no neat way of ignoring the 'sign' for 'line reading' I would probably revert to IR command signalling to the vehicles.

N magnet in the centre
55_________4__________55
--------------N---------------
N magnet to the right [75%]
55_________24_________24
----------------------N-------
S magnet in the centre
55________100_________55
---------------S--------------
S magnet to the left [25%]
74_________74_________55
-------S----------------------

It seems I should be able to decide based on the sum of the readings if I'm dealing with N or S magnet and then position based on that. I'm just failing to write an expression for it and explain why I keep failing exactly

Edmunds

#### edmunds

##### Senior Member
Basically, if the average is below 55, it is N pole and should be treated as such. If it is above 55 - S pole and should be calculated according to that. And I can set a flag in case it is S pole for start condition and store consecutive results in 4 bit variables to have my command. I will try to write some dry code during the weekend.

Edmunds

#### Buzby

##### Senior Member
IMHO, trying to invert some of the magnets for "signalling" is making things really hard for yourself.
I too think the 'string of magnets with embedded data' is going to be a nightmare to make work reliably.

If the OP is willing to revert back to optical methods here is another idea.

Use a single white line for tracking in the usual manner, with a seperate barcode at one side of the line, far enough out of the 'control zone' to cause no disruption to the tracking. ( Or maybe use a variable width centre line to encode the data. )

To make these markings invisible to the human eye use an infrared filter as the road surface, with the white lines etc. underneath.

I have seen this method used to make ID cards which are swiped through a reader like magnetic cards.

The infrared filter used in that application is a very dark red, almost black, and has the texture of cellophane.

And, if a totally non-optical method is needed, here is my half-baked idea .....

Before GPS and LIDAR were available, AGVs ( Automatic Guided Vehicles) in warehouses etc. followed wires embedded in the floor.

There are methods using multiple wires transmitting different constant frequencies to indicate different routes, and methods using a single wire transmitting data to send control commands.

Both the IR and 'embedded wire' ideas I think would be much easier to use than a string of magnets.

Cheers,

Buzby

#### AllyCat

##### Senior Member
Hi,

A "point to point" steering algorithm is going to be more difficult to devise, particularly if the magnet spacing is changing, and when some steering "turn" is already being applied.

Also, I think your sensors are much too far apart. You say you get 55 ....x..... 55 whether there is a N or S in the middle, which implies they're not "seeing" the magnet at all. This means that if the car wanders slightly off track, the middle sensor output will go up or down (depending whether it's a N or S magnet) but it tells nothing about which side it's deviating (and the outer sensors' signals will change only very slightly, at best).

IMHO you need to put the two outside magnets close enough that they both see the mddle magnet at the central (symmetrical) position. Also this makes the middle sensor unnecessary, because you can determine it's polarity from the sum of the L + R signals (being either above or below the "background" level).

The basic maths is easy enough, with pseudocode (avoiding signed maths) such as :

Direction = L - R +110 and
Polarity = L + R
.
IF Polarity < 110 THEN : Direction = 110 - Direction ; Reverse steering direction for a N pole
IF Direction > 110 THEN : Steer Right : ELSE Steer Left ; Can be proportional control (i.e. steer more for numbers further away from 110 ).

In practice, the "110" (bias) will probably need to be measured by a "pre-calibration" process.

Cheers, Alan.

#### techElder

##### Well-known member
I have TO92 packaged devices side by side and if I put a 2mm magnet vertically on top of the centre sensor (would be below in real life) 3mm apart (which is the proposed sensor height above the road, I read about 4 for N pole and 100 for S pole.
Without trying it on hardware, my feeling is that your magnets are much too strong to be trying to measure them that close to a hall sensor and get linear readings. Perhaps I don't have a good picture of the size of your magnets.

Be sure that you are truly measuring the field of the magnet by withdrawing it from the hall sensor and measuring the resultant field. It could be that you are trying to measure in a saturated field and that is like measuring ultrasonic signals too close to the emitter. Sort of like a near field situation.

#### hippy

##### Technical Support
Staff member
I think I've got it now. It's like dropping stick magnets into holes drilled in a bit of wood, then scanning along those to see which way up they are, in the example below, determining it is 'NNS' or 110 -
Code:
``````    |  | ______\
\__/       /
---. .-. .---. .-. .---. .-. .---
| |N| |   | |N| |   | |S| |
| | | |   | | | |   | | | |
| |S| |   | |S| |   | |N| |
| `-' |   | `-' |   | `-' |
`-----'   `-----'   `-----'
1         1         0``````
I am going to stick with N as 1 and S as 0 as that's the most logical definition, likewise N has positive value, S has a negative value in the rest of this. Just invert the binary result after processing if one wants it the other way.

When scanning we want our ADC reading routine to return a positive value when over an N and a negative value over an S.

With three sensors the readings can be combined by doing a signed addition and, unless something's gone bad, whether the result is positive or negative tells us what it is. If we don't get a strong signal we aren't sure if we are over a magnet or not -
Code:
``````MainLoop:
Do
Gosub CheckMagnet
SerTxd( result )
Pause 1000
Loop

CheckMagnet:
sum = lft + mid + rgt
If sum = 0 Then
result = "-"
Else If Positive(sum) Then
If sum < MINIMUM Then
result = "n"
Else
result = "N"
End If
Else
sum = -sum
If sum < MINIMUM Then
result = "s"
Else
result = "S"
End If
End If
Return``````
So moving our sensor over the three 'NNS' magnets should show something like -

---nnnNNNnn--nnNNNNn-sssSSsss---

To actual make that work we need to have some SYMBOL statements and a couple of Macro and Define definitions -
Code:
``````Symbol lft            = w1  ; b3:b2
Symbol mid            = w2  ; b5:b4
Symbol rgt            = w3  ; b7:b6

Symbol sum            = w4  ; b9:b8
Symbol result         = b10

Symbol LFT_SENSOR_PIN = C.1 ; ?
Symbol MID_SENSOR_PIN = C.2 ; ?
Symbol RGT_SENSOR_PIN = C.3 ; ?

Symbol MINIMUM        = 50  ; ?

wVar = w0
#EndMacro

#Define Positive(wVar)  wVar < \$8000``````
And we need an actual 'ConvertSensorReadingInW0' routine to complete the 'ReadSensor' functionality.

When a reading is taken with no magnet the result is 1V, a READADC10 result of about 200. We don't have to worry too much about accuracy because our 'MINIMUM' in the above will filter out readings which are not strong.

We can then determine if a reading is greater or less than that 200 (1V) with a simple 'w0 = 200 - w0'. When over an N the reading is less than 200 so our result is positive, when over an S the reading is higher than 200 so our result is negative. That's convenient because it matches how I want it to be, but I could just negate 'w0' if it were the wrong way up.

It will work because the PICAXE handles two's complements maths correctly.

So now, the final piece in the puzzle -
Code:
``````Symbol NO_MAGNET_OFFSET = 200

w0 = NO_MAGNET_OFFSET - w0
Return``````
We could put that in-line inside the 'ReadSensor' macro, but it's better here because we might want to add some scaling later, and there's nothing wrong with keeping things modular.

I'll put the full code in the next post so it doesn't clutter this one.

And that's it. Okay, not completely, because we need to convert readings into a 1 and 0 sequence, but it will be interesting to see what results it actually gives.

#### hippy

##### Technical Support
Staff member
Code:
``````Symbol lft            = w1  ; b3:b2
Symbol mid            = w2  ; b5:b4
Symbol rgt            = w3  ; b7:b6

Symbol sum            = w4  ; b9:b8
Symbol result         = b10

Symbol LFT_SENSOR_PIN = C.1 ; ?
Symbol MID_SENSOR_PIN = C.2 ; ?
Symbol RGT_SENSOR_PIN = C.3 ; ?

Symbol MINIMUM        = 50  ; ?

wVar = w0
#EndMacro

#Define Positive(wVar)  wVar >= \$8000

MainLoop:
Do
Gosub CheckMagnet
SerTxd( result )
Pause 1000
Loop

CheckMagnet:
sum = lft + mid + rgt
If sum = 0 Then
result = "-"
Else If Positive(sum) Then
If sum < MINIMUM Then
result = "n"
Else
result = "N"
End If
Else
sum = -sum
If sum < MINIMUM Then
result = "s"
Else
result = "S"
End If
End If
Return

Symbol NO_MAGNET_OFFSET = 200

w0 = NO_MAGNET_OFFSET - w0
Return``````

#### AllyCat

##### Senior Member
Hi,

@hippy: I hadn't realised that converting a few "magnet positions" into binary digits could be so complicated.

To me, the really "hard" part will be trying to "navigate" (line follow) using (very) small magnets. @tex has said he thinks the magnet is too strong, and I that it's too weak (for the side sensors), and we're probably both correct ! The magnetic field from a magnet follows the "inverse square law" (at best), so the field strength drops very rapidly as you move away from the magnet, (i.e. it is very non-linear). Non linearity makes the design of any control loop (e.g. steering) much more difficult. What has been described so far will be rather like trying to steer a car accurately with half a turn of "play" (backlash) in the rotation of the steering wheel.

IMHO, first you need to decide if the magnets will be close enough to define a "continuous" line. 2mm diameter magnets would probably need to be about 1mm apart (one reason for using larger magnets ! ). This will at least allow the steering to be a "continuous" (feedback) system.

If the magnets are further apart, then it becomes a "point to point" navigation system, i.e. measure the present "sideways offset" of the magnet and decide which direction to head next. This will be a really challenging algorithm, because (in addition to the present "error") it needs to take into account "Was the previous magnet(s) crossed with the same, or a smaller or larger offset", "How much steering lock was being used up to this point", "Have we been following a straight or curved line up to this point", etc.. Note that all those questions require signed numerical answers. to feed into the (non-linear) algorithm.

An alternative method might be to use a single 3-axis magnetometer (I2C). The X-axis (sideways) output would indicate the "offset" for calculating the steering direction, the Z-axis (upwards) the binary data and the Y-axis (along the track) indicate whether the nearest magnet is ahead or behind of the current position (which might be important unless the processing / control loop is very fast).

To discuss all this properly really needs diagrams showing magnetic field (flux) paths, which certainly I can't do with "ASCII Art". Note that one of the basic "Laws of Physics" is that isolated North or South poles do not exist, they must always occur in pairs, with the magnetic field (flux lines) flowing from N to S poles (and returning usually within the magnet).

Cheers, Alan.

#### hippy

##### Technical Support
Staff member
@hippy: I hadn't realised that converting a few "magnet positions" into binary digits could be so complicated.
I thought it was quite simple over-all. Assuming it does actually work, that the sensors can detect the magnets reliably and give sensible readings. Of course I don't have any similar hardware to try it with so can't be sure. Practice can often be very different to theory.

Detecting the sequence of magnets passed over is a little tricky but again not too complicated.

As for steering, I would have thought it would be little different to detecting a normal stripe; just convert the three sensors to absolute values and the higher they are the more they are on the line, processing that points to where the centre of the line is.

#### AllyCat

##### Senior Member
Hi,
As for steering,..... it would be little different to detecting a normal stripe; just convert the three sensors to absolute values and the higher they are the more they are on the line, processing that points to where the centre of the line is.
But it's not a "normal stripe", it's a "row" (or curve) of randomly-spaced, randomly black (or S) and white (or N) "dots", as far as the steering system is concerned.

I don't know how to multiple-quote in the new forum, however, the OP wrote in #6:

"... the distance between two magnets could be more for straight sections and less for curves, but no testing has been done......... The magnets sticking to each other is not a problem for the size of magnets in relation to imagined distance between them."

It's also worth noting that, for the dimensions envisaged by the OP, each "N" will be surrounded by a (weaker) annulus of "S" (and vice versa) before (at greater distances) the field falls away to the "background" level (which of course includes the Earth's magnetic field and any stray effects from motors, etc.). Also, don't forget that the magnetic field at any point is a Vector, i.e. it has a magnitude and a direction (in three axes).

Cheers, Alan.

#### RNovember

##### Well-known member
I don't know how to multiple-quote in the new forum
Just click reply on two or more different messages.

#### hippy

##### Technical Support
Staff member
But it's not a "normal stripe", it's a "row" (or curve) of randomly-spaced, randomly black (or S) and white (or N) "dots", as far as the steering system is concerned.
I wasn't really considering whether the scheme would work, I was just meaning with regards to getting and processing the sensor readings.

If this is a part of a project which was mentioned some time ago - and I haven't checked - I recall the idea was to go in some direction, pass over some magnets, which would then instruct it how to turn, what path to follow, to get to the next set. That should work in theory. Turning it into reality is 'someone else's problem'

#### AllyCat

##### Senior Member
Hi,

Thanks RNovember. This time I only need to quote one post (#1) :
I need to maintain 'magnet line' following capability while decoding 'messages' coded with N and S pole magnets....... every time I come up with something, I discover it not to work for both polarities of magnets at the same time.
I've tried to explain why it doesn't (maybe can't) work in several posts.

Here is the sort of magnetic flux paths that a "button" (low h to d ratio) magnet produces. Note the direction of the flux lines just a diameter or two away from the vertical axis.

Cheers, Alan.

#### techElder

##### Well-known member
This graphic that Alan put up shows why everything magnetic from speakers to hard drive heads uses magnetic field concentrators of some sort.

If you want to detect a magnetic field then you have to sort of push those curved lines further away from your detector.

You can do that, but you'll need to concentrate the field that you are trying to detect; either at the magnet, the sensor or both.

#### edmunds

##### Senior Member
Hi all,

Thank you for the discussion and code . I hope to get some time later today to test some of this.

As for the discussion about strength of field and field lines etc - you need not to worry. I have done plenty of calculations for selecting the sensitivity of hall devices and proved by testing the math works. Below is the picture of my test setup and as I wrote previously, I can reliably detect 0.1mm change in magnet position over the three sensors. What I have not tested yet is if I could get the same results with just two sensors.

As for "If the magnets are further apart, then it becomes a "point to point" navigation system, i.e. measure the present "sideways offset" of the magnet and decide which direction to head next. This will be a really challenging algorithm, because (in addition to the present "error") it needs to take into account "Was the previous magnet(s) crossed with the same, or a smaller or larger offset", "How much steering lock was being used up to this point", "Have we been following a straight or curved line up to this point", etc.. Note that all those questions require signed numericalanswers. to feed into the (non-linear) algorithm.", Alan, this is exactly what I want to achieve. I understand the challenges (to a high extent), but it is certainly doable. The only question is, if it can be done fast enough, but given I have entirely eliminated the steering motor pulsing that was taking most of the time in the line follower algorithm (see "Fixed pulse train challenge" in the forum), I think I have some margin.

Thank you so far and best regards to all,

Edmunds

#### Attachments

• 248.5 KB Views: 12

#### edmunds

##### Senior Member
Another relevant picture from DRV5053 data sheet.

Edmunds

#### Attachments

• 16.2 KB Views: 4

#### AllyCat

##### Senior Member
Hi,
I can reliably detect 0.1mm change in magnet position over the three sensors.
I accept that you might "reliably" detect a movement of 0.1mm away from the central magnet but can you detect in which direction (both sideways and along the track). Your measurement of 55 .. X .. 55 for both N and S poles suggests that the lateral discrimination will be very poor, and there is none in the track direction (except ultra-frequent measurements).

@tex is correct that the magnetic flux lines are normally "steered" by other materials (because they "dislike" passing through air). The sensor itself probably will affect the flux lines, which makes prediction of the overall behaviour very difficult. On a few occasions I have attempted to "tailor" magnetic fields to a particular application, but failed abysmally, even though I had a few exotic materials such as "mu-metal" available.

As suggested earlier, if I were attempting this project, I would try a 3-axis magnetomter, to at least give sufficient "information" for the steering / navigation algorithm to stand a chance.

PS: I have absolutely no dispute over the linearity of the sensor; IMHO it's the (non-) linearity of the magnetic field (flux) that will give the problems.

Cheers, Alan.

EDIT ADDENDUM : If you are (still) using a multipler of "0" for the left channel (as per #1), then you're already using only two sensors. The "central" position will be the "75%" measurement X .. 24 .. 24 , (or X .. 74 .. 74 ) for the South pole. Add a suitable "bias" value to avoid negative numbers when subtracting (comparing) the two signals. But I'm still not sure how you will (or can) separate signal strength variations caused by the lateral non-linearity, from the lower sensitivity a fraction of a mm ahead or behind the magnet, along the track.

Last edited:

#### edmunds

##### Senior Member
It is lateral movement (closer to left sensor, further from centre, as an example) that I can detect. Away (as in vertical) is probably possible, but I did not test that extensively.

I did understand you were talking about non-linearity of field, not the sensor. However, I believe most of this can be just ignored for a result that is satisfactory.

What I cannot do, is distinguish between lateral and 'along the route' distance. This is a very valid point. But again, simple geometry should help take that into account. Or reacting on max field instance only. Anyway, first steps first - I need an algorithm that can work fast, precisely and reliably with a single S or N magnet. Then I need to extend it to an algorithm that includes steering and thinks there is an endless string of magnets creating endless homogenous magnetic field albeit of changing polarities sometimes. Then I need to start stretching magnets away from each other on a straight section. Only then do I need to attack stretching magnets away for curves.

As for magnetometer, I tried to get TLV493B working, but to my disappointment, just could not get it to talk to picaxe. It would still be my favourite solution - fewer pins used, could be quicker and problem solved with one device. I'm not aware of any other device that would fit the bill - size, voltage available etc. Just a regular (raw data) magnetometer that I did play around with was extremely noisy and I could not make sense of the data. So, I decided to revert to simple ways and give it a serious try.

Edmunds

#### AllyCat

##### Senior Member
Hi,
an endless string of magnets creating endless homogenous magnetic field albeit of changing polarities sometimes.
There cannot possibly be a continuous (homogeneous?) magnetic field because there must be a null (zero) between the positive (e.g. N) and negative (S) field strengths. In fact it's vital to detect this null because it's the point where you need to reverse (invert) the steering direction (relative to the sensed magnetic field direction).

Cheers, Alan.

#### edmunds

##### Senior Member
Hi,

There cannot possibly be a continuous (homogeneous?) magnetic field
Cheers, Alan.
Of course, not. I mean a simplification to develop things step by step.

Edmunds

#### edmunds

##### Senior Member
Dear all,

I have been fighting some hardware problems and while at it built an array of 4 hall effect sensors. The first version of code that seems to be working with the quick test I have time for now pasted below.

Code:
``````'DRV5053 based magnetic line follower test

#picaxe 40x2
#no_data
#no_table
#terminal 9600

Symbol Mag_Pole = bit31     'Line magnet polarity, 1 for N, 0 for S

Symbol sum0 = w27            'b54:b53; Additions
Symbol sum1 = w26            'b52:b51; Additions
Symbol sum2 = w25            'b50:b49; Additions
Symbol sum3 = w24            'b48:b47; Additions
Symbol sum4 = w23            'b46:b45; Additions

Symbol l_error = w22         'b44:b43; Line error

init:
'some hall sensor offset calibration procedure needed

main:
gosub CheckMagnet
select case Mag_Pole
case = 1                  'N magnet, values go up with magnetic field
if sum1 > sum2 then     'magnet on left side
l_error = sum1 - sum2
sertxd ("N magnet ","L",#l_error,CR,LF)
else                    'magnet on right side
l_error = sum2 - sum1
sertxd ("N magnet ","R",#l_error,CR,LF)
endif
case = 0                  'S magnet, values go down with magnetic field
if sum1 < sum2 then     'magnet on left side
l_error = sum2 - sum1
sertxd ("S magnet ","L",#l_error,CR,LF)
else
l_error = sum1 - sum2 'magnet on right side
sertxd ("S magnet ","R",#l_error,CR,LF)
endif
endselect
pause 1000
goto main

CheckMagnet:
select case sum0
case 301 to 399
sertxd ("No magnet, or field too weak", CR, LF)
case < 300          'The most an S magnet can 'take away' from total is ~90, so 3*90+a little must remain
Mag_Pole = 0
else
Mag_Pole = 1
endselect
return``````

Edmunds

Last edited:

#### edmunds

##### Senior Member
Dear all,

I'm reading sensors comfortably, be it two, three or for. I can also calibrate them for offset. I tried calibrating for gain, but there seems to be no need as they come out +/-1 in the scale of 1024, which is plenty for what is needed.

What throws me back to square one is I cannot get my head around math. Normally, google would help, but I have spent hours and hours on research an nothing good comes out. Must be for a reason, but I cannot figure it out.

For my previous 'line follower', I ended up converting 128 (or was it 64) analog values into digital ones or zeroes of a 16 bit word by calibrating to some threshold. 16 turned out to be sufficient resolution for the speed required. Now with hall sensors, I know how to turn them digital (on top of the fact you can actually buy digital), but maximum I can pack is 8, which I almost know, will not be enough for the smooth ride I want and would require too many pins or extra hardware to read.

On the other hand, I can clearly see, analog should work, because I have data looking at which 'I know', where the magnet is with far greater resolution than 8 or even 16 sensors could give. I'm just failing to describe it with an equation. And for some reason I don't find that equation on google either - people normally turn analog values into line/no line, i.e. digital right at the sensor level.

Is that really the only option? I have attached a data set with 4 sensors, if somebody wants to play around. Ideally, I would pack the four sensor values into a 16bit word with 1 standing where the line is and the rest being 0. This would allow me to use most of the code and PID (which was the tricky part) from previous iteration.

Edmunds

P.S. For the first 7 rows of data, the magnet is coming from Y direction (direction of travel for the vehicle). After that it only moves about X axis (lateral for the vehicle). Z (vertical distance between magnet and hall sensors) remain constant @ 3mm.

#### Attachments

• 831 bytes Views: 11
Last edited:

#### tommo_NZ

##### New Member
What if you tried to follow the magnetic field from a single wire carrying alternating current at low voltage. Or.. how do stud finders work?
Regards, tommo_nz

#### premelec

##### Senior Member
FWIW I think it would be possible to have an iron wire and two pickups a la metal detector circuit - similar to white line and photo detectors... not sure if the search coils could be made to _not_ interfere with each other...

#### AllyCat

##### Senior Member
Hi,

I've looked through the data, because if the "human eye/brain" can't decode the data then there's little chance of being able to write an algorithm to do it. I added some "comments" and set "significant" values to bold, but that may be lost in the [ code ] tags. My observations are:

- A number of rows contain "No Usable Data".

- Where the magnet is clearly at one side, the most distant sensor output varies by 10 locally and 30 between the start and end of the data. This indicates how much of the data is "noise" which needs to be ignored.

- In many cases only one sensor is detecting the magnet, but the value varies by well over 100. This is probably because the magnet is "in front" or "behind" (Y direction), but might be because the magnet is outside the edge (which is impossible to detect).

Rich (BB code):
``````368,367,362,372  )
362,369,363,373  )
364,364,368,373  }  No usable data
362,367,363,374  )
361,368,372,396  -  Perhaps approaching RHS
367,363,380,544  )
361,367,388,589  )
363,364,383,587  } Near to RHS (or outside?)
371,368,392,584  )   [ noise of 10 on sensor 1 ]
364,366,375,551  )
367,370,363,433  - Presumably lower because moving away (in Y direction)
367,369,366,387  )
365,367,366,394  } No usable data
368,364,366,391  )
363,371,366,442  +
359,369,378,552  + "Somewhere near" to RHS
358,361,402,579  +
366,367,508,476  -  Between 3 and 4
364,378,630,392  +  Near to 3
355,440,544,376  -  Just Left  of 3
356,599,410,368   + Just right of 2
391,645,376,366  -  Near to 2
499,514,361,368  + Between 1 and 2
577,458,371,365   )  Right of 1
681,410,360,366   }  Slightly right of 1
686,378,363,368  -  Near to 1,
534,363,362,372  +  weaker, so outside LHS or past magnet in Y direction?
412,364,369,366  +
372,364,364,368  - No usable data
373,365,362,367  -
460,359,361,368  )
579,365,357,364  }  Near to 1
702,386,358,367  )
604,431,363,365  )
540,477,358,364  -  Right of 1
426,586,361,364  -  Left of 2
364,615,394,357  +  Slightly right of 2
355,442,522,368  -   Left of 3
346,373,622,387  +  Near to 3
351,355,497,459  -  Between3 and 4
350,353,387,570  }   why are 3 and 4 stronger than next?
354,355,359,529  }
354,353,353,444  }  Near to 4, but varies by over 100
352,355,358,448  }
351,359,369,569  }
351,359,433,516  -  Nearer to 4 than 3
349,355,515,441  -  Nearer to 3 than 4
345,357,598,403  -  Just right of 3
348,407,576,362  -  Just left of 3
354,500,4 sensor54,359  -  Nearer to 2
360,553,425,361  )  Just right of 2
351,553,423,355  )``````
So the basic algorithm might be:
+ Find the sensor with the strongest signal.
+ Use the signal from the senor furthest away as the "background" (null) level.
+ Compare the signal(s) adjacent to the strongest to give an "offset" value. With the amount of noise and non-linearity, it's probable that the best that can be (reliably) resolved is either "Near the stronger sensor" or "Between the two sensors".

Thus, IMHO you will only be able to resolve 7 positions (10 or 15 if really lucky) and there is no way to detect if the "line" is outside the span of the (centre of the) outer sensors. That's probably insufficient for even a "continuous" line-following system, let alone "point to point" navigation.

The problem is that for an analogue system you need to always have "strong" (i.e. much larger than noise) signals on (at least) two sensors. But if you look at my diagram in #18, at a distance of (say) 3mm above and 3mm to the side of the magnet, the field is horizontal, but your sensors respond only to a vertical component. That is why I suggested a 3-axis magnetometer; there appear to be several threads on this forum. However, the maths/algorithm will be complex because it (and any point-to-point navigation system) will require considerable trigonometric calculations.

Cheers, Alan.

PS: Yes of course, following along a current-carrying wire is a much more practical method. But it doesn't meet the OP's original "idea" of encoding additional binary data within the "line" (using reversed magnets).

#### techElder

##### Well-known member
On the other hand, I can clearly see, analog should work, because I have data looking at which 'I know', where the magnet is with far greater resolution than 8 or even 16 sensors could give. I'm just failing to describe it with an equation.
As Alan has expounded on, you provided data isn't as clear to me as it is to your "I know" declaration, but I know exactly what you are saying. Perhaps a diagram comparing the data with your "I know" magnet positions vs. sensor positions?

As you know, the linear data readings are going to be next to impossible to interpret vs. the non-linearity of the mag fields. The reason is that you are measuring with 2D sensors, but the fields are in 3D.

#### hippy

##### Technical Support
Staff member
And for some reason I don't find that equation on google either
That's probably because no one else has done it, or those who have consider it commercially sensitive and aren't going to hand their hard work out in figuring it out for everyone else to copy.

I suspect you are either going to have to find a research paper or project where the possibility of doing this was investigated or figure out equations and algorithms from scratch. I doubt there will be a ready-rolled solution.

The best way would be to start simple, use the data you have and see what that gives you, and refine it so it becomes better. That's probably going to involve a lot of thinking about how it could be done, waiting for your Eureka! moment.

Taking your data I bashed that into a simple PICAXE program. Averaging the totals and seeing which were above average didn't seem to give any useful result but looking to see which was highest looks promising ( the same conclusion AllyCat arrived at ). The following code runs in simulation finds the highest, smooths that to 4-bits and also smooths that to 7-bits. That might be a starting point -
Code:
``````#Macro Sample(a,b,c,d)
b10 = a
b11 = b
b12 = c
b13 = d
Gosub Analyse
#EndMacro

b2 = \$FF
b3 = \$FF

Sample(368,367,362,372)
Sample(362,369,363,373)
Sample(364,364,368,373)
Sample(362,367,363,374)
Sample(361,368,372,396)
Sample(367,363,380,544)
Sample(361,367,388,589)
Sample(363,364,383,587)
Sample(371,368,392,584)
Sample(364,366,375,551)
Sample(367,370,363,433)
Sample(367,369,366,387)
Sample(365,367,366,394)
Sample(368,364,366,391)
Sample(363,371,366,442)
Sample(359,369,378,552)
Sample(358,361,402,579)
Sample(366,367,508,476)
Sample(364,378,630,392)
Sample(355,440,544,376)
Sample(356,599,410,368)
Sample(391,645,376,366)
Sample(499,514,361,368)
Sample(577,458,371,365)
Sample(681,410,360,366)
Sample(686,378,363,368)
Sample(534,363,362,372)
Sample(412,364,369,366)
Sample(372,364,364,368)
Sample(373,365,362,367)
Sample(460,359,361,368)
Sample(579,365,357,364)
Sample(702,386,358,367)
Sample(604,431,363,365)
Sample(540,477,358,364)
Sample(426,586,361,364)
Sample(364,615,394,357)
Sample(355,442,522,368)
Sample(346,373,622,387)
Sample(351,355,497,459)
Sample(350,353,387,570)
Sample(354,355,359,529)
Sample(354,353,353,444)
Sample(352,355,358,448)
Sample(351,359,369,569)
Sample(351,359,433,516)
Sample(349,355,515,441)
Sample(345,357,598,403)
Sample(348,407,576,362)
Sample(354,500,454,359)
Sample(360,553,425,361)
Sample(351,553,423,355)
End

Number:
Select case b0
Case < 10  : SertXd( "  ",#b0," " )
Case < 100 : SertXd( " ", #b0," " )
Else       : SertXd(      #b0," " )
End Select
Return

Analyse:
; Raw Numbers
b0 = b10 : Gosub Number
b0 = b11 : Gosub Number
b0 = b12 : Gosub Number
b0 = b13 : Gosub Number
SerTxd(TAB)

; Highest
b0 = 0 : b1 = b10
If b11 > b1 Then : b0 = 1 : b1 = b11 : End If
If b12 > b1 Then : b0 = 2 : b1 = b12 : End If
If b13 > b1 Then : b0 = 3 : b1 = b13 : End If
Select Case b0
Case 0 : SerTxd("*---")
Case 1 : SerTxd("-*--")
Case 2 : SerTxd("--*-")
Case 3 : SerTxd("---*")
End Select
SerTxd(TAB)

; Highest Smoothed 4-bit
If b2 = \$FF Then : b2 = b0 : End If
Select Case b0
Case > b2 : b2 = b2 + 1
Case < b2 : b2 = b2 - 1
End Select
Select Case b2
Case 0 : SerTxd("*---")
Case 1 : SerTxd("-*--")
Case 2 : SerTxd("--*-")
Case 3 : SerTxd("---*")
End Select
SerTxd(TAB)

; Highest Smoothed and 7-bit Scaled
b0 = b0 * 2
If b3 = \$FF Then : b3 = b0 : End If
Select Case b0
Case > b3 : b3 = b3 + 1 Max 6
Case < b3 : b3 = b3 - 1
End Select
Select Case b3
Case 0 : SerTxd("*------")
Case 1 : SerTxd("-*-----")
Case 2 : SerTxd("--*----")
Case 3 : SerTxd("---*---")
Case 4 : SerTxd("----*--")
Case 5 : SerTxd("-----*-")
Case 6 : SerTxd("------*")
End Select

SerTxd(CR,LF)
Return``````

#### edmunds

##### Senior Member
Wow, lots of ideas and code. Thank you!

I have been tinkering today as well. I have lifted the magnet by 1mm, which helped a lot with 'non-linearity' of my sensor array. As you say, Alan, some of that sideways flux must have been reduced to values not messing up with hall sensors. The below is my best result so far. I'm using linear interpolation to get the column before the last one. The rightmost column is the real magnet distance from centre. y3...y0 are sensor values, next four columns apply gain to sensors, which was calculated by reading the highest possible value from the sensor and then comparing all to the lowest high value of four, x3...x0 are sensor distances from 0 in the middle in mm/10.

Code:
``````Z=4mm
y3    y2    y1    y0    gain 0.99    gain 0.99    gain 1.00    gain 0.98    x3    x2    x1    x0    num    denom    mm from 0    actual distance from 0
335    335    360    434    332    332    360    425    -70    -25    25    75    7265.65        1448.62    5.02    8
334    338    376    431    331    335    376    422    -70    -25    25    75    7454.90        1463.66    5.09    7
335    344    395    417    332    341    395    409    -70    -25    25    75    6751.70        1475.87    4.57    6
342    348    415    409    339    345    415    401    -70    -25    25    75    6118.80        1498.92    4.08    5
336    353    436    388    333    349    436    380    -70    -25    25    75    5495.25        1498.35    3.67    4
332    356    442    372    329    352    442    365    -70    -25    25    75    4750.60        1487.68    3.19    3
340    370    439    364    337    366    439    357    -70    -25    25    75    3225.90        1498.62    2.15    2
341    389    420    358    338    385    420    351    -70    -25    25    75    1799.75        1493.54    1.21    1
340    430    424    346    337    426    424    339    -70    -25    25    75    131.10        1525.38    0.09    0
356    425    389    348    352    421    389    341    -70    -25    25    75    -1591.75    1503.23    -1.06    -1
360    444    373    341    356    440    373    334    -70    -25    25    75    -3219.40    1503.14    -2.14    -2
375    445    358    348    371    441    358    341    -70    -25    25    75    -4178.45    1510.84    -2.77    -3
397    432    358    345    393    428    358    338    -70    -25    25    75    -5587.10    1516.81    -3.68    -4
422    411    343    349    418    407    343    342    -70    -25    25    75    -6900.45    1509.69    -4.57    -5
443    388    348    339    439    384    348    332    -70    -25    25    75    -8347.50    1502.91    -5.55    -6
453    373    340    343    448    369    340    336    -70    -25    25    75    -8594.85    1493.88    -5.75    -7
453    357    339    343    448    353    339    336    -70    -25    25    75    -8223.85    1477.04    -5.57    -8``````

That's probably because no one else has done it, or those who have consider it commercially sensitive and aren't going to hand their hard work out in figuring it out for everyone else to copy.
[/code]
You bet! Your code shows what I did with the magnet quite well actually. And there is a very neat way of extracting the highest of four that I tried to figure out, but could not come up with anything pretty. Thanks!

Looking at my results, I think one thing to try is to always look at only two adjacent sensors that see the magnet most. The distance between my sensors is 5mm and as you can see results around -3 to +3 are very useable. Handling the far right and far left problem will have to be a special case, I guess. More to come.

Edmunds

#### edmunds

##### Senior Member
What if you tried to follow the magnetic field from a single wire carrying alternating current at low voltage. Or.. how do stud finders work?
Regards, tommo_nz
I'm not sure a single wire would be easier to follow than individual magnets. Sending and receiving messages in the wires would be no problem, per se, however, there would be a separate wire needed for every location based message as otherwise the same message would be sent to every car everywhere on the layout. Going into full length of that discussion would take this thread off topic, but the most important reason FOR 'point-to-point' navigation with magnets (as Alan has so accurately named it) is the ease of building a layout and adding such traffic to an existing layout. The only tool you need is a drill. This is not the case for any sort of embedded wires - be it Faller 'fahrdraht' or induction wires similar to Grand Maket Rosija in StPete.

Cheers,

Edmunds

#### edmunds

##### Senior Member
Thus, IMHO you will only be able to resolve 7 positions (10 or 15 if really lucky) and there is no way to detect if the "line" is outside the span of the (centre of the) outer sensors. That's probably insufficient for even a "continuous" line-following system, let alone "point to point" navigation.
15 would actually suffice. The optical line follower followed a 2mm line with an 8mm wide sensor with 15 pos resolution and was performing very well after two months of effort . It was sensitive to ambient light, however, which could only partly be compensated by adjusting brightness of the nearby leds. I have twice the width of the sensor, so maybe I don't have to worry at all about the outer elements and should just stop reading values past 6mm. Also something to think about.

Edmunds

#### hippy

##### Technical Support
Staff member
And there is a very neat way of extracting the highest of four that I tried to figure out
The most optimal way to find the index of the highest, 0 to 3, would probably be -
Code:
``````  b0 = b10 Min b11 Min b12 Min b13
LookDown b0,( b10, b11, b12, b13 ), b0``````
MIN, rather unintuitively, works as a 'highest of' operator.

#### edmunds

##### Senior Member
The below code packs everything into 15bit word. Seems to be working on the 'lab setup' and while it looks massive, it is only a few instructions that actually have to be executed in each loop - takes about 1.4ms, which sounds alright. I'm traveling for the next few days, but then I hope to combine this with PID and hardware controlled stepper pulsing code and take it for a spin. Will report

Cheers,

Edmunds

Code:
``````'DRV5053 based magnetic line follower test
{#picaxe 40x2
#no_data
#no_table
#terminal 9600
}

{Symbol Mag_Pole = bit31     'Line magnet polarity, 1 for N, 0 for S

Symbol sum0 = w27            'b54:b53; Additions
Symbol sum1 = w26            'b52:b51; Additions
Symbol sum2 = w25            'b50:b49; Additions
Symbol sum3 = w24            'b48:b47; Additions
Symbol sum4 = w23            'b46:b45; Additions

Symbol l_error = w22         'b44:b43; Line error

Symbol counter0 = w17        'b34:b33; Just a counter
Symbol counter1 = w16        'b32:b31; Just a counter

Symbol line_pos = w0         'b0:b1; MagLine position

Symbol min_spread = 20       'low treshold for considering adjacent hall sensors equal
}

{init:
setfreq em64

low D.1

sum0 = 0 : sum1 = 0 : sum2 = 0 : sum3 = 0 : sum4 = 0
}
{main:
;pulsout D.1,50    'plug in for timing

; gosub CheckMagnet

Select case counter0
case 0                                                  'sensor closest to LL
if counter1 <> 0 then                                 'if not L, then outside field of view
line_pos = %100000000000000                         'magline beyond or at /bit14
else                                                  'magline towards centre from LL
line_pos = %010000000000000                       'magline under LL /bit13
line_pos = %001000000000000                       'magline towards the centre /bit12
line_pos = %000100000000000                        'magline in between two sensors LL-L /bit11
endif
endif
case 1                                                  'sensor closest to L
if counter1 = 0 then                                   'if LL, then away from centre
line_pos = %000100000000000                        'magline in between two sensors L-LL  /bit11
line_pos = %000010000000000                        'magline outwards from L /bit/10
line_pos = %000001000000000                        'magline under L /bit9
endif
elseif counter1 = 1 then                               'magline towards centre from L
line_pos = %000001000000000                        'magline under L /bit9
line_pos = %000000100000000                        'magline towards the centre /bit8
line_pos = %000000010000000                        'magline in between two sensors L-R /bit7
endif
endif
case 2                                                  'sensor closest to R
if counter1 = 1 then                                   'if L, then towards centre
line_pos = %000000010000000                        'magline in between two sensors L-R  /bit7
line_pos = %000000001000000                        'magline toward centre from R /bit/6
line_pos = %000000000100000                        'magline under R /bit5
endif
elseif counter1 = 2 then                               'magline outwards from R
line_pos = %000000000100000                        'magline under R /bit5
line_pos = %000000000010000                        'magline towards the centre /bit4
line_pos = %000000000001000                        'magline in between two sensors R-RR /bit3
endif
endif
case 3                                                  'sensor closest to RR
if counter1 = 2 then                                  'magline towards centre
line_pos = %000000000001000                        'magline in between two sensors RR-R /bit3
line_pos = %000000000000100                        'magline towards the centre /bit2
line_pos = %000000000000010                        'magline under RR /bit1
endif
else                                                   'magline outwards from RR
line_pos =   %0000000000000001                       'magline beyond or at /bit0
endif
endselect
;pulsout D.1,50    'plug in for timing

sertxd ("Line: ",#bit14,#bit13,#bit12,#bit11,#bit10,#bit9,#bit8,#bit7,#bit6,#bit5,#bit4,#bit3,#bit2,#bit1,#bit0,CR,LF)
pause 8000
goto main
}

{CheckMagnet:
select case sum0
case 1400 to 1500
sertxd ("No magnet, or field too weak", CR, LF)
case < 1400          'The most an S magnet can 'take away' from total is ~90, so 3*90+a little must remain
Mag_Pole = 0
else
Mag_Pole = 1
endselect
return
}``````

#### tommo_NZ

##### New Member
Hi Edmunds, I would think the Faller Car System application would meet most of the requirements of the original brief. It would be very adaptable and scalable to what ever purpose one had in mind, surely.
Regards,
Kevin Thompson