Adafruit I2S MEMS Microphone interface with nRF5340 DK

Hi,

I am trying to connect and acquire the signal from the Adafruit I2S MEMS Microphone using I2s communication with my board (nRF5340 DK). Because I am new in this controller, I was looking to use a sample program as a starting point, specifically the I2S ECHO SAMPLE (https://docs.zephyrproject.org/latest/samples/drivers/i2s/echo/README.html).

What should I change in this code for making it work? I am aware my board doesn't have the audio CODEC (WM8731), therefore when running it fails. Is there maybe another sample more adjusted for my needs?

Thanks.

Parents
  • Hi

    The I2S Echo sample is probably the best starting point, but I would recommend having a look at the nRF5340 Audio application, specifically how it sets up an audio stream with I2S and how it deals with the audio codec:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/applications/nrf5340_audio/README.html

    Let me know if you get stuck on anything specific.

    Best regards,

    Einar 

  • Hello,

    Sorry for the late response, I tried many different ways but still I can't make it work.

    I checked the nRF5340 Audio example, and came to the conclusion there is no need for the audio codec in my case, since I don't have to process any data, I just have to collect it from the I2S interface.

    I modified the I2S echo sample, my goal is just to print the audio data from the I2S MEMS microphone (SPH0645):

    /*
     * Copyright (c) 2021 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/drivers/i2s.h>
    #include <zephyr/drivers/gpio.h>
    #include <string.h>
    
    
    #if DT_NODE_EXISTS(DT_NODELABEL(i2s_rxtx))
    #define I2S_RX_NODE  DT_NODELABEL(i2s_rxtx)
    #define I2S_TX_NODE  I2S_RX_NODE
    #else
    #define I2S_RX_NODE  DT_NODELABEL(i2s_rx)
    #define I2S_TX_NODE  DT_NODELABEL(i2s_tx)
    #endif
    
    #define SAMPLE_FREQUENCY    44100 //-> 44100kHz
    #define SAMPLE_BIT_WIDTH    24 
    #define BYTES_PER_SAMPLE    sizeof(int32_t)//32 bits
    #define NUMBER_OF_CHANNELS  1 //1
    /* Such block length provides an echo with the delay of 100 ms. */
    #define SAMPLES_PER_BLOCK   ((SAMPLE_FREQUENCY / 10) * NUMBER_OF_CHANNELS)
    #define INITIAL_BLOCKS      2
    #define TIMEOUT             1000
    
    #define BLOCK_SIZE  (BYTES_PER_SAMPLE * SAMPLES_PER_BLOCK)
    #define BLOCK_COUNT (INITIAL_BLOCKS + 2)
    K_MEM_SLAB_DEFINE_STATIC(mem_slab, BLOCK_SIZE, BLOCK_COUNT, 4);
    
    static K_SEM_DEFINE(toggle_transfer, 1, 1);
    
    static bool configure_streams(const struct device *i2s_dev_rx,
    			      const struct i2s_config *config)
    {
    	int ret;
    	ret = i2s_configure(i2s_dev_rx, I2S_DIR_RX, config);
    	if (ret < 0) {
    		printk("Failed to configure RX stream: %d\n", ret);
    		return false;
    	}
    	return true;
    }
    
    int main(void)
    {
    	int ret;
    	const struct device *const i2s_dev_rx = DEVICE_DT_GET(I2S_RX_NODE);
    	struct i2s_config config;
    	printk("I2S echo sample\n");
    	if (!device_is_ready(i2s_dev_rx)) {
    		printk("%s is not ready\n", i2s_dev_rx->name);
    		return 0;
    	}
    	config.word_size = SAMPLE_BIT_WIDTH;
    	config.channels = NUMBER_OF_CHANNELS;
    	config.format = I2S_FMT_DATA_FORMAT_I2S;
    	config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
    	config.frame_clk_freq = SAMPLE_FREQUENCY;
    	config.mem_slab = &mem_slab;
    	config.block_size = BLOCK_SIZE;
    	config.timeout = TIMEOUT;
    	if (!configure_streams(i2s_dev_rx, &config)) {
    		return 0;
    	}
    
    	printk("Streams started\n");
    	for (;;) {
    		k_sem_take(&toggle_transfer, K_FOREVER); //Bloquea hasta que esta disponible
    		ret = i2s_trigger(i2s_dev_rx, I2S_DIR_RX, I2S_TRIGGER_START);
    		if (ret != 0) {
    			printk("i2s_trigger failed with %d error\n", ret);
    			return 0;
    		}
    		while (k_sem_take(&toggle_transfer, K_NO_WAIT) != 0) {
    			void *mem_block;
    			uint32_t block_size;
    			ret = i2s_read(i2s_dev_rx, &mem_block, &block_size);
    			if (ret < 0) {
    				printk("Failed to read data: %d\n", ret);
    				break;
    			}
    			unsigned int* value_ptr = (unsigned int*)mem_block;
        		unsigned int value = *value_ptr;
       			printk("Received audio data: %u\n", value);
    		}
    	}
    	return 0;
    }

    My overlay file is the following one: 

    /*
     * Copyright (c) 2021 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
     &pinctrl {
    	i2s0_default_alt: i2s0_default_alt {
    		group1 {
    			psels = <NRF_PSEL(I2S_SCK_M, 0, 7)>,
    				<NRF_PSEL(I2S_LRCK_M, 0, 12)>,
    				//<NRF_PSEL(I2S_SDOUT, 1, 13)>,
    				<NRF_PSEL(I2S_SDIN, 1, 6)>;
    		};
    	};
    };
    
    &clock {
    	hfclkaudio-frequency = <11289600>;
    };
    
    i2s_rxtx: &i2s0 {
    	status = "okay";
    	pinctrl-0 = <&i2s0_default_alt>;
    	pinctrl-names = "default";
    	clock-source = "ACLK";
    };
    &arduino_adc {
    	io-channel-map = <0 &adc 0>, <1 &adc 1>, <2 &adc 2>, <3 &adc 3>, <4 &adc 4>, <5 &adc 5>;
    };
    
    &arduino_header {
    	gpio-map = <0 0 &gpio0 4 0>,
    			   <1 0 &gpio0 5 0>,
    			   <2 0 &gpio0 6 0>,
    			   <3 0 &gpio0 7 0>,
    			   <4 0 &gpio0 25 0>,
    			   <5 0 &gpio0 26 0>,
    			   <6 0 &gpio1 0 0>,
    			   <7 0 &gpio1 1 0>,
    			   <8 0 &gpio1 4 0>,
    			   <9 0 &gpio1 5 0>,
    			   <10 0 &gpio1 6 0>,
    			   <11 0 &gpio1 7 0>,
    			   <12 0 &gpio1 8 0>,
    			   <13 0 &gpio1 9 0>,
    			   <14 0 &gpio1 10 0>,
    			   <15 0 &gpio1 11 0>,
    			   <16 0 &gpio1 12 0>,
    			   <17 0 &gpio1 13 0>,
    			   <18 0 &gpio1 14 0>,
    			   <19 0 &gpio1 15 0>,
    			   <20 0 &gpio1 2 0>,
    			   <21 0 &gpio1 3 0>;
    };
    

    And in my prj.conf I only have this line: 

    CONFIG_I2S=y
    I expected a continous output with the values of what the MEMS microphone detects, but all I get is this:
    *** Booting Zephyr OS build v3.3.99-ncs1 ***
    I2S echo sample
    Streams started
    Received audio data: 0
    Received audio data: 0
    Received audio data: 0
    Received audio data: 0
    Failed to read data: -5


    The microphone works well, it worked in another controller. I don't know what I am doing wrong, it looks like it doesn't detect the microphone...
    Thank you in advance. 
     
  • I would suggest you try to make the unmodified sample work, only changing the overlay to match your hardware, before you start modifying the sample code.

    The sample already supports nRF5340 after all.

    It's much easier to debug that way.

    -Einar

  • Hi,

    I downloaded the sample again and I only took the codec part out. This time I checked with an oscilloscope the I2S signals and after configuring it properly for my MEMS microphone, the signals are all correct.

    However now I would like to print in the serial port the audio values, but couldn't manage to find the way. I took a look on the i2s_read() and i2s_write() but after checking the documentation I think is not what I need.  Could you suggest one function such as i2s_pop_sample() -from the Arduino library driver/i2s.h.

    I will leave the MEMS microphone configuration for other users:

    &pinctrl {
    	i2s0_default_alt: i2s0_default_alt {
    		group1 {
    			psels = <NRF_PSEL(I2S_SCK_M, 0, 7)>,
    				<NRF_PSEL(I2S_LRCK_M, 0, 12)>,
    				<NRF_PSEL(I2S_SDIN, 1, 06)>;
    		};
    	};
    };
    
    
    &clock {
    	hfclkaudio-frequency = <11289600>;
    };
    
    i2s_rxtx: &i2s0 {
    	status = "okay";
    	pinctrl-0 = <&i2s0_default_alt>;
    	pinctrl-names = "default";
    	clock-source = "ACLK";
    };

    #define SAMPLE_FREQUENCY    44100
    #define SAMPLE_BIT_WIDTH    32
    #define BYTES_PER_SAMPLE    sizeof(int16_t)
    #define NUMBER_OF_CHANNELS  1
    /* Such block length provides an echo with the delay of 100 ms. */
    #define SAMPLES_PER_BLOCK   ((SAMPLE_FREQUENCY / 10) * NUMBER_OF_CHANNELS)
    #define INITIAL_BLOCKS      2
    #define TIMEOUT             1000
    

Reply Children
No Data
Related