CircuitPython 3.0 and higher has I2S built in which means you can use this breakout super easily with the supported M0 and M4 Express CircuitPython boards! Supported boards are Feather M0 Express, Feather M4 Express, Metro M0 Express, Metro M4 Express, and ItsyBitsy M0 Express.
Note that Trinket M0, Gemma M0 and ItsyBitsy M4 do not support I2S (the last one is not a typo!)
The M0 boards have multiple I2S pin combinations available. We're going to demonstrate a single pin combination for each board.
Wiring
The following wiring diagrams show how to connect the MAX98357 breakout to your CircuitPython board. You'll be using voltage in, ground, bit clock, left/right clock and data pins.
- VIN is the red wire.
- GND is the black wire.
- BCLK is the blue wire.
- LRC is the yellow wire.
- DIN is the green wire.
For Feather M0 Express, ItsyBitsy M0 Express and Metro M0 Express:
- Connect VIN on the breakout to 3V/3.3 on the board.
- Connect GND on the breakout to G/GND on the board.
- Connect BCLK on the breakout to D1/TX on the board.
- Connect LRC on the breakout to D0/RX on the board.
- Connect DIN on the breakout to D9 on the board.
For Feather M4 Express:
- Connect VIN on the breakout to 3V on the board.
- Connect GND on the breakout to Gnd on the board.
- Connect BCLK on the breakout to TX on the board.
- Connect LRC on the breakout to D10 on the board.
- Connect DIN on the breakout to D11 on the board.
For Metro M4 Express:
- Connect VIN on the breakout to 3.3 on the board.
- Connect GND on the breakout to GND on the board.
- Connect BCLK on the breakout to D3 on the board.
- Connect LRC on the breakout to D9 on the board.
- Connect DIN on the breakout to D8 on the board.
Code Examples
We have two CircuitPython code examples. The first plays a generated tone through the speaker on the breakout. The second plays a wave file. Let's take a look!
Tone Generation
The first example generates one period of a sine wave and then loops it to generate a tone. You can change the volume and the Hz of the tone by changing the associated variables. Inside the loop, we play the tone for one second and stop it for one second.
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries # # SPDX-License-Identifier: MIT import time import array import math import audiocore import board import audiobusio sample_rate = 8000 tone_volume = .1 # Increase or decrease this to adjust the volume of the tone. frequency = 440 # Set this to the Hz of the tone you want to generate. length = sample_rate // frequency # One freqency period sine_wave = array.array("H", [0] * length) for i in range(length): sine_wave[i] = int((math.sin(math.pi * 2 * frequency * i / sample_rate) * tone_volume + 1) * (2 ** 15 - 1)) # For Feather M0 Express, ItsyBitsy M0 Express, Metro M0 Express audio = audiobusio.I2SOut(board.D1, board.D0, board.D9) # For Feather M4 Express # audio = audiobusio.I2SOut(board.D1, board.D10, board.D11) # For Metro M4 Express # audio = audiobusio.I2SOut(board.D3, board.D9, board.D8) sine_wave_sample = audiocore.RawSample(sine_wave, sample_rate=sample_rate) while True: audio.play(sine_wave_sample, loop=True) time.sleep(1) audio.stop() time.sleep(1)
For Feather M0 Express, ItsyBitsy M0 Express and Metro M0 Express, no changes are needed for the code to work.
For Feather M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)
and uncomment # audio = audiobusio.I2SOut(board.D1, board.D10, board.D11)
.
For Metro M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)
and uncomment # audio = audiobusio.I2SOut(board.D3, board.D3, board.D8)
.
Now you'll hear one second of a 440Hz tone, and one second of silence.
You can try changing the Hz of the tone to produce different tones. Try changing the number of seconds in time.sleep()
to produce longer or shorter tones.
Wave File
The second example plays a wave file. We open the file in a readable format. Then inside the loop, we play the file and tell the code to continue playing the file until it's completed. You can use any supported wave file. We've included the wave file used in the code.
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries # # SPDX-License-Identifier: MIT import audiocore import board import audiobusio wave_file = open("StreetChicken.wav", "rb") wave = audiocore.WaveFile(wave_file) # For Feather M0 Express, ItsyBitsy M0 Express, Metro M0 Express audio = audiobusio.I2SOut(board.D1, board.D0, board.D9) # For Feather M4 Express # audio = audiobusio.I2SOut(board.D1, board.D10, board.D11) # For Metro M4 Express # audio = audiobusio.I2SOut(board.D3, board.D9, board.D8) while True: audio.play(wave) while audio.playing: pass
The object setup in the code is the same as above.
For Feather M0 Express, ItsyBitsy M0 Express and Metro M0 Express, no changes are needed for the code to work.
For Feather M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)
and uncomment # audio = audiobusio.I2SOut(board.D1, board.D10, board.D11)
.
For Metro M4 Express, comment out audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)
and uncomment # audio = audiobusio.I2SOut(board.D3, board.D3, board.D8)
.
Now you'll hear the wave file play through and loop.
There's plenty you can do with this example. Try playing a different wave file, or, instead of including while audio.playing: pass
, include a time.sleep()
to have it play for a specified number of seconds. Check out the Audio Out page in the CircuitPython Essentials guide for pause
and resume
features.
Where's my I2S?
We mentioned earlier that the supported M0 boards have multiple I2S pin combinations available to you. The M4 boards have one option. Either way, if you'd like to know what options are available to you, copy the following code into your code.py, connect to the serial console, and check out the output.
These are the results from the ItsyBitsy M0 Express.
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries # # SPDX-License-Identifier: MIT import board import audiobusio from microcontroller import Pin def is_hardware_i2s(bit_clock, word_select, data): try: p = audiobusio.I2SOut(bit_clock, word_select, data) p.deinit() return True except ValueError: return False def get_unique_pins(): exclude = ['NEOPIXEL', 'APA102_MOSI', 'APA102_SCK'] pins = [pin for pin in [ getattr(board, p) for p in dir(board) if p not in exclude] if isinstance(pin, Pin)] unique = [] for p in pins: if p not in unique: unique.append(p) return unique for bit_clock_pin in get_unique_pins(): for word_select_pin in get_unique_pins(): for data_pin in get_unique_pins(): if bit_clock_pin is word_select_pin or bit_clock_pin is data_pin or word_select_pin\ is data_pin: continue if is_hardware_i2s(bit_clock_pin, word_select_pin, data_pin): print("Bit clock pin:", bit_clock_pin, "\t Word select pin:", word_select_pin, "\t Data pin:", data_pin) else: pass
Text editor powered by tinymce.