收起左侧

关于死机、失联问题实在没找到原因--只能硬解了

5
回复
181
查看
[ 复制链接 ]

1

主题

4

回帖

0

牛值

江湖小虾

DIY个硬件看门狗。有死机、失联的朋友感兴趣可以往下看。用飞牛NAS已有大半年了。我对NAS要求不高能远程随时查看备份的资料,偶尔备份下相册就行·为一苦恼的就是经常失联死机···每次都需要断 电重启··用着最稳定的版本是0.9.13,连续8天没死机失联··升级到0.9.15又开始失联··0.913的上一个版本基本每天得死机两次··一开始怀疑内存,有问题换了一根内存故障依旧,经过总结应该是兼容性问题,应为每个版本死机频率不一样,它是不定时的死机。配置如下

微信图片_20250721224534.png
应用只装了相册和OFFICE在线预览其他都卸载了死机依旧。

微信图片_20250721225344.png

确实是不想抛弃,只能硬解了·········做一个算是硬件看门狗。

原理很简单用ESP8266 每隔2分钟PING5次 飞牛NAS的IP如果5次都失败则重启NAS,延时10分钟继续循环每个2分钟ping,给nas启动预留时间。

所需原件如下,ESP8266继电器模块。电源从内部USB插针取5V电源。继电器输出接nas的rest实现失联死机自动重启。

image.png

以下为网页端显示看门狗状态

image.png

有感兴趣的,代码如下:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <ESP8266Ping.h>

// 服务器配置
ESP8266WebServer server(80);

// EEPROM配置
#define EEPROM_SIZE 96  // 存储SSID(32字节) + 密码(64字节)

// 配网模式AP名称和IP
const char* apSSID = "NasWatchDog";
IPAddress apIP(192, 168, 4, 1);  //配网IP可自行修改

// 存储WiFi凭证
String savedSSID = "";
String savedPassword = "";

// Ping相关变量
const IPAddress targetIP(192, 168, 0, 113);  // NAS目标IP地址
unsigned long lastPingTime = 0;
const unsigned long pingInterval = 120000;   // 2分钟(毫秒)
const unsigned long failureDelay = 600000;   // 10分钟(毫秒)
bool pingFailure = false;
unsigned long failureStartTime = 0;
const int pingCount = 5;                     // 每次发送5个Ping包
const int pingTimeout = 200;                 // 每个Ping的超时时间(毫秒)

// WiFi连接状态跟踪
bool isWiFiConnected = false;  // 跟踪WiFi连接状态

int ledPin = 2; // LED引脚

// 呼吸灯变量
int brightness = 0;           // 当前亮度值
int fadeAmount = 5;           // 每次变化的步长
unsigned long previousFadeTime = 0;
const unsigned long fadeInterval = 30; // 呼吸灯更新间隔(毫秒)

void setup() {
  digitalWrite(0, HIGH);  // 初始化为高电平
  pinMode(0, OUTPUT);
  
  Serial.begin(115200);
  delay(10);
  
  // 初始化GPIO0
  

  // 初始化LED引脚
  pinMode(ledPin, OUTPUT);
  **ogWrite(ledPin, 1023);  // 初始化为熄灭状态(高电平)
  
  // 初始化EEPROM
  EEPROM.begin(EEPROM_SIZE);
  
  // 尝试读取保存的WiFi
  readCredentials();
  
  // 尝试连接WiFi
  if (savedSSID.length() > 0) {
    Serial.print("正在连接 ");
    Serial.println(savedSSID);
  
    WiFi.begin(savedSSID.c_str(), savedPassword.c_str());
  
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
      delay(500);
      Serial.print(".");
      attempts++;
    }
  }

  // 检查连接状态
  isWiFiConnected = (WiFi.status() == WL_CONNECTED);

  // 连接失败进入配网模式
  if (!isWiFiConnected) {
    startConfigPortal();
  } else {
    Serial.println("\n连接成功!");
    Serial.print("IP地址: ");
    Serial.println(WiFi.localIP());
  
    // 设置工作模式下的路由
    server.on("/", handleRoot);
    server.on("/reset", handleReset);
    server.begin();
  
    // 初始化Ping计时器(仅在连接成功后)
    lastPingTime = millis();
  }
}

