pimoroni / enviroplus-python

Python library for the Enviro+ environmental monitoring board
https://shop.pimoroni.com/products/enviro-plus
MIT License
380 stars 175 forks source link

Support MEMS microphone #11

Open jk opened 4 years ago

jk commented 4 years ago

I received my enviro+ last week and over the weekend I managed to install the examples and build my own InfluxDB bridge to show all those measurements via Grafana. Had a lot of tinkering fun, thanks :)

But I'm missing a way to interface the MEMS microphone to read out noise levels. I suppose that support is under way, can someone give an ETA or directions where to read further.

Bugierek commented 4 years ago

I agree to me it would be very useful to have code for mems mic readout. If someone is doing prioritization of todo list I'd vote for that :) thanks

Gadgetoid commented 4 years ago

The microphone is set up as a regular audio input via i2s, so any software capable of reading a standard audio device can access it.

The reason Python support is currently missing is because it's something of a challenge sampling a microphone input and performing any meaningful analysis on it on realtime in Python. It's a work in progress, though.

The solution involves a C daemon called FFsockeT the sole purpose of which is to sample the microphone, apply a (libfftw3) FFT and output the transformed data via a socket into a client application- the intent being that Python can consume this datae easily. The source for that is here- https://github.com/pimoroni/FFsockeT

I've been using sndpeek as a mechanism to visualise noise data, albeit I appreciate it has no practical application for those wishing to sample and log data as part of their environmental monitoring solution - https://soundlab.cs.princeton.edu/software/sndpeek/

Internally we also have a rough-and-ready Python application for sampling the microphone:

#
#""Show a text-mode spectrogram using live microphone data."""
import argparse
import math
import numpy as np
import shutil
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import colorsys
import ST7735

#setup display

LCD_CS = 7
LCD_DC = 9 
LCD_BACKLIGHT = 12

disp = ST7735.ST7735(
    port=0,
    cs=ST7735.BG_SPI_CS_FRONT,
    dc=LCD_DC,
    backlight=LCD_BACKLIGHT,
    rotation=90,
    )
WIDTH = disp.width
HEIGHT = disp.height
disp.begin()
img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
draw = ImageDraw.Draw(img)

usage_line = ' press <enter> to quit, +<enter> or -<enter> to change scaling '

def int_or_str(text):
    #"""Helper function for argument parsing."""
    try:
        return int(text)
    except ValueError:
        return text

try:
    columns, _ = shutil.get_terminal_size()
except AttributeError:
    columns = 80

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-l', '--list-devices', action='store_true',
                    help='list audio devices and exit')
parser.add_argument('-b', '--block-duration', type=float,
                    metavar='DURATION', default=50,
                    help='block size (default %(default)s milliseconds)')
parser.add_argument('-c', '--columns', type=int, default=columns,
                    help='width of spectrogram')
parser.add_argument('-d', '--device', type=int_or_str,
                    help='input device (numeric ID or substring)')
parser.add_argument('-g', '--gain', type=float, default=10,
                    help='initial gain factor (default %(default)s)')
parser.add_argument('-r', '--range', type=float, nargs=2,
                    metavar=('LOW', 'HIGH'), default=[100, 2000],
                    help='frequency range (default %(default)s Hz)')
args = parser.parse_args()

low, high = args.range
if high <= low:
    parser.error('HIGH must be greater than LOW')

# Create a nice output gradient using ANSI escape sequences.
# Stolen from https://gist.github.com/maurisvh/df919538bcef391bc89f
colors = 30, 34, 35, 91, 93, 97
chars = ' :%#\t#%:'
gradient = []
for bg, fg in zip(colors, colors[1:]):
    for char in chars:
        if char == '\t':
            bg, fg = fg, bg
        else:
            gradient.append('\x1b[{};{}m{}'.format(fg, bg + 10, char))

