PDA

View Full Version : Hall effect sensors (4 in a circle)



mminasian
07-11-2009, 01:23 AM
Hey guys, so I'm taking a new approach to my project. I've attached a picture which will hopefully describe what I'm trying to do. I have one magnet glued to the inside of a round shaft. I have four hall effect "digital switches" (resistor pulled up to 3.3v or whatever the voltage needs to be for an "on" state). They are spaced 90 degrees around the circle. The idea is to calculate angular speed every 90 degrees (somewhat unnecessary, I think one sensor + one magnet is enough) but then, I take the orders, I don't make them. Also, based on the last sensor hit, and the approximate speed, we can calculate the approximate location of the magnet at any given time. If those familiar with this type of application could chime in on my code, I would much appreciate advice/criticism etc. The sensors don't come until Monday so I can't test yet, I just wanted to see if there were any fatal errors in logic right off the bat. I think the code is decently commented, but let me know if it doesn't make sense.




var
long pins, cntA, cntB, cntC, cntD, time, angular_speed, position, position2
pub initialize
dira[22..25]~ '4 sensors, for use on pins 22-25
pins := 22..25
return pins
pub read
repeat
case ina[pins]
1000 : 'pin 22 is on (magnet activated switch)
position := 0 'gives the absolute 90 degree position for later on
cntA := cnt 'store clk count
waitpeq(1, 23, 0) 'wait until pin 23 is turned on
cntB := cnt 'record new count
time := (cntB - cntA) / 80_000_000 'number of counts over clk frequency
'yields time in seconds for transition
0100 :
position := 90
cntB := cnt
waitpeq(1, 24, 0)
cntC := cnt
time := (cntC - cntB) / 80_000_000
0010 :
position := 180
cntC := cnt
waitpeq(1, 25, 0)
cntD := cnt
time := (cntD - cntC) / 80_000_000
0001 :
position := 270
cntD := cnt
waitpeq(1, 22, 0)
cntA := cnt
time := (cntA - cntD) / 80_000_000
angular_speed = time / 90 'time divided by 90 degrees for angular velocity

pub get_position
if position == 0 'check for last absolute 90 degree position rating
position2 := 0 + (cnt - cntA)*angular_speed 'take the current count - the last known count to figure out how
'long it's been since it hit the last switch, multiply by speed and add
if position == 90
position2 := 90 + (cnt - cntB)*angular_speed
if position == 180
position2 := 180 + (cnt - cntC)*angular_speed
if position == 270
position2 := 270 + (cnt - cntD)*angular_speed
if position2 > 359
position2 := 0
return position2
pub get_speed
return angular_speed

mminasian
07-11-2009, 01:25 AM
Also, MAX RPM is about 10K which is about 166 Hz spinning, and therefore with 4 sensors, I need 666Hz of resolution. I forgot the link to the sensors:

http://www.hamlin.com/specsheets/55100%20IssueAE.pdf

heater
07-11-2009, 01:43 AM
How do you know which way it's turning ?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.

mminasian
07-11-2009, 01:47 AM
mmmm good point, I don't really have track of that, presumably for now we are only going one direction, but I suppose that doesn't account for any odd mistakes. I suppose I could keep track of the last sensor hit using the "position" variable, and set up an if statement i each case. That certainly could get dicey though...

heater
07-11-2009, 03:27 AM
I was just thinking about the start up.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.

mminasian
07-11-2009, 04:47 AM
Its going on a vehicle, which should be moving forward, so I am making the assumption

Nick Mueller
07-11-2009, 05:49 AM
I only had a short gimpse at your code, BUT:
If the position is really important, you'll fail. http://forums.parallax.com/images/smilies/smile.gif
The reason is, that you forgot to consider the acceleration. You can only estimate the position after having read three pulses and by the difference in time calculate the acceleration. Even combistion engines get something like 30% difference in ONE SINGLE revolution. Even worse with high performance engines. (look at YouTube and listen the Renault F1 playing the Marseillaise).

