├── .gitignore ├── .travis.yml ├── .vscode └── extensions.json ├── LICENSE ├── README.md ├── include ├── MasterConfig.h └── README ├── lib └── README ├── platformio.ini ├── scripts ├── mosquitto_pub.sh ├── mosquitto_sub.sh └── mqtt_pub_test.sh ├── src └── main.cpp ├── test └── README └── wireshark-dump └── 04-07-2019_long_tcp_packet.pcapng /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .pioenvs 3 | .piolibdeps 4 | .vscode/.browse.c_cpp.db* 5 | .vscode/c_cpp_properties.json 6 | .vscode/launch.json 7 | .vscode/ipch 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < https://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < https://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < https://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choose one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # - platformio update 39 | # 40 | # script: 41 | # - platformio run 42 | 43 | 44 | # 45 | # Template #2: The project is intended to be used as a library with examples. 46 | # 47 | 48 | # language: python 49 | # python: 50 | # - "2.7" 51 | # 52 | # sudo: false 53 | # cache: 54 | # directories: 55 | # - "~/.platformio" 56 | # 57 | # env: 58 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 59 | # - PLATFORMIO_CI_SRC=examples/file.ino 60 | # - PLATFORMIO_CI_SRC=path/to/test/directory 61 | # 62 | # install: 63 | # - pip install -U platformio 64 | # - platformio update 65 | # 66 | # script: 67 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 68 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ] 7 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ESP32_W5500_MQTT 2 | ================ 3 | 4 | Simple example of using Arduino Ethernet library with ESP32 and W5500 to subscribe and publish to MQTT broker. 5 | 6 | IMPORTANT: 7 | **It has been created to present intermittent connection problems which seems to occur on W5500, but not on WiFi connection.** 8 | 9 | I didn't have time, but the problem/solution described in [this comment](https://github.com/PaulStoffregen/Ethernet/issues/39#issuecomment-711109000) may be related. 10 | 11 | ## Physical connection between ESP32 and W5500 12 | 13 | * GPIO23 <--> MOSI 14 | * GPIO19 <--> MISO 15 | * GPIO18 <--> SCLK 16 | * GPIO5 <--> SCS 17 | * GPIO11 <--> RESET 18 | 19 | It is possible to change pins used for chip-select and reset in 20 | `include/MasterConfig.h` file. 21 | 22 | 23 | ## Configuration 24 | 25 | Fixed IP address of the device (`ETHERNET_IP`) and MQTT hostname (`MQTT_HOSTNAME`) should most probably be changed in `include/MasterConfig.h` to fit your setup. 26 | Changing other configurations in `MasterConfig.h` is optional. 27 | 28 | 29 | ## Running the test 30 | 31 | It has been prepared as PlatformIO project. All dependencies will be automatically downloaded if run with PlatformIO. 32 | 33 | Script for publishing messages (so ESP32 has something to read) has been prepared with Bash and Docker. That means it Docker is required for it and it is simple to run on Linux. It may also work with Windows Subsystem for Linux but it has not been tested. 34 | 35 | 1. Load and run project on ESP32 36 | 2. Start script `scripts/mqtt_pub_test.sh [MQTT_HOST]` 37 | 3. Observe serial output from ESP32 38 | 39 | ### Expected results: 40 | - `Sending uptime message to MQTT: mydevice/uptime <- 15` is visible on serial output periodically, 41 | - `Message arrived [mydevice/listen] 2019-06-20T14:25:11` is visible on serial output periodically 42 | - above should happen indefinitely (until network is available). 43 | 44 | 45 | ### Actual results: 46 | 47 | - ESP32 gets disconnected from network after some time (time periods differs significantly - from few minutes to couple of hours). 48 | 49 | - Log `ERROR: mqttClient has been disconnected. Reconnecting...` is visible on serial output. 50 | 51 | Log `Sending uptime message to MQTT` might still be visible on ESP32 serial output, but message with uptime is not send to MQTT broker at that time. This can be observed by subscribing to MQTT broker on `mydevice/uptime` topic. Subscribing to the topic can be easily achieved with `scripts/mosquitto_sub.sh -h [MQTT_HOST] -t "mydevice/uptime"` (requires Bash and Docker). 52 | -------------------------------------------------------------------------------- /include/MasterConfig.h: -------------------------------------------------------------------------------- 1 | #define ETHERNET_MAC "BA:E5:E3:B1:44:DD" // Ethernet MAC address (have to be unique between devices in the same network) 2 | #define ETHERNET_IP "10.0.88.244" // IP address of RoomHub when on Ethernet connection 3 | 4 | #define ETHERNET_RESET_PIN 11 // ESP32 pin where reset pin from W5500 is connected 5 | #define ETHERNET_CS_PIN 5 // ESP32 pin where CS pin from W5500 is connected 6 | 7 | #define MQTT_HOSTNAME "10.0.88.100" 8 | #define MQTT_PORT 1883 9 | 10 | #define MQTT_PUBLISH_INTERVAL_MS 5000 -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:esp32doit-devkit-v1] 12 | platform = espressif32@1.6.0 13 | board = esp32doit-devkit-v1 14 | framework = arduino 15 | lib_deps = 16 | Ethernet 17 | PubSubClient 18 | upload_port = /dev/ttyUSB0 19 | 20 | monitor_speed = 115200 -------------------------------------------------------------------------------- /scripts/mosquitto_pub.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | docker run --name mosquitto_pub -it --rm --net=host eclipse-mosquitto mosquitto_pub $@ -------------------------------------------------------------------------------- /scripts/mosquitto_sub.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | trap_ctrlc () 4 | { 5 | # perform cleanup here 6 | echo "\n\n" 7 | echo "Removing docker container" 8 | docker kill mosquitto_sub 9 | echo "Cleanup done" 10 | } 11 | 12 | trap "trap_ctrlc" 2 13 | 14 | docker run -d --name mosquitto_sub --rm --net=host eclipse-mosquitto mosquitto_sub $@ 15 | docker logs -f mosquitto_sub 16 | -------------------------------------------------------------------------------- /scripts/mqtt_pub_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" 4 | 5 | MQTT_HOST=$1 6 | 7 | while true; do 8 | currentDate=`date '+%Y-%m-%dT%H:%M:%S'`; 9 | $SCRIPT_DIR/mosquitto_pub.sh -h $MQTT_HOST -t "mydevice/listen" -m "$currentDate" -r; 10 | echo "mydevice/listen <- $currentDate"; 11 | sleep 5; 12 | done -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "MasterConfig.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | IPAddress ipAddress; 9 | PubSubClient mqttClient; 10 | EthernetClient ethClient; 11 | 12 | uint32_t lastMqttPublishTime = 0; 13 | 14 | void macCharArrayToBytes(const char* str, byte* bytes) { 15 | for (int i = 0; i < 6; i++) { 16 | bytes[i] = strtoul(str, NULL, 16); 17 | str = strchr(str, ':'); 18 | if (str == NULL || *str == '\0') { 19 | break; 20 | } 21 | str++; 22 | } 23 | } 24 | 25 | /* 26 | * Wiz W5500 reset function 27 | */ 28 | void ethernetWizReset(const uint8_t resetPin) { 29 | pinMode(resetPin, OUTPUT); 30 | digitalWrite(resetPin, HIGH); 31 | delay(250); 32 | digitalWrite(resetPin, LOW); 33 | delay(50); 34 | digitalWrite(resetPin, HIGH); 35 | delay(350); 36 | } 37 | 38 | void connectEthernet() { 39 | delay(500); 40 | byte* mac = new byte[6]; 41 | macCharArrayToBytes(ETHERNET_MAC, mac); 42 | ipAddress.fromString(ETHERNET_IP); 43 | 44 | Ethernet.init(ETHERNET_CS_PIN); 45 | ethernetWizReset(ETHERNET_RESET_PIN); 46 | 47 | Serial.println("Starting ETHERNET connection..."); 48 | Ethernet.begin(mac, ipAddress); 49 | delay(200); 50 | 51 | Serial.print("Ethernet IP is: "); 52 | Serial.println(Ethernet.localIP()); 53 | } 54 | 55 | void setupMqtt(const char* hostname, uint16_t port, Client& _connectionClient) { 56 | mqttClient.setClient(_connectionClient); 57 | mqttClient.setServer(hostname, port); 58 | } 59 | 60 | void connectToMqtt(const char* deviceName, const char* willTopic, uint8_t willQoS, bool willRetain, const char* willMessage) { 61 | Serial.println("Connecting to MQTT broker..."); 62 | while(!mqttClient.connect(deviceName, willTopic, willQoS, willRetain, willMessage)) { 63 | Serial.print("Connecting to MQTT as "); 64 | Serial.println(deviceName); 65 | delay(1000); 66 | } 67 | Serial.print("Connected to MQTT as "); 68 | Serial.print(deviceName); 69 | Serial.print(". LWT: "); 70 | Serial.print(willTopic); 71 | Serial.print(" -> "); 72 | Serial.println(willMessage); 73 | } 74 | 75 | void mqttCallback(char* topic, byte* payload, unsigned int length) { 76 | Serial.print("Message arrived ["); 77 | Serial.print(topic); 78 | Serial.print("] "); 79 | for (int i=0;i MQTT_PUBLISH_INTERVAL_MS) { 107 | String uptimeInSec = String(now/1000); 108 | Serial.print("Sending uptime message to MQTT: "); 109 | Serial.print("mydevice/uptime <- "); 110 | Serial.println(uptimeInSec); 111 | mqttClient.publish("mydevice/uptime", uptimeInSec.c_str()); 112 | mqttClient.publish("mydevice/fakemessage", "sending long message to check -> of this influence stability"); 113 | mqttClient.publish("mydevice/fakemessage", "and another to check if -> of this influence stability"); 114 | mqttClient.publish("mydevice/fakemessage", "and even one more to check if -> of this influence stability"); 115 | mqttClient.publish("mydevice/fakemessage2", "sending long message to check -> of this influence stability"); 116 | mqttClient.publish("mydevice/fakemessage2", "and another to check if -> of this influence stability"); 117 | mqttClient.publish("mydevice/fakemessage2", "and even one more to check if -> of this influence stability"); 118 | lastMqttPublishTime = now; 119 | } 120 | } -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PIO Unit Testing and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PIO Unit Testing: 11 | - https://docs.platformio.org/page/plus/unit-testing.html 12 | -------------------------------------------------------------------------------- /wireshark-dump/04-07-2019_long_tcp_packet.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jozala/ESP32_W5500_MQTT/c907963f9615db4c17975c69d80fc835ca387bd3/wireshark-dump/04-07-2019_long_tcp_packet.pcapng --------------------------------------------------------------------------------