try:
    import sounddevice as sd

    if args.list_devices:
        print(sd.query_devices())
        parser.exit(0)

    samplerate = 4000 # sd.query_devices(args.device, 'input')['default_samplerate']

    delta_f = (high - low) / (WIDTH - 1)
    fftsize = math.ceil(samplerate / delta_f)
    low_bin = math.floor(low / delta_f)

    def callback(indata, frames, time, status):
        if status:
            text = ' ' + str(status) + ' '
            print('\x1b[34;40m', text.center(args.columns, '#'),
                  '\x1b[0m', sep='')
        if any(indata):
            #print(indata)
            cpy_img = img.copy()
            img.paste(cpy_img, (0,5))
            magnitude = np.abs(np.fft.rfft(indata[:, 0], n=fftsize))
            magnitude *= 500 / fftsize
            #print( magnitude)

            for index in range(len(magnitude[low_bin:low_bin + WIDTH])):
                colour = colorsys.hsv_to_rgb(magnitude[index] , 1 ,1)
                colour = tuple(int(255 * x) for x in colour)
                #print(colour)
                draw.line((index , 0, index + 1, 5), fill = colour)

            disp.display(img)

            #print(*line, sep='', end='\x1b[0m\n')
        else:
            print('no input')

    with sd.InputStream(device=args.device, channels=1, callback=callback,
                        blocksize=int(samplerate * args.block_duration / 1000),
                        samplerate=samplerate):
        while True:
            response = input()
            if response in ('', 'q', 'Q'):
                break
            for ch in response:
                if ch == '+':
                    args.gain *= 2
                elif ch == '-':
                    args.gain /= 2
                else:
                    #print('\x1b[31;40m', usage_line.center(args.columns, '#'),
                     #     '\x1b[0m', sep='')
                    break
except KeyboardInterrupt:
    parser.exit('Interrupted by user')
except Exception as e:
    parser.exit(type(e).__name__ + ': ' + str(e))
Gadgetoid commented 4 years ago

@Bugierek the someone would be me, and this is on my radar! (in fact I'm more or less the only software wrangler at the moment, for better or worse)

Bugierek commented 4 years ago

Thanks for reply. I appreciate your effort to make it all working, great job! At some point I managed to make the adafruit mems i2s mic work on Rpi so hopefully it's a similar task that I'll look into although I'm not a programmer ;) In the beginning it would be enough just to get the signal from mic and scale/calibrate the level into absolute value of total SPL. I think nice FFT analysis could be interesting in the future but having a simple dB SPL or A weighted dBA level readout would be enough. Thanks for working on it :)

Gadgetoid commented 4 years ago

I'm certainly no expert on these matters, but as I understand it A-weighting requires a FFT step in order to produce the per-frequency amplitude bands which are then weighted. The alternative being to use a digital filter to isolate the individual frequency bands one at a time before A-weighting them.

Getting a raw dB SPL without any kind of time to frequency domain conversion is - I believe - a folly since it wouldn't account for either the characterists of human hearing nor the variable frequency response of the microphone itself. Granted it may provide a useful relative measurement of noise level for a particular environment - ie: which times of day are more reletively noisy than others.

I also suspect for most environmental noise analysis that a certain subset of frequencies or events will be particularly of interest- things like obnoxiously driven cars, horns, large trucks passing, etc.

Honestly, this is one of the most difficult challenges I've faced in terms of general understanding of the core concepts. Sound is decidedly more information dense than light levels or temperature.

This is one of those problems where capturing chunks of audio throughout the day and throwing them at machine learning to classify frequency and density of "annoying noise events" would be, I guess, ideal. This looks like a deep rabbit hole, though- https://github.com/tyiannak/pyAudioAnalysis/

Some useful information here, too (for posterity) - https://makersportal.com/blog/2018/9/17/audio-processing-in-python-part-ii-exploring-windowing-sound-pressure-levels-and-a-weighting-using-an-iphone-x

And while I'm bundling information here, the datasheet for the MEMS microphone part - https://media.digikey.com/pdf/Data%20Sheets/Knowles%20Acoustics%20PDFs/SPH0645LM4H-B.pdf

Bugierek commented 4 years ago

Yes you're right that it'd be best to have at least A weighted SPL values and even better some sort of FFT graph.Another way that people look at noise are full octave or third octave bands of frequencies, but it also requires FFT step to calculate bands of frequencies. Actually the Full or 3rd octave bands are the default way that acoustic consultants look at noise data :)

