officinerobotiche / uNAV.X

Project MPLABX for drive uNAV on dsPIC33
http://rnext.it/project/unav/
MIT License
9 stars 2 forks source link

Issue reading encoder at low speeds #36

Closed Myzhar closed 8 years ago

Myzhar commented 9 years ago

After a few test using the PID tuner I faced that using a 400 CPR encoder there are really serious problems reading speeds below 1 rad/sec. Once the motor exceeds 1 rad/sec the PID starts working very well and the speeds are read correctly.

rbonghi commented 9 years ago

I think the problem is in https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L174

Now I don't have time and a correct setup to test this problem at low speeds. @Myzhar or @katodo If you have time, I am happy to help me :smile:

rbonghi commented 9 years ago

@guiott How have you solved this problem in your board?

guiott commented 9 years ago

I don’t exactly know if the problem could be the same. To expand the dynamic range of the Input Capture I vary its Mode in this way: http://www.guiott.com/Lino/Speed/DynamicIC.htm http://www.guiott.com/Lino/Speed/DynamicIC.htm

Il giorno 25/gen/2015, alle ore 19:24, Raffaello Bonghi notifications@github.com ha scritto:

@guiott https://github.com/guiott How have you solved this problem in your board?

— Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71384528.


http://www.guiott.com/

Myzhar commented 9 years ago

@guiott I'm sure that the problem is generated by overflows in the 16bit counter, so the solution is exactly in changing the prescaler. If you look at the screenshoots that I posted on hangout you can see the big oscillations at low speeds...

Myzhar commented 9 years ago

download_20150125_210652

guiott commented 9 years ago

According to this:

https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/system.c#L334 https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/system.c#L334

it seems that the IC is already configured at max events detection. Even if the comment says “every rising edge”, ICM = 1 means every rising and falling edge. But there still is margin on this:

https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/system.c#L333 https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/system.c#L333

halving the interrupt time with ICx = 0

Il giorno 25/gen/2015, alle ore 21:09, Walter Lucetti notifications@github.com ha scritto:

I do not know if it works, I try to attach the screenshoot at the email Il 25/Gen/2015 20:11 "Guido" notifications@github.com ha scritto:

I don’t exactly know if the problem could be the same. To expand the dynamic range of the Input Capture I vary its Mode in this way: http://www.guiott.com/Lino/Speed/DynamicIC.htm < http://www.guiott.com/Lino/Speed/DynamicIC.htm>

Il giorno 25/gen/2015, alle ore 19:24, Raffaello Bonghi < notifications@github.com> ha scritto:

@guiott https://github.com/guiott How have you solved this problem in your board?

— Reply to this email directly or view it on GitHub < https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71384528>.


http://www.guiott.com/

— Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71386750 .

— Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71390154.


http://www.guiott.com/

guiott commented 9 years ago

Of course also the timer2 prescaler can be modified to not overflow in case of a very long delay between two edges of the ICx. Currently it's at 1:1 value, meaning a short time before overflowing. All the chain must be recalculated to have the best range. E.g.: lowering the pulses from the ICx (ICM) and increasing the prescaler in medium to high RPM in order to have the possibility to change ICM at a very low speed.

Myzhar commented 9 years ago

@guiott I have a big doubt: I noticed that we use the same timer (TMR2) for events on IC1 and IC2. Could this lead to problems when events on IC1 and IC2 are synchronous?

rbonghi commented 9 years ago

Could this lead to problems when events on IC1 and IC2 are synchronous?

I think is an exceptional event, but the problem is on overflow variable control on IC interrupt routine.

Raffaello

Il giorno 26/gen/2015, alle ore 08:25, Walter Lucetti notifications@github.com ha scritto:

@guiott I have a big doubt: I noticed that we use the same timer (TMR2) for events on IC1 and IC2. Could this lead to problems when events on IC1 and IC2 are synchronous?

— Reply to this email directly or view it on GitHub.

guiott commented 9 years ago

I’m asking to @rbonghi how the timer is used. If it’s used in free running mode there are no problems at all. In this case the only care to take on is on flagging separately the overflow for the two ICs: https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1265 https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1265

And then to reset the appropriate flag when you’ll use the TMR2 value to measure the time: https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1315 https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1315

for IC1 and: https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1348 https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1348

for IC2.

In fact the TMR2 is used separately by the two ICx just to get a snapshot of its value in ICxBUF registers when the ICx interrupt occurs. Meanwhile the timer is running freely with no care about who is using its register.

See a brief description here: https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/descrEng.txt#290 https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/descrEng.txt#290

and here: https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/descrEng.txt#211 https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/descrEng.txt#211

See Microchip application note AN545 for a detailed discussion about different modes can be used.

Il giorno 26/gen/2015, alle ore 08:25, Walter Lucetti notifications@github.com ha scritto:

@guiott https://github.com/guiott I have a big doubt: I noticed that we use the same timer (TMR2) for events on IC1 and IC2. Could this lead to problems when events on IC1 and IC2 are synchronous?

— Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71422475.


http://www.guiott.com/

Myzhar commented 9 years ago

Ok, my doubt came from STm32 because it starts and stops the timer automatically at raising and falling events and I do not use it in freerun mode

Myzhar commented 9 years ago

I was looking at the code... The variable overTmrL is used here: https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L179 declared here https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L50 and finally incremented here https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L239

Are you sure that this mechanism works? What about if we have an overflow at the very beginning of the startup when the motors are really really slow?

I think that it should must be incremented at every overflow...

guiott commented 9 years ago

