Education and CLUE Sensor Plotter in CircuitPython and ulab

This is a special forum devoted to educators using Adafruit and Arduino products for teaching.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
kevinjwalters
 
Posts: 1025
Joined: Sun Oct 01, 2017 3:15 pm

Education and CLUE Sensor Plotter in CircuitPython and ulab

Post by kevinjwalters »

I thought I'd highlight in more detail some of the educational aspects of my recent guide, CLUE Sensor Plotter in CircuitPython. It wasn't intended to be classroom ready material for there might be bits that can plucked out and used.

The supply of CLUE hardware is limited at the moment but for hardware experiments and demos one possibility here is to make the code run on the Circuit Playground Bluefruit with Gizmo.

Computing

GCSE (UK exam at 16) computing uses flow diagrams (flowcharts) as one way to represent algorithms. There's


The simple UI is discussed in https://learn.adafruit.com/clue-sensor- ... uttons-3-3 . There's some scope here for HCI discussions with limited buttons, cf early digital watches and perhaps more exotic "buttons" like velocity and pressure (aftertouch) sensitive synthesizer keys or cameras with two-stage/half-press shutter releases.

The auto-scaling algorithm needs some improvement so that's an area to explore keeping in mind that auto scaling can be visually confusing to the user and needs to adapt to the data including perhaps trends.

A level (UK exam at 18) computing covers UML class diagrams. There's one with inheritance on https://learn.adafruit.com/clue-sensor- ... urce-class and another one one showing a bloated class on https://learn.adafruit.com/clue-sensor- ... orithm-5-6 . And elsewhere there's the pyreverse generated ones which could be interesting for comparison and a discussion on reverse engineering designs: https://github.com/kevinjwalters/circui ... everse-uml

There's a little bit on accessibility and colour choices mainly around an attempt to offer some options for common colour BANNED issues: https://learn.adafruit.com/clue-sensor- ... bility-5-3

There's a discussion on drawing graphics with a small mention of abstraction but mainly a look at how to efficiently use displayio library as it is currently implemented and with benchmarking to check performance: https://learn.adafruit.com/clue-sensor- ... layio-5-11 . There is mention of reducing resolution too but without benchmarking. I've just started using this elsewhere and scaled lower resolutions are not as fast as I'd like...

The current automatic screen refresh rate isn't ideal for some of the plotting when those refreshes occur during a lengthy screen update and are counter-productive for performance and update rates. The code shows attempts at manual refreshing which weren't successful using the current refresh interface. There's scope for improvement here particularly if there's a simple immediate refresh implemented, see https://github.com/adafruit/circuitpython/issues/2696

There's a little bit of discussion on the implementation in https://learn.adafruit.com/clue-sensor- ... ssion-8-16 - encapsulation gets a mention, there's a discussion on parsing inputs and one that should probably mention enumerated types. There are some allusions to homogene ous interface design in the unit discussion. There's a quick overview of python properties which could be supplemented by comparisons with other OO languages and discussions like https://stackoverflow.com/questions/205 ... -is-needed and https://stackoverflow.com/questions/737 ... -attribute . Mixed in with that there's also a brief discussion and REPL demo of "pass by object reference" which isn't going to be obvious to every programmer.

The Feather M4 make a guest appearance on https://learn.adafruit.com/clue-sensor- ... -generator showing the convenience of REPL and how wav files can be used to generate 2 signals using the 12bit DACs on the SAMD51. This is far from a full demo but the sample rate is trivial to manipulate so could be used for a discussion about (re)constructing analogue signals which is part of GCSE.

It's interesting to compare the CircuitPython implementation (https://github.com/adafruit/Adafruit_Le ... or_Plotter) and the C/C++/Arduino (https://github.com/adafruit/Adafruit_Ar ... orplotter/) implementation.
  • C program is much shorter despite there not being a huge difference in the functionality between the two.
  • C program is much more fluid with screen updates.
  • C program has some interesting nuances in button functionality, worth experimenting with left and right buttons...
  • C libraries can be a bit different, one example is pressure shown in Pa rather than hPa.
  • Volume measurements are very different, C uses a difference between max and min over samples, CircuitPython one uses clue object's RMS calculated value then converts to dB scale.
There's some very practical and detailed discussion about unit testing in https://learn.adafruit.com/clue-sensor- ... on/testing . This includes two genuine bugs that I wrote but never spotted as that code isn't exercised by the current program. Coverage and static analysis in the form of pylint get a mention. Typing gets a mention during the bug hunt on https://learn.adafruit.com/clue-sensor- ... thon/bug-1 with some REPL experimentation and a brief comparison with C++.

There's examples of basic simulation of the sensor with mocking on https://learn.adafruit.com/clue-sensor- ... thon/bug-1 essential to test without the hardware.

The testing mentions boundary data and whilst writing the article and documenting CircuitPython's number representation in I https://learn.adafruit.com/clue-sensor- ... esentation I found a small bug in CircuitPython interpreter exactly in this area https://github.com/adafruit/circuitpython/issues/2736 . There's a bit of history on that page with BANNED Zuse's Z1 which features floating-point and has been rebuilt for the Deutsches Technik Museum in Berlin. I've tried to cover floating-point a bit on there too but it's a big area to cover.