btw that's another project I've found on the subject. A bit outdated but still: https://github.com/SuperShinyEyes/spl-meter-with-RPi

Esteidinger commented 4 years ago

I received my enviro+ last week and over the weekend I managed to install the examples and build my own InfluxDB bridge to show all those measurements via Grafana. Had a lot of tinkering fun, thanks :)

But I'm missing a way to interface the MEMS microphone to read out noise levels. I suppose that support is under way, can someone give an ETA or directions where to read further.

Hi @jk , can you share your updates to push data to InfluxDB and Grafana? I would love to have that data locally for historical purposes. I already have a TIG stack running.

jk commented 4 years ago

@Esteidinger Sure: https://gist.github.com/jk/dc58ef3759b1d61f021281531858a2a9

david-peterson commented 4 years ago

A few notes for people following this issue.

I'm new to Raspberry Pi, and what follows is from my poking at this with a new Pi Zero and Enviro+ with a fresh Raspbian Stretch install from the latest 2019-04-08 image.

But I did get sound working!

If you Google search getting the MEMS mic to work, you'll like land on this article at Adafruit. Don't follow that as-is, it's pretty old and leads your through a lot of unnecessary work.

First, do not use rpi-update to get your system up to date. For the driver stuff, a simple apt-get update and apt-get upgrade is good enough. Or you can use the Pimoroni update script that does that plus updates your python libraries.

Second, you do not need to run rpi-source to download and recompile the kernel. Just install the kernel headers with sudo apt-get install raspberrypi-kernel-headers as mentioned in the second answer here on StackExchange

After that, get the kernel module source and follow the rest of the instructions from the Adafruit article.

Since I have a Pi Zero, I had to change the module source as instructed. And to test the volume control (in the bottom of the Adafruit article) I had to change the name from "Boost Capture Volume" to "Master Capture Volume" (which was down a ways in this thread).

But after modifying the source and building and loading the module I was able to record a wav file using arecord!

Then I had to modify the FFsocket source to open the MEMS mic kernel module by changing it from hw:adau7002 to hw:sndrpisimplecar. And with that I managed to get ffsocket to run and was able to use client.py to read the output and can see varying values in the output array.

I don't know what any of those values mean :-) but it seems to be doing something in response to noise near the Enviro+

kflmiami420 commented 4 years ago

David thank you for your post I will follow your instructions on my Enviro+ plus board. I am working on using the ACD pin to read an external adafruit 1733 anemometer as well by modifying the Gas.py script to include a read function and convert voltage to m/s reading , Then adding another mode to enviro_demo.py to be able to get a display of wind speed.

Bugierek commented 4 years ago

Regarding obtaining the A-Weighted SPL I have found this example: https://docs.smartcitizen.me/Components/Urban%20Sensor%20Board/Noise%20Sensor/ and here are some interesting Github repos related to it:

  1. https://github.com/fablabbcn/smartcitizen-kit-audio
  2. https://github.com/oscgonfer/AudioI2S
Bugierek commented 4 years ago

I have found another implementation here, so it might be helpful to see how it was done on other platform : https://github.com/Tinkerforge/sound-pressure-level-bricklet/

https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Sound_Pressure_Level.html

vschinazi commented 4 years ago

Hi @Gadgetoid I just wanted to follow up on this issue. It would be really great to have a python script to measure noise pollution. I am currently developing a project that will use the Enviro + sensor in 30+ classrooms and getting a measure of noise would be really amazing. Thank you.

kflmiami420 commented 4 years ago

You have to adapt a dead cat attachment to the noise sensor otherwise the hard walls and floors and ceiling will amplify your levels and give you improper levels .

On Mon, Oct 14, 2019 at 10:47 AM vschinazi notifications@github.com wrote:

