我正在使用 Adafruit Feather M0 RFM69 和 Adafruit I2S MEMS 麦克风分接 SPH0645。每一秒我都会使用 I2S 库读取读数(sampleRate = 16000,每个样本的位数 = 32)并通过无线电发送。这一切都很好。
我的问题是,当我想省电时,在我将板子从睡眠中唤醒后,我得到了奇怪的读数(使用 Adafruit_SleepyDog 库)。麦克风在某种程度上仍然可以工作,尽管它的灵敏度要低得多,只能拾取响亮的声音,并且在安静的房间里也能返回 60dB。当我不让它睡觉时,在相同的声音设置下,我得到 40dB。但是,如果我在唤醒后延迟 250 毫秒,麦克风又会像以前一样正常工作,但这显然不节能。
我想知道为什么会这样。我可以做些什么来让麦克风更快地工作吗?我查看了数据表,但它只说:“当施加 Vdd 时,麦克风感应 CLOCK 线,如果频率大于 900KHz,则麦克风进入正常工作模式。” 不过,这甚至不需要几毫秒?提前致谢
#include <I2S.h>
#include <Adafruit_SleepyDog.h>
#include <SPI.h>
#include <RH_RF69.h>
/************ Radio Setup ***************/
#define RF69_FREQ 433.0
#define SLEEP
//#if defined(ARDUINO_SAMD_FEATHER_M0) // Feather M0 w/Radio
#define RFM69_CS 8
#define RFM69_INT 3
#define RFM69_RST 4
#define LED 13
//#endif
// radio
// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS, RFM69_INT);
int transmit_interval = 1000;
int time_counter = 0;
int packetnum = 0;
// MIC
#define SAMPLES 1024//2048 // make it a power of two for best DMA performance
int samples[SAMPLES];
int measurementsdB = 0;
int current_measure;
#define ADC_SOUND_REF 65
#define DB_SOUND_REF 41
int sampleRate1 = 16000;
int bitsPerSample1 = 32;
typedef struct
{
uint8_t measurementdB = 123;
uint8_t battery = 111;
uint8_t test = 222;
} RadioMessage;
RadioMessage struct_message;
void setup()
{
delay(2000); // Wait so its easier to program
Serial.begin(115200);
//while (!Serial) { delay(1); } // wait until serial console is open, remove if not tethered to computer
// Init Mic
if (!I2S.begin(I2S_PHILIPS_MODE, sampleRate1, bitsPerSample1)) {
while (1); // do nothing
}
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);
Serial.println("Feather RFM69 TX Test!");
Serial.println();
// manual reset
digitalWrite(RFM69_RST, HIGH);
delay(10);
digitalWrite(RFM69_RST, LOW);
delay(10);
if (!rf69.init()) {
Serial.println("RFM69 radio init failed");
while (1);
}
Serial.println("RFM69 radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
// No encryption
if (!rf69.setFrequency(RF69_FREQ)) {
Serial.println("setFrequency failed");
}
// If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
// ishighpowermodule flag set like this:
rf69.setTxPower(20, true); // range from 14-20 for power, 2nd arg must be true for 69HCW
// The encryption key has to be the same as the one in the server
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
rf69.setEncryptionKey(key);
Serial.print("RFM69 radio @"); Serial.print((int)RF69_FREQ); Serial.println(" MHz");
//GCLK->GENCTRL.bit.RUNSTDBY=1; // !! can go
}
void loop() {
Serial.println("START");
///// MIC
//PM->APBCMASK.reg |= PM_APBCMASK_I2S;
int a = 0;
while (a == 0) a = I2S.available();
uint8_t current_measure = sample_audio_signal(samples);
///// RADIO
if (true)//((time_counter + transmit_interval) < millis())
{
struct_message.measurementdB = current_measure;
//struct_message.battery = measuredvbat;
// Send a message!
/*
Serial.print("Array content: ");
uint8_t* bla = (uint8_t*) &struct_message;
for (int i = 0; i < 3; i++)
{
Serial.println(bla[i]);
}*/
rf69.send((const uint8_t*) &struct_message, sizeof(struct_message));
rf69.waitPacketSent();
Serial.print("Wait for reply");
// Now wait for a reply
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf69.waitAvailableTimeout(100)) {
// Should be a reply message for us now
if (rf69.recv(buf, &len)) {
Serial.print("Got a reply: ");
Serial.println((char*)buf);
} else {
Serial.println("Receive failed");
}
} else {
Serial.println("No reply, is another RFM69 listening?");
}
Serial.println("Radio sleeping");
rf69.sleep();
time_counter = millis();
}
// sleep time
#ifdef SLEEP
int sleepMS = Watchdog.sleep(10);
delay(250);
#else
delay(1000);
#endif
Serial.println("loop ended");
}
void Blink(byte PIN, byte DELAY_MS, byte loops) {
for (byte i=0; i<loops; i++) {
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
delay(DELAY_MS);
}
}
float sample_audio_signal(int samples[])
{
for (int i=0; i<SAMPLES; i++) {
int sample = 0;
while ((sample == 0) || (sample == -1) ) {
sample = I2S.read();
}
// convert to 18 bit signed
sample >>= 14;
samples[i] = sample;
}
// ok we have the samples, get the mean (avg)
float meanval = 0;
for (int i=0; i<SAMPLES; i++) {
meanval += samples[i];
}
meanval /= SAMPLES;
// subtract it from all samples to get a 'normalized' output
for (int i=0; i<SAMPLES; i++) {
samples[i] -= meanval;
}
// find the 'peak to peak' max
float maxsample, minsample;
minsample = 100000;
maxsample = -100000;
for (int i=0; i<SAMPLES; i++) {
minsample = min(minsample, samples[i]);
maxsample = max(maxsample, samples[i]);
}
int newdB = 20 * log10((float)maxsample / (float)ADC_SOUND_REF) + DB_SOUND_REF;
return newdB;