You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@nuttx.apache.org by Tomek CEDRO <to...@cedro.info> on 2023/06/08 23:53:40 UTC

qencoder / long / float / double / maximum values

Hello world :-)

I am working on ESP32 (no FPU) and using Quadrature Encoder for motor
control and range positioning. Current qencoder implementation stores
counted values on int32_t so the maximum and minimum value is only
around +/- 32k. I need far bigger numbers to be counted and available
for readout quickly.


Long Story Short:

1. I would like to change representing counted values on a big
floating number type with a sign, or just a bigger integer type.
2. I would like to ask what type would be best to represent floating
numbers in NuttX in terms of portability and efficiency.


Short Story Long:

I am thinking of extending (configuration time option) Quadrature
Encoder implementation so it would hold count number on a signed
floating point like R.I where R would indicate full Round and I in the
decimal part would indicate counted Impulses.

That would enable counting large numbers independently of the used
sensor in a single variable. Full round is usually indicated with
additional signal line, or it could be counted using modulo of the
decimal part with a given sensor resolution (i.e. 100 impulses per
round, 1024 impulses per round, etc). This way integer part would
indicate full rounds, while the decimal part would indicate actual
counted impulses.

For instance:

1. We have qencoder sensor with 100 impulses per Round, so initial
value would be 0.0 and moving CW (clockwise) 0.0 -> .. -> 0.99 -> 1.0
-> .. 1.99 -> 2.0 -> etc.

2. We have qencoder sensor with 1024 impulses per Round, so initial
value would be 0.0 and moving CCW (counterclockwise) 0.0 -> -0.1023 ->
-1.0 -> .. -> -1.1023 -> -2.0 -> .. -> -2.1023 -> -3.0 -> etc.

This way no matter what sensor is used the integer part of the readout
will always indicate full round move of a wheel (both are in a single
variable). And the number should be large enough to provide actual
position.

Does that make sense?

Is this a good idea to extend qencoder module for this.. or that
functionality should be implemented on the application level?
Application level could be too slow to calculate this and it only task
is to wait for a specific value and start / stop the motor, then
perform other tasks.

If this makes sense, then what variable type should be selected for
storing counter value? What would be most portable and efficient?
float (32bits)? double (64bits)? long double (80bits)?

If this does not make sense and integer operations would be always
simpler and faster, then what biggest integer type with a sign should
I choose? :-)

Any hints welcome :-)
Tomek

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info

Re: qencoder / long / float / double / maximum values

Posted by Tomek CEDRO <to...@cedro.info>.
On Fri, Jun 9, 2023 at 7:53 AM raiden00pl wrote:
> The index signal (Z index) should be used to reset the encoder position.
> You can miss an encoder step for various reasons, and without periodically
> checking the absolute position (index pin), you will accumulate errors.
> Then, if you set the maximum count of an encoder timer to encoder
> resolution, the values [0, encoder_resolution] map to the position of the
> motor rotor.
> Your app should be responsible for handling zero position crossing and any
> calculation regarding the distance traveled by the rotor.
>
> There are ioctls to handle this (QEIOC_SETPOSMAX, QEIOC_SETINDEX) but ESP32
> doesn't support them.

Thanks Raiden! Can you hint a complete implementation that I can base
on the ESP32 work? :-)

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info

Re: qencoder / long / float / double / maximum values

Posted by raiden00pl <ra...@gmail.com>.
The index signal (Z index) should be used to reset the encoder position.
You can miss an encoder step for various reasons, and without periodically
checking the absolute position (index pin), you will accumulate errors.
Then, if you set the maximum count of an encoder timer to encoder
resolution, the values [0, encoder_resolution] map to the position of the
motor rotor.
Your app should be responsible for handling zero position crossing and any
calculation regarding the distance traveled by the rotor.

There are ioctls to handle this (QEIOC_SETPOSMAX, QEIOC_SETINDEX) but ESP32
doesn't support them.


pt., 9 cze 2023 o 05:22 Tomek CEDRO <to...@cedro.info> napisał(a):

