letscontrolit / ESPEasy

Easy MultiSensor device based on ESP8266/ESP32
http://www.espeasy.com
Other
3.22k stars 2.2k forks source link

Problems with the _P053_PMSx003 Dust Plugin #914

Closed micropet closed 10 months ago

micropet commented 6 years ago

Hello everybody, I have some devices with the dust sensor PMS7003 and some with the SDS021.

The devices with the SDS021 run smoothly for weeks. Those with the PMS7003 only make a few measurements and then hang. The dust levels are no longer updated.

After a reset or disconnection of the voltage, the values are updated only a couple of times, then nothing comes up.

The rest of the measurements, such as BME280 BH1750, continue.

device_4 device_page_1

ShardanX commented 5 years ago

I'm using a ESPEasy version from february so i can't, sadly. The System info says "manual reboot" - which is obviously wrong.

I'm using timing rules to put the sensor to sleep - this might be the reason why reading does not stop for me.

on System#Boot do
   gpio,16,0
   timerSet,1,20
endon

On Rules#Timer=1 do
   LongPulse,16,1,5
   timerSet,1,20
endon

GPIO 16 connected to the "SET" pin at the PMS is used to push the sensor into sleep mode. On system boot the pin is set to 0 (low), sensor sleeps. Timer 1 is set to run for 20 seconds, then trigger a 5 sec pulse on GPIO 16. Timer 1 is set again to 20 seconds so it loops the sensor pulse.

blb4github commented 5 years ago

FYI, maybe it's useful: I'm running a PMS7003 with almost all recent mega-builds and don't experience issues with stability. I'm running on a Wemos Mini D1 in combination with BME280 and BH1750. Maybe relevant is I'm not updating the device to main controller via the Device Setting but via rules:

on System#Boot do gpio,14,0 timerSet,1,50 endon

On Rules#Timer=1 do Longpulse,14,1,30 timerSet,1,300 timerSet,2,28 endon

On Rules#Timer=2 do Publish %sysname%/PMS7003/pm1.0, [PMS7003#PM1.0] Publish %sysname%/PMS7003/pm2.5, [PMS7003#PM2.5] Publish %sysname%/PMS7003/pm10, [PMS7003#PM10] endon

schermafbeelding 2018-08-27 om 15 10 42
TD-er commented 5 years ago

Hmm, that's something that will also be resolved when this PR is finished.

micropet commented 5 years ago

An interesting approach.

I have not got my PMS running since last year. After a restart, only one measurement is executed. Then nothing happens anymore.

What does your device page look like?

Thats mine: device_4

blb4github commented 5 years ago

My device page attached. to get the PMS7003 in sleep you need to connect the Reset Pin, see https://www.letscontrolit.com/wiki/index.php/PMSx003

schermafbeelding 2018-08-30 om 11 07 45
micropet commented 5 years ago

OK, thank you. I do not use Sleepmode.

AndrewB82 commented 5 years ago

Hi,

I am bit struggling with getting the 5003 sensor to sleep - I've been experimenting with rules and followed tutorials above, but sensor seems to be active all time and data is read according to sensor delay setting no matter the GPIO16 set high or low. The fan is also working right from the boot (I can hear it) although the GPIO16 is set to low on boot. Do you have any idea what the problem might be?

Best regards,

Andrzej

TD-er commented 5 years ago

GPIO16 is used to get the ESP8266 out of deep sleep (when connected to GPIO0) This has nothing to do with the sensor itself.

As far as I know, the sensor has to be told to switch the fan on/off and that is not implemented yet. As a work-around you could disable power to the sensor and control that via the ESP8266, but that has to be done via external commands and is not yet included in the plugin for this sensor. It will, but I've been too busy getting stuff stable the last few month, so I've not yet looked into this sensor. :(

AndrewB82 commented 5 years ago

UPDATE: [SOLVED] - it was a wiring issue with SET pin, now it works like a charm.

Thanks for the answer, but I am confused now - @ShardanX described his way of getting the sensor to sleep few posts above, similar to the one on the plugin website:

I'm using a ESPEasy version from february so i can't, sadly. The System info says "manual reboot" - which is obviously wrong.

I'm using timing rules to put the sensor to sleep - this might be the reason why reading does not stop for me.

on System#Boot do
   gpio,16,0
   timerSet,1,20
endon

On Rules#Timer=1 do
   LongPulse,16,1,5
   timerSet,1,20
endon

GPIO 16 connected to the "SET" pin at the PMS is used to push the sensor into sleep mode. On system boot the pin is set to 0 (low), sensor sleeps. Timer 1 is set to run for 20 seconds, then trigger a 5 sec pulse on GPIO 16. Timer 1 is set again to 20 seconds so it loops the sensor pulse.

It does not work for me, however, just as I wrote before. I connected GPIO16 to SET on PMS. Should it work then?

TD-er commented 5 years ago

@AndrewB82 I guess I must be mistaken then, mixing up sensors I guess.

AndrewB82 commented 5 years ago

@TD-er thanks anyway - btw I solved my issue - it was a wiring problem - now the sensor goes to sleep and works like a charm.

TD-er commented 5 years ago

Is it also stable in readings? There is still an issue about these sensors regarding stability of readings. Not the values read, but only occasionally a value is read and others claim to be missed/rejected.

AndrewB82 commented 5 years ago

@TD-er I have set up rules to get readings every 5 minutes and send them to domoticz, but not tested it on longer run. I am planning to put the sensor in some case and then test its working. I will pay attention to this issue.

red55der commented 5 years ago

I'm testing a PMS7003 sensor to. It was running for hours ok, but then got stuck. Now it's get stuck after one or two readings after boot. Use a Wemos D1 mini, GPIO3/1. Going to test with above mentioned rules.

AndrewB82 commented 5 years ago

Mine 5003 has worked flawlessly for almost 2 weeks now with readings every 5 minutes, sent to Domoticz and Fibaro. Readings seem accurate and I see correlation with outside sensors, although from time time some outlier readings occur which I cannot explain.

fzdunek commented 5 years ago

Hi The rules doesn’t work for me. I connected pin set from Pms7003 to gpio16 and fan don’t stop. Any solution ?

AndrewB82 commented 5 years ago

Have you double checked wiring @edwarpan ? For me it was the case. Do you use rules set explicitly in example?

fzdunek commented 5 years ago

Yes, i tried pin Reset and set on pms but still nothing. I used rules from example I have two other devices - OLED and bmp280 you thinking is it a problem? Or the pms be damaged.

On 6 Nov 2018, at 18:22, Andrzej Browarski notifications@github.com wrote:

Have you double checked wiring @edwarpan ? For me it was the case. Do you use rules set explicitly in example?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

AndrewB82 commented 5 years ago

I also have OLED and bme280, but no reset pin, only set on gpio16 and it works.

fzdunek commented 5 years ago

i checked, set pin from pms to d0 (gpio16) and get 5V because earlier i delivered 3.3V from esp. And still nothing. In dust device interval set to 30s. 2 1

I also have OLED and bme280, but no reset pin, only set on gpio16 and it works.

apszowski commented 5 years ago

I had similar problems and I was able to fix it.

The LongPulse command doesn't work properly if you don't configure a Switch Input on the GPIO you want to use.

image

Once I configured the Switch Input it started working :

EVENT: Rules#Timer=1 ACT : Longpulse,16,1,30 SW : GPIO 16 Pulse set for 30 sec ACT : timerSet,1,300 ACT : timerSet,2,28 SW : Switch state 1 Output value 1 EVENT: PMS5003_Enabled#Switch=1.00 Command: timerset Command: timerset EVENT: Rules#Timer=2 ACT : Publish /WeatherStation/PMS5003/pm1.0, 5 ACT : Publish /WeatherStation/PMS5003/pm2.5, 10 ACT : Publish /WeatherStation/PMS5003/pm10, 10 Command: publish Command: publish Command: publish SW : Switch state 0 Output value 0 EVENT: PMS5003_Enabled#Switch=0.00

Without the Switch Input, the GPIO pin would switch to 1 when the LongPulse gets executed, but would never switch back. Using the switch allows it to work.

I also use the rules mentioned by @blb4github instead of sending it via the device controller, and it works very stable now, no timing problems.

on System#Boot do gpio,16,0 timerSet,1,50 endon

On Rules#Timer=1 do Longpulse,16,1,30 timerSet,1,300 timerSet,2,28 endon

On Rules#Timer=2 do Publish /%sysname%/PMS5003/pm1.0, [PMS5003#PM1.0] Publish /%sysname%/PMS5003/pm2.5, [PMS5003#PM2.5] Publish /%sysname%/PMS5003/pm10, [PMS5003#PM10] endon

According to the documentation of the PMSx003 the 30 seconds high on the SET pin are required to get a stable output from the sensor anyway... the 5 seconds simply isn't good enough.

Hopefully this will get fixed in the future so this kind of workarounds isn't necessary.

blb4github commented 5 years ago

I did have problem with Longpulse, sorry I didn't mention before... I did fix it on another way (without switch);I did use gpio,x,0 and gpio,x,1:

on System#Boot do gpio,14,0 timerSet,1,20 endon

On Rules#Timer=1 do gpio,14,1 timerSet,1,300 timerSet,2,28 endon

On Rules#Timer=2 do Publish %sysname%/PMS7003/pm1.0, [PMS7003#PM1.0] Publish %sysname%/PMS7003/pm2.5, [PMS7003#PM2.5] Publish %sysname%/PMS7003/pm10, [PMS7003#PM10] gpio,14,0 endon

AndrewB82 commented 5 years ago

@edwarpan actually, I forgot to mention - I haven't used longpulse either - my solution is similar to the one by @blb4github

jawilczek commented 5 years ago

AndrewB82

Can you describe how you connected ESPEASY with FIBARO?

AndrewB82 commented 5 years ago

Here you have code excerpts - I got it through virtual device button which is shceduled to be pressed every 15 minutes - honestly I found some code on Fibaro Forum and fine tuned it to my needs, but do not remember where exactly:

local thisdevice = fibaro:getSelfId() -- make sure youve correctly set the ip adress of the ESPEasy node local taskId = {"1","3"} -- make sure this matches the task id on your ESPEasy local conn = Net.FHttp(fibaro:getValue(thisdevice, 'IPAddress'), fibaro:getValue(thisdevice, 'TCPPort'))

local values = {}; local valueCounter = 1; local err = false;

local PM25global = "PM25IndoorDIY"; -- this is global variable where PM reading is stored local PM25norm = 25;
local PM10norm = 50;

local varTelegram = "TelegramMessage"; local telegramTimeSTART = 7; local telegramTimeSTOP = 22;

local icon1 = 1105;
local icon2 = 1106;
local icon3 = 1107;
local icon4 = 1108;
local icon5 = 1109;
local icon6 = 1110;
local icon0 = 1112;

local currentHour = os.date("%H");

for i = 1, #taskId do if (not err) then response, status, errorCode = conn:GET('/json?tasknr=' .. taskId[i])

    if errorCode == 0 then
        fibaro:debug("Request "..i.." status: "..status)    
        jsonTable = json.decode(response);
        for j = 1, #jsonTable.TaskValues do
            values[valueCounter] = jsonTable.TaskValues[j].Value
            valueCounter = valueCounter + 1;
        end
    else
        err = true;
        fibaro:debug("Connection Error");
        fibaro:log("Connection Error");
        fibaro:call(thisdevice, "setProperty", "currentIcon", icon0);
        fibaro:call(thisdevice, "setProperty", "ui.lblPM25.value", "Connection Error");
        fibaro:call(thisdevice, "setProperty", "ui.lblPM10.value", "Connection Error");
        fibaro:call(thisdevice, "setProperty", "ui.lblTemperature.value", "Connection Error");
        fibaro:call(thisdevice, "setProperty", "ui.lblHumidity.value", "Connection Error");
        fibaro:call(thisdevice, "setProperty", "ui.lblPressure.value", "Connection Error");

        local counter = 10;  

        fibaro:debug("Telegram buffer: "..fibaro:getGlobalValue(varTelegram));
        while ((fibaro:getGlobalValue(varTelegram) ~= "0") and (counter > 0)) do
            fibaro:debug("Waiting for Telegram buffer - trial no. "..10-counter+1);
            fibaro:sleep(200);
            counter = counter - 1;
        end
        fibaro:sleep(500);
        fibaro:setGlobal(varTelegram,"Uwaga! Problem z połączeniem z domowym czujnikiem pyłu zawieszonego PM2.5.");
    end
end

end

for k = 1, #values do fibaro:debug(values[k]); if (not err) then if (values[k] == "nil") then err = true; fibaro:call(thisdevice, "setProperty", "currentIcon", icon0); fibaro:call(thisdevice, "setProperty", "ui.lblPM25.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblPM10.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblTemperature.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblHumidity.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblPressure.value", "Value Error");

        local counter = 10;  

        fibaro:debug("Telegram buffer: "..fibaro:getGlobalValue(varTelegram));
        while ((fibaro:getGlobalValue(varTelegram) ~= "0") and (counter > 0)) do
            fibaro:debug("Waiting for Telegram buffer - trial no. "..10-counter+1);
            fibaro:sleep(200);
            counter = counter - 1;
        end
        fibaro:sleep(500);
        fibaro:setGlobal(varTelegram,"Uwaga! Domowy czujnik pyłu zawieszonego PM2.5 przesyła błędne dane.");
    end
end

end

if (not err) then

fibaro:setGlobal(PM25global,values[2]);

local PM25Proc = (values[2]/PM25norm)*100;
local PM10Proc = (values[3]/PM10norm)*100;

if (tonumber(values[2]) < 13) then 
    fibaro:call(thisdevice, "setProperty", "currentIcon", icon1);
elseif (tonumber(values[2]) < 37) then
    fibaro:call(thisdevice, "setProperty", "currentIcon", icon2);
elseif (tonumber(values[2]) < 61) then
    fibaro:call(thisdevice, "setProperty", "currentIcon", icon3);
elseif (tonumber(values[2]) < 85) then
    fibaro:call(thisdevice, "setProperty", "currentIcon", icon4);
elseif (tonumber(values[2]) < 121) then
    fibaro:call(thisdevice, "setProperty", "currentIcon", icon5); 
else                            
    fibaro:call(thisdevice, "setProperty", "currentIcon", icon6);
end

if ((PM25Proc > 150) and ((tonumber(currentHour) >= telegramTimeSTART) and (tonumber(currentHour) < telegramTimeSTOP))) then

    local counter = 10;  

    fibaro:debug("Telegram buffer: "..fibaro:getGlobalValue(varTelegram));
    while ((fibaro:getGlobalValue(varTelegram) ~= "0") and (counter > 0)) do
        fibaro:debug("Waiting for Telegram buffer - trial no. "..10-counter+1);
        fibaro:sleep(200);
        counter = counter - 1;
    end
    fibaro:sleep(500);
    fibaro:setGlobal(varTelegram,"Uwaga! Poziom pyłu zawieszonego PM2.5 w pomieszczeniu wynosi "..tostring(PM25Proc).."% normy.");
end

fibaro:call(thisdevice, "setProperty", "ui.lblPM25.value", values[2].." µg/m3 ("..PM25Proc.."%)");
fibaro:call(thisdevice, "setProperty", "ui.lblPM10.value", values[3].." µg/m3 ("..PM10Proc.."%)");
fibaro:call(thisdevice, "setProperty", "ui.lblTemperature.value", values[4].." °C");
fibaro:call(thisdevice, "setProperty", "ui.lblHumidity.value", values[5].."%");
fibaro:call(thisdevice, "setProperty", "ui.lblPressure.value", values[6].." hPa");

end

jawilczek commented 5 years ago

dziękuję za błyskawiczną odpowiedz.

spróbuje zaimplementować u siebie :)


Jacek

W dniu 2019-02-15 09:00, Andrzej Browarski napisał(a):

Here you have code excerpts - I got it through virtual device button which is shceduled to be pressed every 15 minutes - honestly I found some code on Fibaro Forum and fine tuned it to my needs, but do not remember where exactly:

local thisdevice = fibaro:getSelfId() -- make sure youve correctly set the ip adress of the ESPEasy node local taskId = {"1","3"} -- make sure this matches the task id on your ESPEasy local conn = Net.FHttp(fibaro:getValue(thisdevice, 'IPAddress'), fibaro:getValue(thisdevice, 'TCPPort'))

local values = {}; local valueCounter = 1; local err = false;

local PM25global = "PM25IndoorDIY"; -- this is global variable where PM reading is stored local PM25norm = 25; local PM10norm = 50;

local varTelegram = "TelegramMessage"; local telegramTimeSTART = 7; local telegramTimeSTOP = 22;

local icon1 = 1105; local icon2 = 1106; local icon3 = 1107; local icon4 = 1108; local icon5 = 1109; local icon6 = 1110; local icon0 = 1112;

local currentHour = os.date("%H");

for i = 1, #taskId do if (not err) then response, status, errorCode = conn:GET('/json?tasknr=' .. taskId[i])

if errorCode == 0 then
    fibaro:debug("Request "..i.." status: "..status)
    jsonTable = json.decode(response);
    for j = 1, #jsonTable.TaskValues do
        values[valueCounter] = jsonTable.TaskValues[j].Value
        valueCounter = valueCounter + 1;
    end
