How do I find out the “dt” in the complementary filter?

32 posts / 0 new
Author
Message

Okay, now i am really struggling on finding the "dt" in the complementary filter.  I have found the complementary filter equation here https://www.pieter-jan.com/node/11.

This is the equation:

The experession gyrData*dt is the change in rotation angle during a time interval dt. So, dt is just the time between successive samples.

I would suggest that dt is the least of your problems in that equation. You have 3 axes. What are gyrData and accData? And why are they combined that way? You need to get the context of  that equation, not just grab it from the internet without understanding.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Wed. May 8, 2019 - 02:30 PM

dt = delta time.  How often do you read the data?  That's dt.

In consideration of others, please RTFM!

Don't they teach "calculus" in school any more?

https://en.wikipedia.org/wiki/Calculus

The basis of that is integration and differentiation. This is often in terms of dx/dt or dy/dt. Surely you know the meaning of "dt" from that realm?

Hi Jim,

ka7ehk wrote:

So, dt is just the time between successive samples.

So, i need a timer but how do i know when to start and stop the timer?

ka7ehk wrote:

I would suggest that dt is the least of your problems in that equation. You have 3 axes. What are gyrData and accData? And why are they combined that way?

I know that the gyrData is just the gyroscope data in degree per second and the accData is the accelerometer value in degree.

ka7ehk wrote:
You need to get the context of  that equation, not just grab it from the internet without understanding.

I'll try my very best to understand everything in the equation.

jpmargis wrote:

dt = delta time.  How often do you read the data?  That's dt.

Hi jpmargis,

I am reading the data constantly so is there any method that i can get the "dt" from that?

The page you linked to in #1 even contains (though it says "don't just use this"!) the code:

#define dt 0.01							// 10 ms sample rate!

So it's pretty clear what they mean by "dt" from that alone.

clawson wrote:

The page you linked to in #1 even contains (though it says "don't just use this"!) the code:

#define dt 0.01							// 10 ms sample rate!

So it's pretty clear what they mean by "dt" from that alone.

Hi clawson,

The author mentioned about the program is running at 100Hz, but how can i make my program too runs at 100Hz? A 100 times loop?

100Hz == 10ms

What it's saying is that you take readings every 10ms (so a timer interrupt sounds like a plan) and then feed the "new readings" into your filter each time you get a set of 6 readings.

You really need to think about what the data represents and arrange your system to get the most out of it.

If your gyro data is in degrees per second, then you need a known time interval to get the angular change. That implies taking measurements at known time steps. In an MCU system, that usually means that a timer is used to set the interval, and every time the timer "fires", it reads.

There are two criteria for setting the interval. First, it must be longer than the time it takes to gather (e.g. read) and process the data. Second, it must be short relative to the expected motion. For example, lets suppose that it takes 1 second for a person to actually fall. And, lets suppose that you want to take readings DURING the fall. To have useful meaning, you might require 10 samples during the fall time, or a sample rate of 10 per second. This is the same as 10Hz. That is pretty slow, actually, compared to the sensor read time, so you can probably do it at least 10 times faster.

Once you are at THIS place, then you might come to realize that it is sitting there, doing nothing, between samples. That is a great chance to sleep and reduce power consumption. Timer wakes up the MCU, you take your readings and process them, then go back to sleep.

Depending on the MCU you choose, there are multiple kinds of sleep. Some turn EVERYTHING off while others keep the clock and timers running. You would need the latter, probably.

Hope this helps

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Are you using an AVR microcontroller?  If so, which one?

On an AVR you would want to look at the CTC mode for

a timer (Clear-Timer-on-Compare-match) which lets you

set an exact frequency.  Supposing your AVR is running

at 16 MHz, to achieve a 100Hz rate it would need to

count 16,000,000 / 100 = 160,000 cycles.

This is too large a number for even a 16-bit counter (which

can only count up to a maximum of 65536), so you'll have

to employ the clock prescaler to slow down the counting.

