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

SDS011 dust sensor implementation update #139

Merged
merged 9 commits into from Nov 19, 2020

Conversation

danbates2
Copy link
Contributor

@danbates2 danbates2 commented Oct 31, 2020

This uses a much improved library to manage the SDS011 dust sensor.
It enables the rate at which the sensor is read to be changed to assist in the internal laser lasting longer.
As we know, the laser, running 24/7, will reach it's rated life in less than a year.
Setting readinterval to 5 will give a dust sensor reading ever 5 minutes, elongating the life of the sensor to something more like 5 years.

Below is required to install the python library.

$ sudo pip3 install sds011

@danbates2
Copy link
Contributor Author

danbates2 commented Oct 31, 2020

tested, ready to merge.
@TrystanLea
@glynhudson

@TrystanLea
Copy link
Member

Thanks @danbates2 this is great!

Unfortunately Im having trouble with the blocking nature of the read function, when you try and restart or stop emonhub it just hangs there until its finished the latest set of readings. I've had a go at trying to call del from a signal or trigger from the main emonhub thread but no luck so far.

I've also made some other minor modifications here
https://github.com/openenergymonitor/emonhub/commits/sds011

@TrystanLea
Copy link
Member

I tired adding adding the following to emonhub.py in the close section to then call a close method in the interfacer

def close(self):
    """Close hub. Do some cleanup before leaving."""

    self._log.info("Exiting hub...")
    
    for I in self._interfacers.values():
       close = getattr(I, "close", None)
       if callable(close):
           I.close()

    for I in self._interfacers.values():
        I.stop = True
        I.join()

and then in the SDS011 interfacer:

def close(self):
    self._log.info("Closing SDS011")
    # self.sds.ser = False
    sds.__del__()

But no luck, need to somehow get the message that emonhub needs to close/restart into the SDS011 library thread...

@TrystanLea
Copy link
Member

Perhaps using this library might be easier?
https://github.com/ikalchev/py-sds011

@TrystanLea
Copy link
Member

Hmm not sure that Im getting that library to work ... might be that the sds011 has the settings from the previous library and there's some conflict between active and passive mode not sure..

@danbates2
Copy link
Contributor Author

danbates2 commented Nov 1, 2020

@TrystanLea

Unfortunately Im having trouble with the blocking nature of the read function

Right, I see what you mean with the emonhub restarts.

That other library could be the solution in that case.. (that other library gives us easier control of sleep times and readings too..)

I guess another way would be to put the process into a thread.

I also don't know the procedure for emonhub stopping interfacers. Is there a function it calls to stop interfacers?

@TrystanLea
Copy link
Member

I also don't know the procedure for emonhub stopping interfacers. Is there a function it calls to stop interfacers?

Yes and I tried tried to get that to work above, see 3rd comment back, but no luck in affecting the underlying thread unfortunately..

@danbates2
Copy link
Contributor Author

danbates2 commented Nov 1, 2020

Sure. Who knows emonhub better? What's the procedure for closing interfacers?

@TrystanLea
Copy link
Member

That wasnt the issue, the close command was getting through to the interfacer, it was just that it wasnt getting into the sds011 library thread to close it as it where..

@danbates2
Copy link
Contributor Author

When stopping emonhub, the interfacers get stopped too.
Is this always by this?..

def close(self):

@danbates2
Copy link
Contributor Author

Because one option is to put the serial stuff into a thread, and stop the thread when closing the interfacer.

@TrystanLea
Copy link
Member

The interfacers have a run method with a while loop, this loop exists if the stop flag is set to true:
https://github.com/openenergymonitor/emonhub/blob/new_config_format/src/emonhub_interfacer.py#L94

the stop flag is set from emonhub.py when the users attempts to stop/restart emonhub here:
https://github.com/openenergymonitor/emonhub/blob/new_config_format/src/emonhub.py#L148

the run method calls the read method that you see in the SDS011 interfacer:
https://github.com/openenergymonitor/emonhub/blob/new_config_format/src/emonhub_interfacer.py#L99

@danbates2
Copy link
Contributor Author

Cool.
But what about calling

def close(self):

?
I can't see that anywhere.

@danbates2
Copy link
Contributor Author

I can see the stops in the main emonhub, but I can't see how each interfacer is actually closed.
I think emonhub just waits for a read to finish, and doesn't do any more reads.
That seems quite brittle to me.

@danbates2
Copy link
Contributor Author

Guess that's why a non-blocking read is important for being able to stop/start emonhub or an interfacer.

@TrystanLea
Copy link
Member

but I can't see how each interfacer is actually closed.

I think its just that the loop exits when it receives the flag and the interfacer closes automatically, I tried adding an additional close method above that would then have the ability to close a thread within an interfacer e.g by calling sds.del()

Looking at the code behind sds.del() it appears to only delete the socket, but we are not using sockets so I dont think it does anything..

@danbates2
Copy link
Contributor Author

I see what you mean...
Like I say, I think the interfacer just doesn't do any more reads, it's not exiting the def read(). You see what I mean?

@TrystanLea
Copy link
Member

In the case of SDS011 or more generally? Yes the original library was blocking during read()

@danbates2
Copy link
Contributor Author

Yes more generally. I mean emonhub isn't able to exit an interfacer's read(), instead it's dependent on it returning a value. So the blocking library caused a problem.
I'm not fluent with this python anyway. I'm sure an expert would have implemented a blocking library better.

switched library important to do the following:

$ sudo pip3 uninstall sds011
$ sudo pip3 install py-sds011
@danbates2
Copy link
Contributor Author

danbates2 commented Nov 1, 2020

@TrystanLea I've changed the library and now everything is broken. It was working on my laptop with the sensor plugged in by usb, but not on the rpi.
Not sure if command from previous library has put the sds011 on the rpi in some mode I'm not aware of. Shouldn't be the case.
I've tried a few of the extra mode related functions from the new library.
Or there's a datatype issue in emonhub I've missed.

if you're trying the new one :

$ sudo pip3 uninstall sds011
$ sudo pip3 install py-sds011

New problem too, if changing setting in emonhub it jamms up here:

 INFO     MainThread Deleting interfacer 'SDS011'

@danbates2
Copy link
Contributor Author

this is what I'm running on the laptop to test it. might help.

py-sds011-test.py.zip

@danbates2
Copy link
Contributor Author

@TrystanLea Got it.
Try this one.

remember to uninstall the old module and install the new.

@danbates2
Copy link
Contributor Author

danbates2 commented Nov 1, 2020

line 54: self.sensor.set_work_period(read=False, work_time=0)
is what did it, set the mode of the sensor to something compatible with the new method.

@danbates2
Copy link
Contributor Author

@TrystanLea I've been testing the new methods for 24h and it's looking good.

@TrystanLea TrystanLea merged commit 06d0004 into openenergymonitor:master Nov 19, 2020
@TrystanLea
Copy link
Member

Thanks for this Dan, works a treat!

@TrystanLea
Copy link
Member

PS: here's the code to optionally load the module
db4e02c

@danbates2
Copy link
Contributor Author

Handy.
Where did the sudo pip3 install py-sds011 command have to go in the end?

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.

None yet

2 participants