Arduino Wiring & Test

The classic ATmega328P-based Arduino's like the UNO and Metro 328 don't have I2S interfaces, so you can't use this breakout with them

But the newer ATSAMD21-based boards like the Zero, Metro M0, Feather M0 can! (Note, Gemma M0 & Trinket M0 do not have I2S pins available).

You may want to check your board documentation to determine where the I2S interface is. We'll use the Metro M0 pinout:

  • LRCLK / WSEL on Digital #0
  • BCLK on Digital #1
  • DATA IN on Digital #9

Then power from 3.3V + Ground as usual:

We can then run this demo which will generate a sine wave on both left and right channels. Try tweaking the sample rate, amplitude and frequency, see how the quality and volume changes!

 This example generates a sine wave based tone at a specified frequency
 and sample rate. Then outputs the data using the I2S interface.

 Public Domain

#include <I2S.h>

#define FREQUENCY    440  // frequency of sine wave in Hz
#define AMPLITUDE  10000  // amplitude of sine wave
#define SAMPLERATE 44100  // sample rate in Hz

int16_t sinetable[SAMPLERATE / FREQUENCY];
uint32_t sample = 0;

#define PI 3.14159265

void setup() {
  Serial.println("I2S sine wave tone");

  // start I2S at the sample rate with 16-bits per sample
  if (!I2S.begin(I2S_PHILIPS_MODE, SAMPLERATE, 16)) {
    Serial.println("Failed to initialize I2S!");
    while (1); // do nothing

  // fill in sine wave table
  for (uint16_t s=0; s < (SAMPLERATE / FREQUENCY); s++) {
    sinetable[s] = sin(2.0 * PI * s / (SAMPLERATE/FREQUENCY)) * AMPLITUDE;

void loop() {
  if (sample == (SAMPLERATE / FREQUENCY)) {
    sample = 0;

  // write the same sample twice, once for left and once for the right channel
  I2S.write((int16_t) sinetable[sample]);  // We'll just have same tone on both!
  I2S.write((int16_t) sinetable[sample]);

  // increment the counter for the next sample in the sine wave table
Last updated on Nov 21, 2017 Published on Nov 21, 2017