There's a demonstration of the limitations of CircuitPython's time.monotonic() on https://learn.adafruit.com/clue-sensor- ... cuitpython and a graphic alluding to equivalence with escapement in mechanical clocks. There's lot of examples on the page showing the care that's required with types to avoid int promotion to a float. There's some real world examples of minor issues on aircraft showing how even critical code with high quality software engineering practises and thorough testing can still exhibit classic, simple bugs.

Not discussed is some duplication of basic maths for converting scales on the data in the functionality in the PlotSource classes for sensors. There's some potential for using a single class method or similar to implement all of these. There's a subtle question about performance for high rate sensors but the function call overhead could be bench-marked and is probably very low here, cf inlining.
Physics

Calibration is important! There's a image of an old plane on https://learn.adafruit.com/clue-sensor- ... on/sensors as a reference to compass swings. This form of calibration still takes place but often without the laborious physical spinning of the aircraft. There's a more detailed old graphic of this on http://www.lonesentry.com/blog/b-25-com ... -rose.html

The temperature sensor is far from perfect as it's affected (presumably) by heating from the board. There's a second effect which appears to be from reading the sensor itself which also heats it up by small fractions of a degree, see https://learn.adafruit.com/clue-sensor- ... ature-12-2 - Whilst this could be viewed as a flawed sensor/physical placement it could also be compensated for to some extent particular with the board in steady state use.

BMP280 Pressure is pretty good and could be even more accurate with calibration taking into account local altitude and filtering mentioned briefly on https://learn.adafruit.com/clue-sensor- ... ssure-12-4 . The noise can be seen in the video when the lift is stationary and when super-imposed when it's moving at constant velocity. ulab in 5.1.0 is well worth a look here, there an example of filtering pressure on https://learn.adafruit.com/ulab-crunch- ... c-pressure .

The sht31d humidity is very fast to respond changes in humidity which could be a plus and minus is worth exploring - mentioned on https://learn.adafruit.com/clue-sensor- ... idity-12-6

Microphone is good and briefly mentioned on https://learn.adafruit.com/clue-sensor- ... olume-12-6 - this is post-processed to decibels so this could be worth exploring and looking at how to convert and calibrate to sound pressure level scale. The effects of the 16kHz default sample rate could also be explored looking at the volume response to audio frequencies over 8kHz.

The blue sensor from the APDS-9960 RGBC outputs is strangely sensitive to the blue from the Feather's small NeoPixel, mentioned on https://learn.adafruit.com/clue-sensor- ... ivity-12-6 - that's worth comparing with source likes daylight, incandescents and CFL/LED lighting. Cross sensitivity could be worth investigating too. A lot of photos of bright LEDs now end up mis-coloured because the high brightness causes a response on other colours, I believe this is an example, all of these LEDs are set to red in the code and the some of the reflected lights are red but en masse in the right photo the LEDs appear orange to the camera: https://twitter.com/Kitronik/status/1245637199590088704

Proximity is driven by infrared at 950nm mentioned on https://learn.adafruit.com/clue-sensor- ... mity-12-10 . This could sensor could also be used to measure IR reflectivity if the object is always placed at a fixed distance. This subject came up with a lot of non-existent analysis and questionable opprobrium for the tech sector with a no-touch, automatic hand dispenser in 2017. Oddly, a biased, tabloid newspaper in the UK that's more associated with bikini pictures had one of the few articles that bothered to do some minor investigation on the Shenzhen Yuekun Technology dispenser: https://www.dailymail.co.uk/sciencetech ... ACIST.html

The calculation for pressure in inches of mercury in https://github.com/adafruit/Adafruit_Le ... #L173-L187 is only valid at certain temperatures and could be a point of discussion.

Biology

Pulse inspection is the obvious one here mentioned in original post. There's more room for investigation here to find out how commercial pulse oximeters work and if there's any information to be cleaned from the difference or ratio of red/green/blue/clear reflected light that the APDS-9660 colour sensors pick up.

There's more ulab examples in https://learn.adafruit.com/ulab-crunch- ... estimation for filtering and measuring heart rate.

There's some other work going on in this area with exploring reading data from low-cost bluetooth low energy enabled pulse oximeters mentioned in https://blog.adafruit.com/2020/04/01/ic ... -adafruit/ . Keep an eye on Adafruit Blog for more info.

Lifebox

Pulse oximters are important for the developing world and helped by NGOs like https://www.lifebox.org/about-us/

User avatar
oldblackcrow
 
Posts: 221
Joined: Tue Jun 20, 2017 5:54 pm

Re: Education and CLUE Sensor Plotter in CircuitPython and u

Post by oldblackcrow »