If, for example, you set the prescaler to divide-by-8, then

the timer will increment the counter every 8 CPU cycles.

Thus it will only have to count up to 160,000 / 8 = 20,000.

That should get you started, let us know if you need any

more assistance.

--Mike

clawson wrote:

100Hz == 10ms

What it's saying is that you take readings every 10ms (so a timer interrupt sounds like a plan) and then feed the "new readings" into your filter each time you get a set of 6 readings.

Hi Clawson,

So, right now i am getting the gyroscope data in a 100 times loop and it took roughly about 1.046 second with the sleep/delay function. Without the sleep/delay function, the 100 times loop can be done in roughly just 0.03 second.

Give in and learn how to program the timers (and interrupts) in your micro.

ka7ehk wrote:

There are two criteria for setting the interval. First, it must be longer than the time it takes to gather (e.g. read) and process the data. Second, it must be short relative to the expected motion. For example, lets suppose that it takes 1 second for a person to actually fall. And, lets suppose that you want to take readings DURING the fall. To have useful meaning, you might require 10 samples during the fall time, or a sample rate of 10 per second. This is the same as 10Hz. That is pretty slow, actually, compared to the sensor read time, so you can probably do it at least 10 times faster.

Hi Jim,

So, i need to met either one of these criteria in order to correctly define the "dt". But still i am very confused on how can i get the "dt", i knew that "dt" in this case can be refer to the sampling rate. And the author just set the "dt" as 0.01 but i do not see him getting the gyroData for 100 times,or "dt" is just the sampling rate and do not really necessary to take 100 times gyroscope data in order to use it?

ka7ehk wrote:

Once you are at THIS place, then you might come to realize that it is sitting there, doing nothing, between samples. That is a great chance to sleep and reduce power consumption. Timer wakes up the MCU, you take your readings and process them, then go back to sleep.

Depending on the MCU you choose, there are multiple kinds of sleep. Some turn EVERYTHING off while others keep the clock and timers running. You would need the latter, probably.

What i need to achieve now is just to proof that it can detect falls so i guess the sleep and reduction in power consumption will not come in handy for now but still thank you for the suggestion.

avr-mike wrote:

Are you using an AVR microcontroller?  If so, which one?

On an AVR you would want to look at the CTC mode for

a timer (Clear-Timer-on-Compare-match) which lets you

set an exact frequency.  Supposing your AVR is running

at 16 MHz, to achieve a 100Hz rate it would need to

count 16,000,000 / 100 = 160,000 cycles.

This is too large a number for even a 16-bit counter (which

can only count up to a maximum of 65536), so you'll have

to employ the clock prescaler to slow down the counting.

If, for example, you set the prescaler to divide-by-8, then

the timer will increment the counter every 8 CPU cycles.

Thus it will only have to count up to 160,000 / 8 = 20,000.

That should get you started, let us know if you need any

more assistance.

--Mike

Hi Mike,

Unfortunately i am not using an AVR microcontroller for this project but i will more than happy to use it if its suitable for the projects in the future.

clawson wrote:

Give in and learn how to program the timers (and interrupts) in your micro.

Hi clawson,

Right, below are the results i get by using the timers and interrupts.

ckkkkk wrote:

So, right now i am getting the gyroscope data in a 100 times loop and it took 1.046 second with the sleep/delay function. Without the sleep/delay function, the 100 times loop can be done in just 0.03 second.

EDIT : My bad, it is the exact time not roughly.

Last Edited: Thu. May 9, 2019 - 09:37 AM

Point is: You need to have a better number than "roughly". That comes from having something predictable, like a timer, tell when to take each reading.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

This is too large a number for even a 16-bit counter (which can only count up to a maximum of 65536), so you'll have

to employ the clock prescaler to slow down the counting. If, for example, you set the prescaler to divide-by-8, then the timer will increment the counter every 8 CPU cycles.

