QEI Module

classic Classic list List threaded Threaded
17 messages Options
Campbell Letts Campbell Letts
Reply | Threaded
Open this post in threaded view
|

QEI Module

Hey Everyone,

I've put in a pull request to elua/elua on github so feel free to have a look.

As mentioned before, it is a generic qei module for elua with support currently for the lm3s8962.

Cheers,
Campbell


_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
jrambo316 jrambo316
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

Hello,

I am new to eLua and will be working with the lm3s8962.  After studying the datasheet, I have determined that I want to use the QEI functions.  

So, I am guessing that I need to get a development version of the src that has this included.  I have not built a standard elua image yet as I already know I want this module.  I might do that just to test my setup though.

Is there some kind of index that I can easily tell what repo to hookup?  

Regards,
Jim
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

There is a QEI module that has been contributed on a branch and I've
converted them to platform-specific versions but haven't yet merged
them into the master repo:
https://github.com/jsnyder/elua/tree/lm3s_qei

I still need to update documentation for it, but you can refer to
qei.c for function prototypes here:
https://github.com/jsnyder/elua/blob/lm3s_qei/src/platform/lm3s/qei.c
(comments reference what the lua API looks like)

If you could provide some confirmation on the functionality that would
help to let me know if this requires any further work before merging.


On Wed, Mar 7, 2012 at 9:48 PM, jrambo316 <[hidden email]> wrote:

> Hello,
>
> I am new to eLua and will be working with the lm3s8962.  After studying the
> datasheet, I have determined that I want to use the QEI functions.
>
> So, I am guessing that I need to get a development version of the src that
> has this included.  I have not built a standard elua image yet as I already
> know I want this module.  I might do that just to test my setup though.
>
> Is there some kind of index that I can easily tell what repo to hookup?
>
> Regards,
> Jim
>
> --
> View this message in context: http://elua-development.2368040.n2.nabble.com/QEI-Module-tp7182596p7353847.html
> Sent from the eLua Development mailing list archive at Nabble.com.
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev



--
James Snyder
Biomedical Engineering
Northwestern University
http://fanplastic.org/key.txt
ph: (847) 448-0386
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
jrambo316 jrambo316
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

I'll let you know how things go.  My board has not arrived yet.  

2 more questions:
1.  I have been researching the QEI description in the datasheet trying to figure a way to get two velocity sensors per QEI rather than velocity and position.  I am a little confused on the position integrator.  One thing I came up with was to use the Phase A / Phase B switching capability to get a reading on A, switch, get a reading on B, switch, etc.  Unfortunately, this would obviously cut my performance.  Ideas?

Also, I am wondering why the ability to use a timer input capture pin as an edge timer and generate an interrupt does not seem to be supported in the timer documentation.  In this way, I think the general purpose timers could also be used for velocity measurement.  

2.  From other posts, it looks as though you are familiar with eluarpc as well.  I noticed that you guys are working on rpc over ip.  For my purposes, I want to implement rpc over SPI or I2C or both.  Anything in the works for that?

Regards,
Jim
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

On Sat, Mar 10, 2012 at 3:38 PM, jrambo316 <[hidden email]> wrote:
> I'll let you know how things go.  My board has not arrived yet.
>
> 2 more questions:
> 1.  I have been researching the QEI description in the datasheet trying to
> figure a way to get two velocity sensors per QEI rather than velocity and
> position.  I am a little confused on the position integrator.  One thing I
> came up with was to use the Phase A / Phase B switching capability to get a
> reading on A, switch, get a reading on B, switch, etc.  Unfortunately, this
> would obviously cut my performance.  Ideas?

To be honest I'm not certain that would be possible, depending on what
you mean.  Though I've helped to convert the module to a
platform-specific module that someone else provided I haven't looked
into the implementation details of this particular platform.

The phase A & B channels are both needed for a given implementation so
that one can disambiguate between rotation in one direction vs
another.  Otherwise it would be behaving just like a counter. The
velocity should just be a derivative of what the counter that's
integrating both channels has been doing during the last number of
clock cycles (or some filtered version of that).

One can do quadrature decoding in software, or one can also use
separate chips that will convert phase A/B into channels that might be
a bit easier to to work with with just a counter or interrupts like
this one: http://www.lsicsi.com/pdfs/Data_Sheets/LS7183_LS7184.pdf