Volume measurements are very different, C uses a difference between max and min over samples, CircuitPython one uses clue object's RMS calculated value then converts to dB scale.
Is there an easy way to convert the Arduino code to use dB? It seems rather random to not have this data as dB unless there's some weird thing in C++ Arduino that doesn't allow it.

Thanks for any help on this!

User avatar
oldblackcrow
 
Posts: 221
Joined: Tue Jun 20, 2017 5:54 pm

Re: Education and CLUE Sensor Plotter in CircuitPython and u

Post by oldblackcrow »

I figured it out in the Arduino code, anyway... change the following line:

From

Code: Select all

else if (sensornum == 6) {
uint32_t pdm_vol = getPDMwave(256);
To

Code: Select all

else if (sensornum == 6) {
uint32_t pdm_vol = 20. * (log10 (getPDMwave(256)));
Works well enough... Don't know if it's super accurate, but it's definitely in the range.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Education and CLUE Sensor Plotter in CircuitPython and u

Post by adafruit_support_mike »

oldblackcrow wrote:Is there an easy way to convert the Arduino code to use dB? It seems rather random to not have this data as dB unless there's some weird thing in C++ Arduino that doesn't allow it.
Decibels measure ratios. One Bel (the base unit) is a ratio of 10:1. That’s a bit large for most applications, so 0.1 Bel is called a ‘decibel’. 10db = 1 Bel.

To convert Bels and decibels to regular numbers, use them as exponents of the base value 10: 3db = 10^0.3 = 1.995

Things would be nice and simple if it stopped there, but the Bel/decibel system was developed by Bell Labs to work with signals moving through long cables. For that kind of work you spend a lot of time working with signal power rather than voltage or current on their own, and there’s a built-in connection between voltage and current: when you double the voltage across a resistor you also double the current flowing through it, and 2V*2I=4(VI)^2. To double a signal’s power, you have to increase the voltage and current by sqrt(2), not by 2.

Along the way, some tribe of doofuses decided to build the sqrt(2) part into the decibel system for power, so when you talk about power, 1db = 0.05 Bel, or 20db = 1 Bel.

To make things even more complicated, you can’t convert ratios to specific values until you have a reference value to scale up and down. For electrical power the reference is 1 milliwatt, so “decibels of power relative to 1mW” are given units of ‘dbm’ and 0dbm=1mW (10^0=1).

For audio applications, it’s even worse. The human ear responds to high frequencies more than low frequencies, so 1dbm @ 10kHz sounds louder than 1dbm @ 100Hz. To get perceived loudness, we have to use ‘equal loudness’ curves that have been established experimentally. There have been multiple studies to define equal-loudness curves, all of which have come up with slightly different results.

The International Standards Organization has selected a few as common references. The most commonly used one is designated ‘A’, and audio volume measured that way is called ‘A-weighted’ and given units of dbA.

You can only calculate dbA values when you know the frequency content of a given sound. In general, it’s easier to stick to simple power ratios using the dbA reference point of 20 micropascals sound pressure (0dbSPL). That’s been determined as the quietest sound the average human ear can hear.

One specification for microphones and speakers is how they convert between audio power (dbSPL) and electrical power (dbm). You have to look at the datasheet to fnd the sound pressure to signal power reference levels.

User avatar
oldblackcrow
 
Posts: 221
Joined: Tue Jun 20, 2017 5:54 pm

Re: Education and CLUE Sensor Plotter in CircuitPython and u

Post by oldblackcrow »

Thank you! That explains a lot... But sounds like I still have much to learn.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Education and CLUE Sensor Plotter in CircuitPython and u

Post by adafruit_support_mike »

That's kind of the ground state of Making.. there's always more to learn. ;-)

User avatar
kevinjwalters
 
Posts: 1025
Joined: Sun Oct 01, 2017 3:15 pm

Re: Education and CLUE Sensor Plotter in CircuitPython and u

Post by kevinjwalters »

For Physics/Electronics, I've got the Adafruit CLUE (with some different code) doing a current vs voltage graph in Instructables: Make a Component Tester With Adafruit CLUE and Kitronik Inventor's Kit. Also covered in a forum post and Adafruit Blog. It's limited to -3.3V to +3.3V and about 750uA but it can still identify a decent number of different components.

User avatar
oldblackcrow
 
Posts: 221
Joined: Tue Jun 20, 2017 5:54 pm

Re: Education and CLUE Sensor Plotter in CircuitPython and u

Post by oldblackcrow »

Well, Thanks to a guy on Discord, here is the closest we can get to converting to dB with the Clue. I've tested this against the app Smart Tools for Android on my Pixel 4XL and they match reasonably well.

Code: Select all

   else if (sensornum == 6) {
    uint32_t pdm_vol = 25 * (log10(getPDMwave(4000)));
    data_buffer.push(pdm_vol);
    Serial.print("PDM volume: "); Serial.println(pdm_vol);
    plotBuffer(arcada.getCanvas(), "dB",
               data_buffer, data_buffer2, data_buffer3);
  }  
I hope this helps others in the community!

Locked
Please be positive and constructive with your questions and comments.

Return to “For Educators”