void loop() {
  server.handleClient();
  
  // 仅在成功连接WiFi时执行Ping
  if (isWiFiConnected) {
    handlePingLogic();
  }
  
  // 更新呼吸灯效果(仅在非失败状态)
  updateBreathingLED();
}

// 更新呼吸灯效果
void updateBreathingLED() {
  if (pingFailure) {
    // Ping失败时LED常亮
    **ogWrite(ledPin, 0);  // 低电平点亮LED
    return;
  }
  
  unsigned long currentMillis = millis();
  if (currentMillis - previousFadeTime >= fadeInterval) {
    previousFadeTime = currentMillis;

    // 设置PWM亮度
    **ogWrite(ledPin, 1023 - brightness);  // 反转亮度(因为低电平点亮)
  
    // 改变亮度值
    brightness += fadeAmount;
  
    // 反转亮度变化方向
    if (brightness <= 0 || brightness >= 1023) {
      fadeAmount = -fadeAmount;
    }
  }
}

// Ping逻辑处理
void handlePingLogic() {
  unsigned long currentTime = millis();
  
  // 处理失败状态
  if (pingFailure) {
    if (currentTime - failureStartTime >= failureDelay) {
      pingFailure = false;  // 结束失败状态
      lastPingTime = currentTime;  // 重置Ping计时器
      Serial.println("故障延迟结束,恢复正常Ping检测");
    }
    return;  // 在失败状态下跳过Ping
  }
  
  // 执行Ping
  if (currentTime - lastPingTime >= pingInterval) {
    Serial.print("正在Ping ");
    Serial.print(targetIP);
    Serial.println(" 5次...");
  
    int successCount = 0;
  
    // 发送5个Ping包 - 使用Ping库
    for (int i = 0; i < pingCount; i++) {
      bool success = Ping.ping(targetIP, 1);  // 发送1个Ping包
      if (success) {
        successCount++;
        Serial.print("Ping #");
        Serial.print(i + 1);
        Serial.println(" 成功");
      } else {
        Serial.print("Ping #");
        Serial.print(i + 1);
        Serial.println(" 失败");
      }
      delay(100); // 短暂延迟
    }
  
    // 检查所有Ping是否都失败
    if (successCount == 0) {
      Serial.println("全部5次Ping失败! 触发GPIO0");
      digitalWrite(0, LOW);   // 拉低GPIO0
      delay(1000);            // 保持1秒
      digitalWrite(0, HIGH);  // 恢复高电平
  
      pingFailure = true;
      failureStartTime = currentTime;
      Serial.println("进入故障延迟状态");
    } else {
      Serial.print("Ping成功次数: ");
      Serial.println(successCount);
    }
  
    lastPingTime = currentTime;  // 更新最后一次Ping时间
  }
}

// 启动配置门户
void startConfigPortal() {
  Serial.println("\n启动配置模式");
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  WiFi.softAP(apSSID);
  
  Serial.print("AP IP地址: ");
  Serial.println(apIP);

  // 设置配网路由
  server.on("/", handleConfigRoot);
  server.on("/configure", handleConfigure);
  server.begin();
}

// 读取保存的凭证
void readCredentials() {
  Serial.println("读取EEPROM");
  savedSSID = "";
  savedPassword = "";
  
  // 读取SSID (32字节)
  for (int i = 0; i < 32; ++i) {
    char c = char(EEPROM.read(i));
    if (c != 0 && c != 255) savedSSID += c;
  }
  
  // 读取密码 (64字节)
  for (int i = 32; i < 96; ++i) {
    char c = char(EEPROM.read(i));
    if (c != 0 && c != 255) savedPassword += c;
  }
  
  Serial.println("保存的SSID: " + savedSSID);
  Serial.println("保存的密码: " + savedPassword);
}

// 保存凭证到EEPROM
void saveCredentials(String ssid, String password) {
  Serial.println("保存凭证");
  
  // 清除EEPROM
  for (int i = 0; i < EEPROM_SIZE; ++i) {
    EEPROM.write(i, 0);
  }
  
  // 写入SSID
  for (int i = 0; i < ssid.length(); ++i) {
    EEPROM.write(i, ssid[i]);
  }
  
  // 写入密码
  for (int i = 0; i < password.length(); ++i) {
    EEPROM.write(32 + i, password[i]);
  }
  
  EEPROM.commit();
}

