Skip to content

Commit 4533ae0

Browse files
committed
Improve P1P2 Status page (Write command)
1 parent 309d8b7 commit 4533ae0

File tree

4 files changed

+125
-75
lines changed

4 files changed

+125
-75
lines changed

README.md

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,18 @@ The controller has a built-in web interface. You can use this web interface to c
4141
- rollover of counters is synchronized
4242
- content of the P1P2 Status page is updated in the background (fetch API), javascript alert is shown if connection is lost
4343
* user settings:
44-
- can be changed via web interface (see screenshots bellow)
45-
- stored in EEPROM
44+
- can be changed via web interface (see screenshots bellow), all web UI inputs have proper validation
45+
- stored in Arduino EEPROM
4646
- retained during firmware upgrade (only in case of major version change, Arduino loads factory defaults)
47-
- all web interface inputs have proper validation
48-
- factory defaults for user settings can be specified in advanced_settings.h
49-
- settings marked \* are only available if ENABLE_DHCP is defined in the sketch
50-
- settings marked \*\* are only available if ENABLE_EXTRA_DIAG is defined in the sketch
47+
- factory defaults for user settings can be changed in advanced_settings.h
5148
* advanced settings:
52-
- can be changed in sketch (advanced_settings.h)
49+
- can be changed in sketch before comnpilation (advanced_settings.h)
5350
- stored in flash memory
5451

5552
# Hardware
5653
Get the hardware and connect together:
5754

58-
* **Arduino Uno**.<br>Cheap clones are sufficient.
55+
* **Arduino Uno or Mega** (and possibly other boards with ATmega chips).<br>On Mega you have to configure Serial in advanced settings in the sketch.
5956
* **Ethernet shield with WIZnet chip (W5100, W5200 or W5500)**.<br>The ubiquitous W5100 shield for Uno/Mega is sufficient. If available, I recommend W5500 Ethernet Shield. You can also use combo board MCU + ethernet (such as ATmega328 + W5500 board from Keyestudio).<br>ATTENTION: Ethernet shields with ENC28J60 chip will not work !!!
6057
* **Custom P1P2 Uno adapter**.<br>You can [solder your own adapter](https://github.com/Arnold-n/P1P2Serial/tree/main/circuits#p1p2-adapter-as-arduino-uno-hat) or buy one from Arnold-n (his e-mail address can be found on line 3 of his library [P1P2Serial.cpp](https://github.com/Arnold-n/P1P2Serial/blob/main/P1P2Serial.cpp)).
6158

@@ -67,18 +64,19 @@ Here is my HW setup (cheap Arduino Uno clone + W5500 Ethernet shield from Keyest
6764

6865
You can either:
6966
- **Download and flash my pre-compiled firmware** from "Releases".
70-
- **Compile your own firmware**. Download this repository (all *.ino files) and open arduino-altherma-controller.ino in Arduino IDE. If you want, you can check advanced_settings.h for advanced settings (can only be changed in the sketch) and for default factory settings (can be later changed via web interface). Download all required libraries, compile and upload your program to Arduino. The program uses the following external libraries (all are available in Arduino IDE's "library manager"):
71-
- CircularBuffer (https://github.com/rlogiacco/CircularBuffer)
72-
- StreamLib (https://github.com/jandrassy/StreamLib)
67+
- **Compile your own firmware**. Download this repository (all *.ino files) and open arduino-modbus-rtu-tcp-gateway.ino in Arduino IDE. If you want, you can check advanced_settings.h for advanced settings (can only be changed in the sketch) and for default factory settings (can be later changed via web interface). Download all required libraries, compile and upload your program to Arduino. The program uses the following external libraries (all are available in Arduino IDE's "library manager"):
68+
- CircularBuffer (https://github.com/rlogiacco/CircularBuffer)
69+
- StreamLib (https://github.com/jandrassy/StreamLib)
7370

7471
Connect your Arduino to ethernet and use your web browser to access the web interface on default IP: http://192.168.1.254
72+
Enjoy :-)
7573

7674
# Settings
7775

7876
This controller has a built-in webserver which allows you to configure the controller itself, check basic system info of the controller and the status of its connection to the P1/P2 bus.
7977

80-
- settings marked \* are only available if ENABLE_DHCP is defined in the sketch
81-
- settings marked \*\* are only available if ENABLE_EXTENDED_WEBUI is defined in the sketch
78+
- settings marked \* are only available if ENABLE_DHCP is defined in advanced_settings.h
79+
- settings marked \*\* are only available if ENABLE_EXTENDED_WEBUI is defined in advanced_settings.h
8280

8381
## System Info
8482

@@ -131,10 +129,10 @@ This controller has a built-in webserver which allows you to configure the contr
131129
- Requests for the counters packets. If the **Enable Write to P1P2** setting is set to *Automatically*, requests for counter packets are sent even if the controller failed to receive an address (is in read only mode).
132130
- Write commands received via web interface or UDP. These packets are written to the P1/P2 bus and written in Daikin EEPROM.
133131
* **EEPROM Write Quota Reached**. Daily EEPROM Write Quota (configured in **P1P2 Settings**) was reached. The command (received via UDP or from the web interface) was dropped.
134-
* **Write Command Queue Full**. Internal queue (circular buffer) for commands is full. The command (received via UDP or from the web interface) was dropped.
135-
* **Write Command Invalid**. Command received via UDP or from the web interface was invalid, it was dropped. Possible reasons:
132+
* **Write Command Error**. Command received via UDP or from the web interface was invalid, it was dropped. Possible reasons:
136133
- Packet type (first byte) is not supported (PACKET_PARAM_VAL_SIZE in advanced settings is set to zero).
137134
- Incorrect packet length. Command should have 1 byte for type, 2 bytes for parameter number and the correct numer of bytes for the parameter value (see PACKET_PARAM_VAL_SIZE in advanced settings).
135+
- Internal queue (circular buffer) for commands is full.
138136
* **Parity Read Error**.
139137
* **Too Long Read Error**. Packet received is longer than the read buffer.
140138
* **Start Bit Write Error**. Start bit error during write.
@@ -328,6 +326,10 @@ The code was tested on Arduino Uno, ethernet chips W5100 and W5500. It may work
328326
* The random number generator (for random MAC) is seeded through watch dog timer interrupt - this will work only on Arduino (credits to https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library/arduino-random-seed)
329327
* The restart function will also work only on Arduino.
330328

329+
## Ethernet Power On Reset Issue
330+
331+
Sometimes the gateway is running fine for days but after power-up or brief loss of power (caused for example by undervoltage), ethernet connection is lost. What is the problem? The W5x00 chip on the Arduino Ethernet Shield is not initialized correctly upon power-up. There is an easy solution to the issue described in a separate [document here](Ethernet_SW_Reset.md).
332+
331333
## Remote IP settings on the W5500 Chip
332334

333335
The Ethernet.setRetransmissionCount() and Ethernet.setRetransmissionTimeout() commands do not work on W5500 chips because of a bug in the Ethernet.h library (see [this issue](https://github.com/arduino-libraries/Ethernet/issues/140)). As a result, Arduino fails to read data from the P1/P2 bus (read errors, CRC errors) if certain conditions are met:
@@ -352,17 +354,17 @@ As of April 2023:
352354
| **Project** | **[budulinek/<br>arduino-altherma-controller](https://github.com/budulinek/arduino-altherma-controller)** | **[Arnold-n/<br>P1P2Serial](https://github.com/Arnold-n/P1P2Serial)** | **[raomin/<br>ESPAltherma](https://github.com/raomin/ESPAltherma)** | **[tadasdanielius/<br>daikin_altherma](https://github.com/tadasdanielius/daikin_altherma)** | **[speleolontra/<br>daikin_residential_altherma](https://github.com/speleolontra/daikin_residential_altherma)** ||
353355
|------------------------------------|------------------------------------------------------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------|------------------------------------------------------------------------------|------------------------------------------------------------------------------|-------------------------------------------|
354356
| **Hardware** | • Arduino Uno<br>• Ethernet Shield<br>• Custom P1P2 Uno adapter | • Custom all-in-one board | • M5StickC (or any ESP32/ESP8266 board)<br> • external relay (optional) | • Daikin LAN adapter<br>(BRP069A62/ BRP069A61<br>with OLD firmware) | • Daikin LAN adapter<br>(BRP069A62/ BRP069A61<br>with NEW firmware) | • Daikin WLAN adapter<br>(BRP069A78) |
355-
| **Programable MCUs** | 1<br>ATmega328P | 2<br>ATmega328P + ESP8266 | 1<br>ESP32/8266 | --- | --- ||
357+
| **Programable MCUs** | ATmega328P | ATmega328P + ESP8266 | ESP32/8266 | --- | --- ||
356358
| **Connection to Daikin Altherma** | P1/P2 bus | P1/P2 bus | X10A serial port | P1/P2 bus | P1/P2 bus | dedicated slot |
357359
| **Interface** | • Ethernet | • WiFi<br>• Ethernet (optional) | • WiFi | • Ethernet | • Ethernet | • WiFi |
358360
| **Local LAN or Cloud** | Local | Local | Local | Local | Cloud ||
359-
| **Controller configuration** | • web interface<br>• sketch |console<br>• sketch | • sketch | • web interface | • web interface ||
361+
| **Controller configuration** | • web interface |HA<br> • console | • sketch | • web interface | • web interface ||
360362
| **OTA upgrades** | No | Yes | Yes | Yes | Yes ||
361363
| **Read data from Daikin Altherma** | Yes | Yes | Yes | Limited | Limited ||
362364
| **Control Daikin Altherma** | Yes | Yes | Limited | Yes | Yes ||
363365
| **Communication protocol** | UDP | MQTT | MQTT | Websockets | Websockets ||
364366
| **Data format** | HEX | JSON | JSON | JSON | JSON ||
365-
| **Integration with** | • Loxone<br>• other systems (via UDP-HEX) | • Home Assistant<br>• other systems (via MQTT-JSON) | • Home Assistant<br>• other systems (via MQTT-JSON) | • Home Assistant | • Home Assistant ||
367+
| **Integration with** | • Loxone<br><br>• other systems (via UDP-HEX) | • Home Assistant<br><br>• other systems (via MQTT-JSON) | • Home Assistant<br><br>• other systems (via MQTT-JSON) | • Home Assistant | • Home Assistant ||
366368

367369
## Version history
368370

arduino-altherma-controller/02-UDP.ino

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,48 @@ void recvUdp() {
3131
*/
3232
/**************************************************************************/
3333
void checkCommand(byte command[], byte cmdLen) {
34-
if (cmdQueue.available() > cmdLen) { // check available space in queue
35-
if (PACKET_PARAM_VAL_SIZE[command[0] - PACKET_TYPE_CONTROL[FIRST]] != 0 // check if param size is not zero (0 = write command not supported (yet))
36-
&& cmdLen - 3 == (PACKET_PARAM_VAL_SIZE[command[0] - PACKET_TYPE_CONTROL[FIRST]]) // check parameter value size
37-
&& (command[0] >= PACKET_TYPE_CONTROL[FIRST] && command[0] <= PACKET_TYPE_CONTROL[LAST])) { // check packet type
38-
if (changed36Param(command) == true) {
39-
// push to queue (incl. cmdLen)
40-
cmdQueue.push(cmdLen); // first byte in queue is cmdLen
41-
for (byte i = 0; i < cmdLen; i++) {
42-
cmdQueue.push(command[i]);
43-
}
44-
}
45-
} else {
46-
data.eepromDaikin.invalid++; // Write Command Invalid
47-
}
48-
} else {
34+
// Validate packet type and parameter size
35+
byte packetIndex = command[0] - PACKET_TYPE_CONTROL[FIRST];
36+
if (command[0] < PACKET_TYPE_CONTROL[FIRST] || command[0] > PACKET_TYPE_CONTROL[LAST] ||
37+
PACKET_PARAM_VAL_SIZE[packetIndex] == 0 ||
38+
cmdLen - 3 != PACKET_PARAM_VAL_SIZE[packetIndex]) {
39+
data.eepromDaikin.invalid++; // Write Command Invalid
40+
return;
41+
}
42+
// Check queue availability
43+
if (cmdQueue.available() <= cmdLen) {
4944
data.eepromDaikin.invalid++; // Write Queue Full
45+
return;
46+
}
47+
// Check if parameter has changed
48+
if (!changed36Param(command)) return;
49+
// Push command to queue
50+
cmdQueue.push(cmdLen); // First byte in queue is cmdLen
51+
for (byte i = 0; i < cmdLen; i++) {
52+
cmdQueue.push(command[i]);
5053
}
5154
}
5255

56+
// void checkCommand(byte command[], byte cmdLen) {
57+
// if (cmdQueue.available() > cmdLen) { // check available space in queue
58+
// if (PACKET_PARAM_VAL_SIZE[command[0] - PACKET_TYPE_CONTROL[FIRST]] != 0 // check if param size is not zero (0 = write command not supported (yet))
59+
// && cmdLen - 3 == (PACKET_PARAM_VAL_SIZE[command[0] - PACKET_TYPE_CONTROL[FIRST]]) // check parameter value size
60+
// && (command[0] >= PACKET_TYPE_CONTROL[FIRST] && command[0] <= PACKET_TYPE_CONTROL[LAST])) { // check packet type
61+
// if (changed36Param(command) == true) {
62+
// // push to queue (incl. cmdLen)
63+
// cmdQueue.push(cmdLen); // first byte in queue is cmdLen
64+
// for (byte i = 0; i < cmdLen; i++) {
65+
// cmdQueue.push(command[i]);
66+
// }
67+
// }
68+
// } else {
69+
// data.eepromDaikin.invalid++; // Write Command Invalid
70+
// }
71+
// } else {
72+
// data.eepromDaikin.invalid++; // Write Queue Full
73+
// }
74+
// }
75+
5376
/**************************************************************************/
5477
/*!
5578
@brief Deletes command from queue.

arduino-altherma-controller/03-P1P2.ino

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -140,25 +140,42 @@ void processParseRead(uint16_t n, uint16_t delta) {
140140
*/
141141
/**************************************************************************/
142142
void processErrors(uint16_t nread) {
143-
bool packetError[P1P2_LAST];
144-
memset(packetError, 0, sizeof(packetError));
143+
uint8_t packetErrorFlags = 0; // 2-bit flag to store P1P2_WRITE_ERROR and P1P2_READ_ERROR
144+
145145
for (uint16_t i = 0; i < nread; i++) {
146-
if ((EB[i] & ERROR_SB) // collision suspicion due to data verification error in reading back written data
147-
|| (EB[i] & ERROR_BE) // collision suspicion due to data verification error in reading back written data
148-
|| (EB[i] & ERROR_BC)) { // collision suspicion due to 0 during 2nd half bit signal read back
149-
packetError[P1P2_WRITE_ERROR] = true;
146+
uint8_t errors = EB[i];
147+
if (errors & (ERROR_SB | ERROR_BE | ERROR_BC)) { // collision suspicion errors
148+
packetErrorFlags |= (1 << P1P2_WRITE_ERROR);
150149
}
151-
if ((EB[i] & ERROR_PE) // parity error detected
152-
|| (EB[i] & ERROR_OR) // buffer overrun detected (overrun is after, not before, the read byte)
153-
|| (EB[i] & ERROR_CRC)) { // CRC error detected in readpacket
154-
packetError[P1P2_READ_ERROR] = true;
150+
if (errors & (ERROR_PE | ERROR_OR | ERROR_CRC)) { // parity, overrun, or CRC errors
151+
packetErrorFlags |= (1 << P1P2_READ_ERROR);
155152
}
156153
}
157-
for (byte i = 0; i < P1P2_LAST; i++) {
158-
if (packetError[i] == true) data.p1p2Cnt[i]++;
159-
}
154+
if (packetErrorFlags & (1 << P1P2_WRITE_ERROR)) data.p1p2Cnt[P1P2_WRITE_ERROR]++;
155+
if (packetErrorFlags & (1 << P1P2_READ_ERROR)) data.p1p2Cnt[P1P2_READ_ERROR]++;
160156
}
161157

158+
159+
// void processErrors(uint16_t nread) {
160+
// bool packetError[P1P2_LAST];
161+
// memset(packetError, 0, sizeof(packetError));
162+
// for (uint16_t i = 0; i < nread; i++) {
163+
// if ((EB[i] & ERROR_SB) // collision suspicion due to data verification error in reading back written data
164+
// || (EB[i] & ERROR_BE) // collision suspicion due to data verification error in reading back written data
165+
// || (EB[i] & ERROR_BC)) { // collision suspicion due to 0 during 2nd half bit signal read back
166+
// packetError[P1P2_WRITE_ERROR] = true;
167+
// }
168+
// if ((EB[i] & ERROR_PE) // parity error detected
169+
// || (EB[i] & ERROR_OR) // buffer overrun detected (overrun is after, not before, the read byte)
170+
// || (EB[i] & ERROR_CRC)) { // CRC error detected in readpacket
171+
// packetError[P1P2_READ_ERROR] = true;
172+
// }
173+
// }
174+
// for (byte i = 0; i < P1P2_LAST; i++) {
175+
// if (packetError[i] == true) data.p1p2Cnt[i]++;
176+
// }
177+
// }
178+
162179
/**************************************************************************/
163180
/*!
164181
@brief Writes to the P1P2 bus.

0 commit comments

Comments
 (0)