/** * FFTで周波数特性 * https://101010.fun/iot/m5stickc-plus-accel.html * を改変 */ #include <M5StickCPlus.h> #include <arduinoFFT.h> #define SAMPLE_PERIOD 10 // サンプリング間隔(mS) const uint16_t FFTsamples = 64; //This value MUST ALWAYS be a power of 2 double vReal[FFTsamples]; double vImag[FFTsamples]; const double samplingFrequency = 1000.0 / (double)SAMPLE_PERIOD; ArduinoFFT<double> FFT = ArduinoFFT<double>(vReal, vImag, FFTsamples, samplingFrequency); int Y0 = 15; int _height = 135 - Y0; int _width = 240; float dmax = 1000.0; // Sensitive void drawChart(int nsamples) { int band_width = floor(_width / nsamples); int band_pad = band_width - 1; for (int band = 0; band < nsamples; band++) { int hpos = band * band_width; float d = vReal[band]; if (d > dmax) d = dmax; int h = (int)((d / dmax) * (_height) * 0.9); M5.Lcd.fillRect(hpos, _height - h, band_pad, h, BLACK); if ((band % 16) == 0) { M5.Lcd.setCursor(hpos, _height); M5.Lcd.printf("%dHz", (int)((band * 1.0 * samplingFrequency) / FFTsamples)); } } } void setup() { M5.begin(); // M5.Axp.ScreenBreath(24); M5.Lcd.setRotation(3); M5.Lcd.fillScreen(WHITE); M5.Lcd.setTextColor(BLACK); M5.Lcd.setTextSize(2); M5.IMU.Init(); M5.IMU.SetAccelFsr(M5.IMU.AFS_4G); } void DCRemoval(double *vData, uint16_t samples) { double mean = 0; for (uint16_t i = 0; i < samples; i++) { mean += vData[i]; } mean /= samples; for (uint16_t i = 0; i < samples; i++) { vData[i] -= mean; } } void loop() { for (int i = 0; i < FFTsamples; i++) { float ax, ay, az; // 画面短軸方向がx 長軸方向がy 画面に対して垂直がz long t = micros(); M5.IMU.getAccelData(&ax,&ay,&az); // MPU6886から加速度を取得 vReal[i] = az * 1000; // mGに変換 vImag[i] = 0; delayMicroseconds(SAMPLE_PERIOD * 1000 - (micros() - t)); } DCRemoval(vReal, FFTsamples); // 直流分を除去 FFT.windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD); // 窓関数 FFT.compute(FFT_FORWARD); // FFT処理(複素数で計算) FFT.complexToMagnitude(); // 複素数を実数に変換 double x = FFT.majorPeak(); M5.Lcd.fillScreen(WHITE); // 画面をクリア drawChart(FFTsamples / 2); M5.Lcd.setCursor(40, 0); M5.Lcd.printf("Peak: %3.1fHz", x); }