Memsic 2125 - getting tilt angle?
fiddejoh
Posts: 6
Sorry if the topic has been answered, I did a search but couldn't find any threads that answered my question.
I recently got a Memsic 2125 accelerometer and I'm getting the raw values (both X and Y is ~397000).
I found this code to convert it to degrees
Not entirely sure how those formulas work though..
I also found this PDF: http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/vol3/col/nv92.pdf which is using another formula to calculate the tilt angle.
Could someone kindly clarify what I should use?
Thanks in advance!
I recently got a Memsic 2125 accelerometer and I'm getting the raw values (both X and Y is ~397000).
I found this code to convert it to degrees
offset := 90 * (clkfreq / 200) 'offset value for sensor data conversion scale := clkfreq / 800 'scale value for sensor data conversion
Not entirely sure how those formulas work though..
I also found this PDF: http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/vol3/col/nv92.pdf which is using another formula to calculate the tilt angle.
Could someone kindly clarify what I should use?
Thanks in advance!
Comments
Graham
it's from a Parallax Demo that I found here: http://obex.parallax.com/objects/235/
From the file: MX2125 Demo.spin
/ Fredrik
Firstly Paul is using the system clock to measure time not the Pulsein routine so the resolution is 1/clkfreq. He also changes the equation to be in terms of the difference between the pulse length T1 measured (accel.x) and what it would be at 50% duty cycle when T1 = T2/2 and A = 0g.
T2 is clkfreq/100 so at 50% duty when T1 = T2/2:
T1@50% = clkfreq/200
This is basically the offset he uses (ignore the 90 for now)
So what is T1 when A = 1g? This is when the sensor is at 90 degrees
1 = (T1/T2 - 0.5)/0.125 from datasheet and Jon's article
0.125 = T1/T2 - 0.5
0.625 = T1/T2
0.625T2 = T1
T1@1g = 0.652(clkfreq/100) because T2 = clkfreq/100
So what is the difference when A = 1g?
difference = T1 - (clkfreq/200)
difference@1g = T1@1g - (clkfreq/200)
difference@1g = 0.625(clkfreq/100)- (clkfreq/200) Substitute fot T1@1g from above
difference@1g = (clkfreq/100)(0.625 - 0.5)
difference@1g = (clkfreq/100)(0.125)
So when the difference between measured T1 and T1@50% is equal to difference@1g then we want the equation to be equal to 90.
To do this we multiply both sides of the equation for difference by 1/difference@1g this will make the equation equal to one when the sensor is at 1g. We then multiply the equation by 90 so that it is actually 90 when at 1g.
difference*100*90*8/clkfreq (8 because 1/0.125 is 8)
= (T1 - (clkfreq/200))*800*90/clkfreq
= (T1*90 - (clkfreq*90/200)) * (800/clkfreq)
Then let:
offset = (clkfreq*90/200)
scale = clkfreq/800
accel.x = T1
So:
Angle = (accel.x*90 - offset)/scale
I hope that makes some sense, he also just assumes the relationship between g and angle is linear.
Graham
Graham
There is an updated object I did awhile ago that should provide individual Tilt angle information.
obex.parallax.com/objects/140/
Here is a You-Tube video of that DEMO in action...
www.youtube.com/user/ICPolyman#p/u/7/ef7ZAb5fOv8
If there is a question as to where the large numbers (~400K) come from and how they relate to the measured value, it has to do with the speed of the Propeller running at 80MHz
The 'raw' values are simply returning THx which at 0g should be reporting a pulse width of 5ms. 5ms divided by 12.5ns (<-80MHz) equals 400,000. So to get values like you might be more familiar with from the BS2 you could divide the Raw ~400K value by 160. This would in effect give you a 2us resolution (<-- that of the BS2). So a 5ms pulse at 0g divided by 160 would produce an expected value of 2500
Can you please also site the URL where you are finding the deg conversion? In the context that you have provided them they don't seem correct, but looking at the rest of the code it might make more sense.
Typically to convert the 32-Bit Angle returned from the Memsic Coordic operation into something more 'human readable' you typically do a 'shift right' of 19 or divide by 524288... this does an immediate conversion from a 32-Bit Angle into a 13-Bit Angle.
Likewise since all of the graphics routines are localized around a 13-bit Angles, to convert an ordinary Deg value into a 13-Bit Angle you typically apply a formula similar to this...
Angle13 := (Deg *1024)/45
To go the other direction a derivative of these formulas would be used. .i.e.
Deg := (Angle13 * 45)/1024
...I don't really see a need to create a 32-Bit Angle, but if you needed to just shift left the Angle13 value.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 3/9/2010 3:50:42 PM GMT
thank you VERY much! Excellent explanations, it helped me a lot. [noparse]:)[/noparse]
/ Fredrik
5ms would be 0g because it's 50% duty?
> "Can you please also site the URL where you are finding the deg conversion?"
The code Fredrik posted is a snippet from Paul's object (http://obex.parallax.com/objects/235/) but your object contains exactly the same code for offset and scale.
Fredrik,
Glad to be of help.
Graham
right you are, Corrections have been made. It's been awhile since I visited that code, and I was looking at the "Graphics_Demo_v2" program where I didn't see it.
I do see it now in the actual 'core' driver "Memsic2125_v1.2" ... I think when I modified the "Memsic2125_v1.2" I either borrowed some of Pauls code ideas or resolved down a similar path.
Looking at it now it looks like it could be simplified and the *90 could at least be taken out of the equation, but I don't want to mess with anything right now.
If you look at offset ... assuming that the clkfreq is 80MHz ... it resolves to 36,000,000
likewise, if you look at scale ... it resolves to 100,000
How offset and scale are used later basically divides them ... offset / scale = 360 ... to obtain your deg value.
The scaling and offset is necessary to bring the levels to the raw output of the Memsic, and since the output is clock dependent, it must be factored in.
My thinking as far as simplifying is that the existing code below...
...
... Could be simplified to something like the code below with the same results (keep in mind it's untested)
...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Thanks very much for that; the thread has cleared up a nagging question in my head as I explored the Memsic driver. I could not figure out why that factor of 90 was in there. In fact, I was, quite literally writing you an email about this very issue when I came across this thread....
I am using this module with the Analog Devices ADXL 213 accelerometer, and the scaling for this device is different, as is the PWM period (actually, the period is user-settable). Moreover, the ADXL213 has a CAL pin, which enables one to quickly check the correctness of the implementation for reading it.
FWIW, my first foray into Propellerland went quite well as I used a PWM spin module to drive the Memsic spin module, so that I could diagnose what was going on, and this enabled me to quickly sort the matter and get the ADXL 213 going. The overall project is an inertial dynomometer for use in automotive applications.
Graham
Here's what I am using for the ADXL213 (this is the start proc in the Memsic2125_V1.2.spin source):
PUB start(xpin, ypin) : okay
'' Start driver - starts a cog
'' returns false if no cog available
''
'' xpin = x input signal
'' ypin = y input signal
''
stop
'MAM: can't see what the 90 is in the next line. But, clkfreq/200 is 50% of the duty cycle @ 100Hz
'MAM: for the ADXL213, with a duty cycle of 1 Khz, this should be: clkfreq/2000
offset := clkfreq/2000 '90 * (clkfreq / 200) 'offset value for Tilt conversion
'MAM: clkfreq/800 is 12.5% of the duty cycle of 100 Hz. 12.5% is the sensitivity of the Memsic 2125
'MAM: for the ADXL213, with a duty cycle of 1 Khz, this should be: clkfreq/3000. 30% is the sensitivity of the ADXL213
scale := clkfreq/3000 'clkfreq / 800 'scale value for Tilt conversion
ctra_value := $6800_0000 + xpin
ctrb_value := $6800_0000 + ypin
mask_value := |<xpin + |<ypin
okay := cog := cognew(@entry, @calflag) + 1
If one uses the Mx and My procs to retrieve the raw values, you will find that this works for obtaining the (correct) raw accelerometer output in mg. On the ADXL213, as I mentioned, there is a cal pin, which when used, will cause the ADXL to output 750 mg (23% duty). This can easliy be verified by looping back a PWM spin driver into the Memsic driver. Furthermore, it can be verified on the device itself. One of the consequences of not having such a cal function is that one cannot easily confirm the correctness of an implementation for the driver. If all you're interested is an output proportional to acceleration (for example, a feedback on an attitude control system), I suppose it's not a big deal. But, if you are after a reasonably accurate output, it becomes more of an issue. The Memsic would also liikey require some temperature correction if the accel values were to be used on an absolute basis, depending on how it is to be used.
Finally, I have not checked the cordic routines, but the question I have on this part of the implementation is, are those routines computing based on angles in degrees or angles in radians? That was part of what was confusing me on the factor of 90 in the scaling (I was expecting the transcendentals to be done in radians...). It appears that the angles are being computed in degrees. Anyone confirm? I will find out empirically, otherwise.
Thanks,
Mike
Graham