1

我正在使用 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;
4

1 回答 1

0

好的,我得到的最好是 3.8mA。到目前为止,我只是在睡眠期间保持稳压器和内部振荡器 (DFLL) 开启。

在我的设置例程中添加以下代码后,当电路板进入睡眠状态时,麦克风在唤醒后仍然可以工作:

SYSCTRL->DFLLCTRL.bit.RUNSTDBY=1; 
SYSCTRL->VREG.bit.RUNSTDBY=1;

但是,理想情况下,我希望得到的比这要少得多,但是麦克风不起作用……

于 2018-05-01T14:50:04.067 回答