Depending on the needs of the project, it might be possible to
multiplex multiple encoders onto a single QEI, but depending on the
maximum frequency of the quadrature phase info, it's entirely possible
to lose counts.  If for the application you might be confident that
you can do the switching fast enough not to drop counts it might be
possible, but I haven't looked at the qei peripheral in enough detail.

>
> Also, I am wondering why the ability to use a timer input capture pin as an
> edge timer and generate an interrupt does not seem to be supported in the
> timer documentation.  In this way, I think the general purpose timers could
> also be used for velocity measurement.

I think the edge count mode should do what you want?  We don't have
that functionality implemented for eLua, but I think it should
probably be straightforward from the docs?

The platform also certainly supports triggering interrupts on
different edges for GPIO, where you could implement quadrature
decoding in an interrupt handler (with the assumption that the
interrupt can run fast enough to capture all events... this might at
least give you an indication of cases where events are missed if an
interrupt fires while you're still in one that's running).


>
> 2.  From other posts, it looks as though you are familiar with eluarpc as
> well.  I noticed that you guys are working on rpc over ip.  For my purposes,
> I want to implement rpc over SPI or I2C or both.  Anything in the works for
> that?

Either of these should be possible.  SPI might be pretty
straightforward from the existing implementation, since SPI should
mirror way we use a UART on a lot of levels:
luarpc_elua_uart.c

I2C would require working a bit more around that protocol, but
shouldn't be too painful.  If you need help here I can try and provide
some guidance though I haven't put in the time to try and implement
this.

>
> Regards,
> Jim
>
> --
> View this message in context: http://elua-development.2368040.n2.nabble.com/QEI-Module-tp7182596p7361880.html
> Sent from the eLua Development mailing list archive at Nabble.com.
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev



--
James Snyder
Biomedical Engineering
Northwestern University
http://fanplastic.org/key.txt
ph: (847) 448-0386
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
jrambo316 jrambo316
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

I forked the main elua master and merged your lm3s_qei branch, built, and flashed to my board (8962).
When I try:
lm3s.qei.init( qei.CH0, qei.PHA, qei.NO_SWAP, qei.NO_INDEX, 10000 )

I get:
Error: [string "xmodem"]:24: attempt to index global 'qei' (a nil value)

I tested a variation of the led blinker tutorial so I know the board is working and elua is working.
I checked that I merged correctly as the qei files showed up in my forked master.
Did I miss some step to build qei?
Qei is platform specific and should be called "lm3s.qei.etc", right?

Regards,
Jim




jrambo316 jrambo316
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by jbsnyder
I tried:
lm3s.qei.init( lm3s.qei.CH0, lm3s.qei.PHA, lm3s.qei.NO_SWAP, lm3s.qei.NO_INDEX, 10000 )

thinking maybe the constants need to be prefixed with "lm3s." as well and then get:

Waiting for file ... Cdone, got 1387 bytes
#####
jrambo316 jrambo316
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by jbsnyder
[SOLVED]

missing #define BUILD_QEI in platform_conf.h
jrambo316 jrambo316
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by jbsnyder
jbsnyder wrote
If you could provide some confirmation on the functionality that would
help to let me know if this requires any further work before merging.
I have confirmed that the velocity capture is functioning.  That is all I needed to test for my purposes.  I would have tested more if I had a real encoder, but I had to simulate a signal using PWM.  I found an interesting article if anyone else is interested in simulating a more robust encoder:

http://ww1.microchip.com/downloads/en/devicedoc/91091A.pdf

FYI...The PWM on the LM3S8962 doesn't work at frequencies lower than around 6Hz.  TI forum said it was because of 16 bit PWM timer.

Also, I had to add #define BUILD_QEI to get it to work as I said earlier.  

Thanks for your help,
Jim


BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by jrambo316
Hi,

On Mon, Mar 19, 2012 at 5:05 AM, Martin Guy <[hidden email]> wrote:

> On 19 March 2012 00:03, jrambo316 <[hidden email]> wrote:
>> I tried:
>> lm3s.qei.init( lm3s.qei.CH0, lm3s.qei.PHA, lm3s.qei.NO_SWAP,
>> lm3s.qei.NO_INDEX, 10000 )
>
> Hi.  Can I make some suggestions for this module that is being born?
>
> One is to avid all this verbose and repetitive syntax by using a
> string for multi-valued parameters instead of these verbose constants.
> Not only is that more Lua-like and shorter to code, but it is also
> faster as these "platform constants" require several table lookups,
> whereas comparing strings is a single instruction.

