#include "arduinoFFT.h"
#include <Adafruit_SSD1306.h>
#include <ArduinoJson.h>
#include <SoftwareSerial.h>
#define samples 64 //采样点数,2的N次幂
#define halfsamples samples/2
#define NumofCopy halfsamples*sizeof(double)
#define Interval 128/(halfsamples)
Adafruit_SSD1306 display(100);
arduinoFFT FFT = arduinoFFT();
SoftwareSerial ESP_Serial(6, 7); //Tx,Rx
double vReal[samples];
double vImag[samples];
double vTemp[halfsamples];
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
Serial.println("Hello ESP8266.");
setP32(); //设置32分频,加快AD采样
pinMode(8,OUTPUT);
Serial.begin(9600);
ESP_Serial.begin(9600);
delay(2000);
}
void loop() {
// Serial.println("start:"+String(micros()));
for(int i=0;i<samples;i++)
{
vReal[i]=analogRead(A0)-512; //采样
vImag[i] = 0.0;
}
// Serial.println("end:"+String(micros()));
display.clearDisplay();
FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);//加窗
FFT.Compute(vReal, vImag, samples, FFT_FORWARD); //计算fft
FFT.ComplexToMagnitude(vReal, vImag, samples); //计算幅度
//***************************************************
String jsonData= json();
if(jsonData.length()>0){
const size_t capacity = JSON_OBJECT_SIZE(1) + 10;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, jsonData);
const char* root_7 = doc["7"]; // "0"
int numKey=doc["7"].as<int>();
Serial.print(numKey);
digitalWrite(8,numKey);
delay(100);
}else{
//不做操作
delay(100);
}
//*****************************************
for(int i=0;i<halfsamples;i++)
{
display.drawPixel(i*Interval,vTemp[halfsamples-i-1]*0.007+1, WHITE); //显示
display.drawLine(i*Interval, 0, i*Interval,vReal[halfsamples-i-1]*0.007, WHITE);
}
display.display();
memcpy(vTemp, vReal, NumofCopy);
delay(20); //改为128点时可以注释掉,防止刷新太慢
}
//设置32分频
void setP32()
{
ADCSRA|=(1<<ADPS2);
ADCSRA&=~(1<<ADPS1);
ADCSRA|=(1<<ADPS0);
}
//获取sep8266上发送过来的数据
String json(){
String comdata = "";
while(ESP_Serial.available() > 0){//串口接收到数据
comdata += char(ESP_Serial.read());//获取串口接收到的数据
}
Serial.print(comdata);
return comdata;
}
我分析了一下,应该串口接收处理那段不正常吧。我看到你用的是SoftwareSerial,软串口功能限制很多的,它基本只能工作在查询模式,没有中断,发送还行,接收经常丢。前面处理FFT的时候如果发送方发送了数据,它实际上是收不到的,而FFT的处理是有点耗时的,这就会导致丢掉很多数据,而你的发送方也不太可能准确找到它处理完FFT的时间点。
建议换硬件串口再试试。另外,即使换硬件串口,对串口数据的分析建议也加上一个通讯控制协议,否则还是很容易丢失或接收不完整。在一次loop中很可能是接收不完的,你需要在每次接收的时候,放到一个缓冲区,然后接收完一次,判断缓冲区里是否有一帧完整数据,有就提取出来,没有就留着继续接收。
引用chatGPT作答,根据您提供的代码,我可以看出几个潜在的问题:
1.setP32() 函数似乎没有被调用。您在 setup() 函数中定义了该函数,但是没有在 loop() 函数中调用。这可能会导致采样速率不正确。
2.在 loop() 函数的串口通信部分,您使用了 delay(100) 来等待串口数据的到来。这样做可能会导致程序的响应变慢,尤其是当没有数据到来时,程序会一直停在这里。您可以使用 Serial.available() 函数来检查是否有数据到来,并且不要在等待数据时使用 delay() 函数。
3.在 loop() 函数的串口通信部分,您没有检查接收到的数据是否是有效的 JSON 格式。如果接收到的数据不是有效的 JSON 格式,解析函数 deserializeJson() 可能会出现错误。
4.在 loop() 函数中,您使用了 memcpy() 函数来复制数组 vReal 的前一半数据到数组 vTemp 中。但是,您没有初始化数组 vTemp 的值。这可能会导致 vTemp 数组中包含无效的数据。
5.您使用 ESP_Serial 对象来接收数据,并且使用 Serial 对象来输出调试信息。建议使用 Serial 对象来接收数据并输出调试信息,因为在调试过程中,Serial 对象可能更容易使用。
希望这些信息可以帮助您找到程序中的问题。