Closed erkr closed 2 weeks ago
Update; I was able to determine the right math for calculating the CO value by mapping points from the datasheet onto a double log graph and find a matching function (see here). Pseudo code for the CO calculation should be:
if (red_f > 3.4f) {
CO = 0.0;
}
else if (red_f < 0.01) {
CO = 1000.0;
}
else {
CO = 4.2/ pow(red_f,1.2);
}
I will determine the other sensors as well
Ammonia (here):
if (red_f > 0.98f) {
Ammonia = 0.0;
}
else if (red_f < 0.2532) {
Ammonia = 0.0; // outside the ammonia range->unlikely
}
else {
Ammonia = 0.9/ pow(red_f,4.6);
}
Methane (here):
if (red_f > 0.9f) {
Methane = 0.0;
}
else if (red_f < 0.5) {
Methane = 0.0; // outside the range->unlikely
}
else {
Methane = 630/ pow(red_f,4.4);
}
Ethanol (here):
if (red_f > 1.0f) {
Ethanol = 0.0;
}
else if (red_f < 0.02) {
Ethanol = 0.0; // outside the range->unlikely
}
else {
Ethanol = 1.52/ pow(red_f,1.55);
}
Note: unsure about the range. The ethanol line starts around 1ppm, spec mentions 10-500ppm. I took above 1ppm
H2 (here):
if (red_f > 0.9f) {
H2 = 0.0;
}
else if (red_f < 0.02) {
H2 = 0.0; // outside the range->unlikely
}
else {
H2 = 0.85/ pow(red_f,1.75);
}
Last but not least. NO2 on the OX sensor (here):
if (ox_f < 0.3f) {
NO2 = 0.0;
}
else {
NO2 = 0.164 * pow(0x_f,0.975);
}
This sensor is almost linear. The original formula is close. Mainly the original threshold (1.1) is way too high, so it only will register concentrations above 0.15ppm. That should start at 0.05ppm (threshold 0.3)
Update; I was able to determine the right math for calculating the CO value by mapping points from the datasheet onto a double log graph and find a matching function (see here). Pseudo code for the CO calculation should be:
if (red_f > 3.4f) { CO = 0.0; } else if (red_f < 0.01) { CO = 1000.0; } else { CO = 4.2/ pow(red_f,1.2); }
I will determine the other sensors as well
Working on a PR for this. Are they by chance backwards in some? CO example below
if (red_f > 3.4f) {
CO = 0.0; // Should be 1000.0
}
else if (red_f < 0.01) {
CO = 1000.0; // Should be 0
}
else {
CO = 4.2/ pow(red_f,1.2);
}
Thanks for working on this🥳
Working on a PR for this. Are they by chance backwards in some? CO example below
No, I believe I got that right. Note in the graph the relation sensor readout of RED vs CO is negative. So smaller readouts are higher CO values. A readout of 3.4 represents the top left of the CO curve (1ppm), 0.01 represents the bottom right 1000ppm
Small remark. This formula:
CO = 4.2 / pow(red_f,1.2);
It's mathematically equal to:
CO = 4.2 * pow(red_f,-1.2);
Note the minus sign in pow(). Whatever you prefer☺️
Created a PR that matches. Mind taking a look @erkr
Looks great. How does the process work? Will this be a dev version that we can test before realising it to the public?
Looks great. How does the process work? Will this be a dev version that we can test before realising it to the public?
You can test the PR using External Components
Please confirm on the PR itself once tested.
The problem
I noticed that the sensor readings for the mics_4514 are way off. The current code two issues: Low concentrations are ignored, higher values are calculated wrong.
Here is the graph for the datasheet for the RED sensor (the OX based sensors have the same issue):
I marked the thresholds used in code for the various sensors with colored dots. Two issues for each sensor:
Which version of ESPHome has the issue?
Firmware: 2024.6.6 (Jul 8 2024, 07:53:53)
What type of installation are you using?
Home Assistant Add-on
Which version of Home Assistant has the issue?
core 2024.7
What platform are you using?
mics_4514
Board
ESP32-C3 (Apollo Air-1 device)
Component causing the issue
mics_4514
Example YAML snippet
n/a the issue is in the component code itself. Here a code snippet of the component.
(https://github.com/esphome/esphome/blob/3920029aff9dd85fd5f0775945b8426c03da471c/esphome/components/mics_4514/mics_4514.cpp#L71-L80)
Anything in the logs that might be useful for us?
Additional information
No response