【雕爷学编程】Arduino动手做(149)---MAX9814咪头传感器模块4

news2024/10/6 14:38:26

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/751841.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在Windows 8和10中检查最后一次的启动模式

Windows 8、Windows 8.1 和 Windows 10 中的用户可以在 PC 上执行混合关机(快速启动)、完全关机或休眠。 快速启动(又名:hiberboot、混合启动或混合关机)在 Windows 中默认打开,是一种帮助你的电脑在关机后更快启动的设置。甚至比休眠还要快。 休眠是一种主要为笔记本电…

Linux下Nginx升级

nginx版本升级不会覆盖配置文件&#xff0c;但以防万一升级前请先备份配置文件或者配置文件夹 默认配置文件地址&#xff1a;/usr/local/nginx/conf/nginx.conf 1.下载 wget -c http://nginx.org/download/nginx-1.24.0.tar.gz 2.解压 tar -xvf nginx-1.24.0.tar.gz 3.nginx…

【图像处理】使用 Python 进行图像增强

一、说明 图像增强技术的深度和复杂性往往在一系列捕获和共享中被忽视。从傅里叶变换到白平衡和直方图处理&#xff0c;各种方法都可以将普通照片转换为引人注目的图像。这篇博文旨在解开这些技术。 我在节日期间拍了一张照片&#xff0c;在夜间庆祝活动中。遗憾的是&#xff0…

OpenCV中掩膜(Mask)、setTo()、copyTo()、clone()、inRange()的定义与使用

文章目录 1、掩膜(Mask)是什么&#xff08;1&#xff09;从物理的角度来看&#xff1a;&#xff08;2&#xff09;图像处理中的掩膜Mask&#xff08;3&#xff09;掩膜的用法&#xff1a;&#xff08;4&#xff09;掩膜Mask 的运算&#xff1a; 2、setTo()函数&#xff1a;将图…

【动手学习深度学习--逐行代码解析合集】17使用块的网络(VGG)

【动手学习深度学习】逐行代码解析合集 17使用块的网络&#xff08;VGG&#xff09; 视频链接&#xff1a;动手学习深度学习–使用块的网络&#xff08;VGG&#xff09; 课程主页&#xff1a;https://courses.d2l.ai/zh-v2/ 教材&#xff1a;https://zh-v2.d2l.ai/ 1、VGG网络…

【UniApp开发小程序】顶部导航栏和底部导航栏设置+iconfont图标引入

文章目录 顶部导航栏和底部导航栏设置创建几个需要底部导航栏切换的页面使用阿里巴巴矢量图标库完成底部导航栏tabBar设置页面顶部导航栏标题 样式优化 顶部导航栏和底部导航栏设置 在正式开发小程序的功能之前&#xff0c;首先需要确定小程序的主要框架。 创建几个需要底部导…

组件的创建,引用,样式隔离以及methods,data,properties和数据事件监听

组件的创建&#xff0c;引用&#xff0c;样式隔离以及methods,data,properties和数据事件监听 1. 组件的创建2. 组件的引用2.1. 局部引用2.2. 全局引用2.3. 组件和页面的区别 3. 组件的样式隔离3.1. 默认情况&#xff0c;组件样式隔离性3.2. 修改组件的样式隔离选项 4. 组件的d…

短视频抖音seo矩阵系统源码开发者思路(一)

一套优秀的短视频获客系统&#xff0c;支持短视频智能剪辑、短视频定时发布&#xff0c;短视频排名查询及优化&#xff0c;短视频智能客服等&#xff0c;那么短视频seo系统具体开发应该具备哪些功能呢&#xff1f;今天小编就跟大家分享一下我们的技术开发思路。 抖音矩阵系统源…

go-zero微服务实战——etcd服务注册与发现

etcd简介 浅谈etcd服务注册与发现 etcd官网 etcd中文文档 apt安装etcd&#xff0c;启动命令十分简单etcd。 etcd分为v2版本和v3版本&#xff0c;命令有所不一样&#xff0c;使用命令etcdctl h查看 如上图所示并没有出现API的版本&#xff0c;此时是使用默认的v2版本&#x…