Sorry, I don't understand this part. A single instruction? You mean
the hashes? They still have to be computed first, which isn't quite a
single instruction.

> Numerical values
> are appropriate at the C level: there is a Lua function to convert
> string parameters into integers: for example:
>
>  static const char const *args[] =
>    { "off", "on", "left", "right", NULL };
>
>  switch ( luaL_checkoption( L, 1, NULL, args ) )
>  {
>  case 0: ...
>  case 1: ...
>  case 2: ...
>  case 3: ...
>  default: return luaL_argerror( L, 1, NULL );
>  }
>
> Since we now have qei modules on two platforms i would also suggest
> making a generic qei.*() module rather than ending up with a different
> interfaces on each platform. After all, qei can ultimately be
> implemented on any platform using GPIO interrupts.

I completely agree with this, as long as somebody (not me, as I'm
completely lost when it comes to qei) can imagine a good enough
platform interface.

>
> These two suggestions would  turn the above code into:
>
> qei.init("CH0", "PHA", "NO_SWAP", "NO_INDEX". 10000)

It looks OK (albeit a bit weird for me, but that's just because of the
current syntax). I'm still worried about the penalty introduced by
string comparisons.

>
> For yes/no values it is more Lua-like just to use true and false, not
> verbose constants. Of course, they may not be boolean values - I don't
> know as I could find no documentation.
>
> So my 3rd suggestion: would be for elua-devs always to update the
> manual at the same time as they implement the interface - as part of
> the exact same commit that extends or changes the Lua interface, not
> as a final afterthought. That also ensuring that the manual remains
> complete and correct.

That would be ideal, indeed. I've sinned a lot in this area, because
writing docs is simply very difficult for me. But I'll try to keep in
mind your request.

> You can still decide to change the Lua interface when it turns out not
> to be right - then you also change tha manual again.
>
> Thanks and happy hacking

Thank you.

Best,
Bogdan

>
>   M
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

On 19 March 2012 22:38, Bogdan Marinescu <[hidden email]> wrote:
> On Mon, Mar 19, 2012 at 5:05 AM, Martin Guy <[hidden email]> wrote:
>> On 19 March 2012 00:03, jrambo316 <[hidden email]> wrote:
>>> I tried:
>>> lm3s.qei.init( lm3s.qei.CH0, lm3s.qei.PHA, lm3s.qei.NO_SWAP,
>>> lm3s.qei.NO_INDEX, 10000 )

>> qei.init("CH0", "PHA", "NO_SWAP", "NO_INDEX". 10000)

>> Not only is that more Lua-like and shorter to code, but it is also
>> faster as these "platform constants" require several table lookups,
>> whereas comparing strings is a single instruction.
>
> Sorry, I don't understand this part. A single instruction? You mean
> the hashes? They still have to be computed first, which isn't quite a
> single instruction.
>
> I'm still worried about the penalty introduced by
> string comparisons.

All strings in Lua are "interned", i.e. they are hashed and stored
when they are generated - in this case at compile-time - and if there
are two copies of the same string they are always made into two
references to the same internal copy, thereby saving memory.
This also means that comparing two strings for equality is simply done
by seeing if they both refer to the same internal copy - a single
pointer comparison.