Hi @Gadgetoid https://github.com/Gadgetoid I just wanted to follow up on this issue. It would be really great to have a python script to measure noise pollution. I am currently developing a project that will use the Enviro + sensor in 30+ classrooms and getting a measure of noise would be really amazing. Thank you.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pimoroni/enviroplus-python/issues/11?email_source=notifications&email_token=AKFAE2ZCQYLDSCW4TPSJJR3QOSBB3A5CNFSM4H62SO7KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBFAWOQ#issuecomment-541723450, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKFAE24Q22DKTVSFSVMKNHDQOSBB3ANCNFSM4H62SO7A .

vschinazi commented 4 years ago

You have to adapt a dead cat attachment to the noise sensor otherwise the hard walls and floors and ceiling will amplify your levels and give you improper levels .

Oh wow, thank you for the heads up! What do you recommend for that? Do you actually have a working python script for the microphone? Would you be able to share that?

Gadgetoid commented 4 years ago

Sorry I should have mentioned that the noise/microphone code is currently pending review and merge in a pull-request which you can find here: https://github.com/pimoroni/enviroplus-python/pull/33

I'll keep this issue open because I don't believe Python is the best/only way to do this, and alternate setups which access the i2s microphone could be useful or interesting to others.

Bugierek commented 4 years ago

Hi, I have found another piece of code that might help with getting the fft noise levels: https://github.com/colin-guyon/rpi-audio-levels

Sorry for flooding this topic with bunch of links, I'm not a dev and can't really code, but hopefully in some of these examples there will be something useful and helpful to get it working well on Rpi.

seaniedan commented 4 years ago

There is some sound code written now, but when I do (on a fresh install of Raspbian): git clone https://github.com/pimoroni/enviroplus-python cd enviroplus-python sudo ./install.sh I get 'SyntaxError: invalid syntax' in the install script (see attached), and then (after reboot): pi@raspberrypi:~/enviroplus-python/examples $ python3 ./noise-profile.py Traceback (most recent call last): File "./noise-profile.py", line 3, in from enviroplus.noise import Noise File "/usr/local/lib/python3.7/dist-packages/enviroplus-0.0.3-py3.7.egg/enviroplus/noise.py", line 1, in ModuleNotFoundError: No module named 'sounddevice' enviroplus_problems.txt

seaniedan commented 4 years ago

in case anyone is wondering, this seemed to help: pip3 install sounddevice

bluemeerkat commented 4 years ago

Hi, I am another one interested in being able to measure noise pollution in terms of dBA, which would clearly be useful in an Environmental monitoring board. (In fact we wrongly assumed this would be provided before buying the board). Before I try out some of the ideas suggested by @Bugierek, since most of a year has elapsed since this issue was first raised, I wondered if perhaps something has changed and Pimoroni (@Gadgetoid) might have some usable library either available or in development?

Now, I notice that there is now a noise.py library with three functions to obtain noise profile and mean amplitudes at a frequency range or ranges. But it's not clear what units these return and I don't think they fit the bill for dBA (which involves root-squared-mean values and A-weighting according to a curve). Am I wrong @Gadgetoid - or can these be easily adapted for dBA?

(Apologies if you see this twice - I thought I posted it yesterday - but it seems to have been my imagination :-) )

Thanks a lot.

ftosteve commented 4 years ago

Hi. Another who bought several Enviro+ hoping to measure dBA. Looking around other repo's dBA looks quite intense. I hope Pimoroni can help us all. Thanks

LucaTurina commented 3 years ago

Hi. Also bought an Enviro+ hoping to measure dBA. Would love to get some input here! Thank you :-)

riffo-online commented 3 years ago

Hello to everyone! I bought Enviro+ mainly to acquire data related to indoor environments and mainly for noise level (dB or dBA). I'm not an experienced programmer and I can't find an example "ready-to-use" on the Web to detect the noise level in dB or dBA. Has anyone found something? it would be crucial for me! THANK YOU very much to anyone who has suggestions on this!

alaub81 commented 3 years ago

Anybody else got this error on running the noise-profile.py:

Traceback (most recent call last):
  File "noise-profile.py", line 29, in <module>
    low, mid, high, amp = noise.get_noise_profile()
  File "/root/.local/lib/python3.7/site-packages/enviroplus/noise.py", line 67, in get_noise_profile
    recording = self._record()
  File "/root/.local/lib/python3.7/site-packages/enviroplus/noise.py", line 89, in _record
    dtype='float64'
  File "/root/.local/lib/python3.7/site-packages/sounddevice.py", line 275, in rec
    ctx.input_dtype, callback, blocking, **kwargs)
  File "/root/.local/lib/python3.7/site-packages/sounddevice.py", line 2578, in start_stream
    **kwargs)
  File "/root/.local/lib/python3.7/site-packages/sounddevice.py", line 1416, in __init__
    **_remove_self(locals()))
  File "/root/.local/lib/python3.7/site-packages/sounddevice.py", line 812, in __init__
    extra_settings, samplerate)
  File "/root/.local/lib/python3.7/site-packages/sounddevice.py", line 2651, in _get_stream_parameters
    info = query_devices(device)
  File "/root/.local/lib/python3.7/site-packages/sounddevice.py", line 564, in query_devices
    raise PortAudioError('Error querying device {}'.format(device))

Installed also the sounddevice and the libportaudio2 I am using a raspberry pi zero w. Everything else of the example scripts is working well.

ftosteve commented 3 years ago

Hi Gadgetoid. Is there any news on the development obtaining dBA/SPL with the MEMs microphone? I would find this extremely useful in my project. I now have 20 of these HAT's with the intention of buying at least 60 for a factory monitoring system. If you have any code you need testing, I would be happy to help. I can also gain access to a handheld calibrated SPL meter to check accuracy. Thanks Steve PS: Have also been mailing your colleague Matt at Pimoroni about this subject and he pointed me here.

seaniedan commented 3 years ago

Hey Steve, drop me a line - follow the link to my website. I have some ideas for you.

ChristophDerndorfer commented 3 years ago

@seaniedan @ftosteve, do you have any updates from your discussions that you can share publicly?

ftosteve commented 3 years ago

Nothing from me sorry. I have been offline for a few weeks. I did look at seaniedan's link but nothing related to this subject.

Gadgetoid commented 3 years ago

Sorry for the lack of response here, but I've had nothing useful to add. Not only does my fundamental lack of understanding somewhat hamstring me here, but a variety of other factors mean I haven't had the time to even look into it.

ChristophDerndorfer commented 3 years ago

Thanks for the quick replies.

Though admittedly I find it quite frustrating that a company specifically advertising a product to be useful for noise measurements (see the screenshot below from the Enviro product page) still hasn't managed to even provide a basic tutorial on how to achieve that since mid-2019... :-/

image

roscoe81 commented 3 years ago

I started looking at this issue this week and I think that I've made some progress. The main issue was setting up the I2S microphone with adjustable gain level. Have a look here: https://github.com/roscoe81/northcliff_spl_monitor

The sampling rate of 16kHz and the very basic A-curve compensation are still major limitations and I haven't spent a lot of time performing calibration, but I've done some comparisons with an iPhone app and there is reasonable correlation.

Hoping that this can be a base for further development.

Cumberland-Pi commented 3 years ago

Hi roscoe81, Thanks for this, it's really useful. The code comments help enormously. I'm currently working on something that I hope will show sound levels on the display in 'real time', which I'll try & share later. Anyway, stupid question No. 1: I couldn't get the mic working on my Enviro (not +) unless I commented out the 'dmic_sv' - I can't work out what this mic is, can you explain?

Hi Gadgetoid, stupid question No. 2: I'm trying to fathom out what the data ranges are that returned by the mems mic. I came across this https://forums.pimoroni.com/t/enviro-bit-get-noise-level/12616 which quotes a range of 0..443 from a document. However the data type holding the sound level is a numpy float64, I can't find any reference to any min/max values on the mems mic data sheet. float 64 has the following ranges:

Machine parameters for float64

precision = 15 resolution = 1.0000000000000001e-15 machep = -52 eps = 2.2204460492503131e-16 negep = -53 epsneg = 1.1102230246251565e-16 minexp = -1022 tiny = 2.2250738585072014e-308 maxexp = 1024 max = 1.7976931348623157e+308 nexp = 11 min = -max