else
    err = true;
    fibaro:debug("Connection Error");
    fibaro:log("Connection Error");
    fibaro:call(thisdevice, "setProperty", "currentIcon", icon0);
    fibaro:call(thisdevice, "setProperty", "ui.lblPM25.value",

"Connection Error"); fibaro:call(thisdevice, "setProperty", "ui.lblPM10.value", "Connection Error"); fibaro:call(thisdevice, "setProperty", "ui.lblTemperature.value", "Connection Error"); fibaro:call(thisdevice, "setProperty", "ui.lblHumidity.value", "Connection Error"); fibaro:call(thisdevice, "setProperty", "ui.lblPressure.value", "Connection Error");

      local counter = 10;

    fibaro:debug("Telegram buffer:

"..fibaro:getGlobalValue(varTelegram)); while ((fibaro:getGlobalValue(varTelegram) ~= "0") and (counter > 0)) do fibaro:debug("Waiting for Telegram buffer - trial no. "..10-counter+1); fibaro:sleep(200); counter = counter - 1; end fibaro:sleep(500); fibaro:setGlobal(varTelegram,"Uwaga! Problem z połączeniem z domowym czujnikiem pyłu zawieszonego PM2.5."); end end

end

for k = 1, #values do fibaro:debug(values[k]); if (not err) then if (values[k] == "nil") then err = true; fibaro:call(thisdevice, "setProperty", "currentIcon", icon0); fibaro:call(thisdevice, "setProperty", "ui.lblPM25.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblPM10.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblTemperature.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblHumidity.value", "Value Error"); fibaro:call(thisdevice, "setProperty", "ui.lblPressure.value", "Value Error");

      local counter = 10;

    fibaro:debug("Telegram buffer:

"..fibaro:getGlobalValue(varTelegram)); while ((fibaro:getGlobalValue(varTelegram) ~= "0") and (counter > 0)) do fibaro:debug("Waiting for Telegram buffer - trial no. "..10-counter+1); fibaro:sleep(200); counter = counter - 1; end fibaro:sleep(500); fibaro:setGlobal(varTelegram,"Uwaga! Domowy czujnik pyłu zawieszonego PM2.5 przesyła błędne dane."); end end

end

if (not err) then

fibaro:setGlobal(PM25global,values[2]);

local PM25Proc = (values[2]/PM25norm)100; local PM10Proc = (values[3]/PM10norm)100;

if (tonumber(values[2]) < 13) then fibaro:call(thisdevice, "setProperty", "currentIcon", icon1); elseif (tonumber(values[2]) < 37) then fibaro:call(thisdevice, "setProperty", "currentIcon", icon2); elseif (tonumber(values[2]) < 61) then fibaro:call(thisdevice, "setProperty", "currentIcon", icon3); elseif (tonumber(values[2]) < 85) then fibaro:call(thisdevice, "setProperty", "currentIcon", icon4); elseif (tonumber(values[2]) < 121) then fibaro:call(thisdevice, "setProperty", "currentIcon", icon5); else fibaro:call(thisdevice, "setProperty", "currentIcon", icon6); end

if ((PM25Proc > 150) and ((tonumber(currentHour) >= telegramTimeSTART) and (tonumber(currentHour) < telegramTimeSTOP))) then

local counter = 10;

fibaro:debug("Telegram buffer:

"..fibaro:getGlobalValue(varTelegram)); while ((fibaro:getGlobalValue(varTelegram) ~= "0") and (counter > 0)) do fibaro:debug("Waiting for Telegram buffer - trial no. "..10-counter+1); fibaro:sleep(200); counter = counter - 1; end fibaro:sleep(500); fibaro:setGlobal(varTelegram,"Uwaga! Poziom pyłu zawieszonego PM2.5 w pomieszczeniu wynosi "..tostring(PM25Proc).."% normy."); end

fibaro:call(thisdevice, "setProperty", "ui.lblPM25.value", values[2].." µg/m3 ("..PM25Proc.."%)"); fibaro:call(thisdevice, "setProperty", "ui.lblPM10.value", values[3].." µg/m3 ("..PM10Proc.."%)"); fibaro:call(thisdevice, "setProperty", "ui.lblTemperature.value", values[4].." °C"); fibaro:call(thisdevice, "setProperty", "ui.lblHumidity.value", values[5].."%"); fibaro:call(thisdevice, "setProperty", "ui.lblPressure.value", values[6].." hPa");

end

-- You are receiving this because you commented. Reply to this email directly, view it on GitHub [1], or mute the thread [2].

Links:

[1] https://github.com/letscontrolit/ESPEasy/issues/914#issuecomment-463943676 [2] https://github.com/notifications/unsubscribe-auth/AbK3uuqFGEq8XboAYqPShZA8MYSQ-sHNks5vNmkGgaJpZM4SNQbs

zbx-sadman commented 4 years ago

Hello @ShardanX

Due to datasheet the PMSx003 have a lifetime of around 8000h, so permanently driven it will run for 333 days. The laser diode has a limited lifetime so after this period the values will get unreliable.

Can you post link to the datashet with 8000h lifetime?

Plantower support answer me about PMS-A003 sensor:

Our sensor lifetime in our datasheet is 3years, but actually it can use more than 4.5year with works continuously.

Best regards,
Holly Gao(Ms.)

Sales Executive-Marketing Dept.
Beijing Plantower Technology Co., Ltd.
#613,Building 9,Yuxi Road No.9,Houshayu,Shunyi District,Beijing, P.R.China.

I see in the PMS 5003/7003/A003 manuals "MTTF ≥3 Year(Y)"

mrdc commented 4 years ago

@blb4github

I did have problem with Longpulse, sorry I didn't mention before... I did fix it on another way (without switch);I did use gpio,x,0 and gpio,x,1:

on System#Boot do gpio,14,0 timerSet,1,20 endon

On Rules#Timer=1 do gpio,14,1 timerSet,1,300

@AndrewB82

actually, I forgot to mention - I haven't used longpulse either - my solution is similar to the one by @blb4github

It shouldn't work when we set GPIO High for PMSx003 SET Pin - sensor won't sleep. We need to cycle sleep/awake:

on System#Boot do
gpio,YOUR_GPIO_FOR_SET_PIN,0
timerSet,1,30
endon

On Rules#Timer=1 do
gpio,YOUR_GPIO_FOR_SET_PIN,1
timerSet,2,30

On Rules#Timer=2 do
gpio,YOUR_GPIO_FOR_SET_PIN,0
timerSet,1,30
tonhuisman commented 10 months ago

This seems to be solved, so can be closed.