给出一个基于arduino的oled简易示波器的代码,将上述界面修改为两个部分(右侧,左侧),右侧分两部分显示波形图和fft转换图,左侧显示幅值、中值、频率、和采样率,要求可以在串口监视器上修改数值,要求使用的函数都是arduino中的库函数,根据上述的fft转换方法给出代码
时间: 2024-04-21 07:22:31 浏览: 16
下面是一个基于 Arduino 的 OLED 简易示波器的代码,其中将界面分为两个部分(右侧和左侧),右侧显示波形图和 FFT 转换图,左侧显示幅值、中值、频率和采样率。你可以通过串口监视器来修改参数值。
```c++
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "arduinoFFT.h"
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
arduinoFFT FFT = arduinoFFT();
const uint16_t samples = 64;
const double signalFrequency = 1000;
const double samplingFrequency = 5000;
const uint8_t amplitude = 100;
double vReal[samples];
double vImag[samples];
double fftMagnitudes[samples / 2];
void setup()
{
Serial.begin(115200);
while (!Serial)
;
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
}
void loop()
{
if (Serial.available() > 0)
{
amplitude = Serial.parseInt();
Serial.print("Amplitude: ");
Serial.println(amplitude);
}
double cycles = (((samples - 1) * signalFrequency) / samplingFrequency);
for (uint16_t i = 0; i < samples; i++)
{
vReal[i] = int8_t((amplitude * (sin((i * (twoPi * cycles)) / samples))) / 2.0);
vImag[i] = 0.0;
}
display.clearDisplay();
display.setCursor(0, 0);
display.print("Amplitude: ");
display.println(amplitude);
display.print("Mean: ");
display.println(mean(vReal, samples), 4);
display.print("Frequency: ");
display.println(signalFrequency);
display.print("Sampling Rate: ");
display.println(samplingFrequency);
display.drawLine(64, 0, 64, SCREEN_HEIGHT, WHITE); // 分隔线
drawWaveform();
drawFFT();
display.display();
}
void drawWaveform()
{
int offsetX = 66;
int offsetY = 0;
int waveWidth = SCREEN_WIDTH - offsetX;
int waveHeight = SCREEN_HEIGHT / 2;
double xScale = waveWidth / (samples - 1);
double yScale = waveHeight / (amplitude * 2);
for (int i = 0; i < samples - 1; i++)
{
int x1 = offsetX + i * xScale;
int y1 = offsetY + waveHeight - (vReal[i] * yScale);
int x2 = offsetX + (i + 1) * xScale;
int y2 = offsetY + waveHeight - (vReal[i + 1] * yScale);
display.drawLine(x1, y1, x2, y2, WHITE);
}
}
void drawFFT()
{
int offsetX = 66;
int offsetY = SCREEN_HEIGHT / 2;
int fftWidth = SCREEN_WIDTH - offsetX;
int fftHeight = SCREEN_HEIGHT / 2;
FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, samples, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, samples);
double xScale = fftWidth / (samples / 2);
double yScale = fftHeight / (samples / 2);
for (int i = 0; i < samples / 2 - 1; i++)
{
int x1 = offsetX + i * xScale;
int y1 = offsetY + fftHeight - (fftMagnitudes[i] * yScale);
int x2 = offsetX + (i + 1) * xScale;
int y2 = offsetY + fftHeight - (fftMagnitudes[i + 1] * yScale);
display.drawLine(x1, y1, x2, y2, WHITE);
}
}
double mean(double *vData, uint16_t bufferSize)
{
double sum = 0.0;
for (uint16_t i = 0; i < bufferSize; i++)
{
sum += vData[i];
}
return sum / bufferSize;
}
```
在这个代码中,我们使用了 `Adafruit_SSD1306` 库来控制 OLED 显示屏,并使用了 `arduinoFFT` 库来进行 FFT 转换。
在 `setup()` 函数中,我们初始化 OLED 显示屏和串口。
在 `loop()` 函数中,我们首先检查是否有可用的串口输入。如果有输入,我们将其解析为振幅值,并将其打印到串口监视器中。
然后,我们生成波形数据并显示在左侧部分。波形数据通过 `drawWaveform()` 函数绘制在屏幕上。
接下来,我们进行 FFT 转换,并将转换结果绘制在右侧部分。FFT 转换结果通过 `drawFFT()` 函数绘制在屏幕上。
最后,我们在屏幕上显示幅值、中值、频率和采样率。
希望这个代码满足你的需求!如果你有其他问题,请随时提问。