Arduino--ESP8266--SmartConfig+EEPROM

/************************************************************************************/
/*
                               SmartConfig+EEPROM
                        程序内容:利用手机APP一键组网  增加一个EEPROM的读写来进行WIFI名称
                 SmartConfig操作步骤:
                   1, 8266 端作为station,进入smartconfig, 等待手机端发出的用户名和密码。
                   2, 手机端把填写当前网络的密码通过UDP广播;
                   3, 8266 获取到信息之后推出smartconfig配置,连接网络;
                 EEPROM读写操作
                   1.申请内存数
                   2.读或写
                   3.写入覆盖寄存器地址内容  写回flash之前会把整一块sector全部擦除掉,也就意味着就算我们begin(1)最终也是会擦除4096字节空间。但是size的大小决定了内存空间的剩余量以及回写的快慢,所以根据具体情况来设置size。
                   4.写入结束 并释放内存

*/
/************************************************************************************/


/*
    SmartConfig相关函数在ESP8266WiFiSTA库中
      相关函数
           bool beginSmartConfig(); //启动配网  返回值:是否启动配网模式成功
           bool stopSmartConfig();  //停止配网  返回值:是否停止配网模式成功
           bool smartConfigDone();  //完成配网  返回值:是否完成配网模式


     EEPROM相关函数
          void begin(size_t size);                           //申请具体大小的ram内存空间。size(4的倍数)
          uint8_t read(int const address);                   //读寄存器地址  address复位0-4096
          void write(int const address, uint8_t const val);  //在相应寄存器地址 写入一个8进制数值
          bool commit();                                     //覆盖写入的相应寄存器地址  返回值表示覆盖成功
          void end();                                        // 用于写入flash,并且释放内存空间
*/
//#include 
#include    //WIFI 头文件
#include        //第三方库
#include           //I2C库头文件
#include         //EEPROM



#define LED D9
long debouncdDelay = 500;  //延时间隔
long lastDebounceTime = 0; //最近记录的一次时间
//显示屏的接口配置
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ D6, /* data=*/ D5, /* reset=*/ U8X8_PIN_NONE);   // ESP32 Thing, pure SW emulated I2C
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ D6, /* data=*/ D5);   // ESP32 Thing, HW I2C with pin remapping

// 配置热点的参数信息(IP,网关,子掩码)
//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)      Serial.print(message)


struct config_type
{
  char stassid[32];
  char stapsw[64];
};
config_type config;

bool flag = 0;                           //读取EEPROM联网,是否成功标志位
uint8_t WifiEEPROM_Buff[50] = {0};
uint8_t Time_val = 0;
/*
   保存参数到EEPROM
*/
void saveConfig()
{
  Serial.println("Save config!");
  Serial.print("stassid:");
  Serial.println(config.stassid);
  Serial.print("stapsw:");
  Serial.println(config.stapsw);
  EEPROM.begin(1024);
  uint8_t *p = (uint8_t*)(&config);
  for (int i = 0; i < sizeof(config); i++)
  {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();
}

/*
   从EEPROM加载参数
*/
void loadConfig()
{
  EEPROM.begin(1024);
  uint8_t *p = (uint8_t*)(&config);
  for (int i = 0; i < sizeof(config); i++)
  {
    *(p + i) = EEPROM.read(i);
  }
  EEPROM.commit();
  Serial.println("-----Read config-----");
  Serial.print("stassid:");
  Serial.println(config.stassid);
  Serial.print("stapsw:");
  Serial.println(config.stapsw);
}
void Connect_STA(const char *wifiname, const char *psw)
{
  WiFi.begin(wifiname, psw);
  //判断网络状态是否连接上,没连接上就延时500ms,并且打出一个点,模拟连接过程
  //笔者扩展:加入网络一直都连不上 是否可以做个判断,由你们自己实现
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Time_val++;
    DebugPrint(".");
    DebugPrint(WiFi.status());
    if (Time_val > 20)
    {
      Time_val = 0;
      flag = 0;
      return;
    }
  }
  if (WiFi.status() == WL_CONNECTED)
  {
    flag = 1;
    //输出mac地址
    DebugPrintln(String("Connected, mac address: ") + WiFi.macAddress().c_str());

    //输出station IP地址,这里的IP地址由DHCP分配
    DebugPrintln(String("Connected, IP address: ") + WiFi.localIP().toString());

    //输出子网掩码地址
    DebugPrintln(String("Subnet mask: ") + WiFi.subnetMask().toString());

    //输出网关 IP地址
    DebugPrintln(String("Gataway IP: ") + WiFi.gatewayIP().toString());

    //输出hostname
    DebugPrintln(String("Default hostname: ") + WiFi.hostname());
    //设置新的hostname
    WiFi.hostname("Station_host_1");
    DebugPrintln(String("New hostname: ") + WiFi.hostname());

    //输出SSID
    DebugPrintln(String("SSID: ") + WiFi.SSID());

    //输出psk
    DebugPrintln(String("psk: ") + WiFi.psk());

    //输出BSSID
    DebugPrintln(String("BSSID: ") + WiFi.BSSIDstr());

    //输出RSSI
    DebugPrintln(String("RSSI: ") + WiFi.RSSI() + " dBm");
  }
}
void smartConfig()
{
  WiFi.mode(WIFI_STA);
  Serial.println("\r\nWait for Smartconfig");
  delay(2000);
  // 等待配网
  WiFi.beginSmartConfig();
  while (1)
  {
    Serial.print(".");
    delay(500);
    Time_val++;
    if (Time_val > 20)
    {
      Time_val = 0;
      flag = 0;
      break;
    }
    if (WiFi.smartConfigDone())
    {
      Serial.println("SmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      WiFi.setAutoConnect(true);                       // 设置自动连接
      strcpy(config.stassid, WiFi.SSID().c_str());
      strcpy(config.stapsw, WiFi.psk().c_str());
      saveConfig();
      break;
    }
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP().toString());
}
void setup() {
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);         //初始化led io
  digitalWrite(LED, LOW);       //配置io输出为低电平

  pinMode(D5, OUTPUT);    // SSD1306 SDA
  pinMode(D6, OUTPUT);    // SSD1306 SCL
  digitalWrite(D5, 0);
  digitalWrite(D6, 0);

  DebugBegin(115200);   //配置串口
  loadConfig(); //读取账号和密码
  Connect_STA(config.stassid, config.stapsw);

  if(!flag)
  {
    DebugPrint("****************上次没有配网成功,执行一键配网功能*************************" );
    DebugPrint("/n");
    smartConfig();
  }

  u8g2.begin();                  // 显示屏初始化配置
  u8g2.enableUTF8Print();        // 使print支持UTF8字集

  ESP.wdtEnable(5000);            //使能软件看门狗的触发间隔
}

void loop() {
  // put your main code here, to run repeatedly:
  ESP.wdtFeed();  //喂狗
  if (millis() - lastDebounceTime > debouncdDelay)
  {
    lastDebounceTime = millis();  //重新赋值上一次时间
    u8g2.firstPage();
    do {
      u8g2.setFont(u8g2_font_5x8_tf);
      u8g2.setFontDirection(0);
      u8g2.drawStr(0, 8, " AP_SSID:");
      u8g2.drawStr(0, 18, " AP_PSW:");
    } while ( u8g2.nextPage() );
    digitalWrite(D9, !digitalRead(D9));   //配置io输出为 读取当前IO口状态的反向值
  }
}

你可能感兴趣的:(Arduino,ESP8266)