GEMMA M0 boards can run CircuitPython — a different approach to programming compared to Arduino sketches. In fact, CircuitPython comes factory pre-loaded on GEMMA M0. If you’ve overwritten it with an Arduino sketch, or just want to learn the basics of setting up and using CircuitPython, this is explained in the Adafruit GEMMA M0 guide.
Below is CircuitPython code that works similarly (though not exactly the same) as the Arduino sketch shown on a prior page. To use this, plug the GEMMA M0 into USB…it should show up on your computer as a small flash drive…then edit the file “code.py” with your text editor of choice. Select and copy the code below and paste it into that file, entirely replacing its contents (don’t mix it in with lingering bits of old code). When you save the file, the code should start running almost immediately (if not, see notes at the bottom of this page).
If GEMMA M0 doesn’t show up as a drive, follow the GEMMA M0 guide link above to prepare the board for CircuitPython.
# SPDX-FileCopyrightText: 2013 Phil Burgess for Adafruit Industries # SPDX-FileCopyrightText: 2017 Mikey Sklar for Adafruit Industries # # SPDX-License-Identifier: BSD-3-Clause # LED VU meter for Arduino and Adafruit NeoPixel LEDs. # Hardware requirements: # - M0 boards # - Adafruit Electret Microphone Amplifier (ID: 1063) # - Adafruit Flora RGB Smart Pixels (ID: 1260) # OR # - Adafruit NeoPixel Digital LED strip (ID: 1138) # - Optional: battery for portable use (else power through USB or adapter) # Software requirements: # - Adafruit NeoPixel library # Connections: # - 3.3V to mic amp + # - GND to mic amp - # - Analog pin to microphone output (configurable below) # - Digital pin to LED data input (configurable below) # See notes in setup() regarding 5V vs. 3.3V boards - there may be an # extra connection to make and one line of code to enable or disable. # Written by Adafruit Industries. Distributed under the BSD license. # This paragraph must be included in any redistribution. # fscale function: # Floating Point Autoscale Function V0.1 # Written by Paul Badger 2007 # Modified fromhere code by Greg Shakar # Ported to Circuit Python by Mikey Sklar import time import board import neopixel from rainbowio import colorwheel from analogio import AnalogIn n_pixels = 16 # Number of pixels you are using mic_pin = AnalogIn(board.A1) # Microphone is attached to this analog pin led_pin = board.D1 # NeoPixel LED strand is connected to this pin sample_window = .1 # Sample window for average level peak_hang = 24 # Time of pause before peak dot falls peak_fall = 4 # Rate of falling peak dot input_floor = 10 # Lower range of analogRead input # Max range of analogRead input, the lower the value the more sensitive # (1023 = max) input_ceiling = 300 peak = 16 # Peak level of column; used for falling dots sample = 0 dotcount = 0 # Frame counter for peak dot dothangcount = 0 # Frame counter for holding peak dot strip = neopixel.NeoPixel(led_pin, n_pixels, brightness=1, auto_write=False) def remapRange(value, leftMin, leftMax, rightMin, rightMax): # this remaps a value fromhere original (left) range to new (right) range # Figure out how 'wide' each range is leftSpan = leftMax - leftMin rightSpan = rightMax - rightMin # Convert the left range into a 0-1 range (int) valueScaled = int(value - leftMin) / int(leftSpan) # Convert the 0-1 range into a value in the right range. return int(rightMin + (valueScaled * rightSpan)) def fscale(originalmin, originalmax, newbegin, newend, inputvalue, curve): invflag = 0 # condition curve parameter # limit range if curve > 10: curve = 10 if curve < -10: curve = -10 # - invert and scale - # this seems more intuitive # postive numbers give more weight to high end on output curve = (curve * -.1) # convert linear scale into lograthimic exponent for other pow function curve = pow(10, curve) # Check for out of range inputValues if inputvalue < originalmin: inputvalue = originalmin if inputvalue > originalmax: inputvalue = originalmax # Zero Refference the values originalrange = originalmax - originalmin if newend > newbegin: newrange = newend - newbegin else: newrange = newbegin - newend invflag = 1 zerorefcurval = inputvalue - originalmin # normalize to 0 - 1 float normalizedcurval = zerorefcurval / originalrange # Check for originalMin > originalMax # -the math for all other cases # i.e. negative numbers seems to work out fine if originalmin > originalmax: return 0 if invflag == 0: rangedvalue = (pow(normalizedcurval, curve) * newrange) + newbegin else: # invert the ranges rangedvalue = newbegin - (pow(normalizedcurval, curve) * newrange) return rangedvalue def drawLine(fromhere, to): if fromhere > to: to, fromhere = fromhere, to for index in range(fromhere, to): strip[index] = (0, 0, 0) while True: time_start = time.monotonic() # current time used for sample window peaktopeak = 0 # peak-to-peak level signalmax = 0 signalmin = 1023 c = 0 y = 0 # collect data for length of sample window (in seconds) while (time.monotonic() - time_start) < sample_window: # convert to arduino 10-bit [1024] fromhere 16-bit [65536] sample = mic_pin.value / 64 if sample < 1024: # toss out spurious readings if sample > signalmax: signalmax = sample # save just the max levels elif sample < signalmin: signalmin = sample # save just the min levels peaktopeak = signalmax - signalmin # max - min = peak-peak amplitude # Fill the strip with rainbow gradient for i in range(0, len(strip)): strip[i] = colorwheel(remapRange(i, 0, (n_pixels - 1), 30, 150)) # Scale the input logarithmically instead of linearly c = fscale(input_floor, input_ceiling, (n_pixels - 1), 0, peaktopeak, 2) if c < peak: peak = c # keep dot on top dothangcount = 0 # make the dot hang before falling if c <= n_pixels: # fill partial column with off pixels drawLine(n_pixels, n_pixels - int(c)) # Set the peak dot to match the rainbow gradient y = n_pixels - peak strip.fill = (y - 1, colorwheel(remapRange(y, 0, (n_pixels - 1), 30, 150))) strip.write() # Frame based peak dot animation if dothangcount > peak_hang: # Peak pause length dotcount += 1 if dotcount >= peak_fall: # Fall rate peak += 1 dotcount = 0 else: dothangcount += 1
This code requires the neopixel.py library. A factory-fresh board will have this already installed. If you’ve just reloaded the board with CircuitPython, create the “lib” directory and then download neopixel.py from Github.
Page last edited January 22, 2025
Text editor powered by tinymce.