Hall effect sensors (4 in a circle)
mminasian
Posts: 26
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[noparse][[/noparse]22..25]~ '4 sensors, for use on pins 22-25 pins := 22..25 return pins pub read repeat case ina[noparse][[/noparse]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
Comments
http://www.hamlin.com/specsheets/55100 IssueAE.pdf
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
If the position is really important, you'll fail.
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 OK, a bit crude. But it must be OK, they are the French.
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
Post Edited (Nick Mueller) : 7/10/2009 10:55:59 PM GMT
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[noparse][[/noparse]pins] again will not work......
··· if you have defined a constant (or variable) you can say case ina[noparse][[/noparse]Pin0..Pin0+3] or case ina[noparse][[/noparse]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[noparse][[/noparse]4] and use Cntr[noparse][[/noparse]0], Cntr[noparse][[/noparse]1] etc.
··· This way your GetPosition method would be written more efficiently like
··· ··· x := position/90
······· position2 := x*90+(cnt-Cntr[noparse][[/noparse]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, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" LCD Composite video display, eProto for SunSPOT
www.tdswieter.com
http://www.hamlin.com/specsheets/55100%20IssueAE.pdf
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.
(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[noparse][[/noparse]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
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[noparse][[/noparse]0] and also later when you use Cntr[noparse][[/noparse]x] you do not have the array.....
··· Also I do not understand what you are trying to do with the Cntr[noparse]/noparse 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
···
Post Edited (SamMishal) : 7/13/2009 11:11:54 PM GMT
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
Post Edited (Nick Mueller) : 7/14/2009 12:13:55 AM GMT
@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???
Use the code-tag and pay attention to have a space after every [noparse][[/noparse]
Nick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Never use force, just go for a bigger hammer!
The DIY Digital-Readout for mills, lathes etc.:
YADRO
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· ·
Sam