which is a bit different from what the thread says. What is the theoretical max of the amplitude measurement I should expect from the mic?

Stupid question No. 3: I note in the example noise-amps-at-freqs.py that you have this line following a reading: *amps = [n 32 for n in amps]**

what is the significance of 32 in this instance?

Apologies if this information is widely available - I can't find it anywhere.

roscoe81 commented 3 years ago

I believe that dmic_sv represents Digital Microphone Soft Volume. @Cumberland-Pi . In which file did you comment it out?

Cumberland-Pi commented 3 years ago

I took a copy of your northcliff_spl_monitor. Until I commented out the mic line, I got an exception (couldn't find device)

def _record(self):
    return sounddevice.rec(
        int(self.duration * self.sample_rate),
        samplerate=self.sample_rate,
        #device = "dmic_sv",
        blocking=True,
        channels=1,
        dtype='float64'
    )

I got it working on my Enviro. I'm now trying to splice it into the app wot I wrote, which displays a horizontal bar chart of the measurements at various bands. I'll post the code if & when I get it cleaned up. It's a hacked mess at the moment.

Anyway, thanks for your code.

ChristophDerndorfer commented 3 years ago

@Cumberland-Pi, great news, and let us know if you need anyone to test your code even in early stages. :)

roscoe81 commented 3 years ago

@Cumberland-Pi I suspect that if the script couldn't find "dmic-sv", the I2S microphone setup (as per the Setup section of the README) hasn't been successfully completed. I might be wrong, but you might find that the northcliff_spl_monitor code won't run successfully without it because I found that the microphone level needed to be increased to get reasonable readings. I've also now updated my code to include the ability to provide graphical displays. The display types can be selected as command line arguments that are shown in the updated README.

Cumberland-Pi commented 3 years ago

@roscoe81 Thanks for the info, something to investigate, as I am getting strange results. Note to self - ALWAYS read the README before grabbing the code :-| Also good to know you've added the graphical stuff. I'll have a look. @ChristophDerndorfer. Cheers for the offer.

ftosteve commented 3 years ago

@roscoe81 Sorry for delay in testing, been snowed under. Finally got to try your instructions and code. Took me a while to get past the the 'Use alsamixer to set adau7002 capture level to 100' line as after selecting the device with F6, the F4 to 'Capture' keeps closing the mixer... I got around this, rightly or wrongly, by pressing F5(All) and setting level to 100 there.

Running your .py I get dB(A) reading on the screen that is about ~5dB(A) more than my phone app, which is not bad as an indicator. Of course I am not sure how accurate my phone app/mic is so am reasonably happy to get that close. On Monday I am back at work so will try and 'borrow' the calibrated SPL meter and see how close it really is. As my application is for a factory, I am happy just to know it its above 100dB(A) or not. Thanks loads for this by the way, very much appreciated...

On a side note. I want to replicate my pi/enviro devices 50+ times. If I image the SD and put on the other devices, will all the settings be transferred across. For instance, the soundcard id, alsamixer 100% settings etc, etc? Or are these settings stored somewhere else in the Pi?

Thanks again, Steve

roscoe81 commented 3 years ago

@ftosteve Glad that you found it useful and that's strange about the alsamixer setup. I've further tweaked the calibration in the latest code update but I'm still not totally happy with its measurements across the entire sound level range. It's in the experimental stage and I wouldn't recommend it being used in its current state to provide reliable sound level measurements.

I would expect that imaging the SD will replicate all the required settings.

Cumberland-Pi commented 3 years ago

@roscoe81 Got my sound app mentioned above working, and I've incorporated your Noise class.

Here's the code: (edited as I can't seem to link my github rep. so loaded python file as text)

spl_meter.txt

Comments always welcome.

I plan to splice in Ross' displays at some later date.

roscoe81 commented 3 years ago

I’ve updated my code to Version 1.0 that now uses streaming to overcome the microphone's startup "plop" that was identified in the excellent review here. It’s performance seems to be much better than the previous version.

dguk25 commented 3 years ago

