ported to Circuit Python
This commit is contained in:
parent
b60ca2cf02
commit
03f41f6aca
3 changed files with 428 additions and 0 deletions
|
|
@ -0,0 +1,232 @@
|
||||||
|
/*
|
||||||
|
LED VU meter for Arduino and Adafruit NeoPixel LEDs.
|
||||||
|
|
||||||
|
Hardware requirements:
|
||||||
|
- Most Arduino or Arduino-compatible boards (ATmega 328P or better).
|
||||||
|
- 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 from code by Greg Shakar
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define N_PIXELS 16 // Number of pixels in strand
|
||||||
|
#define MIC_PIN A1 // Microphone is attached to this analog pin
|
||||||
|
#define LED_PIN 1 // NeoPixel LED strand is connected to this pin
|
||||||
|
#define SAMPLE_WINDOW 10 // Sample window for average level
|
||||||
|
#define PEAK_HANG 24 //Time of pause before peak dot falls
|
||||||
|
#define PEAK_FALL 4 //Rate of falling peak dot
|
||||||
|
#define INPUT_FLOOR 10 //Lower range of analogRead input
|
||||||
|
#define INPUT_CEILING 300 //Max range of analogRead input, the lower the value the more sensitive (1023 = max)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
byte peak = 16; // Peak level of column; used for falling dots
|
||||||
|
unsigned int sample;
|
||||||
|
|
||||||
|
byte dotCount = 0; //Frame counter for peak dot
|
||||||
|
byte dotHangCount = 0; //Frame counter for holding peak dot
|
||||||
|
|
||||||
|
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// This is only needed on 5V Arduinos (Uno, Leonardo, etc.).
|
||||||
|
// Connect 3.3V to mic AND TO AREF ON ARDUINO and enable this
|
||||||
|
// line. Audio samples are 'cleaner' at 3.3V.
|
||||||
|
// COMMENT OUT THIS LINE FOR 3.3V ARDUINOS (FLORA, ETC.):
|
||||||
|
// analogReference(EXTERNAL);
|
||||||
|
|
||||||
|
// Serial.begin(9600);
|
||||||
|
strip.begin();
|
||||||
|
strip.show(); // Initialize all pixels to 'off'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
unsigned long startMillis= millis(); // Start of sample window
|
||||||
|
float peakToPeak = 0; // peak-to-peak level
|
||||||
|
|
||||||
|
unsigned int signalMax = 0;
|
||||||
|
unsigned int signalMin = 1023;
|
||||||
|
unsigned int c, y;
|
||||||
|
|
||||||
|
|
||||||
|
// collect data for length of sample window (in mS)
|
||||||
|
while (millis() - startMillis < SAMPLE_WINDOW)
|
||||||
|
{
|
||||||
|
sample = analogRead(MIC_PIN);
|
||||||
|
if (sample < 1024) // toss out spurious readings
|
||||||
|
{
|
||||||
|
if (sample > signalMax)
|
||||||
|
{
|
||||||
|
signalMax = sample; // save just the max levels
|
||||||
|
}
|
||||||
|
else if (sample < signalMin)
|
||||||
|
{
|
||||||
|
signalMin = sample; // save just the min levels
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude
|
||||||
|
|
||||||
|
// Serial.println(peakToPeak);
|
||||||
|
|
||||||
|
|
||||||
|
//Fill the strip with rainbow gradient
|
||||||
|
for (int i=0;i<=strip.numPixels()-1;i++){
|
||||||
|
strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Scale the input logarithmically instead of linearly
|
||||||
|
c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(c < peak) {
|
||||||
|
peak = c; // Keep dot on top
|
||||||
|
dotHangCount = 0; // make the dot hang before falling
|
||||||
|
}
|
||||||
|
if (c <= strip.numPixels()) { // Fill partial column with off pixels
|
||||||
|
drawLine(strip.numPixels(), strip.numPixels()-c, strip.Color(0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the peak dot to match the rainbow gradient
|
||||||
|
y = strip.numPixels() - peak;
|
||||||
|
|
||||||
|
strip.setPixelColor(y-1,Wheel(map(y,0,strip.numPixels()-1,30,150)));
|
||||||
|
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
// Frame based peak dot animation
|
||||||
|
if(dotHangCount > PEAK_HANG) { //Peak pause length
|
||||||
|
if(++dotCount >= PEAK_FALL) { //Fall rate
|
||||||
|
peak++;
|
||||||
|
dotCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dotHangCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Used to draw a line between two points of a given color
|
||||||
|
void drawLine(uint8_t from, uint8_t to, uint32_t c) {
|
||||||
|
uint8_t fromTemp;
|
||||||
|
if (from > to) {
|
||||||
|
fromTemp = from;
|
||||||
|
from = to;
|
||||||
|
to = fromTemp;
|
||||||
|
}
|
||||||
|
for(int i=from; i<=to; i++){
|
||||||
|
strip.setPixelColor(i, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float fscale( float originalMin, float originalMax, float newBegin, float
|
||||||
|
newEnd, float inputValue, float curve){
|
||||||
|
|
||||||
|
float OriginalRange = 0;
|
||||||
|
float NewRange = 0;
|
||||||
|
float zeroRefCurVal = 0;
|
||||||
|
float normalizedCurVal = 0;
|
||||||
|
float rangedValue = 0;
|
||||||
|
boolean invFlag = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// condition curve parameter
|
||||||
|
// limit range
|
||||||
|
|
||||||
|
if (curve > 10) curve = 10;
|
||||||
|
if (curve < -10) curve = -10;
|
||||||
|
|
||||||
|
curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
|
||||||
|
curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function
|
||||||
|
|
||||||
|
/*
|
||||||
|
Serial.println(curve * 100, DEC); // multply by 100 to preserve resolution
|
||||||
|
Serial.println();
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t Wheel(byte WheelPos) {
|
||||||
|
if(WheelPos < 85) {
|
||||||
|
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
|
||||||
|
}
|
||||||
|
else if(WheelPos < 170) {
|
||||||
|
WheelPos -= 85;
|
||||||
|
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WheelPos -= 170;
|
||||||
|
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
192
3D_Printed_LED_Microphone_Flag/3D_Printed_LED_Microphone_Flag.py
Normal file
192
3D_Printed_LED_Microphone_Flag/3D_Printed_LED_Microphone_Flag.py
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
# 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 board
|
||||||
|
import neopixel
|
||||||
|
import time
|
||||||
|
from analogio import AnalogIn
|
||||||
|
import array
|
||||||
|
|
||||||
|
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
|
||||||
|
input_ceiling = 300 # Max range of analogRead input, the lower the value the more sensitive (1023 = max)
|
||||||
|
|
||||||
|
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 wheel(pos):
|
||||||
|
# Input a value 0 to 255 to get a color value.
|
||||||
|
# The colours are a transition r - g - b - back to r.
|
||||||
|
if (pos < 0) or (pos > 255):
|
||||||
|
return (0, 0, 0)
|
||||||
|
if (pos < 85):
|
||||||
|
return (int(pos * 3), int(255 - (pos*3)), 0)
|
||||||
|
elif (pos < 170):
|
||||||
|
pos -= 85
|
||||||
|
return (int(255 - pos*3), 0, int(pos*3))
|
||||||
|
else:
|
||||||
|
pos -= 170
|
||||||
|
return (0, int(pos*3), int(255 - pos*3))
|
||||||
|
|
||||||
|
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):
|
||||||
|
originalrange = 0
|
||||||
|
newrange = 0
|
||||||
|
zerorefcurval = 0
|
||||||
|
normalizedcurval = 0
|
||||||
|
rangedvalue = 0
|
||||||
|
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)
|
||||||
|
curve = pow(10, curve) # convert linear scale into lograthimic exponent for other pow function
|
||||||
|
|
||||||
|
# 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
|
||||||
|
normalizedcurval = zerorefcurval / originalrange # normalize to 0 - 1 float
|
||||||
|
|
||||||
|
# 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):
|
||||||
|
|
||||||
|
fromheretemp = 0
|
||||||
|
|
||||||
|
if (fromhere > to):
|
||||||
|
fromheretemp = fromhere
|
||||||
|
fromhere = to
|
||||||
|
to = fromheretemp
|
||||||
|
|
||||||
|
for i in range(fromhere, to):
|
||||||
|
strip[i] = (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):
|
||||||
|
|
||||||
|
sample = mic_pin.value / 64 # convert to arduino 10-bit [1024] fromhere 16-bit [65536]
|
||||||
|
|
||||||
|
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] = wheel(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, wheel(remapRange(y, 0, (n_pixels - 1), 30, 150)))
|
||||||
|
strip.write()
|
||||||
|
|
||||||
|
# Frame based peak dot animation
|
||||||
|
if(dothangcount > peak_hang): # Peak pause length
|
||||||
|
if(++dotcount >= peak_fall): # Fall rate
|
||||||
|
peak += 1
|
||||||
|
dotcount = 0
|
||||||
|
else:
|
||||||
|
dothangcount += 1
|
||||||
4
3D_Printed_LED_Microphone_Flag/README.md
Normal file
4
3D_Printed_LED_Microphone_Flag/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# 3D_Printed_LED_Microphone_Flag
|
||||||
|
|
||||||
|
Code to accompany this tutorial:
|
||||||
|
https://learn.adafruit.com/3d-printed-led-microphone-flag
|
||||||
Loading…
Reference in a new issue