Sorry, I've not understood. The only reason for what the TMR2 triggers an interrupt is when the register overflows over 2^16. The TMR2 register is initialized at the beginning to 0XFFFF before enabling it and its interrupt. So, the variable is always incremented at the right moment.

@rbonghi Isn't it?

Il giorno 26/gen/2015, alle ore 16:37, Walter Lucetti <notifications@github.com mailto:notifications@github.com> ha scritto:

I was looking at the code... The variable overTmrL is used here: https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L179 https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L179 declared here https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L50 https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L50 and finally incremented here https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L239 https://github.com/officinerobotiche/uNAV.X/blob/develop/src/system/interrupts.c#L239 Are you sure that this mechanism works? What about if we have an overflow at the very beginning of the startup when the motors are really really slow?

I think that it should must be incremented at every overflow...

— Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71479491.


http://www.guiott.com/ http://www.guiott.com/

rbonghi commented 9 years ago

:+1:

Myzhar commented 9 years ago

My double is on the control "if (timePeriodL)". This means that if "timePeriodL" (as for timePeriodR naturally) is zero (starting condition), the overflow is not takes into account.

If the robot moves at very low speed we can have overflows without incrementing the variable "overTmrL".

It is a limit case, but it can happens!

guiott commented 9 years ago

Let’s ask to @rbonghi

in my version there isn’t such a check https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1265 https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#1265

Il giorno 27/gen/2015, alle ore 09:37, Walter Lucetti notifications@github.com ha scritto:

My double is on the control "if (timePeriodL)". This means that if "timePeriodL" (as for timePeriodR naturally) is zero (starting condition), the overflow is not takes into account.

If the robot moves at very low speed we can have overflows without incrementing the variable "overTmrL".

It is a limit case, but it can happens!

— Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71609369.


http://www.guiott.com/

Myzhar commented 9 years ago

I agree with that code. I think that I understood the code enough to start to try to solve this issue.

Myzhar commented 9 years ago

@guiott

I have a doubt. I read with great care your code and I think that I found a possible problem. It is a limit case, but it can happen.

We use the same timer (TMR2) for both IC1 and IC2, so when we change the scale factor we affect the speed measures of both the motors because we use the same KVel.

What does it happen when a motor is moving really slow and the other really fast? This is the case of the rotation on the place using a wheel as rotation pin...

I stated this according to this line of code: https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#665

guiott commented 9 years ago

I'm not changing the TMR2 prescaler but the input capture mode of each single ICx. I.e. the way it's triggered by the encoder pulses: every edge every rising edge every 4th rising edge every 16th rising edge

If you look at here:

https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#553 https://code.google.com/p/dspid4w/source/browse/trunk/dsPID4W.X/src/dsPID4W.c#553

you can see that I change the ICx prescaler according to the speed of every single wheel, even in different way if the run differently.

Il giorno 28/gen/2015, alle ore 19:13, Walter Lucetti <notifications@github.com mailto:notifications@github.com> ha scritto:

@guiott https://github.com/guiott I have a doubt. I read with great care your code and I think that I found a possible problem. It is a limit case, but it can happen.

We use the same timer (TMR2) for both IC1 and IC2, so when we change the scale factor we affect the speed measures of both the motors.

What does it happen when a motor is moving really slow and the other really fast? This is the case of the rotation on the place using a wheel as rotation pin...

— Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71885220.


http://www.guiott.com/ http://www.guiott.com/

katodo commented 9 years ago

ok, but this is usefull for high speed encoder, no for speed near 0, it's right?

Mauro Soligo by Sony Xperia Z

guiott commented 9 years ago

It's useful anyway to expand the dynamic range of the input capture peripherals. You can find the right values for TMR2 and ICx modes in order to find the best compromise for your system.

Keep in mind that you have a 16 bit timer. Using carefully the overflow bit you can expand this to a larger (equivalent) value but it's still a limited value.

Using the ICx modes too you can further expand the dynamic (by a value of 32) finding a good value for both high speed (let's say every 16th rising edge) avoiding to much interrupts that can overflow the MCU capabilities, still maintaining a good range at very low speed where you are able to catch every single edge of the encoders.

All of that still keeping an high rate of speed sampling to have a very responsive PID control.

Il giorno 28/gen/2015, alle ore 20:03, Katodo notifications@github.com ha scritto:

ok, but this is usefull for high speed encoder, no for speed near 0, it's right?

Mauro Soligo by Sony Xperia Z — Reply to this email directly or view it on GitHub https://github.com/officinerobotiche/uNAV.X/issues/36#issuecomment-71894227.


http://www.guiott.com/

rbonghi commented 9 years ago

Hello guys! I've an idea to improve the quality of estimation for velocity. In according with, http://www.officinerobotiche.it/tutorial/encoder/ (sorry is an italian page) on "Metodi per calcolare la velocità", we've two different type of estimate velocity from encoders.

  1. Base time velocity - We using this method with IC system. (Fixed angular space, but we measure time between pulses) - Minimum error at high velocity
  2. Base space velocity - We'll measure difference of space using QEI dividend with fixed time (example rate of timer) - Minimum error at low velocity

If we'll use in both we should decrease the error at low velocity. :smile: I remember that 2 type of measure is "free" because we'll add a little function to evaluate this number.

rbonghi commented 9 years ago

schermata 2015-01-30 alle 23 59 08

I using https://github.com/officinerobotiche/uNav_PID_Tuner and I look a strange curve. When the second motor cross zero, the control output on motor zero generate a different number.

@Myzhar