That is aanother reason why building strings one character at a time
is so incredibly slow, such as:
s="" for i=1,1000 do s = s .. "U" end
Apart from the string copying at every step, each new string has to be
hashed to see if there is another string with the same value. In this
case, however it is a win.
They recommend building a table and concatenating after:
s={} for i=1,1000 do s[#s+1] = "U" end s=table.concat(s)
If you change this in life.lua, the program runs 10 or 20 times faster.

    M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by BogdanM
On 19 March 2012 22:38, Bogdan Marinescu <[hidden email]> wrote:
>> Since we now have qei modules on two platforms i would also suggest
>> making a generic qei.*() module rather than ending up with a different
>> interfaces on each platform. After all, qei can ultimately be
>> implemented on any platform using GPIO interrupts.
>
> I completely agree with this, as long as somebody (not me, as I'm
> completely lost when it comes to qei) can imagine a good enough
> platform interface.

One practical way to do this might be exactly what we are doing now:
implement platform versions for new, unfamiliar subsystems, then when
several platforms have the same kind of modules running on different
hardware, it begins to become apparent what their common features are
- at that point someone brave can promote the different platform
modules to a generic module.
How does that sound as a development strategy?

    M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by Martin Guy
On Tue, Mar 20, 2012 at 1:06 AM, Martin Guy <[hidden email]> wrote:

> On 19 March 2012 22:38, Bogdan Marinescu <[hidden email]> wrote:
>> On Mon, Mar 19, 2012 at 5:05 AM, Martin Guy <[hidden email]> wrote:
>>> On 19 March 2012 00:03, jrambo316 <[hidden email]> wrote:
>>>> I tried:
>>>> lm3s.qei.init( lm3s.qei.CH0, lm3s.qei.PHA, lm3s.qei.NO_SWAP,
>>>> lm3s.qei.NO_INDEX, 10000 )
>
>>> qei.init("CH0", "PHA", "NO_SWAP", "NO_INDEX". 10000)
>
>>> Not only is that more Lua-like and shorter to code, but it is also
>>> faster as these "platform constants" require several table lookups,
>>> whereas comparing strings is a single instruction.
>>
>> Sorry, I don't understand this part. A single instruction? You mean
>> the hashes? They still have to be computed first, which isn't quite a
>> single instruction.
>>
>> I'm still worried about the penalty introduced by
>> string comparisons.
>
> All strings in Lua are "interned", i.e. they are hashed and stored
> when they are generated - in this case at compile-time - and if there
> are two copies of the same string they are always made into two
> references to the same internal copy, thereby saving memory.

True. However, this only happens on the Lua side. On the C side you
still need to use C strings. If you look at the implementation of
luaL_checkoption, you'll see something like this:

LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
                                 const char *const lst[]) {
  const char *name = (def) ? luaL_optstring(L, narg, def) :
                             luaL_checkstring(L, narg);
  int i;
  for (i=0; lst[i]; i++)
    if (strcmp(lst[i], name) == 0)
      return i;
  return luaL_argerror(L, narg,
                       lua_pushfstring(L, "invalid option " LUA_QS, name));
}

'strcmp' all the way. However, on the C side you could use a table
with the strings options as keys and the corresponding values (for
example lm3s.qei.PHA) as values. Unfortunately, this consumes RAM and
brings back one table access.

Best,
Bogdan

> This also means that comparing two strings for equality is simply done
> by seeing if they both refer to the same internal copy - a single
> pointer comparison.
>
> That is aanother reason why building strings one character at a time
> is so incredibly slow, such as:
> s="" for i=1,1000 do s = s .. "U" end
> Apart from the string copying at every step, each new string has to be
> hashed to see if there is another string with the same value. In this
> case, however it is a win.
> They recommend building a table and concatenating after:
> s={} for i=1,1000 do s[#s+1] = "U" end s=table.concat(s)
> If you change this in life.lua, the program runs 10 or 20 times faster.
>
>    M
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by Martin Guy
On 20 March 2012 00:06, Martin Guy <[hidden email]> wrote:
>>> qei.init("CH0", "PHA", "NO_SWAP", "NO_INDEX". 10000)
>
>>> Not only is that more Lua-like and shorter to code, but it is also
>>> faster as these "platform constants" require several table lookups,
>>> whereas comparing strings is a single instruction.
>>
>> Sorry, I don't understand this part. A single instruction?

> All strings in Lua are "interned", i.e. they are hashed and stored
> ...
> This also means that comparing two strings for equality is simply done
> by seeing if they both refer to the same internal copy - a single
> pointer comparison.

Sorry that's irrelevant as in this case it's comparing against C
strings, not Lua strings.

     M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by BogdanM
> True. However, this only happens on the Lua side. On the C side you
> still need to use C strings.

Indeed

> example lm3s.qei.PHA)
> brings back one table access.

Three. One in the global table for lm3s, then qei in that then PHA in that.
  The main reason though is concise syntax to improve program
readability and reduce finger and eye wear :)
 But I expect that either is relatively small fry compared to the rest
of the overhead of running the interpreter itself. it would be
interesting to run some tests using the two mechanisms for dummy
routines that do nothing, then time their execution using the eLua
timers. Of course, I'm betting that short strings are faster :)

   M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by jrambo316


