37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目三十二:使用FFT库的迷你音乐频谱仪(声谱可视化器)
实验接线方法: max9814接A0
oled模块 Ardunio Uno
GND---------GND接地线
VCC---------5V 接电源
SDA---------A4
SCL ------- A5
实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目三十二:使用FFT库的迷你音乐频谱仪(声谱可视化器)
实验接线方法: max9814接A0
oled模块 Ardunio Uno
GND---------GND接地线
VCC---------5V 接电源
SDA---------A4
SCL ------- A5
*/
#include "arduinoFFT.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SAMPLES 64 // power of 2
#define SAMPLING_FREQ 8000 // 12 kHz Fmax = sampleF /2
#define AMPLITUDE 150 // 灵敏度
#define FREQUENCY_BANDS 14
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define BARWIDTH 11
#define BARS 11
#define ANALOG_PIN A0
#define OLED_RESET -1 // 重置引脚 #(如果共享 Arduino 重置引脚,则为 -1)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
double vImag[SAMPLES];
double vReal[SAMPLES];
unsigned long sampling_period_us;
arduinoFFT fft = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);
//调整参考以去除背景噪声
float reference = log10(80.0);
double coutoffFrequencies[FREQUENCY_BANDS];
void setup() {
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
for (;;); // Don't proceed, loop forever
}
// Setup display
display.clearDisplay();
display.display();
display.setRotation(0);
display.invertDisplay(false);
sampling_period_us = (1.0 / SAMPLING_FREQ ) * pow(10.0, 6);
// 计算截止频率,以对数标度为基数 POt
double basePot = pow(SAMPLING_FREQ / 2.0, 1.0 / FREQUENCY_BANDS);
coutoffFrequencies[0] = basePot;
for (int i = 1 ; i < FREQUENCY_BANDS; i++ ) {
coutoffFrequencies[i] = basePot * coutoffFrequencies[i - 1];
}
// 绘制虚线以分离频段
for (int i = 0; i < BARS - 1 ; i++) {
for (int j = 0; j < SCREEN_HEIGHT ; j += 4) {
display.writePixel((i + 1)*BARWIDTH + 2 , j, SSD1306_WHITE );
}
}
display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
}
int oldHeight[20];
int oldMax[20];
double maxInFreq;
void loop() {
// 采样
for (int i = 0; i < SAMPLES; i++) {
unsigned long newTime = micros();
int value = analogRead(ANALOG_PIN);
vReal[i] = value;
vImag[i] = 0;
while (micros() < (newTime + sampling_period_us)) {
yield();
}
}
// 计算 FFT
fft.DCRemoval();
fft.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
fft.Compute(FFT_FORWARD);
fft.ComplexToMagnitude();
double median[20];
double max[20];
int index = 0;
double hzPerSample = (1.0 * SAMPLING_FREQ) / SAMPLES; //
double hz = 0;
double maxinband = 0;
double sum = 0;
int count = 0;
for (int i = 2; i < (SAMPLES / 2) ; i++) {
count++;
sum += vReal[i];
if (vReal[i] > max[index] ) {
max[index] = vReal[i];
}
if (hz > coutoffFrequencies[index]) {
median[index] = sum / count;
sum = 0.0;
count = 0;
index++;
max[index] = 0;
median[index] = 0;
}
hz += hzPerSample;
}
// 计算每个频段的中值和最大值
if ( sum > 0.0) {
median[index] = sum / count;
if (median[index] > maxinband) {
maxinband = median[index];
}
}
int bar = 0;
for (int i = FREQUENCY_BANDS - 1; i >= 3; i--) {
int newHeight = 0;
int newMax = 0;
// 计算实际分贝
if (median[i] > 0 && max[i] > 0 ) {
newHeight = 20.0 * (log10(median[i] ) - reference);
newMax = 20.0 * (log10(max[i] ) - reference);
}
// 调整最小和最大级别
if (newHeight < 0 || newMax < 0) {
newHeight = 1;
newMax = 1;
}
if (newHeight >= SCREEN_HEIGHT - 2) {
newHeight = SCREEN_HEIGHT - 3;
}
if (newMax >= SCREEN_HEIGHT - 2) {
newMax = SCREEN_HEIGHT - 3;
}
int barX = bar * BARWIDTH + 5;
// 删除旧水平中位数
if (oldHeight[i] > newHeight) {
display.fillRect(barX, newHeight + 1, 7, oldHeight[i], SSD1306_BLACK);
}
// 删除旧的最大级别
if ( oldMax[i] > newHeight) {
for (int j = oldMax[i]; j > newHeight; j -= 2) {
display.drawFastHLine(barX , j, 7, SSD1306_BLACK);
}
}
// 绘制新的最大级别
for (int j = newMax; j > newHeight; j -= 2) {
display.drawFastHLine(barX , j, 7, SSD1306_WHITE);
}
// 绘制新的级别中位数
display.fillRect(barX , 1, 7, newHeight, SSD1306_WHITE);
oldMax[i] = newMax;
oldHeight[i] = newHeight;
bar++;
}
display.drawFastHLine(0 , SCREEN_HEIGHT - 1, SCREEN_WIDTH, SSD1306_WHITE);
display.display();
}
Arduino实验场景图
项目三十二:使用FFT库的迷你音乐频谱仪(声谱可视化器)(完整测试视频2分41秒)
https://v.youku.com/v_show/id_XNTgwNzU4MDIzNg==.html?spm=a2hcb.playlsit.page.1
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目三十三:Arduino OLED 频谱分析仪
Arduino实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目三十三:Arduino OLED 频谱分析仪
实验接线方法: max9814接A0
oled模块 Ardunio Uno
GND---------GND接地线
VCC---------5V 接电源
SDA---------A4
SCL ------- A5
*/
#include <fix_fft.h>
#include <ssd1306.h>
#include <nano_engine.h>
// These are user-adjustable
#define LOG_OUTPUT // Uncomment to enable logarithmic output (exchanges absolute resoluton for more readable output; may require different below params)
#define SAMPLING_FREQUENCY 15000 // Sampling frequency (Actual max measured frequency captured is half)
#define TIME_FACTOR 2 // Smoothing factor (lower is more dynamic, higher is smoother) ranging from 1 to 10+
#define SCALE_FACTOR 15 // Direct scaling factor (raise for higher bars, lower for shorter bars)
#ifdef LOG_OUTPUT
const float log_scale = 64. / log(64. / SCALE_FACTOR + 1.); // Attempts to create an equivalent to SCALE_FACTOR for log function
#endif
const float coeff = 1. / TIME_FACTOR; // Time smoothing coefficients (used to factor in previous data)
const float anti_coeff = (TIME_FACTOR - 1.) / TIME_FACTOR;
const unsigned int sampling_period_us = round(1000000 * (2.0 / SAMPLING_FREQUENCY)); // Sampling period (doubled to account for overclock)
int8_t data[64], buff[32]; // used to store FFT input/output and past data
unsigned long microseconds; // used for timekeeping
int summ, avg; // used for DC bias elimination
NanoEngine<TILE_32x32_MONO> engine; // declares nanoengine
void setup()
{
OSCCAL = 240; // Overclocks the MCU to around 30 MHz, set lower if this causes instability, raise if you can/want
ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear ADC prescaler bits
ADCSRA |= bit (ADPS2); // sets ADC clock in excess of 10kHz
ADCSRA |= bit (ADPS0);
ssd1306_128x64_i2c_init(); // initializes OLED
ssd1306_clearScreen(); // clears OLED
engine.begin(); // inititalizes nanoengine
};
void loop()
{
summ = 0;
for (int i = 0; i < 64; i++) {
microseconds = micros();
data[i] = ((analogRead(A0)) >> 2) - 128; // Fitting analogRead data (range:0 - 1023) to int8_t array (range:-128 - 127)
summ += data[i];
while (micros() < (microseconds + sampling_period_us)) { // Timing out uC ADC to fulfill sampling frequency requirement
}
}
// Eliminating remaining DC component (produces usable data in FFT bin #0, which is usually swamped by DC bias)
avg = summ / 64;
for (int i = 0; i < 64; i++) {
data[i] -= avg;
}
fix_fftr(data, 6, 0); // Performing real FFT
// Time smoothing by user-determined factor and user-determined scaling
for (int count = 0; count < 32; count++) {
if (data[count] < 0) data[count] = 0; // Eliminating negative output of fix_fftr
#ifdef LOG_OUTPUT
else data[count] = log_scale * log((float)(data[count] + 1)); // Logarithmic function equivalent to SCALING_FACTOR*log2(x+1)
#else
else data[count] *= SCALE_FACTOR; // Linear scaling up according to SCALE_FACTOR
#endif
data[count] = (float)buff[count] * anti_coeff + (float)data[count] * coeff; // Smoothing by factoring in past data
buff[count] = data[count]; // Storing current output as next frame's past data
if (data[count] > 63) data[count] = 63; // Capping output at screen height
}
// Output to SSD1306 using nanoengine canvas from library
engine.refresh(); // Mark entire screen to be refreshed
engine.canvas.clear(); // Clear canvas as previous data
for (int i = 0; i < 8; i++) {
engine.canvas.drawVLine(i * 4, 31 - (data[i] + 1), 31); // Draw to canvas data for lower-leftest sector (FFT bins 0 - 7, lower half)
}
engine.canvas.blt(0, 32); // Outputs canvas to OLED with an offset (x pixels, y pixels)
engine.canvas.clear();
for (int i = 0; i < 8; i++) {
if (data[i] > 31) engine.canvas.drawVLine(i * 4, 31 - (data[i] - 31), 31); // Draw to canvas data for upper-leftest sector (FFT bins 0 - 7, upper half)
}
engine.canvas.blt(0, 0);
engine.canvas.clear();
for (int i = 8; i < 16; i++) {
engine.canvas.drawVLine((i - 8) * 4, 31 - (data[i] + 1), 31); // FFT bins 8 - 15, lower half
}
engine.canvas.blt(32, 32);
engine.canvas.clear();
for (int i = 8; i < 16; i++) {
if (data[i] > 31) engine.canvas.drawVLine((i - 8) * 4, 31 - (data[i] - 31), 31); // FFT bins 9 - 15, upper half
}
engine.canvas.blt(32, 0);
engine.canvas.clear();
for (int i = 16; i < 24; i++) {
engine.canvas.drawVLine((i - 16) * 4, 31 - (data[i] + 1), 31); // FFT bins 16 - 23, lower half
}
engine.canvas.blt(64, 32);
engine.canvas.clear();
for (int i = 16; i < 24; i++) {
if (data[i] > 31) engine.canvas.drawVLine((i - 16) * 4, 31 - (data[i] - 31), 31); // FFT bins 16 - 23, upper half
}
engine.canvas.blt(64, 0);
engine.canvas.clear();
for (int i = 24; i < 32; i++) {
engine.canvas.drawVLine((i - 24) * 4, 31 - (data[i] + 1), 31); // FFT bins 24 - 31, lower half
}
engine.canvas.blt(96, 32);
engine.canvas.clear();
for (int i = 24; i < 32; i++) {
if (data[i] > 31) engine.canvas.drawVLine((i - 24) * 4, 31 - (data[i] - 31), 31); // FFT bins 24 - 31, upper half
}
engine.canvas.blt(96, 0);
}
Arduino实验场景图
项目三十三:Arduino OLED 频谱分析仪(视频,法语版《因为爱情》3分12秒)
https://v.youku.com/v_show/id_XNTgwNzY3ODkwNA==.html?spm=a2hcb.playlsit.page.1
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目三十四:八位音乐反应式 LED 灯条
Arduino实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目三十四:八位音乐反应式 LED 灯条
实验接线方法: max9814接A0
oled模块 Ardunio Uno
GND---------GND接地线
VCC---------5V 接电源
SDA---------A4
SCL ------- A5
*/
#include <Adafruit_NeoPixel.h>
#include <math.h>
#define N_PIXELS 8
#define MIC_PIN A0
#define LED_PIN 6
#define SAMPLE_WINDOW 5
#define PEAK_HANG 24
#define PEAK_FALL 4
#define INPUT_FLOOR 10
#define INPUT_CEILING 50
byte peak = 16;
unsigned int sample;
byte Count = 0;
byte HangCount = 0;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
strip.setBrightness(22);
strip.show();
strip.begin();
}
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;
if (curve > 10) curve = 10;
if (curve < -10) curve = -10;
curve = (curve * -.1) ;
curve = pow(10, curve);
if (inputValue < originalMin) {
inputValue = originalMin;
}
if (inputValue > originalMax) {
inputValue = originalMax;
}
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
Serial.print(OriginalRange, DEC);
Serial.print(" ");
Serial.print(NewRange, DEC);
Serial.print(" ");
Serial.println(zeroRefCurVal, DEC);
Serial.println();
delay(10);
if (originalMin > originalMax ) {
return 0;
}
if (invFlag == 0) {
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
}
else
{
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}
void loop() {
unsigned long startMillis = millis();
float peakToPeak = 0;
unsigned int signalMax = 0;
unsigned int signalMin = 1023;
unsigned int c, y;
while (millis() - startMillis < SAMPLE_WINDOW)
{
sample = analogRead(MIC_PIN);
if (sample < 1024)
{
if (sample > signalMax)
{
signalMax = sample;
}
else if (sample < signalMin)
{
signalMin = sample;
}
}
}
peakToPeak = signalMax - signalMin;
for (int i = 0; i <= strip.numPixels() - 1; i++) {
strip.setPixelColor(i, Wheel(map(i, 0, strip.numPixels() - 1, 30, 150)));
}
c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);
if (c < peak) {
peak = c;
HangCount = 0;
}
if (c <= strip.numPixels()) {
drawLine(strip.numPixels(), strip.numPixels() - c, strip.Color(0, 0, 0));
}
y = strip.numPixels() - peak;
strip.setPixelColor(y - 1, Wheel(map(y, 0, strip.numPixels() - 1, 30, 150)));
strip.show();
if (HangCount > PEAK_HANG) {
if (++Count >= PEAK_FALL) {
peak++;
Count = 0;
}
}
else {
HangCount++;
}
}
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);
}
}
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);
}
}
实验串口返回情况
Arduino实验场景图
项目三十四:八位音乐反应式 LED 灯条
(实验视频)
https://v.youku.com/v_show/id_XNTgwODQ3NzI5Mg==.html?spm=a2hcb.playlsit.page.1
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目三十五:十六位音乐反应式 LED 灯条
实验接线方法: max9814接A0
oled模块 Ardunio Uno
GND---------GND接地线
VCC---------5V 接电源
SDA---------A4
SCL ------- A5
实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
<span style="background-color: rgb(255, 255, 255);">实验一百五十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器</span>
项目三十五:十六位音乐反应式 LED 灯条
实验接线方法: max9814接A0
oled模块 Ardunio Uno
GND---------GND接地线
VCC---------5V 接电源
SDA---------A4
SCL ------- A5
*/
#include <Adafruit_NeoPixel.h>
#include <math.h>
#define N_PIXELS 16
#define MIC_PIN A0
#define LED_PIN 6
#define SAMPLE_WINDOW 5
#define PEAK_HANG 24
#define PEAK_FALL 4
#define INPUT_FLOOR 10
#define INPUT_CEILING 50
byte peak = 16;
unsigned int sample;
byte Count = 0;
byte HangCount = 0;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
strip.setBrightness(22);
strip.show();
strip.begin();
}
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;
if (curve > 10) curve = 10;
if (curve < -10) curve = -10;
curve = (curve * -.1) ;
curve = pow(10, curve);
if (inputValue < originalMin) {
inputValue = originalMin;
}
if (inputValue > originalMax) {
inputValue = originalMax;
}
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
Serial.print(OriginalRange, DEC);
Serial.print(" ");
Serial.print(NewRange, DEC);
Serial.print(" ");
Serial.println(zeroRefCurVal, DEC);
Serial.println();
delay(10);
if (originalMin > originalMax ) {
return 0;
}
if (invFlag == 0) {
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
}
else
{
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}
void loop() {
unsigned long startMillis = millis();
float peakToPeak = 0;
unsigned int signalMax = 0;
unsigned int signalMin = 1023;
unsigned int c, y;
while (millis() - startMillis < SAMPLE_WINDOW)
{
sample = analogRead(MIC_PIN);
if (sample < 1024)
{
if (sample > signalMax)
{
signalMax = sample;
}
else if (sample < signalMin)
{
signalMin = sample;
}
}
}
peakToPeak = signalMax - signalMin;
for (int i = 0; i <= strip.numPixels() - 1; i++) {
strip.setPixelColor(i, Wheel(map(i, 0, strip.numPixels() - 1, 30, 150)));
}
c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);
if (c < peak) {
peak = c;
HangCount = 0;
}
if (c <= strip.numPixels()) {
drawLine(strip.numPixels(), strip.numPixels() - c, strip.Color(0, 0, 0));
}
y = strip.numPixels() - peak;
strip.setPixelColor(y - 1, Wheel(map(y, 0, strip.numPixels() - 1, 30, 150)));
strip.show();
if (HangCount > PEAK_HANG) {
if (++Count >= PEAK_FALL) {
peak++;
Count = 0;
}
}
else {
HangCount++;
}
}
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);
}
}
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);
}
}
Arduino实验场景图
项目三十五:十六位音乐反应式 LED 灯条(实验视频)
https://v.youku.com/v_show/id_XNTgwODQ4Njk2MA==.html?spm=a2hcb.playlsit.page.1
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目四十:十六位音乐频谱灯条
Arduino实验开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
实验六十一:直条16位 WS2812B 5050 RGB LED内置全彩驱动彩灯模块
项目四十:十六位音乐频谱灯条
*/
#include "FastLED.h"
#define OCTAVE 1 // // Group buckets into octaves (use the log output function LOG_OUT 1)
#define OCT_NORM 0 // Don't normalise octave intensities by number of bins
#define FHT_N 256 // set to 256 point fht
#include <FHT.h> // include the library
//int noise[] = {204,188,68,73,150,98,88,68}; // noise level determined by playing pink noise and seeing levels [trial and error]{204,188,68,73,150,98,88,68}
// int noise[] = {204,190,108,85,65,65,55,60}; // noise for mega adk
int noise[] = {204,195,100,90,85,80,75,75}; // noise for NANO
//int noise[] = {204,198,100,85,85,80,80,80};
float noise_fact[] = {15, 7, 1.5, 1, 1.2, 1.4, 1.7,3}; // noise level determined by playing pink noise and seeing levels [trial and error]{204,188,68,73,150,98,88,68}
float noise_fact_adj[] = {15, 7, 1.5, 1, 1.2, 1.4, 1.7,3}; // noise level determined by playing pink noise and seeing levels [trial and error]{204,188,68,73,150,98,88,68}
#define LED_PIN 6
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
// Params for width and height
const uint8_t kMatrixWidth = 8;
const uint8_t kMatrixHeight = 8;//----------was 27
//#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
#define NUM_LEDS 64
CRGB leds[NUM_LEDS];
int counter2=0;
void setup() {
Serial.begin(9600);
delay(1000);
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness (33);
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
// TIMSK0 = 0; // turn off timer0 for lower jitter
ADCSRA = 0xe5; // set the adc to free running mode
ADMUX = 0x40; // use adc0
DIDR0 = 0x01; // turn off the digital input for adc0
}
void loop() {
int prev_j[8];
int beat=0;
int prev_oct_j;
int counter=0;
int prev_beat=0;
int led_index=0;
int saturation=0;
int saturation_prev=0;
int brightness=0;
int brightness_prev=0;
while (1) { // reduces jitter
cli(); // UDRE interrupt slows this way down on arduino1.0
for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
while (!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= 0x0200; // form into a signed int
k <<= 6; // form into a 16b signed int
fht_input[i] = k; // put real data into bins
}
fht_window(); // window the data for better frequency response
fht_reorder(); // reorder the data before doing the fht
fht_run(); // process the data in the fht
fht_mag_octave(); // take the output of the fht fht_mag_log()
// every 50th loop, adjust the volume accourding to the value on A2 (Pot)
if (counter >= 50) {
ADMUX = 0x40 | (1 & 0x07); // set admux to look at Analogpin A1 - Master Volume
while (!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
delay(10);
while (!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
float master_volume=(k+0.1)/1000 +.75; // so the valu will be between ~0.5 and 1.---------------------+.75 was .5
Serial.println (master_volume);
for (int i=1; i<8; i++) {
noise_fact_adj[i]=noise_fact[i]*master_volume;
}
ADMUX = 0x40 | (0 & 0x07); // set admux back to look at A0 analog pin (to read the microphone input
counter = 0;
}
sei();
counter++;
// End of Fourier Transform code - output is stored in fht_oct_out[i].
// i=0-7 frequency (octave) bins (don't use 0 or 1), fht_oct_out[1]= amplitude of frequency for bin 1
// for loop a) removes background noise average and takes absolute value b) low / high pass filter as still very noisy
// c) maps amplitude of octave to a colour between blue and red d) sets pixel colour to amplitude of each frequency (octave)
for (int i = 1; i < 8; i++) { // goes through each octave. skip the first 1, which is not useful
int j;
j = (fht_oct_out[i] - noise[i]); // take the pink noise average level out, take the asbolute value to avoid negative numbers
if (j<10) {j=0;}
j= j*noise_fact_adj[i];
if (j<10) {j=0;}
else {
j= j*noise_fact_adj[i];
if (j>180) {
if (i>=7) {
beat+=2;
}
else {
beat+=1;
}
}
j=j/30;
j=j*30; // (force it to more discrete values)
}
prev_j[i]=j;
// Serial.print(j);
// Serial.print(" ");
// this fills in 11 LED's with interpolated values between each of the 8 OCT values
if (i>=2) {
led_index=2*i-3;
prev_oct_j=(j+prev_j[i-1])/2;
saturation=constrain(j+50, 0,255);//-----------50 was 30
saturation_prev=constrain(prev_oct_j+50, 0,255);
brightness=constrain(j, 0,255);
brightness_prev=constrain(prev_oct_j, 0,255);
if (brightness==255) {
saturation=50;
brightness=200;
}
if (brightness_prev==255) {
saturation_prev=50;
brightness_prev=200;
}
for (uint8_t y=0;y<kMatrixHeight;y++){
leds[XY(led_index-1,y)] = CHSV(j+y*30,saturation, brightness);
if (i>2){
prev_oct_j=(j+prev_j[i-1])/2;
leds[ XY(led_index-2,y)]=CHSV(prev_oct_j+y*30,saturation_prev, brightness_prev);
}
}
}
}
if (beat>=7) {
fill_solid(leds, NUM_LEDS, CRGB::Gray);
FastLED.setBrightness(200);
}
else {
if (prev_beat!=beat) {
FastLED.setBrightness(40+beat*beat*5);
prev_beat=beat;
}
}
FastLED.show();
if (beat) {
counter2+=((beat+4)/2-2);
if (counter2<0) {counter2=1000;}
if (beat>3 && beat<7) {
FastLED.delay (20);
}
beat=0;
}
// Serial.println();
}
}
// Param for different pixel layouts
const bool kMatrixSerpentineLayout = false;
// Set 'kMatrixSerpentineLayout' to false if your pixels are
// laid out all running the same way, like this:
// Set 'kMatrixSerpentineLayout' to true if your pixels are
// laid out back-and-forth, like this:
uint16_t XY( uint8_t x, uint8_t y)
{
uint16_t i;
if( kMatrixSerpentineLayout == false) {
i = (y * kMatrixWidth) + x;
}
if( kMatrixSerpentineLayout == true) {
if( y & 0x01) {
// Odd rows run backwards
uint8_t reverseX = (kMatrixWidth - 1) - x;
i = (y * kMatrixWidth) + reverseX;
} else {
// Even rows run forwards
i = (y * kMatrixWidth) + x;
}
}
i=(i+counter2)%NUM_LEDS;
return i;
}
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十九:MAX9814麦克风放大器模块 MIC话筒声音放大/咪头传感器
项目四十:十六位音乐频谱灯条
实验视频剪辑
https://v.youku.com/v_show/id_XNTgwODYxOTI5Ng==.html?spm=a2hcb.playlsit.page.1