> On Fri, Jun 9, 2023 at 3:24 AM Nathan Hartman wrote:
> > I know it is sometimes unpopular to suggest adding more Kconfigs but
> maybe
> > this is something that should be configurable, allowing developers to
> > choose if they need a 64-bit count for range or a 32- (or even 16-) bit
> > count for efficiency. The needed speed and counter size really depends on
> > how the application is going to use the qencoder.
>
> Allright, mystery solved, the value returned is just a ESP32 specific
> register value (16-bit), according to the documentation this is mostly
> used for direction and speed decoding.. I will have to adapt it to a
> position value stored on a 32-bit or even 64-bit variable.. using
> floating numbers seems overkill.. thank you everyone for the hints!
> :-)
>
> --
> CeDeROM, SQ7MHZ, http://www.tomek.cedro.info
>

Re: qencoder / long / float / double / maximum values

Posted by Tomek CEDRO <to...@cedro.info>.
On Fri, Jun 9, 2023 at 3:24 AM Nathan Hartman wrote:
> I know it is sometimes unpopular to suggest adding more Kconfigs but maybe
> this is something that should be configurable, allowing developers to
> choose if they need a 64-bit count for range or a 32- (or even 16-) bit
> count for efficiency. The needed speed and counter size really depends on
> how the application is going to use the qencoder.

Allright, mystery solved, the value returned is just a ESP32 specific
register value (16-bit), according to the documentation this is mostly
used for direction and speed decoding.. I will have to adapt it to a
position value stored on a 32-bit or even 64-bit variable.. using
floating numbers seems overkill.. thank you everyone for the hints!
:-)

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info

Re: qencoder / long / float / double / maximum values

Posted by raiden00pl <ra...@gmail.com>.
> Thanks Raiden! Can you hint a complete implementation that I can base
> on the ESP32 work? :-)

You can look at
https://github.com/apache/nuttx/blob/master/arch/arm/src/stm32/stm32_qencoder.c
and search for CONFIG_STM32_QENCODER_INDEX_PIN.

sob., 10 cze 2023 o 02:53 Tomek CEDRO <to...@cedro.info> napisał(a):

> On Fri, Jun 9, 2023 at 3:24 AM Nathan Hartman wrote:
> > I know it is sometimes unpopular to suggest adding more Kconfigs but
> maybe
> > this is something that should be configurable, allowing developers to
> > choose if they need a 64-bit count for range or a 32- (or even 16-) bit
> > count for efficiency. The needed speed and counter size really depends on
> > how the application is going to use the qencoder.
>
> I am wondering on something more universal than #ifdef CONFIG and
> wrapping the whole lines of duplicated code..
>
> Maybe a void pointer that would be then casted to a type based on a CONFIG?
>
> Any hints welcome :-)
>
> --
> CeDeROM, SQ7MHZ, http://www.tomek.cedro.info
>

Re: qencoder / long / float / double / maximum values

Posted by Tomek CEDRO <to...@cedro.info>.
On Fri, Jun 9, 2023 at 3:24 AM Nathan Hartman wrote:
> I know it is sometimes unpopular to suggest adding more Kconfigs but maybe
> this is something that should be configurable, allowing developers to
> choose if they need a 64-bit count for range or a 32- (or even 16-) bit
> count for efficiency. The needed speed and counter size really depends on
> how the application is going to use the qencoder.

I am wondering on something more universal than #ifdef CONFIG and
wrapping the whole lines of duplicated code..

Maybe a void pointer that would be then casted to a type based on a CONFIG?

Any hints welcome :-)

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info

Re: qencoder / long / float / double / maximum values

Posted by Nathan Hartman <ha...@gmail.com>.
On Thu, Jun 8, 2023 at 8:12 PM Tomek CEDRO <to...@cedro.info> wrote:

