Electronics

FFT CircuitPython Library

Overview (TL;DR)

Clone the FFT repo and have fun!

CircuitPython_FFT Library

If you have an edge badge or i2s mic and another badge that is CircuitPython capable clone the demo repo as well

Edge-Badge Audio Spectrum demo repo

My Experience with CircuitPython

I have been playing with the Adafruit Circuit Python for a while now on the PyGamer board . Using the Adafruit libraries to light up the NeoPixels and to display pictures and text on the screen.

Adafruit PyGamer Running Customized PyBadger code

Then I learned that the Hackaday Supercon attendees would be given an Adafruit Edge Badge along with the official badge. This had a built in microphone which sparked my interest on creating an audio spectrum waterfall plot of the measured frequency.

Adafruit Edge Badge running audio waterfall code

This was a bit of a problem because the library that python uses to perform the Fast Fourier Transform (FFT) did not have a CircuitPython port. So I decided to write my own code in CircuitPython to compute the FFT. Now I could have written c code to run underneath but I have not gotten to that point yet, and also wanted to get this done for Supercon, which required a few other parts, so that drove my decision to just use pure python. I am not going to go over all the details of the spectrum waterfall code but I want to go over my FFT library and my experience creating it.

Using the tools Adafruit has published that help users build new libraries for their platform I was able to create a working library. I followed the Creating and Sharing a CircuitPython Library Guide which details all the things you need to do to set up the library. But the first thing you should do is create some working code, this will be the template for the code you need to include in your library.

Then once you have an idea on what you need to include, you can create the library skeleton using the Adafruit CookieCutter template. You need to install the CookieCutter dependency with pip and point it to the Adafruit template. Then all you need to do is follow the instructions in the rest of the guide I linked above.

When it came to adding my code to the library I took a look at Adafruit’s other repos like the Adafruit PyBadger that contained mostly python constructs to see how they were implemented. I choose to just add my code as functions that could be called, but look around to see if there is a better way to structure your code.

I also looked to see how error handling occured but could not find much for CircuitPython so I will investigate this further and add error checking in upcoming improvements when I have time …

Testing My Library

I needed to test that my code ran on the hardware but that it was also producing accurate results against a known FFT algorithm. This meant that I needed to get some data off the CircuitPython hardware. I investigated having code running on the board save a file to the internal file system but learned that you would need to disable external file system writes. This can be shown in this Adafruit CircuitPython Storage Guide. I decided that it was a bit overkill for my use, since I would not be continuously logging data, so I decided to just write the results to the serial console and copy it off manually.

Then I wrote a cPython file to import the numpy.fft library so I could perform verification. The results are shown below based on the verification folder in my FFT library.

Error was calculated as the sum of all the differences between the values in an array of size 256.

  • sum error numpy fft->ifft results
    • 3.182600063920295e-14
  • sum error circuitpy fft->ifft results
    • 0.0007082194730612704
  • sum error numpy vs circuitpy samples
    • 0.013183941265780881
  • sum error numpy vs circuitpy fft
    • 0.13177639795198584
  • sum error numpy vs circuitpy ifft
    • 0.013204903929738273
  • sum error numpy vs circuitpy fft with cp_samples
    • 0.007974316051057972
  • sum error numpy vs circuitpy ifft with cp_samples
    • 0.0007082194730633953

From this we can see that the CircuitPython FFT library produces good results against numpy when both use the samples generated by CircuitPython, But that numpy is still far superior in precision. This could be down to how many bits of precision the micro-controller can support in memory or a quirk of the algorithm, but needs further investigation.

Demo With Adafruit Edge-Board

Once I had finished the library I changed my edge-badge code that I had created at Supercon to use the new library but it basically works the same as before just with a more portable design that others can now use as well.

Link to video of the badge on twitter:

Conclusions

I have really enjoyed using CircuitPython, as it is a much simpler method to playing with micro-contollers than Arduino. The ecosystem that Adafruit has developed makes it a breeze for developers, new and old, to quickly get a project off the ground and running. I hope more boards and manufactures make CircuitPython an option on their products as it provides fast visual feedback and is a simple way to work with micro-controller hardware. I also hope more people start creating libraries for the ecosystem so that future users have an easier time developing new creative things.

2 thoughts on “FFT CircuitPython Library”

  1. Hi Tom,
    I just wanted to say thank you for finally enabling CircuitPython support fft operations!
    I was waiting for that for some time now.
    Kudos!

Comments are closed.