mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
Version 1.1. See ChangeLog
This commit is contained in:
131
README.md
131
README.md
@@ -1,10 +1,10 @@
|
||||
# EMS-ESP-Boiler
|
||||
|
||||
EMS-ESP-Boiler is an controller running on an ESP8266 to communicate with EMS (Energy Management System) based Boilers from the Bosch range. This includes the Buderus and Nefit ranger of boilers, heaters and thermostats.
|
||||
EMS-ESP-Boiler is a project to build a controller circuit running with an ESP8266 to communicate with EMS (Energy Management System) based Boilers and Thermostats from the Bosch range and compatibles such as Buderus, Nefit, Junkers etc.
|
||||
|
||||
There are 3 parts to this project, first the design of the circuit, second the code to deploy to an ESP8266 based microcontroller and lastly settings for Home Assistant to monitor data and issue direct commands via MQTT.
|
||||
There are 3 parts to this project, first the design of the circuit, second the code for the ESP8266 microcontroller firmware and lastly an example configuration for Home Assistant to monitor the data and issue direct commands via MQTT.
|
||||
|
||||
[](CHANGELOG.md)
|
||||
[](CHANGELOG.md)
|
||||
[](https://github.org/xoseperez/espurna/tree/dev/)
|
||||
[](LICENSE)
|
||||
|
||||
@@ -23,7 +23,11 @@ There are 3 parts to this project, first the design of the circuit, second the c
|
||||
- [EMS Reading and Writing](#ems-reading-and-writing)
|
||||
- [The ESP8266 Source Code](#the-esp8266-source-code)
|
||||
- [Supported EMS Types](#supported-ems-types)
|
||||
- [Supporting other Thermostats types](#supporting-other-thermostats-types)
|
||||
- [Supported Thermostats](#supported-thermostats)
|
||||
- [RC20 (Moduline 300)](#rc20-moduline-300)
|
||||
- [RC30 (Moduline 400)](#rc30-moduline-400)
|
||||
- [RC35](#rc35)
|
||||
- [TC100/TC200 (Nefit Easy)](#tc100tc200-nefit-easy)
|
||||
- [Customizing The Code](#customizing-the-code)
|
||||
- [Using MQTT](#using-mqtt)
|
||||
- [The Basic Shower Logic](#the-basic-shower-logic)
|
||||
@@ -33,28 +37,30 @@ There are 3 parts to this project, first the design of the circuit, second the c
|
||||
- [Using ESPurna](#using-espurna)
|
||||
- [Using Pre-built Firmware](#using-pre-built-firmware)
|
||||
- [Building Using Arduino IDE](#building-using-arduino-ide)
|
||||
- [Known Issues and ToDo's](#known-issues-and-todos)
|
||||
- [Known Issues](#known-issues)
|
||||
- [Wish List](#wish-list)
|
||||
- [Your Comments and Feedback](#your-comments-and-feedback)
|
||||
- [DISCLAIMER](#disclaimer)
|
||||
|
||||
## Introduction
|
||||
|
||||
My original intention for this home project with to build my own smart thermostat for my Nefit Trendline boiler and then have it controlled via [Home Assistant](https://www.home-assistant.io/) on my mobile phone. I had a few ESP32s and ESP8266s lying around from previous IoT projects and building a specific circuit to decode the EMS messages was a nice challenge into more complex electronic circuits. I then began adding new features such as timing how long the shower was running for and triggering an alarm (actually a shot of cold water!) after a certain duration.
|
||||
My original intention for this home project with to build my own smart thermostat for my Nefit Trendline boiler and then have it controlled automatically via [Home Assistant](https://www.home-assistant.io/) on my mobile phone. I had a few ESP32s and ESP8266s lying around from previous IoT projects and building a specific circuit to decode the EMS messages was a nice challenge into designing complete end-to-end complex electronic circuits. I then began adding new features such as timing how long the shower would be running for and subsequently triggering an alarm (actually a shot of cold water) after a certain period.
|
||||
|
||||
Acknowledgments and kudos to the following people and their open-sourced projects:
|
||||
Acknowledgments and kudos to the following people and their open-sourced projects that have helped me get this far:
|
||||
|
||||
**susisstrolch** - Probably the first working version of the EMS bridge circuit I could find designed for the ESP8266. I borrowed Juergen's [schematic](https://github.com/susisstrolch/EMS-ESP12) and parts of his code logic.
|
||||
**susisstrolch** - Probably the first working version of the EMS bridge circuit I found designed for the ESP8266. I borrowed Juergen's [schematic](https://github.com/susisstrolch/EMS-ESP12) and parts of his code logic.
|
||||
|
||||
**bbqkees** - Kees built a [circuit](https://github.com/bbqkees/Nefit-Buderus-EMS-bus-Arduino-Domoticz) and wrote some sample Arduino code to read from the EMS and push messages to Domoticz. His SMD board is also available to purchase from him directly.
|
||||
**bbqkees** - Kees built a [circuit](https://github.com/bbqkees/Nefit-Buderus-EMS-bus-Arduino-Domoticz) and some sample Arduino code to read from the EMS and push messages to Domoticz. His SMD board is also now available for purchase.
|
||||
|
||||
**EMS Wiki** - A comprehensive [reference](https://emswiki.thefischer.net/doku.php?id=wiki:ems:telegramme) for decoding the EMS telegrams, which I found not always to be 100% accurate. It's in German so use Google Translate if you need help.
|
||||
|
||||
## Supported Boilers Types
|
||||
|
||||
Most Bosch branded boilers that support the Logamatic EMS (and EMS+) bus protocols work with this design. Which are Nefit, Buderus, Worcester and Junkers and copyrighted.
|
||||
Most Bosch branded boilers that support the Logamatic EMS (and EMS+) bus protocols work with this design. Which are Nefit, Buderus, Worcester and Junkers and copyrighted. Please make sure you read the **Disclaimer** carefully before sending ambigious messages to your EMS bus as you cause device damage.
|
||||
|
||||
## Supported ESP8266 devices
|
||||
|
||||
I've tested the code and circuit with a few ESP8266 development boards such as the Wemos D1 Mini, Wemos D1 Mini Pro, Nodemcu0.9 and Nodemcu2 boards. It will also work on bare ESP8266 chips such as the 12s but do make sure you disabled the LED support and wire the UART correctly as this is switched (explained below).
|
||||
I've tested the code and circuit with a few ESP8266 development boards such as the Wemos D1 Mini, Wemos D1 Mini Pro, Nodemcu0.9 and Nodemcu2 boards. It will also work on bare ESP8266 chips such as the E-12s but do make sure you disabled the LED support and wire the UART correctly as the code doesn't use the normal Rx and Tx pins. This is explained below.
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -72,22 +78,23 @@ Use the telnet client to inform you of all activity and errors real-time. This i
|
||||
|
||||

|
||||
|
||||
If you type 'v 3' and Enter, it will toggle verbose logging showing you more detailed messages. I use ANSI colors with white text for info messages, green for well formatted telegram packages (which have validated CRC checks), red for corrupt packages and yellow for send responses.
|
||||
If you type 'l 4' and Enter, it will toggle verbose logging showing you more detailed messages. I use ANSI colors with white text for info messages, green for well formatted telegram packages (which have validated CRC checks), red for corrupt packages and yellow for send responses.
|
||||
|
||||

|
||||
|
||||
To see the current values of the Boiler and its parameters type 's' and hit Enter. Watch out for unsuccessful telegram packets in the #CrcErrors line.
|
||||
|
||||

|
||||
|
||||
Commands can be issued directly to the EMS bus typing in a letter followed by an optional parameter and pressing Enter. Supported commands are:
|
||||
|
||||
- **r** to send a read command to the boiler. The 2nd parameter is the type. For example 'b 33' will request type UBAParameterWW and bring back the Warm Water temperatures from the Boiler.
|
||||
- **b** to send a read command to the boiler. The 2nd parameter is the type. For example 'b 33' will request type UBAParameterWW and bring back the Warm Water temperatures from the Boiler.
|
||||
- **t** is similar, but to send a read command to the thermostat.
|
||||
- **T** set the thermostat temperature to the given celsius value
|
||||
- **w** to adjust the temperature of the warm water from the boiler
|
||||
- **a** to turn the warm water on and off
|
||||
- **a** to turn the warm tap water on and off
|
||||
- **h** to list all the recognized EMS types
|
||||
- **p** to toggle the Polling response on/off (note it's not necessary to have Polling enabled to work)
|
||||
- **P** to toggle the Polling response on/off (note it's not necessary to have Polling enabled to work)
|
||||
- **m** to set the thermostat mode to manual or auto
|
||||
- **S** to toggle the Shower Timer functionality on/off
|
||||
- **A** to toggle the Shower Timer Alert functionality on/off
|
||||
@@ -118,7 +125,8 @@ And lastly if you don't fancy building the circuit, [bbqkees](http://www.domotic
|
||||
|
||||
### Powering The EMS Circuit
|
||||
|
||||
The EMS circuit will work with both 3.3V and 5V. It's easiest though to power directly from the ESP8266's 3V3 line and run a steady 5V into the microcontroller. Powering the ESP8266 microcontroller can be either
|
||||
The EMS circuit will work with both 3.3V and 5V. It's easiest though to power directly from the ESP8266's 3V3 line and run a steady 5V into the microcontroller. Powering the ESP8266 microcontroller can be either:
|
||||
|
||||
- via the USB if your dev board has one
|
||||
- using an external 5V power supply into the 5V vin on the board
|
||||
- powering from the 3.5" service jack on the boiler. This will give you 8V so you need a buck converter (like a [Pololu D24C22F5](https://www.pololu.com/product/2858)) to step this down to 5V to provide enough power to the ESP8266 (250mA at least)
|
||||
@@ -128,7 +136,6 @@ The EMS circuit will work with both 3.3V and 5V. It's easiest though to power di
|
||||
| ------------------------------------------ |
|
||||
|  |
|
||||
|
||||
|
||||
## How The EMS Bus Works
|
||||
|
||||
Packages are sent to the EMS "bus" from the Boiler and any other compatible connected devices via serial TTL transmission. The protocol is 9600 baud, 8N1 (8 bytes, no parity, 1 stop bit). Each package is terminated with a break signal `<BRK>`, a 11-bit long low signal of zeros.
|
||||
@@ -151,7 +158,7 @@ Our circuit acts as a service key and thus uses an ID 0x0B. This ID is reserved
|
||||
|
||||
### EMS Polling
|
||||
|
||||
The bus master (boiler) sends out a poll request every second by sending out a sequential list of all possible IDs as a single byte followed by the break signal. The ID always has its high 7th bit set so in the code we're looking for 1 byte messages matching the format `[dest|0x80] <BRK>`.
|
||||
The bus master (boiler) sends out a poll request every second by sending out a sequential list of all possible IDs as a single byte followed by the break signal. The ID always has its high 8th bit (MSB) set so in the code we're looking for 1 byte messages matching the format `[dest|0x80] <BRK>`.
|
||||
|
||||
Any connected device can respond to a Polling call with an acknowledging by sending back a single byte with its own ID. In our case we would listen for a `[0x8B] <BRK>` (meaning us) and then send back `[0x0B] <BRK>` to say we're alive and ready. Although I found this is not needed for normal operation so it's disabled as default in the code.
|
||||
|
||||
@@ -175,7 +182,7 @@ The tables below shows which types are broadcasted regularly by the boiler (ID 0
|
||||
| Source (ID) | Type ID | Name | Description | Frequency |
|
||||
| ----------------- | ------- | ----------------- | --------------------------------------------------- | ---------- |
|
||||
| Thermostat (0x17) | 0x06 | RCTime | returns time and date on the thermostat | 60 seconds |
|
||||
| Thermostat (0x17) | 0x91 | RC20StatusMessage | returns current and set temperatures | 60 seconds |
|
||||
| Thermostat (0x17) | 0x91 | RC30StatusMessage | returns current and set temperatures | 60 seconds |
|
||||
| Thermostat (0x17) | 0xA3 | RCTempMessage | returns temp values from external (outdoor) sensors | 60 seconds |
|
||||
|
||||
Refer to the code in `ems.cpp` for further explanation on how to parse these message types and also reference the EMS Wiki.
|
||||
@@ -184,15 +191,15 @@ Refer to the code in `ems.cpp` for further explanation on how to parse these mes
|
||||
|
||||
Telegram packets can only be sent after the Boiler sends a poll to the sending device. The response can be a read command to request data or a write command to send data. At the end of the transmission a poll response is sent from the client (`<ID> <BRK>`) to say we're all done and free up the bus for other clients.
|
||||
|
||||
When doing a request to read data the `[src]` is our device (0x0B) and the `[dest]` has it's 7-bit set. Say we were requesting data from the thermostat we would use `[dest] = 0x97` since RC30 has an ID of 0x17.
|
||||
When doing a request to read data the `[src]` is our device `(0x0B)` and the `[dest]` must have has it's MSB (8th bit) set. Say we were requesting data from the thermostat we would use `[dest] = 0x97` since RC30 has an ID of 0x17.
|
||||
|
||||
When doing a write request, the 7th bit is masked in the `[dest]`. After this write request the destination device will send either a single byte 0x01 for success or 0x04 for fail.
|
||||
Following a write request, the `[dest]` doesn't have the 8th bit set and after this write request the destination device will send either a single byte 0x01 for success or 0x04 for failure.
|
||||
|
||||
Every telegram sent is echo'd back to Rx.
|
||||
|
||||
## The ESP8266 Source Code
|
||||
|
||||
*Disclaimer*: This code here is really for reference only, I don't expect anyone to use as is since it's highly tailored to my environment and my needs. Most of the code however is self explanatory with comments here and there. If you wish to make some changes start with the `defines` and `const` sections at the top of `boiler.ino`.
|
||||
*Disclaimer*: This code here is really for reference only, I don't expect anyone to use "as is" since it's highly tailored to my environment and my needs. Most of the code however is self explanatory with comments here and there in the code.
|
||||
|
||||
The code is built on the Arduino framework and is dependent on these external libraries:
|
||||
|
||||
@@ -213,27 +220,45 @@ The code is built on the Arduino framework and is dependent on these external li
|
||||
|
||||
`ems.cpp` defines callback functions that handle all the broadcast types listed above (e.g. 0x34, 0x18, 0x19 etc) plus these extra types:
|
||||
|
||||
| Source (ID) | Type ID | Name | Description |
|
||||
| ----------------- | ------- | ----------------------------- | ---------------------------------------- |
|
||||
| Boiler (0x08) | 0x33 | UBAParameterWW | reads selected & desired warm water temp |
|
||||
| Boiler (0x08) | 0x14 | UBATotalUptimeMessage | |
|
||||
| Boiler (0x08) | 0x15 | UBAMaintenanceSettingsMessage | |
|
||||
| Boiler (0x08) | 0x16 | UBAParametersMessage | |
|
||||
| Thermostat (0x17) | 0xA8 | RC20Temperature | sets operating modes for a RC20 & RC30 |
|
||||
| Thermostat (0x17) | 0x02 | Version | reads Version major/minor |
|
||||
| Thermostat (0x18) | 0x0A | EasyTemperature | thermostat monitor for an TC100/Easy |
|
||||
| Source (ID) | Type ID | Name | Description |
|
||||
| ----------------- | ---------------- | ----------------------------- | ---------------------------------------- |
|
||||
| Boiler (0x08) | 0x33 | UBAParameterWW | reads selected & desired warm water temp |
|
||||
| Boiler (0x08) | 0x14 | UBATotalUptimeMessage | |
|
||||
| Boiler (0x08) | 0x15 | UBAMaintenanceSettingsMessage | |
|
||||
| Boiler (0x08) | 0x16 | UBAParametersMessage | |
|
||||
| Thermostat (0x17) | 0xA8 | RC20Set | sets operating modes for an RC20 |
|
||||
| Thermostat (0x10) | 0xA7 | RC30Set | sets operating modes for an RC30 |
|
||||
| Thermostat | 0x02 | Version | reads Version major/minor |
|
||||
| Thermostat | 0x91, 0x41, 0x0A | Status Message | read monitor values |
|
||||
|
||||
In `boiler.ino` you can make calls to automatically send these read commands. See the function *regularUpdates()*
|
||||
|
||||
#### Supporting other Thermostats types
|
||||
### Supported Thermostats
|
||||
|
||||
The code is originally designed for a Moduline300 (RC30) thermostat.
|
||||
Modify `EMS_ID_THERMOSTAT` in `myconfig.h` to the thermostat type you want to support.
|
||||
|
||||
To adjust for a RC35 first change `EMS_ID_THERMOSTAT` in `ems.cpp`. A RC35 thermostat has 4 heating circuits and to read the values use different Monitor type IDs (e.g. 0x3E, 0x48, etc). The mode (0=night, 1=day, 2=holiday) is the first byte of the telegram and the temperature is the value of the 2nd byte divided by 2. Then to set temperature values use the Working Mode with type IDs (0x3D, 0x47,0x51 and 0x5B) respectively. Set the offset (byte 4 of the header) to determine which temperature you're changing; 1 for night, 2 for day and 3 for holiday. The data value is the desired temperature multiplied by 2 as a single byte.
|
||||
#### RC20 (Moduline 300)
|
||||
|
||||
There is limited support for an Nefit Easy TC100) thermostat. The current room temperature and setpoint temperature can be read. What still needs fixing is
|
||||
- reading the mode (manual vs clock)
|
||||
- setting the temperature
|
||||
Read and write of setpoint temp and mode supported.
|
||||
|
||||
#### RC30 (Moduline 400)
|
||||
|
||||
Read and write of setpoint temp and mode supported.
|
||||
|
||||
Type's 3F, 49, 53, 5D are identical. So are 4B, 55, 5F and mostly zero's. Types 40, 4A, 54 and 5E are also the same.
|
||||
|
||||
#### RC35
|
||||
|
||||
***not implemented yet***!
|
||||
|
||||
An RC35 thermostat can support up to 4 heating circuits each controlled with their own Monitor and Working Mode IDs.
|
||||
|
||||
Fetching the thermostats setpoint temp us by requesting 0x3E and looking at the 3rd byte in the data telegram (data[2]) and dividing by 2.
|
||||
The mode is on type 0x47 (or 0x3D) and the 8th byte (data[7]). 0=off, 1=on, 2=auto
|
||||
|
||||
#### TC100/TC200 (Nefit Easy)
|
||||
|
||||
There is limited support for an Nefit Easy TC100/TC200 type thermostat. The current room temperature and setpoint temperature can be read. What I'm still figuring out is how to read the mode and set the temperature values without sending http post commands to their web server.
|
||||
|
||||
### Customizing The Code
|
||||
|
||||
@@ -286,7 +311,7 @@ PlatformIO is my preferred way. The code uses a modified version [ESPHelper](htt
|
||||
**On Windows:**
|
||||
|
||||
- Download [Git](https://git-scm.com/download/win) (install using the default settings)
|
||||
- Download and install [Visual Studio Code](https://code.visualstudio.com/docs/?dv=win) (VSC)
|
||||
- Download and install [Visual Studio Code](https://code.visualstudio.com/docs/?dv=win) (VSC). It's like 40MB so don't confuse with the commercial Microsoft Visual Studio.
|
||||
- Restart the PC (if using Windows) to apply the new PATH settings. It should now detect Git
|
||||
- Install these VSC extensions: PlatformIO IDE & GitLens, and then click reload to activate them
|
||||
- Git clone this repo, eith using `git clone` from PlatformIO's terminal or the Git GUI interface
|
||||
@@ -295,6 +320,8 @@ PlatformIO is my preferred way. The code uses a modified version [ESPHelper](htt
|
||||
**On Linux (e.g. Ubuntu under Windows10):**
|
||||
|
||||
- make sure Python 2.7 is installed
|
||||
- make sure you have a Linux distro installed (https://docs.microsoft.com/en-us/windows/wsl/install-win10)
|
||||
- Do:
|
||||
```python
|
||||
% pip install -U platformio
|
||||
% sudo platformio upgrade
|
||||
@@ -322,19 +349,17 @@ PlatformIO is my preferred way. The code uses a modified version [ESPHelper](htt
|
||||
7. Build the web interface: `node node_modules/gulp/bin/gulp.js`. This will create a compressed `code/espurna/static/index.html.gz.h`. If you get warnings about lf during the building edit `gulpfile.js` and change the line `'failOnError': true` to `false` as a temporary workaround.
|
||||
8. Modify the platformio.ini file making sure you add `-DUSE_CUSTOM_H -DUSE_EXTRA` to the `debug_flags`
|
||||
9. Copy the following files from EMS-ESP-Boiler repo to where you installed ESPurna
|
||||
|
||||
```c
|
||||
espurna/index.html -> code/html/index.html
|
||||
espurna/custom.h -> code/config/custom.h
|
||||
espurna/boiler-espurna.ino -> code/espurna/boiler-espurna.ino
|
||||
ems*.* -> code/espurna/
|
||||
```
|
||||
|
||||
10. Now build and upload as you usually would with PlatformIO (or ctrl-arl-t and choose the right build). Look at my version of platformio.ini as an example.
|
||||
11. When the firmware loads, use a wifi connected pc/mobile to connect to the Access Point called ESPURNA_XXXXXX. Use 'fibonacci' as the password. Navigate to `http://192.168.4.1` from a browser, set a new username and password when prompted, log off the wifi and reconnect to the AP using these new credentials. Again go to 192.168.4.1
|
||||
12. In the ADMIN page enable Telnet and SAVE
|
||||
13. In the WIFI page add your home wifi details, click SAVE and reboot, and go to the new IP
|
||||
14. Configure MQTT
|
||||
11. When the firmware loads, use a wifi connected pc/mobile to connect to the Access Point called ESPURNA_XXXXXX. Use 'fibonacci' as the password. Navigate to `http://192.168.4.1` from a browser, set a new username and password when prompted, log off the wifi and reconnect to the AP using these new credentials. Again go to 192.168.4.1
|
||||
12. In the ADMIN page enable Telnet and SAVE
|
||||
13. In the WIFI page add your home wifi details, click SAVE and reboot, and go to the new IP
|
||||
14. Configure MQTT
|
||||
|
||||
The Telnet functions are `BOILER.READ`, `BOILER.INFO` and a few others for reference. `HELP` will list them. Add your own functions to expand the functionality by calling the EMS* functions as in the examples.
|
||||
|
||||
@@ -378,18 +403,24 @@ Porting to the Arduino IDE can be a little tricky but it is possible.
|
||||
- Put all the files in a single sketch folder (`ESPHelper.*, boiler.ino, ems.*, emsuart.*`)
|
||||
- cross your fingers and hit CTRL-R to compile...
|
||||
|
||||
## Known Issues and ToDo's
|
||||
## Known Issues
|
||||
|
||||
Some annoying issues that need fixing:
|
||||
|
||||
- Very infrequently an EMS write command is not sent, probably due to a collision somewhere in the UART between an incoming Rx and a Poll. The retries in the code fix this for now.
|
||||
- I've seen a few duplicate telegrams being processed. Again, it's harmless and not a big issue, but still a bug.
|
||||
|
||||
Here's my top things I'm still working on:
|
||||
## Wish List
|
||||
|
||||
- Complete the ESP32 version. It's surprisingly a lot easier doing the UART handling on an ESP32 with the ESP-IDF SDK. I have a first version beta that is working.
|
||||
- Find a better way to control the 3-way valve to switch the warm water off quickly rather than deactivating the warm water heater each time. There is an unsupported call to do this, but I think its too risky and experimental. I'd love to get my hands on an Nefit Easy, sniff the packets being sent and reverse engineer the logic. Anyone help?
|
||||
- Measure amount of gas in m3 per day for the hot water vs the central heating, and convert this into cost in Home Assistant
|
||||
- Support changing temps on an Nefit Easy. To do this you must send XMPP messages directly to the thermostat. See this project: https://github.com/robertklep/nefit-easy-core
|
||||
- Store custom params like wifi credentials, mqtt, thermostat type on ESP8266 using SPIFFS
|
||||
- Automatic detection of thermostat type
|
||||
- Add support for a temperature sensor on the circuit (DS18B20)
|
||||
|
||||
## Your Comments and Feedback
|
||||
|
||||
Any comments, suggestions or code changes are very welcome. Please post a GitHub issue.
|
||||
Any comments, suggestions or code contributions are very welcome. Please post a GitHub issue.
|
||||
|
||||
## DISCLAIMER
|
||||
|
||||
This code and libraries were developed from information gathered on the internet and many hours of reverse engineering the communications between the EMS bus and thermostats. It is **not** based on any official documentation or supported libraries from Buderus/Junkers/Nefit (and associated companies) and therefore there are no guarantees whatsoever regarding the safety of your devices and/or their settings, or the accuracy of the information provided.
|
||||
Reference in New Issue
Block a user