-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
435 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<classpath> | ||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> | ||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> | ||
<classpathentry kind="src" path="src"/> | ||
<classpathentry kind="output" path="bin"/> | ||
</classpath> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<projectDescription> | ||
<name>ppd42ns-driver</name> | ||
<comment></comment> | ||
<projects> | ||
</projects> | ||
<buildSpec> | ||
<buildCommand> | ||
<name>org.eclipse.jdt.core.javabuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
<buildCommand> | ||
<name>org.eclipse.pde.ManifestBuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
<buildCommand> | ||
<name>org.eclipse.pde.SchemaBuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
</buildSpec> | ||
<natures> | ||
<nature>org.eclipse.pde.PluginNature</nature> | ||
<nature>org.eclipse.jdt.core.javanature</nature> | ||
</natures> | ||
</projectDescription> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
eclipse.preferences.version=1 | ||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled | ||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 | ||
org.eclipse.jdt.core.compiler.compliance=1.8 | ||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error | ||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error | ||
org.eclipse.jdt.core.compiler.source=1.8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
eclipse.preferences.version=1 | ||
pluginProject.equinox=false | ||
pluginProject.extensions=false | ||
resolve.requirebundle=false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2019 Shigeru Ishida | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Manifest-Version: 1.0 | ||
Bundle-ManifestVersion: 2 | ||
Bundle-Name: java driver for ppd42ns - dust sensor module | ||
Bundle-SymbolicName: ppd42ns-driver | ||
Bundle-Version: 0.1.0 | ||
Automatic-Module-Name: ppd42ns-driver | ||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||
Import-Package: com.pi4j.io.gpio;version="1.2.0", | ||
com.pi4j.io.gpio.event;version="1.2.0", | ||
org.slf4j;version="[1.7.25,1.8.0)" | ||
Export-Package: io.github.s5uishida.iot.device.ppd42ns.driver;version="0.1.0" | ||
Bundle-Vendor: Shigeru Ishida (s5uishida) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,98 @@ | ||
# ppd42ns-driver | ||
# ppd42ns-driver | ||
ppd42ns-driver is a java library that operates dust sensor called [PPD42NS](http://wiki.seeedstudio.com/Grove-Dust_Sensor/) to connect PPD42NS to GPIO terminal of Raspberry Pi 3B and make it for use in java. | ||
I releases this in the form of the Eclipse plug-in project. | ||
You need Java 8 or higher. | ||
|
||
I use [Pi4J](http://wiki.seeedstudio.com/Grove-Dust_Sensor/) | ||
for gpio communication in java and have confirmed that it works in Raspberry Pi 3B ([Raspbian Buster Lite OS](https://www.raspberrypi.org/downloads/raspbian/) (2019-07-10)). | ||
|
||
## Connection of PPD42NS and Raspberry Pi 3B | ||
**Connect with `Vin <--> Vin`,`GND <--> GND`, `PM2.5 <--> Tx`.** | ||
[This](https://github.com/mauricecyril/pidustsensor) is also helpful. | ||
- `Pins` of [PPD42NS](http://wiki.seeedstudio.com/Grove-Dust_Sensor/) | ||
- Vin (pin#3 - Red) | ||
- GND (pin#1 - Black) | ||
- PM2.5 (pin#4 - Yellow) | ||
- [GPIO of Raspberry Pi 3B](https://www.raspberrypi.org/documentation/usage/gpio/README.md) | ||
- Vin --> (4) | ||
- GND --> (6) | ||
- Tx --> (8) GPIO14 | ||
|
||
## Install Raspbian Buster Lite OS (2019-07-10) | ||
The reason for using this version is that it is the latest as of July 2019 and [BlueZ](http://www.bluez.org/) 5.50 is included from the beginning, and use Bluetooth and serial communication simultaneously. | ||
|
||
## Configuration of Raspbian Buster Lite OS | ||
- Edit `/boot/cmdline.txt` | ||
``` | ||
console=serial0,115200 --> removed | ||
``` | ||
- Edit `/boot/config.txt` | ||
``` | ||
@@ -55,6 +55,10 @@ | ||
# Enable audio (loads snd_bcm2835) | ||
dtparam=audio=on | ||
+enable_uart=1 | ||
+dtoverlay=pi3-miniuart-bt | ||
+core_freq=250 | ||
+ | ||
[pi4] | ||
# Enable DRM VC4 V3D driver on top of the dispmanx display stack | ||
dtoverlay=vc4-fkms-v3d | ||
``` | ||
When editing is complete, reboot. | ||
|
||
## Install WiringPi Native Library | ||
Pi4J depends on the [WiringPi](http://wiringpi.com/) native library by Gordon Henderson. | ||
The Pi4J native library is dynamically linked to WiringPi. | ||
``` | ||
# apt-get update | ||
# apt-get install wiringpi | ||
``` | ||
|
||
## Install jdk11 on Raspberry Pi 3B | ||
For example, [jdk11 apt-install](https://apt.bell-sw.com/) at [BELLSOFT](https://bell-sw.com/) is shown below. | ||
``` | ||
# wget -q -O - https://download.bell-sw.com/pki/GPG-KEY-bellsoft | apt-key add - | ||
# echo "deb [arch=armhf] https://apt.bell-sw.com/ stable main" | tee /etc/apt/sources.list.d/bellsoft.list | ||
# apt-get update | ||
# apt-get install bellsoft-java11 | ||
``` | ||
|
||
## Install git | ||
If git is not included, please install it. | ||
``` | ||
# apt-get install git | ||
``` | ||
|
||
## Use this with the following bundles | ||
- [SLF4J 1.7.26](https://www.slf4j.org/) | ||
- [Pi4J 1.2 (pi4j-core.jar)](https://pi4j.com/download/pi4j-1.2.zip) | ||
|
||
I would like to thank the authors of these very useful codes, and all the contributors. | ||
|
||
## How to use | ||
The following sample code will be helpful. | ||
**In the following code, ppd42ns.read() takes about 30 seconds to measure.** | ||
``` | ||
import io.github.s5uishida.iot.device.ppd42ns.driver.PPD42NSDriver; | ||
import io.github.s5uishida.iot.device.ppd42ns.driver.PPD42NSObservationData; | ||
public class MyPPD42NS { | ||
private static final Logger LOG = LoggerFactory.getLogger(MyPPD42NS.class); | ||
public static void main(String[] args) { | ||
PPD42NSDriver ppd42ns = PPD42NSDriver.getInstance(); | ||
ppd42ns.open(); | ||
while (true) { | ||
PPD42NSObservationData data = ppd42ns.read(); | ||
LOG.info(data.toString()); | ||
} | ||
// if (ppd42ns != null) { | ||
// ppd42ns.close(); | ||
// } | ||
} | ||
} | ||
``` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
source.. = src/ | ||
output.. = bin/ | ||
bin.includes = META-INF/,\ | ||
.,\ | ||
LICENSE |
191 changes: 191 additions & 0 deletions
191
src/io/github/s5uishida/iot/device/ppd42ns/driver/PPD42NSDriver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
package io.github.s5uishida.iot.device.ppd42ns.driver; | ||
|
||
import java.util.Date; | ||
import java.util.concurrent.BlockingQueue; | ||
import java.util.concurrent.LinkedBlockingQueue; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.pi4j.io.gpio.GpioController; | ||
import com.pi4j.io.gpio.GpioFactory; | ||
import com.pi4j.io.gpio.GpioPinDigitalInput; | ||
import com.pi4j.io.gpio.Pin; | ||
import com.pi4j.io.gpio.PinPullResistance; | ||
import com.pi4j.io.gpio.PinState; | ||
import com.pi4j.io.gpio.RaspiGpioProvider; | ||
import com.pi4j.io.gpio.RaspiPin; | ||
import com.pi4j.io.gpio.RaspiPinNumberingScheme; | ||
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent; | ||
import com.pi4j.io.gpio.event.GpioPinListenerDigital; | ||
|
||
/* | ||
* Refer to http://wiki.seeedstudio.com/Grove-Dust_Sensor/ | ||
* | ||
* @author s5uishida | ||
* | ||
*/ | ||
public class PPD42NSDriver { | ||
private static final Logger LOG = LoggerFactory.getLogger(PPD42NSDriver.class); | ||
|
||
private final Pin GPIO_IN = RaspiPin.GPIO_14; | ||
private final int OBSERVE_TIMEOUT_MILLIS = 30000; | ||
private final int GPIO_IN_TIMEOUT_MILLIS = 50000; | ||
|
||
private final GpioController gpio; | ||
|
||
private GpioPinDigitalInput diPin; | ||
private String logPrefix; | ||
|
||
private final AtomicInteger useCount = new AtomicInteger(0); | ||
private final BlockingQueue<PPD42NSObservationData> queue = new LinkedBlockingQueue<PPD42NSObservationData>(); | ||
|
||
private static PPD42NSDriver ppd42ns; | ||
|
||
private PPD42NSGpioPinListenerDigital ppd42nsListener; | ||
|
||
synchronized public static PPD42NSDriver getInstance() { | ||
if (ppd42ns == null) { | ||
ppd42ns = new PPD42NSDriver(); | ||
} | ||
return ppd42ns; | ||
} | ||
|
||
private PPD42NSDriver() { | ||
GpioFactory.setDefaultProvider(new RaspiGpioProvider(RaspiPinNumberingScheme.BROADCOM_PIN_NUMBERING)); | ||
gpio = GpioFactory.getInstance(); | ||
logPrefix = "[" + getName() + "] "; | ||
} | ||
|
||
synchronized public void open() { | ||
try { | ||
LOG.debug(logPrefix + "before - useCount:{}", useCount.get()); | ||
if (useCount.compareAndSet(0, 1)) { | ||
diPin = gpio.provisionDigitalInputPin(GPIO_IN, PinPullResistance.PULL_DOWN); | ||
diPin.setShutdownOptions(true); | ||
ppd42nsListener = new PPD42NSGpioPinListenerDigital(this, queue); | ||
diPin.addListener(ppd42nsListener); | ||
LOG.info(logPrefix + "opened SPI SLCK."); | ||
} | ||
} finally { | ||
LOG.debug(logPrefix + "after - useCount:{}", useCount.get()); | ||
} | ||
} | ||
|
||
synchronized public void close() { | ||
try { | ||
LOG.debug(logPrefix + "before - useCount:{}", useCount.get()); | ||
if (useCount.compareAndSet(1, 0)) { | ||
diPin.removeAllListeners(); | ||
gpio.unprovisionPin(diPin); | ||
gpio.shutdown(); | ||
LOG.info(logPrefix + "closed SPI SLCK."); | ||
} | ||
} finally { | ||
LOG.debug(logPrefix + "after - useCount:{}", useCount.get()); | ||
} | ||
} | ||
|
||
public String getName() { | ||
return GPIO_IN.getName().replaceAll("\\s", "_"); | ||
} | ||
|
||
public String getLogPrefix() { | ||
return logPrefix; | ||
} | ||
|
||
public PPD42NSObservationData read() { | ||
queue.clear(); | ||
ppd42nsListener.start(); | ||
try { | ||
return queue.poll(GPIO_IN_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); | ||
} catch (InterruptedException e) { | ||
LOG.warn("caught - {}", e.toString()); | ||
return null; | ||
} | ||
} | ||
|
||
/****************************************************************************************************************** | ||
* Sample main | ||
******************************************************************************************************************/ | ||
public static void main(String[] args) { | ||
PPD42NSDriver ppd42ns = PPD42NSDriver.getInstance(); | ||
ppd42ns.open(); | ||
|
||
while (true) { | ||
PPD42NSObservationData data = ppd42ns.read(); | ||
LOG.info(data.toString()); | ||
} | ||
|
||
// if (ppd42ns != null) { | ||
// ppd42ns.close(); | ||
// } | ||
} | ||
|
||
class PPD42NSGpioPinListenerDigital implements GpioPinListenerDigital { | ||
private final Logger LOG = LoggerFactory.getLogger(PPD42NSGpioPinListenerDigital.class); | ||
|
||
private final PPD42NSDriver ppd42ns; | ||
private final BlockingQueue<PPD42NSObservationData> queue; | ||
|
||
private Date startTime; | ||
private long startLowTimeMillis; | ||
private long totalLowTimeMillis; | ||
|
||
public PPD42NSGpioPinListenerDigital(PPD42NSDriver ppd42ns, BlockingQueue<PPD42NSObservationData> queue) { | ||
this.ppd42ns = ppd42ns; | ||
this.queue = queue; | ||
} | ||
|
||
public void reset() { | ||
startTime = null; | ||
startLowTimeMillis = -1; | ||
totalLowTimeMillis = 0; | ||
} | ||
|
||
public void start() { | ||
reset(); | ||
startTime = new Date(); | ||
} | ||
|
||
private float pcs2ugm3(float pcs) { | ||
double density = 1.65 * Math.pow(10, 12); | ||
double r25 = 0.44 * Math.pow(10, -6); | ||
double vol25 = (4 / 3) * Math.PI * Math.pow(r25, 3); | ||
double mass25 = density * vol25; | ||
double K = 3531.5; | ||
return (float)(pcs * K * mass25); | ||
} | ||
|
||
@Override | ||
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { | ||
LOG.trace(ppd42ns.getLogPrefix() + "{} -> {}", event.getPin(), event.getState()); | ||
|
||
if (startTime == null) { | ||
return; | ||
} | ||
|
||
Date currentTime = new Date(); | ||
if (event.getState() == PinState.LOW) { | ||
startLowTimeMillis = currentTime.getTime(); | ||
return; | ||
} else if (event.getState() == PinState.HIGH && startLowTimeMillis > 0) { | ||
totalLowTimeMillis += currentTime.getTime() - startLowTimeMillis; | ||
} else { | ||
return; | ||
} | ||
|
||
if ((currentTime.getTime() - startTime.getTime()) >= OBSERVE_TIMEOUT_MILLIS) { | ||
float ratio = 100f * ((float)totalLowTimeMillis) / ((float)(currentTime.getTime() - startTime.getTime())); | ||
float pcs = (float)(1.1 * Math.pow(ratio, 3) - 3.8 * Math.pow(ratio, 2) + 520.0 * ratio + 0.62); | ||
float ugm3 = pcs2ugm3(pcs); | ||
PPD42NSObservationData data = new PPD42NSObservationData(startTime, currentTime, pcs, ugm3); | ||
queue.offer(data); | ||
LOG.trace(ppd42ns.getLogPrefix() + "offer - {}", data.toString()); | ||
reset(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.