【雕爷学编程】Arduino动手做(149)---MAX9814咪头传感器模块4
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
实验开源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | /* 【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实验开源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | /* 【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实验开源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | /* 【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
实验开源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | /* 【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实验开源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | /* 【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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~