// 库导入
#include <Wire.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <WiFi.h>
#include <WebServer.h> // 这里修复了!
#include <arduinoFFT.h>
// ==================== 引脚定义 ====================
#define MPU6050_SDA 21
#define MPU6050_SCL 22
#define DS_PIN 4
#define OLED_RESET -1
#define LED_PIN 18
#define BUZZER_PIN 19
// ==================== OLED配置 ====================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ==================== 传感器初始化 ====================
Adafruit_MPU6050 mpu;
OneWire oneWire(DS_PIN);
DallasTemperature ds(&oneWire);
// ==================== FFT配置 ====================
#define FFT_SIZE 128
double vReal[FFT_SIZE];
double vImag[FFT_SIZE];
ArduinoFFT<double> FFT = ArduinoFFT<double>(vReal, vImag, FFT_SIZE, 100);
float vibration_rms = 0.0;
// ==================== WOKI WiFi ====================
const char* ssid = "Wokwi-GUEST";
const char* password = "";
WebServer server(80); // 云端网页服务器
// ==================== 状态变量 ====================
float temp = 0.0;
uint8_t oled_page = 0;
unsigned long temp_timer = 0;
unsigned long page_timer = 0;
String temp_status = "正常";
String vib_status = "正常";
String total_status = "正常";
// ==================== 阈值 ====================
#define RMS_NORMAL 1.0
#define RMS_WARN 1.5
#define TEMP_NORMAL_MIN 20
#define TEMP_NORMAL_MAX 30
#define TEMP_WARN_MIN 10
#define TEMP_WARN_MAX 40
// ==================== 云端网页显示 ====================
void handleRoot() {
String html = "<html>";
html += "<head><meta charset='UTF-8'>";
html += "<meta http-equiv='refresh' content='1'>";
html += "<title>ESP32 设备监测云端</title>";
html += "<style>body{text-align:center;font-size:28px;margin-top:60px;}</style>";
html += "</head>";
html += "<body>";
html += "<h2>ESP32 机械设备状态监测</h2>";
html += "<p>温度:" + String(temp) + " ℃</p>";
html += "<p>振动 RMS:" + String(vibration_rms) + " g</p>";
html += "<p>温度状态:" + temp_status + "</p>";
html += "<p>振动状态:" + vib_status + "</p>";
html += "<p>总状态:" + total_status + "</p>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// ==================== 初始化 ====================
void setup() {
Serial.begin(115200);
Wire.begin(MPU6050_SDA, MPU6050_SCL);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while(1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
if(!mpu.begin()) {
while(1);
}
mpu.setAccelerometerRange(MPU6050_RANGE_2_G);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
delay(100);
ds.begin();
Serial.println("连接WiFi: Wokwi-GUEST");
WiFi.begin(ssid, password);
int timeout = 0;
while (WiFi.status() != WL_CONNECTED && timeout++ < 20) {
delay(500);
Serial.print(".");
}
server.on("/", handleRoot);
server.begin();
Serial.println("\nWiFi 连接成功 ✅");
Serial.print("云端地址:");
Serial.println(WiFi.localIP());
Serial.println("==================== 系统启动 ====================");
}
// ==================== 报警 ====================
void setAlarm() {
if (total_status == "正常") {
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
}
else if (total_status == "预警") {
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZZER_PIN, LOW);
}
else {
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZZER_PIN, HIGH);
}
}
// ==================== RMS计算 ====================
void getVibrationRMS() {
double sum = 0;
sensors_event_t a, g, temp;
for(int i=0; i<FFT_SIZE; i++) {
mpu.getEvent(&a, &g, &temp);
double ax = a.acceleration.x;
double ay = a.acceleration.y;
double az = a.acceleration.z;
double acc = sqrt(ax*ax + ay*ay + az*az);
vReal[i] = acc;
vImag[i] = 0;
sum += acc * acc;
delay(10);
}
vibration_rms = sqrt(sum / FFT_SIZE);
}
void doFFT() {
FFT.windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.compute(FFT_FORWARD);
FFT.complexToMagnitude();
}
// ==================== 温度 ====================
void getTemperature() {
if(millis() - temp_timer > 5000) {
ds.requestTemperatures();
temp = ds.getTempCByIndex(0);
temp_timer = millis();
}
}
void diagnosisTemp() {
if (temp < TEMP_WARN_MIN || temp > TEMP_WARN_MAX) {
temp_status = "故障";
} else if (temp < TEMP_NORMAL_MIN || temp > TEMP_NORMAL_MAX) {
temp_status = "预警";
} else {
temp_status = "正常";
}
}
// ==================== 振动诊断 ====================
void diagnosisVib() {
if(vibration_rms < RMS_NORMAL) {
vib_status = "正常";
}
else if(vibration_rms < RMS_WARN) {
vib_status = "预警";
}
else {
vib_status = "故障";
}
}
void diagnosisTotal() {
if (temp_status == "故障" || vib_status == "故障") {
total_status = "故障";
}
else if (temp_status == "预警" || vib_status == "预警") {
total_status = "预警";
}
else {
total_status = "正常";
}
}
// ==================== OLED ====================
void oledDisplay() {
if(millis() - page_timer > 3000) {
oled_page = (oled_page +1) %3;
page_timer = millis();
}
display.clearDisplay();
if(oled_page ==0) {
display.setCursor(0,0);
display.println("=== 实时数据 ===");
display.print("Temp: "); display.print(temp); display.println(" C");
display.print("RMS: "); display.print(vibration_rms); display.println(" g");
display.print("Status: "); display.println(total_status);
}
if(oled_page ==1) {
display.setCursor(0,0);
display.println("=== FFT Spectrum ===");
for(int i=2; i<64; i++) {
int h = vReal[i] * 8;
h = constrain(h,0,20);
display.drawLine(i*2, 63, i*2, 63-h, SSD1306_WHITE);
}
}
if(oled_page ==2) {
display.setCursor(0,0);
display.println("=== Diagnosis ===");
display.print("Temp: "); display.println(temp_status);
display.print("Vib: "); display.println(vib_status);
display.print("Total: "); display.println(total_status);
}
display.display();
}
// ==================== 串口 ====================
void serialPrint() {
Serial.println("==================== 实时数据 ====================");
Serial.print("温度:"); Serial.print(temp); Serial.println(" ℃");
Serial.print("振动RMS:"); Serial.print(vibration_rms); Serial.println(" g");
Serial.print("温度状态:"); Serial.println(temp_status);
Serial.print("振动状态:"); Serial.println(vib_status);
Serial.print("总状态:"); Serial.println(total_status);
Serial.println("==================================================\n");
}
// ==================== 主循环 ====================
void loop() {
getVibrationRMS();
doFFT();
getTemperature();
diagnosisTemp();
diagnosisVib();
diagnosisTotal();
setAlarm();
oledDisplay();
serialPrint();
server.handleClient();
delay(100);
}