As an alternative you can use a variable to extend the timing bitwidth.  Say a 16bit timer extended with 8 bit variable gives up to 24bits of timing (2^24 possible counts).....The advantage is you still have great timing resolution when you want it.  Disadvantage is it takes some memory (for the byte variable) & repetitive overhead.

I never appreciated this built-in til I worked with some 32 bit pic timers...Gee, I can time for over a full hour down to the microsecond??!!  Using only hardware--fantastico!!!

Not sure why they couldn't do same for avr...32 bits worth of flip flops is nothing...if you need to read 4 result registers, so what?  I suppose, they don't want to erode market share for the other chips.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. May 8, 2019 - 11:35 PM

The OP stated he’s using a raspberry pi.
Unfortunately with linux real time performance is not guaranteed, so if you want consistent results from your sensor, then you’re not using the right platform. Put simply- your delays aren’t guaranteed. If linux decides to do some network, filesystem or any other task, then your task gets delayed and randomly at that.

Use something like an Arduino to give consistent timing and pass the data across to the pi for processing.

Most IC sensors and/or sensor systems are not "self timing" in the sense that you could set an interval and say "give me a reading every 250us" :-(

Even the microcontroller peripherals that have a continuous sampling mode usually have a very limited set of possible timing options, and providing control over "dt" will mean using both a timer peripheral and the interface to the sensor.

This is one of the reasons that "little" CPUs like AVRs survive even in a world where you can get a raspberry Pi for about the same prices as an Arduino board, even though the Pi theoretically is many times more powerful.   The Arduino will happily (and relatively easily) read a sensor at a fixed and accurate dt, and buffer it up for the more complex algorithms on a Pi or PC to handle (but not with accurate timing on the PC side.)

Many, maybe most, STMicro accelerometers ARE self timed. They will even assert an interrupt line when a new sample is ready.,

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

ka7ehk wrote:

Point is: You need to have a better number than "roughly". That comes from having something predictable, like a timer, tell when to take each reading.

Jim

Hi Jim,

My bad, those are the exact time for 100 times of data reading from the gyroscope with / without the sleep/delay function.

Kartman wrote:
The OP stated he’s using a raspberry pi. Unfortunately with linux real time performance is not guaranteed, so if you want consistent results from your sensor, then you’re not using the right platform. Put simply- your delays aren’t guaranteed. If linux decides to do some network, filesystem or any other task, then your task gets delayed and randomly at that. Use something like an Arduino to give consistent timing and pass the data across to the pi for processing.

Hi Kartman,

Yes, i am using the Raspberry Pi for the project but unfortunately it is a restricted project whereas only raspberry pi is allow to use.

You’d want to understand the limitations of the chosen platform then.

Ok, to be honest so far i only knew that "dt" in this case can be refer to the sampling rate. The author just set the "dt" as 0.01 and i know this is because the gyroscope has a 100Hz Output data rate which means it can output 100 readings in a second, but the author did no output the data 100 times instead he just uses the "dt" as 0.01 .  Am i missing something here?

I can’t help but think you are missing some fundamental knowlege. You seem to obsess about things that are most likely the least of your worries. As to why you might need a gyro for fall detection is beyond me - unless you want to detect if the person is doing the electric boogaloo or the lambada before they fall.

Kartman wrote:
Why not ask the author? I can’t help but think you are missing some fundamental knowlege. You seem to obsess about things that are most likely the least of your worries. As to why you might need a gyro for fall detection is beyond me - unless you want to detect if the person is doing the electric boogaloo or the lambada before they fall.

Hi Kartman,

I did email him few weeks ago, but no luck getting his reply tho. Therefore, i come back to the forum again and seek for help.

def read_GyroscopeScaled(xAccelRotation,yAccelRotation):
# Read data back from 0x43(67), 6 bytes
# Gyrometer X-Axis MSB, X-Axis LSB, Y-Axis MSB, Y-Axis LSB, Z-Axis MSB, Z-Axis LSB

xGyroAngle = 0
yGyroAngle = 0
cfXangle = 0
cfYangle = 0
cfXangle2 = 0
cfYangle2 = 0
current_time = time.time()

# Convert the data
xGyro = data[0] * 256 + data[1]
if xGyro > 32767 :
xGyro -= 65536

yGyro = data[2] * 256 + data[3]
if yGyro > 32767 :
yGyro -= 65536

zGyro = data[4] * 256 + data[5]
if zGyro > 32767 :
zGyro -= 65536

xGyroDPS = (xGyro - GyroxOff) / Gyro_scale
yGyroDPS = (yGyro - GyroyOff) / Gyro_scale
zGyroDPS = (zGyro - GyrozOff) / Gyro_scale
end = time.time()
dt =  end - current_time
xGyroAngle += xGyroDPS * dt
yGyroAngle += yGyroDPS  * dt
previous_time = current_time
cfXangle = 0.98 * (cfXangle + xGyroDPS * dt) + 0.02 * (xAccelRotation)
cfYangle = 0.98 * (cfYangle + yGyroDPS * dt) + 0.02 * (yAccelRotation)
cfXangle2 = 0.98 * (cfXangle + xGyroAngle) + 0.02 * (xAccelRotation)
cfYangle2 = 0.98 * (cfYangle + yGyroAngle) + 0.02 * (yAccelRotation)
print ("X-Axis Degree per second : %.2f" %xGyroDPS)
print ("Y-Axis Degree per second : %.2f" %yGyroDPS)
print ("Z-Axis Degree per second : %.2f" %zGyroDPS)
print ("X Gyro angle: %f" %xGyroAngle)
print ("Y Gyro angle: %f" %yGyroAngle)
print ("CF x Angle: %f" %cfXangle)
print ("CF y Angle: %f" %cfYangle)
print ("CF x Angle2: %f" %cfXangle2)
print ("CF y Angle2: %f" %cfYangle2)



According to the author's formula for complementary filter, he uses this formula

    cfXangle = 0.98 * (cfXangle + xGyroDPS * dt) + 0.02 * (xAccelRotation)
cfYangle = 0.98 * (cfYangle + yGyroDPS * dt) + 0.02 * (yAccelRotation)

and the results i get by using this formula are under the (CF x & y Angle) below. But if i change the formula into this

cfXangle2 = 0.98 * (cfXangle + xGyroAngle) + 0.02 * (xAccelRotation)
cfYangle2 = 0.98 * (cfYangle + yGyroAngle) + 0.02 * (yAccelRotation)

I noticed that i get different results from the above formula which are under the (CF x&y Angle2) below. So, which one is the correct one? Also all the data are acquired when the gyroscope is stationary, do they look normal?

These are the results i get.

Note the zero offsets for rotational velocity. Those need correction, also.

Your equation change assumes that you have new values every second. I highly doubt that is correct. You need to use the ACTUAL time difference. If you cannot insure what the sample rate is, then you ought to measure it in real time, perhaps using a timer capture function. But RPi may not have this. Does it have a milliseconds counter? If so, you might be able to use that.

This is really a situation where you are hobbling yourself by using the RaspberryPi. It simply is not very good at realtime processing which is exactly what you need.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

ka7ehk wrote:

Note the zero offsets for rotational velocity. Those need correction, also.

Hi Jim,

Yes, i did get 100 of the gyroscope data to correct the offset but its still have the zero offset error tho.

ka7ehk wrote:
Your equation change assumes that you have new values every second. I highly doubt that is correct. You need to use the ACTUAL time difference. If you cannot insure what the sample rate is, then you ought to measure it in real time, perhaps using a timer capture function. But RPi may not have this. Does it have a milliseconds counter? If so, you might be able to use that.

This is really a situation where you are hobbling yourself by using the RaspberryPi. It simply is not very good at realtime processing which is exactly what you need.

I am using python for this, therefore i can use the time function in python. So, what i should be doing is get the time when i first run the loop and then the next time i'll need to minus the previous loop time in order to get the "dt"? Like current_gyro_sample_time - previous_gyro_sample_time?