pimoroni / enviro

MIT License
101 stars 79 forks source link

Something odd about the Sound values on Enviro Urban #98

Closed MrDrem closed 1 year ago

MrDrem commented 1 year ago

I've just got an Enviro Urban too. Set it up outside yesterday, and the sound for the last 12 hours looks like this:

image

I'm taking readings every minute, and the only change is at 04:02 in the morning, and is only a difference of 0.01?

I think that there must be something wrong in the calculations here!

tbbuck commented 1 year ago

That's something I've also been wondering about, and haven't had the time to investigate.

Looking at my logs, taken from recordings every 15 minutes, I have 3,495 total readings, of which 3,489 are at 1.50, five at 1.51, and a single case of 1.56.

MrDrem commented 1 year ago

OK, looking at the code from https://github.com/pimoroni/enviro/blob/main/enviro/boards/urban.py the code block for sound is this:

  sample_time_ms = 500
  start = time.ticks_ms()
  min_value = 1.65
  max_value = 1.65
  while time.ticks_ms() - start < sample_time_ms:
    value = noise_adc.read_u16() / (3.3 * 65535)
    min_value = min(min_value, value)
    max_value = max(max_value, value)

  noise_vpp = round((max_value - min_value), 3)

Looking at it, the min_value and max_value are set to 1.65. Volume samples are taken every ms (?) until half a second is reached. Each sample value is divided by 216265.5 (or 3.3 * 65535, I'm not sure what those two values represent) Each calculated value is compared to the current min and max values, and if it's higher or lower than the currently stored value it replaces it. After the half a second is up, the minimum value is taken away from the maximum value, and the result is rounded (which may cause fun as the numbers are floats) The number is then rounded again as part of the process of passing it back ("noise": round(noise_vpp, 2),)

I'm wondering if the minimum value comes out at around .15, and the max never gets high enough to replace the initially set value. noise_adc.read_u16 readings would need to be over 356838 to change the upper value and then the lower readings between 21627 & 43253 to give 1.5 as a final reading.

I'm fairly sure that the 1.51 (& 1.56) values are to do with the problems with rounding floating numbers in micropython.

MrDrem commented 1 year ago

I also wonder if the noise_vpp = round((max_value - min_value), 3) should in fact be noise_vpp = round((max_value - min_value)*2, 3) to give a rough average value. This might be done better by putting the numbers into an array and then averaging it if so.

tbbuck commented 1 year ago

Great work! Just for giggles to see what happens, I've initialized min_value to 65535 and max_value with 0.

Shall report back once the real-world readings come in.

MrDrem commented 1 year ago

I also wonder if the noise_vpp = round((max_value - min_value), 3) should in fact be noise_vpp = round((max_value - min_value)*2, 3) to give a rough average value. This might be done better by putting the numbers into an array and then averaging it if so.

It can't be this, as an average would add them and then divide them.

tbbuck commented 1 year ago

Nearly 3 days of readings taken every 15 minutes: 270 readings at 0.01, and single ones at 0.02 and 0.07.

I'm based in the commutersville suburbs - quiet at night, and really not that quiet during the daytime :)

taisau commented 1 year ago

Looking at another (temperature) project where they use a similar "formula to compute the voltage from a digital sample in 16 bits mode," they used: Vtemp=sample3.3V/65535 but we have something different: value = noise_adc.read_u16() / (3.3 65535)

ZodiusInfuser commented 1 year ago

Had a look at this code, and @taisau is correct that the value line is wrong. It should multiply by 3.3, then divide by 65535 (or divide first then multiply).

I have now pushed a fix for this to the patch branch, that seems to output close to 0.0 when there is no sound, and over 2 when I rub my finger over the mic whilst it's taking a reading. If you have time to test this I would welcome it. Also, if there's any preferred units that the mic should return let me know.

It's currently the peak-to-peak voltage of the measured signal, which from checking the schematic is 10x what the actual microphone produces due to the onboard op-amp. It would be nice if the value was in decibels but I've not figured that out yet. Here's the datasheet if you wish to investigate: https://www.mouser.co.uk/datasheet/2/218/know_s_a0010769161_1-2271807.pdf

ZodiusInfuser commented 1 year ago

There is a new release that fixes this issue: https://github.com/pimoroni/enviro/releases/tag/v0.0.9 I'll therefore close this but please re-open it or raise a new issue if you update and experience the problem again. Thanks