thanks @roscoe81 for moving this forward it's really frustrating that a board that's advertised for noise level sensing doesn't have ANY documentation around using this sensor! I also bought it on the presumption that this would work. I've got your code working... but do you also see regular spikes even when completely silent? really keen to get this board working for ambient light and noise level detection, but need it to be fairly reliable. the lux detection seems pretty good. anyone got any other suggestions for a HAT that would support both noise and light detection out of the box?

roscoe81 commented 3 years ago

Thanks for the feedback @dguk25 I didn't see the spikes when I did the initial testing but I have experienced them, depending on the prior state of the Raspberry Pi Zero. It seemed that the code had problems with the timing of the callback and main loop. The latest version of my code now seems to address that issue. I also found that microphone drift was no longer an issue - presumably because the samples were being processed properly. I also added the ability to cycle through the display types via the proximity sensor. Please let me know if this latest version addresses the spike issue that you found.

dguk25 commented 3 years ago

Great work @roscoe81 ! No longer see the spikes and generally performs pretty well ;) I'm interested in what you mean by "the sampling rate of 16kHz and the very basic A-curve compensation are still major limitations"... do you think the sensor is fundamentally limited, or just that further development is needed to harness it? I'm looking to utilise it for ambient noise levels, but I'm starting to wonder if the directional nature of the MEMS microphone might be a hinderance.

roscoe81 commented 3 years ago

Glad that you're seeing progress @dguk25 The sampling rate is now 48kHz, so that limitation has now been addressed. The A-curve compensation is still limited by my code at the moment, due to it only having three frequency bands. Apart from the start-up "plop" and DC offset that were addressed by streaming in Version 1.0, I don't see any inherent limitations of the MEMS microphone in doing the job and I think the next steps are to add more frequency bands and to implement an asyncio coroutine to optimise processing capacity. They're on my to-do list and I suspect that the only potential roadblock is the limited processing power of the Raspberry Pi Zero. I've already seen that when I've tried to integrate the noise measurement code into my enviro-monitor.

I've now added a maximum sound level line (along with the time and date when it was recorded) to Display 1 in my latest code update. I've found that to be quite useful.

roscoe81 commented 3 years ago

I’ve now integrated noise level measurement into my enviro-monitor and it seems to work reasonably well.

dguk25 commented 3 years ago

I’ve now integrated noise level measurement into my enviro-monitor and it seems to work reasonably well.

Brilliant. Will check it out later today. Thanks for the note above as well. The maximum sound level line works really well 👍

ChristophDerndorfer commented 3 years ago

@roscoe81, thanks a lot for all your work! I've finally had a chance to test the current version northcliff_spl_monitor.py and it seems to work well. I hope to find some time next week to compare the measured noise levels with some apps I have installed on my phone.

Three issues I ran into while following the instructions in the README were:

  1. Using alsamixer to set adau7002 capture level to 50 doesn't work for me. I can start the alsamixer and switch to the adau7002 via F6 but as soon as I hit F4 to get to the capture mode the program quits and I'm back on the commandline. Maybe it's related to the fact that I'm SSHing into the RPi Zero W rather than an actual terminal but I haven't found a solution for this issue yet. Is anyone else here running into it?
  2. Upon the first execution of your script I got an error message about matplotlib not being available on my system. Running sudo pip3 install matplotlib quickly fixed the issue but maybe the requirement can be added to the README so others aren't confused about it.
  3. On my Pi Zero W starting the script takes about 14 seconds and so initially I had thought that it had crashed. Is that the same on your system?

And a final question: Is there any difference in the noise measurement implementation between enviro-monitor and the stand-alone script?

Thanks again and keep up the great work.

ChristophDerndorfer commented 3 years ago

Quick update on the alsamixer issue: When physically logged into the console via a keyboard I was able to change the capture level as documented. So the behaviour I was seeing definitely seems to be related to me being connected via SSH beforehand.

roscoe81 commented 3 years ago

Thanks for your feedback @ChristophDerndorfer In term of your three issues.

  1. I haven't seen that issue with alsamixer and I log in via VNC
  2. I'll add that in the README.
  3. Yes, I have a similar startup time.

I've found that the measurements between the two implementations are identical but the cycle rates are slower on the enviro-monitor