the bottleneck is more MCU-side.
I think it would be possible to prevent the monitoring from affecting the control loop.
The idea would be to setup a e.g. 10khz timer (like paul gould did) where the control loop happens and put readings in a FIFO buffer. Then buffer would then be emptied when the MCU idles, or interrupt based.
in the main loop() function, we could e.g. listen for commands
asyncio on the GUI side might be interesting for other reasons, although my impression is the GUI is very responsive despite the constant serial comms.
On the MCU side, I think there is a lot that could be done, but I think care should be taken to keep it separate from the “simple and generic” interface we have now. Any Arduino has a Serial object, but not all of them have timers that work in the same way, etc…
I know you like SAMD - I think on SAMD it should be possible to drive the SERCON using DMA, with almost no overhead to the main loop. But this will hardly be portable to other MCUs. So I think a good approach here could also be to write alternative “monitoring backends”, which can be kept separate from the main code (not wasting space and confusing the people not using them). The “pros” that want DMA-based monitoring for their MCU can then select from the available backends, or code their own.
I’m sure some people have been thinking about other channels than Serial (UDP on ESP32 for example, or MQTT, etc…). There could be backends for that too!
In terms of the existing SimpleFOC implementation, I would keep it simple, and keep it on Serial. This will be what 90% of users want when first testing it out, and what the less advanced users can realistically manage.
A possible optimization might be a binary mode for monitoring.
At the moment we send a bunch of 32 bit floats as ASCII. This incurs a penalty both in terms of ASCII conversion of the data, and sending some extra bytes.
I think converting to a binary format might improve the performance somewhat.
The ASCII format could be default, and we could keep it for the commander, but the binary format could be used by the monitoring when called from the SimpleFOC Studio…
On the MCU side, I think there is a lot that could be done, but I think care should be taken to keep it separate from the “simple and generic” interface we have now. Any Arduino has a Serial object, but not all of them have timers that work in the same way, etc…
Agreed, also with your backend idea. the default could be a backend that synchroneously write via the configured Stream. I think it would still be doable to keep the FIFO idea without losing generality.
I know you like SAMD - I think on SAMD it should be possible to drive the SERCON using DMA, with almost no overhead to the main loop. But this will hardly be portable to other MCUs. So I think a good approach here could also be to write alternative “monitoring backends”, which can be kept separate from the main code (not wasting space and confusing the people not using them). The “pros” that want DMA-based monitoring for their MCU can then select from the available backends, or code their own.
Well it’s the dev board I have in stock, and my initial plan was to reproduce Paul Gould’s controller. Lots have happend since. I’m more and more interested with the SMT32G4. But yeah, I do want DMA-based/async monitoring. And I totally agree we should design a binary protocol. Another thing I’d like to see are timestamps which would become crucial it we go async
Just so you know, I’ve put quite a bit of effort on the data logging side. I chose to go separate way from the commander interface since I aim for real-time data logging performance, probably on a separate, outbound-only. data link. I won’t be needing SimpleFOCStudio’s connectors. I tried, but I then found a solution that’s both simpler and much, much higher performing. I should be ready for a little demo by monday or tuesday.
Beware, it’s Pyside6-only (pyqt5 is GPL, btw), uses QtQML, and it parses C-code sunch as “Arduino-FOC/src/common/foc_utils.h” to genrate parsers automatically. It’s going to be a bit nasty at first, but don’t worry, I hate nasty code.
for example, to send a struct from MCU, it becomes as simple as:
I had some time today and I have decided to implement your suggestion to add a Jogging control.
The fast reverse button reduces the current target by 2 times the specified increment, the reverse button reduces the current target by the specified increment … etc. Stop button, in angle control mode, sets the current angle as target angle and in velocity control sets the target to zero.
Just got time to implement your second suggestion os something similar. Each custom command has a name and a value as yoy can see at the bellow.
Once you have defied each custom command in rder to execute each of them you have to select it and once selected press the space key (⎵) or right arrow key (→).
You are right, It’s a bit annoying having to add the custom commands every time yo execute the application. I will add the functionality of being able to save custom commands in the JSON file and also saving the “M” o whatever parameter of the engine. When I have it done I will let you know, it is a minimal change that adds quite value
First of all, thank you very much Jorge for this fantastic tool, very useful!
I have seen a bug, when changing the low pass filter of ‘d’, edit the ‘q’ wrongly.
This happens in device tree mode, in form view mode it works correctly
I have been using SimpleFOCStudio for a few weeks with the STM32F446RE without any problems
Now I have switched to ESP32 (the same configuration, but I have it seems that I have to tune the parameters again) but I find that it does not connect correctly with the application.
From the Arduino IDE and with the CoolTermWin it works without problems, but with the Studio it does not connect from the main screen (Three or Form View)
I have come to connect by doing the following:
Connect from “Cmd Line”, (from there it always connects me correctly) with the sequence:
MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: Index search …
And then go to the main screen.
If I try to connect directly from the main screen 90% of the time it doesn’t succeed.
Always with the same configuration and testing 115200.
In any case, even though I connect, after a few minutes the change of parameters starts to go very slowly until I see similar data (but wrong) to those of the “motor.monitor ();” and it crashes
Traceback (most recent call last):
File "C: \ Users \ Jorge-PC \ Desktop \ SimpleFOCStudio \ src \ gui \ configtool \ graphicWidget.py", line 116, in upDateGraphic
signals = np.array (signalList, dtype = float)
ValueError: could not convert string to float: '.'
Traceback (most recent call last):
File "C: \ Users \ Jorge-PC \ Desktop \ SimpleFOCStudio \ src \ gui \ configtool \ graphicWidget.py", line 116, in upDateGraphic
signals = np.array (signalList, dtype = float)
ValueError: could not convert string to float: '\ r2.35695452340005.00'
Traceback (most recent call last):
File "C: \ Users \ Jorge-PC \ Desktop \ SimpleFOCStudio \ src \ gui \ configtool \ graphicWidget.py", line 116, in upDateGraphic
signals = np.array (signalList, dtype = float)
ValueError: could not convert string to float: ''
Has anyone had these problems or been able to prove that it is not just my thing?
These types of errors are not easy to correct as they are difficult to reproduce.
My guess about what is happening is that for some reason that I am not aware of, the MCU is sending unparsable values in a float [ '\ r2.35695452340005.00' ] and the application starts throwing exceptions until it crashes.
One thing that could be done to see where the error comes from is to analyze if the strings sent by the MCU that later are parsed to floats.
I will try to investigate the problem, because apart from this problem, I have others in control.
Even adjusting the parameters a bit (as little as I could), from 20rad/s it destabilizes, when with the STM32F4 I get 120rad/s without problems. Exactly the same configuration (motor, driver, and encoder).
Just so you see, I just skipped this in the window: