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

sen5x: add TPS & PM number concentration #6694

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from

Conversation

CodeInPolish
Copy link
Contributor

@CodeInPolish CodeInPolish commented May 7, 2024

What does this implement/fix?

This change adds a new command, listed as being available in FW >0.7

New entities can be configured:

  • pm_n_x_x for PM number concentration in #/cm3 (0.5, 1.0, 2.5, 4 and 10µm are available)
  • tps for typical particle size

The implementation is based on sensirion's own Embedded driver, available here.

This command returns the Mass Concentration, the Number Concentration and Typical Particle Size.
Since we already get the Mass Concentration from the SEN5X_CMD_READ_MEASUREMENT command, the new command will not update the Mass Concentration, to prevent doubling the export frequency of those entities.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Other

Related issue or feature (if applicable): fixes

Pull request in esphome-docs with documentation (if applicable): esphome/esphome-docs#

Test Environment

  • ESP32
  • ESP32 IDF
  • ESP8266
  • RP2040
  • BK72xx
  • RTL87xx

Example entry for config.yaml:

  - platform: sen5x
    pm_n_0_5:
      name: "PM <0.5µm Number concentration"
      id: pm_n_0_5
      accuracy_decimals: 1
    pm_n_1_0:
      name: "PM <1.0µm Number concentration"
      id: pm_n_1_0
      accuracy_decimals: 1
    pm_n_2_5:
      name: "PM <2.5µm Number concentration"
      id: pm_n_2_5
      accuracy_decimals: 1
    pm_n_4_0:
      name: "PM <4µm Number concentration"
      id: pm_n_4_0
      accuracy_decimals: 1
    pm_n_10_0:
      name: "PM <10µm Number concentration"
      accuracy_decimals: 1
    pm_tps:
      name: "Typical Particle size"
      id: pm_tps
      accuracy_decimals: 1

Checklist:

  • The code change is tested and works locally.
  • Tests have been added to verify that the new code works (under tests/ folder).

If user exposed functionality or configuration variables are added/changed:

image image

@codecov-commenter
Copy link

codecov-commenter commented May 7, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 54.25%. Comparing base (4d8b5ed) to head (9c8eb69).
Report is 571 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #6694      +/-   ##
==========================================
+ Coverage   53.70%   54.25%   +0.54%     
==========================================
  Files          50       50              
  Lines        9408     9587     +179     
  Branches     1654     1689      +35     
==========================================
+ Hits         5053     5201     +148     
- Misses       4056     4062       +6     
- Partials      299      324      +25     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

This change adds a new command, listed as being available in FW >0.7
New entities can be configured:
- pm_n_x_x for PM number concentration in #/cm3
- tps for typical particle size
@CodeInPolish CodeInPolish force-pushed the enh_sen5x_with_pm_number_concentration branch from 700ceba to 8fc28a5 Compare May 7, 2024 21:47
@CodeInPolish CodeInPolish marked this pull request as ready for review May 7, 2024 22:18
@probot-esphome
Copy link

probot-esphome bot commented May 7, 2024

Hey there @martgras, mind taking a look at this pull request as it has been labeled with an integration (sen5x) you are listed as a code owner for? Thanks!
(message by CodeOwnersMention)

tests/test11.5.yaml Outdated Show resolved Hide resolved
tests/components/sen5x/test.esp32-c3-idf.yaml Outdated Show resolved Hide resolved
esphome/components/sen5x/sen5x.cpp Outdated Show resolved Hide resolved
Comment on lines 333 to 337
if (this->get_pm_number_concentration_and_tps_) {
// delay the extra reading to allow update_measured_values to complete.
this->set_timeout(30, [this]() { this->update_measured_pm_(); });
}
}
Copy link
Member

Choose a reason for hiding this comment

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

There is no guarantee that this will be enough time. Ideally the component would be changes to have a small state machine and run through the stage one at a time in loop once triggered by the update function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's very true. Wouldn't a loop in the update function block the main event loop though?

Another approach I was testing was to perform only one reading (either pm with rh/t/nox/vox or full pm) per update.
If get_pm_number_concentration_and_tps_ was true, we would need to halve the user specified update_interval in the setup with set_update_interval and while it was reporting the correct update interval when dumping the config, the sensor was still exporting entities with the original period (i.e. halving it didn't affect the actual period between update calls).

I brainstormed a little and came up with another solution:

  • use an FSM with 3 states: idle, update_measured_values_progress, update_measured_values_done
  • set the idle, update_measured_values_progress and update_measured_values_done accordingly
  • create a small helper function to determine the current state of the FSM. This would be responsible for caling itself with a this->set_timeout(10) if the state isn't update_measured_values_done
  • Finally, trigger update_measured_pm_() function (from the helper function) when the FSM is in update_measured_values_done state and reset the FSM to idle in update_measured_pm_()

This would ensure update_measured_values_() has had enough time to complete without blocking the main event loop with a loop. What are your thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

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

No, in the loop state machine you can check the current time against the start time of the last state change and when enough time has passed, you read the data and publish. No delays and timeouts are needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jesserockz thank you. I misunderstood what you said earlier (and also didn't know loop was still triggered for PollingComponent)

I went ahead and implemented the brainstormed solution, because it's less code and less complicated than a full blown FSM for all the tasks to perform. If that's not an acceptable solution, let me know.

@esphome esphome bot marked this pull request as draft May 7, 2024 23:37
@esphome
Copy link

esphome bot commented May 7, 2024

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@CodeInPolish CodeInPolish marked this pull request as ready for review May 8, 2024 21:16
@esphome esphome bot requested a review from jesserockz May 8, 2024 21:16
@CodeInPolish CodeInPolish force-pushed the enh_sen5x_with_pm_number_concentration branch from 8e34154 to c075183 Compare May 8, 2024 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants