Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revision of PDM code to have proper sinc filter and maybe dB-gain-managed output #2

Open
ladyada opened this issue Feb 1, 2018 · 13 comments
Assignees

Comments

@ladyada
Copy link

ladyada commented Feb 1, 2018

Dean @deanm1278 kindly volunteered to port his Arduino-calibrated code to CODAL!

@pelikhan
Copy link

pelikhan commented Feb 1, 2018

Thank you @deanm1278!

@jamesadevine
Copy link
Contributor

Fantastic news @ladyada! Thanks @deanm1278 😄

@deanm1278
Copy link
Contributor

hi @jamesadevine I have a Q:
What am I doing wrong in this code:


#include "CircuitPlayground.h"
#include "SAMD21DMAC.h"
#include "SAMD21PDM.h"
#include "LevelDetector.h"

CircuitPlayground cplay;

SAMD21DMAC dma;
SAMD21PDM mic(cplay.io.microphoneData, cplay.io.microphoneClock, dma, 22000);
LevelDetector lvl(mic, 0, 0);

void test(Event){
    asm volatile("NOP;");
}

int main(){
    cplay.messageBus.listen(DEVICE_ID_SYSTEM_LEVEL_DETECTOR,LEVEL_THRESHOLD_HIGH,test); 

    mic.enable();   

    release_fiber();
}

This should initialize the mic and then generate an event when the PDM level goes above or below 0 right?

LevelDetector::pullRequest() only gets called once and then DataStream seems to spin out here on all further requests:

if (full() && this->isBlocking == false)
        return DEVICE_NO_RESOURCES;

Is there something else I should be doing to release the buffer?

@jamesadevine
Copy link
Contributor

LevelDetector lvl(mic, 0, 0);

Off the top of my head, you may be hitting a corner case in the code, I think it presumes that the two values are different, not the same...

LevelDetector lvl(mic, 1, 0);

Would likely work, I'll give it a look in a bit 😄

@jamesadevine
Copy link
Contributor

@deanm1278 HEY!

Sorry this took a little while to get back to you, here's a sample that will work...:

#include "CircuitPlayground.h"
#include "SAMD21DMAC.h"
#include "SAMD21PDM.h"
#include "LevelDetector.h"
#include "StreamNormalizer.h"

CircuitPlayground cplay;

SAMD21DMAC dma;
SAMD21PDM mic(cplay.io.microphoneData, cplay.io.microphoneClock, dma, 22000);
LevelDetector lvl(mic.output, 70, 30);

void high(Event)
{
    cplay.io.led.setDigitalValue(1);
}

void low(Event)
{
    cplay.io.led.setDigitalValue(0);
}

int main()
{
    cplay.messageBus.listen(DEVICE_ID_SYSTEM_LEVEL_DETECTOR,LEVEL_THRESHOLD_HIGH,high);
    cplay.messageBus.listen(DEVICE_ID_SYSTEM_LEVEL_DETECTOR,LEVEL_THRESHOLD_LOW,low);

    mic.enable();

    release_fiber();
}

I've also added some samples we had knocking about on an old repository to the circuit-playground repo (https://github.com/lancaster-university/codal-circuit-playground/tree/master/samples)

@jamesadevine
Copy link
Contributor

P.S. I've found that sample works best if you blow directly at the mic 😄

@deanm1278
Copy link
Contributor

@jamesadevine ok thanks very much! I'll check it out when I have a minute to get back to this. Was mine not working because I'm supposed to use mic.output instead of mic?

@jamesadevine
Copy link
Contributor

Yes, that's correct 😄 sorry didn't spot it in my cursory glance...

@deanm1278
Copy link
Contributor

ok @jamesadevine @pelikhan I have made a bunch of PDM updates here:
https://github.com/adafruit/codal-samd21/blob/master/source/SAMD21PDM.cpp

and have also updated the LevelShifter stream to use dB SPL here:
adafruit/codal-core@a4e9a36

If this is not the correct place for the dB SPL code, or it should go in it's own stream please let me know.

So that I can be sure things are correct before I submit a PR, is there any way to print things via USB CDC similar to Arduino Serial.print()?

Thanks!

@jamesadevine
Copy link
Contributor

There's a uf2 equivalent yes, see uf2tool.

Alternately just attach a usb to serial cable, to TX and RX on the cplay.

By default dmesg uses uf2 to debug, if you flip the DMESG_SERIAL_DEBUG flag and have DMESG_BUFFER_SIZE set to something reasonable, it will use Serial instead.

@jamesadevine
Copy link
Contributor

@deanm1278 WRT your code, I think there should be a separation of concerns... It seems like your modifications to LevelDetector has two purposes:

  1. Conversion to DB.
  2. Floating point based threshold detection.

So for me it feels like these should be two separate nodes in the stream:

Microphone -> decibels conversion -> floating point level detector

I think it's useful to have both versions of the level detector, so I think that your floating point level detector should be a separate class.

What do you think @deanm1278 @finneyj ? Does it make sense to separate out the decibels conversion?

@deanm1278
Copy link
Contributor

Ok I've broken out a separate dB SPL level detector (see my PRs in codal-samd21 and codal-core).
IMO a separate db conversion stream would be kind of redundant since it's only meaningful when calculated over a given window. LevelDetectorSPL.getValue() can be used to return the value of the last calculation if no actual level detection is needed.

@jamesadevine
Copy link
Contributor

@deanm1278 Agreed, cool. I've given your PRs a quick review, it took me a little while to be able to test 😄

I like that we now use an SI unit for the microphone, it opens up a whole bunch more educational scenarios in the classroom. Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants