I have DSM501a Sensor try to use it with ESP8266 according to this article and datasheet
Unfortunately, I can’t get stable or reasonable reading
What do I miss?
Low is the inverse of high, right? It should be easy enough to work out the inverse if you have any reliable detection and you know the duration.
What results are you getting when you use it?
I think if you invert your pins then I believe your high and low pulses will swap places. And that might solve that aspect.
pin:
number: GPIOXX
inverted: true
My interpretation of the calculation required is that you need to “calculate the % of low time in a period and then multiply it by 100” to get the “low ratio”.
Whereas I think the pulse width sensor will send each width value. So there’s prob more processing to do.
There’s also the duty cycle sensor which might come in handy. But I think it might keep accumulating so you might need to figure out how to reset it.
There’s various filters for moving average type calculations that might be helpful.
Once you’ve got the low ratio I believe you still need to use the numbers in the chart to convert it to the right units. You’d probably use a calibrate linear filter for that.
@Mahko_Mahko Actually I tried many methods but no one was close at less for me
finally, I decided to use Custom Sensor Component I tested This code below it works perfectly without ESPhome
int pin = 14;//DSM501A input D8
unsigned long duration;
unsigned long starttime;
unsigned long endtime;
unsigned long sampletime_ms = 30000;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;
void setup() {
Serial.begin(115200);
pinMode(pin,INPUT);
delay(10);
}
void loop() {
duration = pulseIn(pin, LOW);
lowpulseoccupancy += duration;
endtime = millis();
if ((endtime-starttime) > sampletime_ms)
{
ratio = (lowpulseoccupancy-endtime+starttime + sampletime_ms)/(sampletime_ms*10.0); // Integer percentage 0=>100
concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve mg/m3
lowpulseoccupancy = 0;
starttime = millis();
Serial.print("lowpulseoccupancy:");
Serial.print(lowpulseoccupancy);
Serial.print(" ratio:");
Serial.print(ratio);
Serial.print(" DSM501A:");
Serial.println(concentration);
}
}
src/main.cpp:49:6: error: 'void DSM501A::setup()' cannot be overloaded with 'void DSM501A::setup()'
49 | void setup() {
| ^~~~~
In file included from src/main.cpp:46:
src/DSM501A.h:19:8: note: previous declaration 'void DSM501A::setup()'
19 | void setup() override {
| ^~~~~
/config/A/Config/Device_Base.yaml:78:1: error: expected '}' at end of input
78 |
| ^
In file included from src/main.cpp:46:
src/DSM501A.h:11:56: note: to match this '{'
11 | class DSM501A : public PollingComponent, public Sensor {
| ^
/config/A/Config/Device_Base.yaml:78:1: error: expected unqualified-id at end of input
78 |
| ^
*** [.pioenvs/d1-mini/src/main.cpp.o] Error 1
========================= [FAILED] Took 48.27 seconds =========================
sensor:
- platform: duty_cycle
pin: GPIO12
name: Line 4 (PM2.5)
update_interval: 30s
filters:
- lambda: return (1 - x)* 100.0; #invert the percent (1-x) and then multiply by 100.
- calibrate_linear:
# Map the real values from the chart as per below.
- 0.0 -> 0.0
- 10.0 -> 12.1
However duty_cycle works on interrupts, which may not be 100% accurate if some interrupts were missing due to processing on some other stuff (ex. display).
I decided to use median filter to smooth result in case of not accurate reading.
Hello, thank you for clearing up my misconception that the PPD42NS and DSM501a sensors are the same
I used the code you provided for 2.5. It displays appropriate values.
I applied the same formula for 1.0. Unfortunately, the data is obviously incorrect.
Could you also provide the calculation formula for 1.0?
Thank you.