====== Setting and maintaining a static IP address to ESP8266 ====== ===== Introduction ===== The main reason for writing this article is the frustration that I experienced when I tried to configure an ESP8266 with a static IP address, as required by one of my projects. Although the first time after flashing the program, the IP address was set properly, then after a restart, the system presented an erratic behaviour. Sometimes the DHCP client was activated and a dynamic IP address was acquired by the DHCP server, while other times, the static IP address was set properly. This unstable behaviour made my head spin and caused me to search deeply under the hood. Unfortunately, most articles available on-line convey conflicting information, depending on the firmware or libraries people are using. I consider as the most helpful source of documentation the information found in [[https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/station-class.html|Station Class]]. I still have my doubts regarding the "proper" way of doing things, but since I am having success with the method that I have implemented, I decided to publish it and save fellow engineers valuable time and headaches. The article presents issues that need to be considered when setting a static IP address to your ESP8266 project which connects to a Wireless Access Point in STA mode . ===== Connecting to a Wireless Access Point ===== The process of connecting to an Access Point is not something that happens once in the lifetime of a project. Most examples found on-line show a few lines of code in the ''setup()'' section. But in real life, an Access Point may stop functioning due to a power-down, or even be replaced. Our client must try to connect in any case it is not connected. ESP8266 is equipped with several functions that take place in the background, assisting in automating the WiFi re-connection. But we should not forget that sometimes the micro-controller may have other tasks to perform besides the WiFi interface. Especially in cases where actions must be performed with strict timing requirements, it is obvious that we should maintain control at all times, both at the WiFi connection and re-connection code, as well as the rest of our software. To cope with this issue, my approach disables the automatic re-connection functions of the ESP8266 and does everything manually. As a result, the connection code must reside in the ''loop()'' section instead of the ''setup()''. This is the typical approach for any connection-oriented communication methods. My connection code is in a function called ''connectWiFi()'' which is called in the ''loop()'' section when there is no WiFi connection, or when I choose to do so. One could also experiment with the ''WiFi.isConnected()'' function instead of the ''WiFi.status()'' and let me know the result. The ''ethernetReceive()'' is my function which checks if there is an incoming packet and process it. I will discuss about the ''connectWiFi()'' below. For this method to work, we must instruct the libraries to avoid automatic connection and re-connection. See [[esp8266:esp8266-setting-static-ip#WiFi persistence and auto-connection|below]]. The example below is a bit simplistic but it conveys the idea. void loop() { if (WiFi.status() == WL_CONNECTED) { ethernetReceive(); // Function to process incoming packets } else { if (i_want_to_do_so && nothing_more_important_to_do) { connectWiFi(); } } //... other program code } ===== Arduino IDE settings ===== ESP8266 firmware is designed to store the configuration data of the last achieved connection in its flash memory. Libraries may use this information to re-connect after a temporary failure. I have not been able to understand exactly how this is performed and under which conditions, so I decided to take things in my own hands. In the ''Tools'' tab of Arduino IDE, there is a setting named ''Erase Flash''. The user has the following options: * Only Sketch * Sketch and WiFi Settings * All flash Contents When programming a new program and in order to erase any data from previous programs, I select ''Sketch and WiFi Settings''. ===== WiFi persistence and auto-connection ===== See [[https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/generic-class.html|Generic Class - persistent]] for details regarding this feature. In addition, we might have an additional reason to disable this feature for projects that are intended to operate 24x7, due to this: Quote: "Frequently calling these functions could cause wear on the flash memory..." As a result, I decide to set: WiFi.persistent(false); WiFi.setAutoConnect(false); WiFi.setAutoReconnect(false); ===== DHCP client disable ===== Library function ''WiFi.config()'' is supposed to disable the ESP8266 DHCP client and set the IP configuration of station interface to user defined arbitrary values. The syntax, as shown [[https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/station-class.html#config|here]] is: WiFi.config(local_ip, gateway, subnet, dns1, dns2) Please note the order of the arguments which differs from the syntax of the [[https://www.arduino.cc/en/Reference/WiFiConfig|Arduino WiFi library]], which is: WiFi.config(ip, dns, gateway, subnet); The reason that the designers of the ESP8266 core classes decided on a different argument order is beyond my understanding! Anyway, there is something tricky about ''WiFi.config()'' that I have never seen it mentioned in any online article: Function will return true if configuration change is applied successfully. If configuration can not be applied, because e.g. module is not in station or station + soft access point mode, then false will be returned. This tells us that sometimes the configuration change may not be applied successfully. The documentation does not provide an exhaustive list of all reasons that may result to this situation. Therefore, our code must check for the return value. In the example code below, it is assumed that if the project is not able to communicate, there is no reason to continue, so it re-tries until the configuration change is applied. No DNS server is set in this snippet. Other projects may exit, perform some other activities and try to connect at time intervals. while (!WiFi.config(localIPaddress, gateway, subnetMask)) { delay(500); } Perhaps, other actions need to be taken after several attempts, such as a restart. It was not necessary in any of my projects. If you find any additional information, please let me know. ===== Configuration data ===== Make sure that the IP addresses provided to ''WiFi.config()'' are proper IP addresses. In my experiments, it happened that instead of a gateway IP address, the code submitted the subnet mask 255.255.255.0. This is considered as an error by ''WiFi.config()'' and if the function is not inserted in the error-checking loop shown above, the ESP8266 will activate the DHCP client and you will try desperately to figure out what has happened!!! ===== Example connectWiFi() function ===== #define WIFI_RECONNECT_TIMER 500 const char* wifi_ssid = "********"; const char* wifi_password = "********"; IPAddress staticIP(192,168,1,22); IPAddress gateway(192,168,1,9); IPAddress subnetMask(255,255,255,0); void connectWiFi(void) { Serial.print("********** Connecting to WiFi : '"); Serial.print(configuration.wifi_ssid); Serial.print("'"); Serial.println(); // The following did not appear in the Station Class documentation. Perhaps it is the default mode //WiFi.mode(WIFI_STA); WiFi.persistent(false); WiFi.setAutoConnect(false); WiFi.setAutoReconnect(false); while (!WiFi.config(staticIP, gateway, subnetMask)) { delay(500); } WiFi.begin(wifi_ssid, wifi_password); int i = 0; while (WiFi.status() != WL_CONNECTED) { Serial.print("."); // avoid long lines if (++i > 80) { Serial.println(); i = 0; } delay(WIFI_RECONNECT_TIMER); } Serial.println(); Serial.print("-> Connected to WiFi access point: "); Serial.print(wifi_ssid); Serial.println(); } ===== Conclusion ===== There is a huge amount of information in the ESP8266 documentation. Unfortunately, most of the software documentation presents the static situation of classes and methods, while the dynamic situation of how these classes and methods interact in order to achieve the optimum result is not so clear. In this article, I presented my experiences with connecting an ESP8266 to a Wireless Access Point and the way to do it reliably, as mandated by projects that operate 24x7. Perhaps the information in this article is not complete, or contains errors or does not apply in all conditions and with all ESP8266 modules. If you would like to share your experiences, please feel free to contact me. ~~DISQUS~~