These machines are inherently unstable, and the software generally has two tasks to perform. Firstly it has to stabilise the machine and secondly it needs to respond to events such as commands from a radio control, reading GPS signals or other sensors, and so on. The first task can be seen as mapping an unstable real machine onto a stable virtual one: a machine which will respond to commands like "turn pi/2 radians clockwise", "move at 100mm/s" and suchlike. To achieve stability this task needs to run in real time: in the case of balancing robots a 5mS loop time is typical.
The task of responding to events and communicating with the stable virtual machine does not usually require realtime performance.
I can see four implementation options:
- Use two Pyboards.
- Write a single high speed control loop performing both functions.
- Use cooperative multi-tasking.
- Run the real time loop as a timer callback.
In principle it's ideal. The code is executed at a precise frequency with time critical elements like integrators and filters being serviced at known intervals regardless of the behaviour of the rest of the code or of the garbage collector. But it does impose limitations on the code, and of that in any device drivers it calls, namely they must not use the heap. This immediately rules out floating point processing (unless done in assembler). Integer processing is usually feasible but does require a good deal of attention to scaling issues. As for device drivers, these vary. And I've yet to establish whether the basic communications methods of the various links supported by MicroPython are interrupt friendly (i2c.send(), i2c.recv() for example). Likewise for other buses and interfaces.
Any thoughts or comments?