// 配网页面HTML
const char* configPage = 
"<html>"
"<head>"
  "<meta charset='UTF-8'>"
  "<meta name='viewport' content='width=device-width, initial-scale=1'>"
  "<style>"
    "body{font-family:'Microsoft YaHei',Arial;text-align:center;margin-top:50px}"
    "input{padding:10px;width:80%;max-width:300px;margin:10px}"
    "button{padding:10px 20px;background:#4CAF50;color:white;border:none;cursor:pointer}"
    "h1{color:#333}"
  "</style>"
"</head>"
"<body>"
  "<h1>WiFi 配置</h1>"
  "<form action='/configure' method='POST'>"
    "<input type='text' name='ssid' placeholder='WiFi名称' required><br>"
    "<input type='password' name='password' placeholder='WiFi密码' required><br>"
    "<button type='submit'>保存并连接</button>"
  "</form>"
"</body>"
"</html>";

// 配置页面处理
void handleConfigRoot() {
  server.send(200, "text/html", configPage);
}

// 处理配置请求
void handleConfigure() {
  if (server.method() != HTTP_POST) {
    server.send(405, "text/plain", "方法不允许");
    return;
  }
  
  String newSSID = server.arg("ssid");
  String newPassword = server.arg("password");
  
  if (newSSID.length() == 0) {
    server.send(400, "text/plain", "SSID不能为空");
    return;
  }
  
  saveCredentials(newSSID, newPassword);
  
  server.send(200, "text/html", 
    "<html>"
    "<head><meta charset='UTF-8'></head>"
    "<body style='font-family:\"Microsoft YaHei\",Arial;text-align:center;'>"
    "<h1>凭证已保存!</h1>"
    "<p>设备正在重启,将尝试连接到: " + newSSID + "</p>"
    "<p>请等待约20秒,然后在路由器中检查已连接设备。</p>"
    "</body></html>");
  
  delay(2000);
  ESP.restart();
}

// 工作模式首页
void handleRoot() {
  String html = "<html>"
                "<head><meta charset='UTF-8'></head>"
                "<body style='font-family:\"Microsoft YaHei\",Arial;text-align:center;'>"
                "<h1>看门狗 已连接!</h1>"
                "<p>SSID: " + savedSSID + "</p>"
                "<p>IP地址: " + WiFi.localIP().toString() + "</p>"
                "<p>Ping状态: " + String(pingFailure ? "故障延迟中(10分钟)" : "活动状态") + "</p>"
                "<p>Ping目标: 192.168.0.113</p>"
                "<p><a href='/reset'>重置WiFi设置</a></p>"
                "</body></html>";
  server.send(200, "text/html", html);
}

// 重置WiFi设置 
void handleReset() {
  saveCredentials("", ""); // 清除凭证
  server.send(200, "text/html", 
              "<html>"
              "<head><meta charset='UTF-8'></head>"
              "<body style='font-family:\"Microsoft YaHei\",Arial;text-align:center;'>"
              "<h1>WiFi设置已重置!</h1>"
              "<p>设备将重启进入配置模式</p>"
              "</body></html>");
  delay(2000);
  ESP.restart();
}

收藏
送赞
分享

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

3

主题

16

回帖

5

牛值

初出茅庐

你怀疑是死机,有没有怀疑过网卡睡死?

不是网卡问题,链接显示器无输出,硬盘指示灯不亮系统盘无数据读写  详情 回复
前天 09:57

1

主题

4

回帖

0

牛值

江湖小虾

前天 09:57 楼主 显示全部楼层
勤善乐仁 发表于 2025-7-22 09:43
你怀疑是死机,有没有怀疑过网卡睡死?

不是网卡问题,链接显示器无输出,硬盘指示灯不亮系统盘无数据读写

3

主题

16

回帖

5

牛值

初出茅庐

加装模块实现强制重启,对机器硬盘和数据好吗?长期使用的话,建议换主板或板U都换掉。

9

主题

28

回帖

0

牛值

fnOS系统内测组

我把硬盘休眠关了,最近就没有出现这个问题。

18

主题

31

回帖

0

牛值

初出茅庐

我是重启或者关机大概率会显示两个盘无法卸载,然后提示watchdog did not stop,机器就直接失联,但是机器还在运行状态,所有风扇都转,需要彻底断 电才能开机,已经困扰我很久了,现在准备换一个主板了。目前配置是10400+微星b460迫击炮wifi

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则