android editText获取不到数据

问题分析&#xff1a;在onActivityCreated一开始就创建了findViewById&#xff0c;这时获取的是默认值&#xff0c;需要在点击按钮时重新加载才能获取到输入数据。 需要在点击按钮时重新加载数据&#xff1a;

Android Studio中java编程时禁止生成警告

1、打开Android Studio&#xff0c;进入主界面 2、进入软件后&#xff0c;点击菜单栏的File 3、在File选项中选择Settings 4、进入Settings选择Version Control -> Subversion -> Presentation 5、去掉勾选 Show merge source in history and anotations 6、最后点击确定…

在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型

在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型 用到的区域文件、地图标记文件、路径信息文件、模型文件 提取码&#xff1a;99jq 使用vite创建vue3项目 npm create vitelatestcd到创建的项目文件夹中 npm install安装Cesium npm i cesium vite-plugin-cesium…

一文详解常见标准化组织

从事软件研发工作多年&#xff0c;在工作中有时会查阅一些通信相关的国际标准。然而&#xff0c;对于制定这些标准的组织&#xff0c;一直缺乏一个系统的了解。本文将对几个常见的标准化组织进行介绍&#xff0c;其中包括ITU、3GPP、GSMA和CCSA&#xff0c;了解它们的背景、成立…

零基础学习C#编程的步骤和建议

如果你是零基础&#xff0c;希望学习C#编程语言&#xff0c;以下是一些建议的学习步骤&#xff1a; 基础概念和语法&#xff1a;开始学习C#之前&#xff0c;了解基本的编程概念和语法是很重要的。可以通过在线教程、编程书籍或视频教程来学习C#的基础知识&#xff0c;包括变量…

JVM中类加载的过程

文章目录 一、类加载是什么二、类加载过程1.加载2.验证3.准备4.解析5.初始化 三、什么时候进行类加载四、双亲委派模型1.三大类加载器2.加载过程 总 一、类加载是什么 把.class文件加载到内存中&#xff0c;得到类对象的过程。 二、类加载过程 1.加载 找到.class文件&#xff…

数据预处理matlab

matlab数据的获取、预处理、统计、可视化、降维 数据的预处理 - MATLAB & Simulink - MathWorks 中国https://ww2.mathworks.cn/help/matlab/preprocessing-data.html 一、数据的获取 1.1 从Excel中获取 使用readtable() 例1&#xff1a; 使用spreadsheetImportOption…

给大家推荐几款好用的格式转换工具

在数字化时代&#xff0c;我们经常需要处理各种不同的文件格式。有时我们可能需要将视频转换为适用于特定设备的格式&#xff0c;有时又需要将音频文件转换为可编辑的格式&#xff0c;或者将文档转换为更通用的类型。这就是格式转换工具的重要性所在。然而&#xff0c;在众多的…

纯css3实现小鸡从鸡蛋破壳而出动画特效

实现一个使用纯css3实现小鸡破壳的效果 示例效果如下所示 示例代码 <template><div><div class"eggWrapper"><div class"chickHead"><div class"eyeDiv"></div><div class"eyeDiv"></di…

一文详解 Okio 输入输出流

在 OkHttp 的源码中&#xff0c;我们经常能看到 Okio 的身影&#xff0c;这篇文章&#xff0c;我们把Okio拿出来进行一个详细的介绍学习。 输入输出的概念简述Okio 简介工程中引入 OkioAPI 简介及使用介绍 一、输入输出 在正式介绍 Okio 之前&#xff0c;让我们先回忆一下输…

STM32自学笔记14-步进电机驱动项目-TB67H450驱动

目前的项目是一种2相4线步进电机的闭环驱动电路&#xff0c;使用的电机驱动芯片是TB67H450&#xff0c;再使用磁编码器MT6816&#xff0c;使用FOC算法&#xff0c;基于STM32F1单片机。 这一节是步进电机的驱动芯片驱动研究 首先研究驱动芯片TB67H450的datasheet 这是一个PWM斩…