Main Site Documentation

Project - Cerberus firmware for NETMF 4.3RTM compiled with GCC + Quadrature encoder feature


#1

Cerberus firmware for NETMF 4.3RTM compiled with GCC + Quadrature encoder feature

This code is the difference from NetMF Porting Kit 4.3 merged with GHI’s Open Source NETMF Ports
Install first NetMF Porting Kit 4.3, then merge with GHI’s Open Source NETMF Ports, then merge with this code.

The compilation work with GNU Tools for ARM Embedded Processors (https://launchpad.net/gcc-arm-embedded). This will NOT work with Yagarto. Be carefull to install the toolchain in a directory without space like “C:\GCC_ARM”, do not use “C:\Program Files…”

The compilation processus is the same as for Hydra (in the Wiki).

This work is based on code and information from the CW2, Taylorza, Walkyrie MT and probably some more.

Bonus: this solution comes with a full features interop harware Quadrature encoder driver with input capture callback.


#2

@ NicolasG - Very Nice!!!


#3

Nice indeed! Thanks!

There was some speculation in another thread that the FPU wasn’t being used in the current Cerberus builds and that’s why the Mountaineer boards were so much faster. So, you have confirmed it?


#4

Excellent!


#5

Indeed it is an amazing work…thank you very much.

Concerning Encoder feature, what about posting a code snippet in order to show some common use cases? What kind of frequency could we expect to manage with your driver?


#6

@ Innovactive: I updated the codeshare with a sample code for quadrature encoder.
The encoder count is hardware, i configure an input filter of 8 clock cycle. According to STM32 datasheet, it should accept more than 1MHz input signal.
Capture count is hardware but callbacks are interrupt driven. It seem to capture events at about 10µs interval (manual test with a simple wire without debounce circuit).
The events are queued by NetMF so you can handle it later but when the queue is full, event are ignored.
Note that timestamp is made by soft, so it is not totally accurate.


#7

@ NicolasG:

Because of .netmf thread scheduling inner working and hal completion management I suspect that one can’t actually handle more that some tens pulses per second, but I should do some test to confirm that.

Maybe it could be reasonable to develop a managed interface that enables “user” application to subscribe to encoder driver notifications in either timely constrained or pulse-count constraint modes, that is respectively being notified with accumulated pulse-count at regular time intervals and/or at regular pulse-count intervals (say, every 100 pulses) with hardware timestamp (or pulse rate, similarly). This way it could be useful both for slow pulse sources (and potentially able to be stopped, too) like a bike odometer and for motors with 300 pulses per round (perhaps x2, as for quadrature encoders) running at 1000 rpm!

Also, being aimed to quadrature encoders, it would be amazing whether such driver would also report direction and computed rate (managing both pulse sources, I mean).

Would it be hard to develop, according to you?


#8

Encoder position and event capture should be thought as independent features.
There is no problem to get position from 0 to 300kHz source.
On the other hand, capture random event positions at a sustained rate of hundreds of kHz is not a reallistic task.
It can do the job for more than 100 positions/s with some burst from time to time and that’s good for me.

The timestamp can be delayed only by another interrupt, the probability is almost negligible and the value is not likely to be more than some tens of µs.

Speed measurement can be done easily in managed software. Just set up a timer and monitor the Count property. Same for direction.

Very high speed data acquisition can be achieved by hardware only using DMA but I don’t need it now.


#9

WOW. Seriously. I can independently confirm that this works! I have built a lot of .NET MF firmware, but never got GCC to work with Cerb and I have always had to fix various errors to make it work. I followed your instructions and was able to build (without any error), deploy, and run a simple application. Not a single modification! Bravo!

Thanks NicolasG! I anticipate that because of this we’ll start to see a variety of firmware builds that start floating around with a variety of different features. One thing I think you should do is change the GHI information. This should be clearly marked as a non-GHI built firmware. I’m sure they won’t want to field support issues from someone else’s custom firmware.

Also, I would love to see GHI switch to GCC going forward, particularly for the open source offerings.

By the way, I used this compiler (as recommended): gcc-arm-none-eabi-4_6-2012q4-20121016.exe - https://launchpad.net/gcc-arm-embedded/4.6/4.6-2012-q4-update/+download/gcc-arm-none-eabi-4_6-2012q4-20121016.exe
Installed it to "C:\GCC_46"
Installed the 4.3PK, then copied GHI source and NicolasG source on top
Then executed this:
C:\MicroFrameworkPK_v4_3>setenv_gcc.cmd 4.6.2 c:\GCC_46
C:\MicroFrameworkPK_v4_3>cd Solutions\FEZCerberus
C:\MicroFrameworkPK_v4_3\Solutions\FEZCerberus>msbuild /t:build /p:flavor=release;memory=flash

Then, using MFDeploy, I deployed the ER_CONFIG and ER_FLASH from here: C:\MicroFrameworkPK_v4_3\BuildOutput\THUMB2\GCC4.6\le\FLASH\release\FEZCerberus\bin\tinyclr.hex

Note: Some of the 4.2 references will no longer work, so those will have to be recompiled… Such as the Gadgeteer stuff.

P.S. I am using Windows 8 x64 for all the compiling. Also, the 4.3 firmware requires VS2012 Desktop Edition or higher.

-Valkyrie-MT


#10

Glad to see it works for others :slight_smile:

After build, you can create a dfu file to install your custom tinybooter.
Rename “C:\MicroFrameworkPK_v4_3\BuildOutput\THUMB2\GCC4.6\le\FLASH\release\FEZCerberus\bin\tinybooter.hex” to “tinybooter.s19”.
Run [em]DFU File Manager[/em], chose GENERATE a DFU, click [S19 or Hex…] and select your s19 file.
Change target name to something relevant like “Internal Flash”.
Click on [Generate…] and save your DFU file.

You can now reboot your Cerberus in DFU mode and deploy tinybooter with STDFUTester.

This fix the double USB restart caused by the change of USB device ID in last GHI code commit, out of sync with actual tinybooter.


#11

Nice work on the encoders, it always struck me as a feature missing from NETMF (we chose the Cortex parts for our core product because of this inbuilt functionality…)

The maximum frequency depends also on the input filtering configured in the counter control registers.

Would be super cool if you could schedule callbacks at particular counts. e.g. Generate an event when the counter is at 1000pulses, similar to how the CNC move tables used to work in old PLCs. Then you can leave the counting in hardware (where it belongs) and use NETMF for basic trapezoidal/positioning control.


#12

I thought about that. It is not necessary except if you want to sell another hardware platform like Netduino.
For a consumer USB device, the vendor and product Id are set in code and you must customize the driver to display your company name.
The consumer will not know anything about NetMF.

I considered that to evaluate 1Mhz. I didn’t test it, i need less than 50kHz now and never more than 300kHz (max output of BEI encoders).

I plan to implement a similar feature with Output Compare. The counter can compare a register value and set an output when the count is equal (and also generate an interrupt). This is how PWM is generated.
However this is not really usefull in my application as is we use a 32 bits counter intended to count up.
Configure the counter to generate a pulse every 1000 pulse is a bit more complex. We have to increment the compare value in the ISR (easy) but we also have to configure another timer to generate a pulse of known with.


#13

@ NicolasG, that’s what I had in mind - something to generate an interrupt at a defined point, then if you wanted another interrupt you’d reset the event/comparator


#14

Personally I feel that the encoder should never fire an event. It should count in hardware and that is all. It should be up to the user to set up a timer to inspect the count from the encoder every 10ms, or 100ms or whatever. From that possision and speed can be calculated.

Having an event that fires every 1000 counts is useless. What if it turns to pos 999 and stops? Then you will never get an event again, and you will be oblivious of it. Inspecting the count value at a known interval is required for most motor control applications, and it is most usefull when used with user input methods.


#15

@ GMod, I’m pretty sure my original post was misinterpreted. I’m not talking about a repeated event, I’m talking about move tables. Nobody should be doing precision closed loop motor control with NETMF, it’s the wrong tool.

But, when you want to hack together a quick and dirty trapezoidal control to get from here to there, the problem is easier to solve. You are, of course, free to check encoder values whenever you want, but it’s nice if you can write code against anticipated events.

This is all heading a little OT :slight_smile:


#16

Event is useless to monitor a position. It must be done by a thread or a timer.
I just plan to generate an output trigger at a specified position interval. That can be usefull.


#17

Hello Nicolas,

this is perfect! I can also confirm that it works for me! Thank you this means new ways to implement time-defendant code!

Merry x-mas!

Jan


#18

Thank you. I’m glad to see someone else interested in this work.


#19

This is amazing! Thank you so much, much appreciated!!


#20

amazing :slight_smile: