Closed fontanon closed 4 years ago
Actually, including in the sketch Adafruit_ZeroDMA instead of SPI produces the same error:
#include <I2S.h>
#include <Adafruit_ZeroDMA.h>
void setup() {
}
void loop() {
}
/tmp/arduino_build_458350/libraries/Adafruit_ZeroDMA/Adafruit_ZeroDMA.cpp.o: In function `DMAC_Handler':
Adafruit_ZeroDMA.cpp:(.text.DMAC_Handler+0x0): multiple definition of `DMAC_Handler'
/tmp/arduino_build_458350/libraries/I2S/utility/DMA.cpp.o:DMA.cpp:(.text.DMAC_Handler+0x0): first defined here
collect2: error: ld returned 1 exit status
we don't really use/support the official arduino i2s library, try the Audio library fork we have
@fontanon
did you find a workaround?
@ladyada thanks! do you maybe have a small pointer how I would use the mic in with a MEMS microphone? Or which sketch should I use?
sorry no idea!
@ladyada ok thanks.
https://learn.adafruit.com/adafruit-i2s-mems-microphone-breakout/arduino-wiring-and-test
This tutorial is busted then (the part with the ArduinoSound library).
yep - i2s is not supported right now, you can remove the zerodma library from within the adafruit arduino core for now look in Arduino15 folder
@fontanon
did you find a workaround?
Yes @dennischrist I actually make it work by importing and using Adafruit_ZeroI2S instead of the I2S library itself!
https://github.com/adafruit/Adafruit_ZeroI2S
I'll be actually submitting soon to github a full firmware example using Adafruit_ZeroI2S to communicate with the microphone and arduino-lmic (which depends on SPI) to report via LoRaWAN the measurements.
Hi @dennischrist @ladyada find below a sample arduino sketch file illustrating how we make it work. I hope it helps.
// Sample firmware to illustrate how to interface with I2S devices and
// using arduino-lmic library with Adafruit Feather M0 Boards.
#include <Arduino.h>
#include <stdio.h>
#include <math.h>
// Most relevant libraries here: Adafruit-samd v1.5.2 (board) + Adafruit_ZeroI2S + arduino-lmic
#include <Adafruit_ZeroI2S.h>
#include <lmic.h>
#include <hal/hal.h>
// Mic sampling parameters
// Unsing InvenSense INMP441 via I2S interface
// Further hardware info: https://www.invensense.com/wp-content/uploads/2015/02/INMP441.pdf
#define SAMPLERATE_HZ 44100
int32_t audiosamples = 128;
const int sample_delay = 1000;
// Pin mapping for RFM95w LoRaWAN interface (via LMIC)
// Further hardware info: https://www.hoperf.com/modules/lora/RFM95.html
const lmic_pinmap lmic_pins = {
.nss = 8,
.rxtx = LMIC_UNUSED_PIN,
.rst = LMIC_UNUSED_PIN,
.dio = {3, 6, LMIC_UNUSED_PIN},
};
// The I2S interface with the Mic using Adafruit Library.
Adafruit_ZeroI2S i2s;
void setup() {
// Configure serial port.
Serial.begin(115200);
Serial.println("Zero I2S Audio Tone Generator");
// Initialize the I2S transmitter.
if (!i2s.begin(I2S_32_BIT, SAMPLERATE_HZ)) {
Serial.println("Failed to initialize I2S transmitter!");
while (1);
}
// Enable receive PIN 11 for Digital Output.
i2s.enableRx();
pinMode(11, OUTPUT);
}
void loop() {
// This is a stereo Mic. But we'll only read from LEFT channel
digitalWrite(11, LOW);
float sound;
int32_t left,right;
int i;
int sample=0;
// Read a bunch of samples!!!
int32_t samples[audiosamples];
for (int i = 0; i < audiosamples; i++) {
i2s.read(&left, &right);
delay(1); // Workaround delay to prevent oversizing the buffer
sample = left;
// convert to 18 bit signed
sample >>= 14;
samples[i] = abs(sample);
}
// Calculate mean (avg) over samples
float meanval = 0;
for (int i = 0; i < audiosamples; i++) {
meanval += samples[i];
}
meanval /= audiosamples;
// subtract it from all samples to get a 'normalized' output
for (int i = 0; i < audiosamples; i++) {
samples[i] -= meanval;
}
// find the 'peak to peak' max
float maxsample, minsample;
minsample = 100000;
maxsample = -100000;
for (int i = 0; i < audiosamples; i++) {
minsample = min(minsample, samples[i]);
maxsample = max(maxsample, samples[i]);
}
sound = 10 * log(maxsample - minsample);
Serial.println(sound);
delay(1000); // Let's just process a measurement each second.
}
@fontanon this is brilliant, it works great on the featherM0 WiFi. Thank you for posting your example!
@fontanon I was trying your code to interface the Adafruit I2S microphone with Adafruit Feather M0 datalogger. My objective is to write audio data in the SD card.
I observed that, the datarate of Arduino's I2S library is faster compared to the Adafruit_I2S library. Although I made this observation by looking at the output of Serial.plotter
as shown below.
Output of Arduino serial monitor with Arduino's I2S library.
Output of Arduino serial monitor with Adafruit_I2S library.
I'm using the following code which is a adaptation of your code:
`
//enable/disable the part of code that is involved with SD card actions bool SDENABLE = 0;
//audio intake settings.
int32_t audiosamples = 128; //128 because 512B/4B = 32B. 512B is what we can write in one block of the SD card. 4B is the size of the variable
// The I2S interface with the Mic using Adafruit Library. Adafruit_ZeroI2S i2s;
//for sd card const int chipSelect = 4; const int writeIndicator = 8;
void setup() { // Open serial communications and wait for port to open: // Configure serial port. Serial.begin(115200); Serial.println("Zero I2S Audio Tone Generator");
// Initialize the I2S transmitter. if (!i2s.begin(I2S_32_BIT, SAMPLERATE_HZ)) { Serial.println("Failed to initialize I2S transmitter!"); while (1); }
// Enable receive PIN 11 for Digital Output. i2s.enableRx(); pinMode(11, OUTPUT);
//LED to indicate correct writing
pinMode(writeIndicator,OUTPUT);
if(SDENABLE){
//check SD card status
if(!SD.begin(chipSelect)){
Serial.println("Card failed, or not present");
//don't do anything more
while(1);
}
Serial.println("Card Initialised");
}
}
void loop() {
// This is a stereo Mic. But we'll only read from LEFT channel
//digitalWrite(11, LOW);
float sound;
int32_t left,right;
int i;
int sample=0;
// Read a bunch of samples!!! int32_t samples[audiosamples]; //char charSamples[audiosamples];
for (int i = 0; i < audiosamples; i++) { i2s.read(&left, &right); //delay(1); // Workaround delay to prevent oversizing the buffer sample = left; //Serial.println(sample); // convert to 18 bit signed //sample >>= 14; //samples[i] = abs(sample); Serial.println(sample); samples[i] = sample;
} if(SDENABLE){ //store data in SD card; File dataFile = SD.open("datalog.dat",FILE_WRITE);
//if file is available, write to it
if(dataFile){
dataFile.write((const uint8_t *)&samples, sizeof(samples));
dataFile.close();
digitalWrite(writeIndicator, HIGH);
}
} }`
Why is the Serial.monitor showing a slowed down version for the Adafruit_I2S microphone?
I wonder why Adafruit_ZeroDMA is trying to redefine DMAC_Handler when it was previously defined by the I2S library. The Adafruit-samd v1.5.2 includes both I2S and SPI libraries. It is actually the SPI one which includes Adafruit_ZeroDMA.
I'm wondering whether any fix could be applied so both I2S and SPI could be included in a sketch for Arduinocore-samd v1.5.2, or whether Adafruit_ZeroDMA could check and reuse DMAC_Handler if it was previously defined.
Below the steps to reproduce.