Jason Dorie's FC software
michaellangford99
Posts: 19
in Robotics
For benchmarking purposes, how fast does Jason Dorie's flight controller poll the sensors?
Thanks!
Thanks!
Comments
The altimeter/pressure data is an exception, as it may not be available that often, so the status byte is checked. If a new reading is available, it's read and the pressure is converted to an altitude estimate.
The flight loop and IMU update runs slower than this - 250hz, as set here: https://github.com/parallaxinc/Flight-Controller/blob/master/Firmware-C/constants.h#L32
Having the sensors read more often means that the gyro/accel values are always within 1/500th of a second when the IMU is updated, so their lag is lower than if I had read them at 250hz. It's worth mentioning that even 250hz is probably overkill for a larger quad - more mass and a larger radius means that the quad will move slower and be less affected by wind or turbulence, so it doesn't need to react as quickly. I've seen them run at 100hz, or even 50hz with good flight characteristics. For a smaller more nimble quad, the higher rate is desirable.
Jason, would you recommend switching to C/C++, or should Spin be able to manage the flight loop?
P.S. let me know if this should be reposted into a completely new thread.
X = X + (Y * 0.0) is just X
and
X = X + (Y * 1.0) is just X + Y
That kind of thing.
Spin is going to be the limiting factor here at some point - The F32 library rips through the floating point math, but Spin is required to set it up and get the answers back. I used the same F32 library in C++ for the flight controller, but I added the ability to set up a stream of instructions for it to process, and wrote it out as a sequence of bytes in memory that the F32 driver consumes as it processes. It's much faster, but it's a pain to work that way. I ended up writing a compiler to convert normal C/C++ expressions to the bytecode format I use so I didn't have to change it by hand.
This is what the input to the float stream processor looks like:
https://github.com/parallaxinc/Flight-Controller/blob/FloatStreamCompiler/Firmware-C/QuatIMU_QuatUpdate.inc
The form is:
(opcode), (input1), (input2), (output)
Anything that looks like a label turns into a single constant byte value, so each instruction to process is 4 bytes. The (opcodes) are an index into the list of instructions supported by the F32 driver, and the (input) / (output) values are indices into an array of 32 bit values. Usually they're floats, but some are integers.
This is a list of labels and their indices in the float array:
https://github.com/parallaxinc/Flight-Controller/blob/FloatStreamCompiler/Firmware-C/QuatIMU_vars.inc
Using it looks like this:
https://github.com/parallaxinc/Flight-Controller/blob/FloatStreamCompiler/Firmware-C/quatimu.cpp#L350
I customized the driver a bit to pull out instructions I wasn't using, make room for some new ones, and add the stream processor.
would then become
The problem with doing this is that you'd still be using Spin to set up the operations and move the results around, and that's likely going to be your limiting factor. That said, it might be ok depending on how complicated the rest of your code is. I initially had code that updated an orientation matrix using fixed-point math, entirely in Spin, and I could run that at 250Hz. I had to work to get it that fast, but it's possible.
For C and ASM it's possible to use both, and you can even use Spin-based PASM objects. I do this a lot in the Elev8-FC code because I started with Spin and then converted to C/C++ after I was well into the project, and already had a bunch of assembly drivers. You need to write the "interface" code in C, but that's usually pretty thin. You can also use the GAS (Gcc ASsembler) format, but I didn't go that route. There are posts in the forums and probably stuff in the Learn docs on Parallax's site, but it's a more advanced topic so you'll have to dig a bit.
You might find it helpful to look at one of the simpler Elev8-FC drivers, like RC.cpp / and RC_driver_ppm.spin.
https://github.com/parallaxinc/Flight-Controller/tree/master/Firmware-C
SimpleIDE automatically extracts the PASM block from a Spin file and assembles it, and then you use the use_cog_driver and load_cog_driver macros to get the address of and launch the pasm code.
Look here:
https://github.com/parallaxinc/Flight-Controller/blob/9316b160db272c567c985d68add06d26c3283aa1/Firmware-C/rc.cpp#L42
...and here:
https://github.com/parallaxinc/Flight-Controller/blob/master/Firmware-C/rc_driver_ppm.spin
Note that all the Spin code in that file is ignored - the code in the cpp provides the same functionality.