microbit-foundation / micropython-microbit-v2

Temporary home for MicroPython for micro:bit v2 as we stablise it before pushing upstream
MIT License
41 stars 22 forks source link

Microphone events and threshold inconsistency #160

Open davidtkaye opened 10 months ago

davidtkaye commented 10 months ago

I got frustrated with microphone.set_threshold seemingly to make no difference to a project, so decided to run some test code to see whether sound events were being triggered at different levels.

I got some very strange inconsistent results with loud/quiet events. It seems like the loud event only triggers above a much higher threshold than the one set, and the quiet event seems to be triggering whenever the loud event is not, making the threshold set for that irrelevant? I apologise if I am not correctly understanding how these events work.

Here's the code I used and some sample outputs

from microbit import *

microphone.set_threshold(SoundEvent.LOUD, 80)
microphone.set_threshold(SoundEvent.QUIET, 20)

for _ in range(10):
    if microphone.current_event() == SoundEvent.LOUD:
        print('loud event: {}'.format(microphone.sound_level()))
    elif microphone.current_event() == SoundEvent.QUIET:
        print('quiet event: {}'.format(microphone.sound_level()))
    sleep(1000)

image image

microbit-carlos commented 10 months ago

The events are raised when the thresholds are crossed, so if you are in a quiet room below the quiet level, and make loud short noise, the "loud" event will be raised first and the "quiet" event will follow.

Using the microphone.current_event() will always returned the last recorded event, independently of how long ago it was. So, in the previous example, microphone.current_event() will first return a LOUD event, then a QUIET event, and it will keep to return QUIET until the next LOUD event.

Using the microphone.was_event(SoundEvent.LOUD) will return True or False if the event was raised since the last time microphone.was_event() was called, so that is more likely what you'll want to use.

Hope that helped, let us know if you have any other questions 👍

davidtkaye commented 10 months ago

Thanks for that clarification. I still don't think that explains the behaviour I'm seeing here.

In the very first example a loud sound was made and held. The loud threshold is crossed so we get a loud event (151), but then we see a quiet event when the sound is still above both the loud and quiet thresholds at 107.

In the second example the loud threshold was clearly crossed when the sound was 82 and 96: it should not have dropped below the quiet threshold of 20 at any point, yet we get only quiet events, no loud ones.

I take your point about using was_event: I was really only using the current_event method to try and figure out why changing the thresholds was having no effect by trying to take readings and measurements as close together as possible. I still think that changing the thresholds doesn't affect the behaviour when using was_event, it's just more difficult to show evidence of this!

davidtkaye commented 10 months ago

Here's some further proof that things are not working correctly with microphone threshold setting and events. This code just takes 20 samples over 2 seconds and spits out the sample levels and any events that were recorded. In the first example we never see a loud event despite the threshold clearly being crossed. In the second example we see a second quiet event despite the sound never falling back below the threshold once it is crossed. I am sure there is a bug here you can find with a bit of further experimentation.

from microbit import *

microphone.set_threshold(SoundEvent.LOUD, 80)
microphone.set_threshold(SoundEvent.QUIET, 20)

samples = []
for _ in range(20):
    samples.append(microphone.sound_level())
    sleep(100)

print(microphone.get_events())
print(samples)

image image