> On Fri, Jun 9, 2023 at 1:53 AM Tomek CEDRO wrote:
> > I am working on ESP32 (no FPU) and using Quadrature Encoder for motor
> > control and range positioning. Current qencoder implementation stores
> > counted values on int32_t so the maximum and minimum value is only
> > around +/- 32k. I need far bigger numbers to be counted and available
> > for readout quickly.
>
> Sorry its 2AM here and I sit too much in front of the computer with no
> fresh air :-P
>
> int is 32 bit with range unsigned 4.294E9 aka 4,294,967,295 and
> -2,147,483,648 to 2,147,483,647 signed.
>
> long is 64 bit with range 1.833E19 unsigned and
> -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 signed.
>
> I need to get familiar with the qencoder code more and know why there
> is a 32k modulo.
>
> I know that float and double are discouraged in embedded. Maybe its a
> silly idea to use floating numbers where speed is important. Will
> changing INT to LONG impact performance a lot?



I know it is sometimes unpopular to suggest adding more Kconfigs but maybe
this is something that should be configurable, allowing developers to
choose if they need a 64-bit count for range or a 32- (or even 16-) bit
count for efficiency. The needed speed and counter size really depends on
how the application is going to use the qencoder.

Nathan

Re: qencoder / long / float / double / maximum values

Posted by Tomek CEDRO <to...@cedro.info>.
On Fri, Jun 9, 2023 at 2:22 AM Gregory Nutt wrote:
> We don't normally use int or long types explicitly since these types are
> different with different tools or hardware.  int32_t is always 32 bits
> wide, int64_t is always 64 bits wide and will be typedef'ed in
> include/stdint.h to the correct underlying type.
>
> If you have no FPU, have you considered using fixed precision real
> numbers.  See include/fixedmath.h.  They work well as long as the range
> of values is restrained.

TANK U SIR! :-)

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info

Re: qencoder / long / float / double / maximum values

Posted by Gregory Nutt <sp...@gmail.com>.
On 6/8/2023 6:11 PM, Tomek CEDRO wrote:
> On Fri, Jun 9, 2023 at 1:53 AM Tomek CEDRO wrote:
>> I am working on ESP32 (no FPU) and using Quadrature Encoder for motor
>> control and range positioning. Current qencoder implementation stores
>> counted values on int32_t so the maximum and minimum value is only
>> around +/- 32k. I need far bigger numbers to be counted and available
>> for readout quickly.
> Sorry its 2AM here and I sit too much in front of the computer with no
> fresh air :-P
>
> int is 32 bit with range unsigned 4.294E9 aka 4,294,967,295 and
> -2,147,483,648 to 2,147,483,647 signed.
>
> long is 64 bit with range 1.833E19 unsigned and
> -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 signed.
>
> I need to get familiar with the qencoder code more and know why there
> is a 32k modulo.
>
> I know that float and double are discouraged in embedded. Maybe its a
> silly idea to use floating numbers where speed is important. Will
> changing INT to LONG impact performance a lot?
>
> :-)

We don't normally use int or long types explicitly since these types are 
different with different tools or hardware.  int32_t is always 32 bits 
wide, int64_t is always 64 bits wide and will be typedef'ed in 
include/stdint.h to the correct underlying type.

If you have no FPU, have you considered using fixed precision real 
numbers.  See include/fixedmath.h.  They work well as long as the range 
of values is restrained.


Re: qencoder / long / float / double / maximum values

Posted by Tomek CEDRO <to...@cedro.info>.
On Fri, Jun 9, 2023 at 1:53 AM Tomek CEDRO wrote:
> I am working on ESP32 (no FPU) and using Quadrature Encoder for motor
> control and range positioning. Current qencoder implementation stores
> counted values on int32_t so the maximum and minimum value is only
> around +/- 32k. I need far bigger numbers to be counted and available
> for readout quickly.

Sorry its 2AM here and I sit too much in front of the computer with no
fresh air :-P

int is 32 bit with range unsigned 4.294E9 aka 4,294,967,295 and
-2,147,483,648 to 2,147,483,647 signed.

long is 64 bit with range 1.833E19 unsigned and
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 signed.

I need to get familiar with the qencoder code more and know why there
is a 32k modulo.

I know that float and double are discouraged in embedded. Maybe its a
silly idea to use floating numbers where speed is important. Will
changing INT to LONG impact performance a lot?

:-)

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info