--
James Snyder
Biomedical Engineering
Northwestern University
http://fanplastic.org/key.txt
ph: (847) 448-0386

On Mar 18, 2012, at 23:05, Martin Guy <[hidden email]> wrote:

> On 19 March 2012 00:03, jrambo316 <[hidden email]> wrote:
>> I tried:
>> lm3s.qei.init( lm3s.qei.CH0, lm3s.qei.PHA, lm3s.qei.NO_SWAP,
>> lm3s.qei.NO_INDEX, 10000 )
>
> Hi.  Can I make some suggestions for this module that is being born?

Yep. One FYI on this module is that I converted it to platform specific form for now until we can boil it down to a generic model.

I somewhat like some of the simplicity of the stm32 quadrature module's simplicity and functionality but it's extremely basic.

>
> One is to avid all this verbose and repetitive syntax by using a
> string for multi-valued parameters instead of these verbose constants.
> Not only is that more Lua-like and shorter to code, but it is also
> faster as these "platform constants" require several table lookups,
> whereas comparing strings is a single instruction. Numerical values
> are appropriate at the C level: there is a Lua function to convert
> string parameters into integers: for example:
>
>  static const char const *args[] =
>    { "off", "on", "left", "right", NULL };
>
>  switch ( luaL_checkoption( L, 1, NULL, args ) )
>  {
>  case 0: ...
>  case 1: ...
>  case 2: ...
>  case 3: ...
>  default: return luaL_argerror( L, 1, NULL );
>  }
>
> Since we now have qei modules on two platforms i would also suggest
> making a generic qei.*() module rather than ending up with a different
> interfaces on each platform. After all, qei can ultimately be
> implemented on any platform using GPIO interrupts.

Yep. I'll have to comb through this thread a little more ( I've been out of town), but we could lay out a proposed API based on discussions and then have some discussion then just implement that on current qei platforms.

It would be great to not bike shed that thread and maybe set a date for wrapping up the module for a first rev. I think I'll do the proposal in eLua documentation format.

>
> These two suggestions would  turn the above code into:
>
> qei.init("CH0", "PHA", "NO_SWAP", "NO_INDEX". 10000)
>
> For yes/no values it is more Lua-like just to use true and false, not
> verbose constants. Of course, they may not be boolean values - I don't
> know as I could find no documentation.

There's some other discussion I'll need to dig into before commenting on this.

>
> So my 3rd suggestion: would be for elua-devs always to update the
> manual at the same time as they implement the interface - as part of
> the exact same commit that extends or changes the Lua interface, not
> as a final afterthought. That also ensuring that the manual remains
> complete and correct.
> You can still decide to change the Lua interface when it turns out not
> to be right - then you also change tha manual again.

The module was a contribution originally, and so far all I've done is convert it to a platform specific module (which is another thing we might want to make more clear on how to do since varying platforms have some messiness in platform specific module table setup in platform.c). Regardless this will need docs before it is merged. I think I neglected to document the stm32 module. I'll bump both up to be the next set of commits to get in.

>
> Thanks and happy hacking
>
>   M
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Re: QEI Module

In reply to this post by Martin Guy


--
James Snyder
Biomedical Engineering
Northwestern University
http://fanplastic.org/key.txt
ph: (847) 448-0386

On Mar 19, 2012, at 19:09, Martin Guy <[hidden email]> wrote:

> On 19 March 2012 22:38, Bogdan Marinescu <[hidden email]> wrote:
>>> Since we now have qei modules on two platforms i would also suggest
>>> making a generic qei.*() module rather than ending up with a different
>>> interfaces on each platform. After all, qei can ultimately be
>>> implemented on any platform using GPIO interrupts.
>>
>> I completely agree with this, as long as somebody (not me, as I'm
>> completely lost when it comes to qei) can imagine a good enough
>> platform interface.
>
> One practical way to do this might be exactly what we are doing now:
> implement platform versions for new, unfamiliar subsystems, then when
> several platforms have the same kind of modules running on different
> hardware, it begins to become apparent what their common features are
> - at that point someone brave can promote the different platform
> modules to a generic module.
> How does that sound as a development strategy?

That sounds good. I think we've started that on an ad hoc basis. Shall we wait a bit before proposing an API (add another platform) or throw in with one this week?

>
>    M
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev