Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and fix PID sensor (PID_USE_LOCAL_SENSOR) read race condition #22162

Merged
merged 3 commits into from
Sep 20, 2024

Conversation

spacelama
Copy link
Contributor

@spacelama spacelama commented Sep 18, 2024

Refactor PID since it was calling pid.tick willy-nilly upon demand from MQTT and the web (PIDShowValues and PIDShowValuesWeb had fundamental side-effects!) instead of on a periodic basis (and was being called with time interval of 0 when those times lined up!). Refactor web/mqtt display because there was shared code (that code turned out to be misguided and belonged in Every_Second loop, but now we are also similar to 39 thermostat)

Logging revealed that the vast majority of the time the sensor JSON was parsed to obtain current sensor data when using PID local sensor, it was failing to parse (and it would typically only work for a second around TELE_PERIOD, but even then, not reliably). This bug almost certainly affects xdrv_39_thermostat too, but using xsns_75_prometheus.ino as a template, we are able to update PV once per second, which allows us to be a lot more responsive. There is no danger of being "too responsive" because that's the point of PID, and the PID loop already scales feedback by interval between ticks.

Fixes #22094 tested against both local sensor and MQTT set PV

Description:

Related issue (if applicable): fixes #22094

Checklist:

  • The pull request is done against the latest development branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR and the code change compiles without warnings
  • The code change is tested and works with Tasmota core ESP8266 V.2.7.7
  • The code change is tested and works with Tasmota core ESP32 V.3.0.4
  • I accept the CLA.

NOTE: The code change must pass CI tests. Your PR cannot be merged unless tests pass

Refactor PID since it was calling pid.tick willy-nilly upon demand
from MQTT and the web instead of on a periodic basis (and was being
called with time interval of 0 when those times lined up!).  Refactor
web/mqtt display because there was shared code (that code turned out
to be misguided and belonged in Every_Second loop, but now we are also
similar to 39 thermostat)

Logging revealed that the vast majority of the time the sensor JSON
was parsed to obtain current sensor data when using PID local sensor,
it was failing to parse (and it would typically only work for a second
around TELE_PERIOD, but even then, not reliably).  This bug almost
certainly affects xdrv_39_thermostat too, but using
xsns_75_prometheus.ino as a template, we are able to update PV once
per second, which allows us to be a lot more responsive.  There is no
danger of being "too responsive" because that's the point of PID, and
the PID loop already scales feedback by interval between ticks.
@eku
Copy link
Contributor

eku commented Sep 18, 2024

A lot of additional log output. Did you need them for analysis and do they add value to the release?

@spacelama
Copy link
Contributor Author

I did need them for analysis, and they are at the DEBUG level. They will also help people when they're looking what to populate PID_LOCAL_SENSOR_NAME/PID_LOCAL_SENSOR_TYPE etc with.

Can probably do away with PIDShowValues now that it doesn't have side-effects, and PIDEverySecond, "Got isNum", maybe convert "not valid JSON" to error or INFO or similar (but might want it throttled, but perhaps the existence of the "PID: Local temperature sensor missing for longer than PID_MAX_INTERVAL" would prompt the user to turn on DEBUG which would then highlight this error).

I'll push a new commit...

@eku
Copy link
Contributor

eku commented Sep 19, 2024

they are at the DEBUG level

Yes, but they increase the images size a lot.

@sfromis
Copy link
Contributor

sfromis commented Sep 19, 2024

Some drivers have "additional development debug" wrapped in #ifdef (or even commented out after development finished), to avoid the code size increase.

@@ -276,12 +292,14 @@ void PIDShowSensor() {
JsonParserToken value_token = root[PID_LOCAL_SENSOR_NAME].getObject()[PSTR(PID_LOCAL_SENSOR_TYPE)];
if (value_token.isNum()) {
sensor_reading = value_token.getFloat();
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PID: PIDProcessSensor: Got isNum: %s"), buf.c_str());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented out code.

Copy link
Owner

@arendst arendst Sep 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to. Always usefull when debugging and as commented take up no code space.

@arendst arendst merged commit 694691e into arendst:development Sep 20, 2024
59 checks passed
@blacknell
Copy link
Contributor

Good stuff @spacelama

@Wintespe
Copy link

Mhm, you remove line 255 in your changes of the PID controller.

PIDShowSensor(); // set actual process value

Refer to:
PID-Feature computes with outdated temperature values #17636

We are back to outdated temperature values.
Now missing:

Pid.pid.setPv(sensor_reading, Pid.last_pv_update_secs);

This function sets the current process data in the PID algorithm. This no longer happens in
PIDEverySecond()

but in the time slice of TelePeriod. Therefore, if the outdated data,

@spacelama
Copy link
Contributor Author

@Wintespe , see my reply again your comment in #22094 .

josef109 pushed a commit to josef109/Tasmota that referenced this pull request Nov 7, 2024
arendst#22162)

* Refactor and fix PID sensor (PID_USE_LOCAL_SENSOR) read race condition

Refactor PID since it was calling pid.tick willy-nilly upon demand
from MQTT and the web instead of on a periodic basis (and was being
called with time interval of 0 when those times lined up!).  Refactor
web/mqtt display because there was shared code (that code turned out
to be misguided and belonged in Every_Second loop, but now we are also
similar to 39 thermostat)

Logging revealed that the vast majority of the time the sensor JSON
was parsed to obtain current sensor data when using PID local sensor,
it was failing to parse (and it would typically only work for a second
around TELE_PERIOD, but even then, not reliably).  This bug almost
certainly affects xdrv_39_thermostat too, but using
xsns_75_prometheus.ino as a template, we are able to update PV once
per second, which allows us to be a lot more responsive.  There is no
danger of being "too responsive" because that's the point of PID, and
the PID loop already scales feedback by interval between ticks.

* Reduce logging of PID now that query side-effects removed

* Comment out all new logging, but leave present for next debugger
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PID PID_LOCAL_SENSOR_NAME doesn't seem to update Pv
6 participants