www.youtube.com/watch?v=N2zSfNpUxT8 (http://www.youtube.com/watch?v=N2zSfNpUxT8) OK, a bit crude. But it must be OK, they are the French. http://forums.parallax.com/images/smilies/wink.gif

Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

Post Edited (Nick Mueller) : 7/10/2009 10:55:59 PM GMT

SamMishal
07-11-2009, 06:13 PM
MMinasion,

There are a few SYNTAX and Semantic problems with your program.

Pressing F9 will actually compile the program but without downloading to the propeller
and would work even if you do not have a propeller even connected to the PC.

This way you can find some of the Syntax problems.

The semantic problems are another thing and you need to run the program to find them
but here is a list:

1- You are not defining the Clock parameters and so on in the Con section
2- the line Pins := 22..25· does not work.......Syntax problem
··· what you need here is to use constants. Also the statement Return pins does not work.....SPIN does not use this syntax to return
··· a result from the function. You can either use Result := pins.......or you can define your function with a named return
··· like this
······· Pub Initialize : pins
···and then when you want to return a value you say
······· pins := some value
··
·· but any way the syntax pins:= 22..25··· is an error in the first place and using a constant to define the first pin in the
·· sequence is the way to go

3- in the case statement case ina[pins] again will not work......
··· if you have defined a constant (or variable) you can say case ina[Pin0..Pin0+3] or case ina[Pin0+3..Pin0]
··· where Pin0 is the first pin number in the sequence.

4- binary numbers like the ones you use in the case statement must have % in front of them
·· when you say 1000 then that would be taken as one thousand by the compiler. But if you say··
·· %1000 then it becomes binary.

5- You case statements are confused....%0100 would be Pin 23 not pin 24 also %0010 is 24 not 25 and %0001 would be 25 not 22
··· so you WaitPeq statements are using the wrong pin numbers for the cases.

6- the line···· angular_speed = time / 90·····is an error you need to use the := operator

7- in your case statement you are assuming the FIXED Pin numbers even though your intent was to have
··· them change according to the definition at the top.....use the Constant

8- In the getposition method you should really use an array so instead of CNTA then CNTB etc.
··· it would be better to have Cntr[4] and use Cntr[0], Cntr[1] etc.
··· This way your GetPosition method would be written more efficiently like
··· ··· x := position/90
······· position2 := x*90+(cnt-Cntr[x])*angular_speed
··· instead of all the if-statements.

9- When you calculate the time using······ time := (cntA - cntD) / 80_000_000
··· there are two problems
····· a- you are assuming clock speed.....it is better to use ClkFreq
····· b- CntA is smaller than CntD.....so you are going to get a negative time


These are the few I could find

Also I forgot.....most Hall effect sensors are Analog.....you may need a comparator
unless the sensors you bought are digital.....check that out..

Regards

Sam

····

Post Edited (SamMishal) : 7/11/2009 11:24:58 AM GMT

Timothy D. Swieter
07-11-2009, 06:27 PM
I didn't look at the program, however the idea of a magnetic encoder is a neat idea. I believe Allegro Microsystems has some off the shelf ICs that take care of the particulars and spit out the data. Check out the product on their web site, maybe it can provide some inspiration (or be an option for you).

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com (http://www.brilldea.com) - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com (http://www.tdswieter.com)

mminasian
07-14-2009, 05:12 AM
@ Sam: Many thanks for all of your suggestions, I have implemented them, along with Nick's acceleration point below. I think is a little more up to standard. I was waiting to compile the other program until the sensors came in (tomorrow). I ended up using the hamlin sensors from digikey:


http://www.hamlin.com/specsheets/55100%20IssueAE.pdf
(http://<br>http://www.hamlin.com/specsheets/55100%20IssueAE.pdf<br>)

I am using the three wire "Digital Switch version." I will have resistors to pull the output to 3.3 V. I don't think I need a comparator?

Updated code, I think this is more along the right track.

ALSO: I couldn't find the matching magnets to go with the hall effect, so I called Hamlin, and told them about my project and they were more than happy to drop 5 of them in the mail to me free of charge! Great service.




var
long pins, cntr, time, time2, angular_speed, angular_speed2, angular_acceleration, position, position2
byte x
con
#22 Pin1, Pin2, Pin3, Pin4
pub initialize
dira[Pin1..Pin4]~ '4 sensors, for use on pins 22-25

pub read
repeat
time2 := time
case ina[Pin1..Pin4]
%1000 : 'pin 22 is on (magnet activated switch)
position := 0 'gives the absolute 90 degree position for later on
cntr[0] := cnt 'store clk count
waitpeq(1, Pin2, 0) 'wait until pin 23 is turned on
cntr := cnt 'record new count
time := (cntr - cntr[0]) / _CLKFREQ 'number of counts over clk frequency
'yields time in seconds for transition
%0100 :
position := 90
cntr := cnt
waitpeq(1, Pin3, 0)
cntr := cnt
time := (cntr - cntr) / _CLKFREQ
%0010 :
position := 180
cntr := cnt
waitpeq(1, Pin4, 0)
cntr := cnt
time := (cntr - cntr) / _CLKFREQ
%0001 :
position := 270
cntr := cnt
waitpeq(1, Pin1, 0)
cntr[0] := cnt
time := (cntr[0] - cntr) / _CLKFREQ
angular_speed2 := angular_speed
angular_speed := time / 90 'time divided by 90 degrees for angular velocity
angular_acceleration := (angular_speed - angular_speed2) / (time + time_2)


pub get_position http://forums.parallax.com/images/smilies/tongue.gifosition2
x := position / 90
position2 := 90*x + (cnt - cntr[x])*angular_speed + (angular_acceleration / 2) * (cnt - cntr[x]) * (cnt-cntr[x])
if position2 > 359
position2 := 0
pub get_speed
Result := ((angular_speed + angular_speed2) / 2)

pub get_acceleration :angular_acceleration





(for whatever reason the cntr index isn't showing up on this post!, the logic is standard though and should be correct)

Also, Sam in reference to Point number 9, I don't believe the clock will be negative, as you can see that before that time statement, I have set the cntr[0] to a point in time past cntr. Also, in reference to point number 5, the case statements checks once it has achieved a state, and then I am waiting until it gets to the next position, hence the pins are staggered by one.

Clock speed is set in the main program.

Thanks again to all as always. I can't wait to test this out!

Post Edited (mminasian) : 7/13/2009 10:18:19 PM GMT

SamMishal
07-14-2009, 06:05 AM
hi mminasian,
Just a few problems....
1- You have not defined the array Cntr.....you just defined one variable called Cntr but then you are using
······ Cntr[0] and also later when you use Cntr[x] you do not have the array.....
··· Also I do not understand what you are trying to do with the Cntr[] any way but it definately is not going to give
··· you the right results the way you have done it especially with the lines I have highlighted in red.

··· See the code below with the lines in RED being problem lines.

2- WaitPeq(1,PinX,0) ..... is a problem ......you need to use
··· waitPeq( |< Pinx, |< Pinx , 0)·· .....

··· the first parameter of WaitPEQ is the state is for each bit in the 32 bits for each pin and the
··· second is a Mask......so you need to put the 1 in the right bit corresponding to the pin and so in the mask too.
··· you can use the |< operator or the << operator to shift the 1 t o create the state and mask.....read about WaitPEQ in the
··· manual.

3- the line
····· ····angular_acceleration·:=·(angular_speed·-·angular_speed2)·/·(time·+·time_2)
··· don't you need to subtract not add....you want Delta time no??

4- It is better to use ClkFreq instead of _ClkFreq......if you have the Propeller manual.....read the section
··· Titled _ClkFreq vs ClkFreq on page 66.....it explains why it is better to use the ClkFreq function



var
long pins, cntr, time, time2, angular_speed, angular_speed2, angular_acceleration, position, position2
byte x
con
#22 Pin1, Pin2, Pin3, Pin4
pub initialize
dira[Pin1..Pin4]~ '4 sensors, for use on pins 22-25

pub read
repeat
time2 := time
case ina[Pin1..Pin4]
%1000 : 'pin 22 is on (magnet activated switch)
position := 0 'gives the absolute 90 degree position for later on
cntr[0] := cnt 'store clk count
waitpeq(1, Pin2, 0) 'wait until pin 23 is turned on
cntr := cnt 'record new count
time := (cntr - cntr[0]) / _CLKFREQ 'number of counts over clk frequency
'yields time in seconds for transition
%0100 :
position := 90
cntr := cnt
waitpeq(1, Pin3, 0)
cntr := cnt
time := (cntr - cntr) / _CLKFREQ
%0010 :
position := 180
cntr := cnt
waitpeq(1, Pin4, 0)
cntr := cnt
time := (cntr - cntr) / _CLKFREQ
%0001 :
position := 270
cntr := cnt
waitpeq(1, Pin1, 0)
cntr[0] := cnt
time := (cntr[0] - cntr) / _CLKFREQ
angular_speed2 := angular_speed
angular_speed := time / 90 'time divided by 90 degrees for angular velocity
angular_acceleration := (angular_speed - angular_speed2) / (time + time_2)


pub get_position osition2
x := position / 90
position2 := 90*x + (cnt - cntr[x])*angular_speed + (angular_acceleration / 2) * (cnt - cntr[x]) * (cnt-cntr[x])
if position2 > 359
position2 := 0
pub get_speed
Result := ((angular_speed + angular_speed2) / 2)

pub get_acceleration :angular_acceleration



···

Post Edited (SamMishal) : 7/13/2009 11:11:54 PM GMT

Nick Mueller
07-14-2009, 06:28 AM
@mminasian:

I do not know what exact positions you need. I initially (or in the middle) thought that you do need to know 5 distinct positions that do not change with RPM. I guess you need them for getting the motor to run or better to start running.
If it is so that you need 5 fixed position use 5 damned sensors and not 4. You will have big jerks when you start the motor and you need 1/2 a revolution and then will only get a *wild* guess about the position.

Edit:
With your software, you'll only get a position when the motor is running. Each case statement will wait 'till hell frezes over in the waitpeq-statement.


Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

Post Edited (Nick Mueller) : 7/14/2009 12:13:55 AM GMT

mminasian
07-14-2009, 08:00 AM
@Nick Good call, I will have a startup mode...this is a secondary object not the primary. I am doing something different than before, there are only 4 fixed positions now, I'm taking a completely different tac on it than I did in the other posts.

@Sam Like I said for whatever reason the forum isn't posting my code correctly. It isn't showing the indices properly, this is what I am actually doing:

e.g.
var
long cntr, time, time2, angular_speed, angular_speed2, angular_acceleration, position2

%0100 :
position := 1
cntr := cnt
waitpeq(1, Pin3, 0)
cntr := cnt
time := (cntr - cntr) / CLKFREQ

Etc. The stupid code formatting on the forum is editing those out.


Also, the time is the amount over two different sets of 90 degrees. The delta T is the amount over the total of both time ranges.

I will look into fixing my WaitPEQ statements as well. Thanks guys!

EDIT: The index is STILL not showing in the code, the forum seems to use it to change font size???

Nick Mueller
07-14-2009, 08:34 AM
> EDIT: The index is STILL not showing in the code, the forum seems to use it to change font size???

Use the code-tag and pay attention to have a space after every [

Nick

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!

The DIY Digital-Readout for mills, lathes etc.:
YADRO (http://www.yadro.de)

SamMishal
07-15-2009, 06:28 PM
SamMishal·said...
Also the statement Return pins does not work.....SPIN does not use this syntax to return
oops.......This is one of these rare occasions where I am not so right http://forums.parallax.com/images/smilies/blush.gif http://forums.parallax.com/images/smilies/lol.gif·
See the manual page 196 it says it all.......proof of my fallibility after all.....I have to revise
my whole outlook on life and the meaning of my existence......I thought that only other people
make mistakes.....well well....I am not a god after all· ·http://forums.parallax.com/images/smilies/tongue.gif

Samhttp://forums.parallax.com/images/smilies/nono.gif

JonnyMac
07-15-2009, 09:06 PM
Shouldn't you use the absolute operator in your differential time calculation?



%0100 : position := 1
cntrstart := cnt
waitpeq(1, Pin3, 0)
cntrend := cnt
time := ||(cntrend - cntrstart) / CLKFREQ