Browse Source

ppd42ns: Initial implementation of the Grove dust sensor

jrvandr: removed unnecessary mraa_init()

Signed-off-by: Zion Orent <zorent@ics.com>
Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: John Van Drasek <john.r.van.drasek@intel.com>
Zion Orent 10 years ago
parent
commit
7d40425391

+ 3
- 0
examples/CMakeLists.txt View File

@@ -69,6 +69,7 @@ add_executable (mpr121-example mpr121.cxx)
69 69
 add_executable (ublox6-example ublox6.cxx)
70 70
 add_executable (yg1006-example yg1006.cxx)
71 71
 add_executable (wt5001-example wt5001.cxx)
72
+add_executable (ppd42ns-example ppd42ns.cxx)
72 73
 
73 74
 include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
74 75
 include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@@ -125,6 +126,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/mpr121)
125 126
 include_directories (${PROJECT_SOURCE_DIR}/src/ublox6)
126 127
 include_directories (${PROJECT_SOURCE_DIR}/src/yg1006)
127 128
 include_directories (${PROJECT_SOURCE_DIR}/src/wt5001)
129
+include_directories (${PROJECT_SOURCE_DIR}/src/ppd42ns)
128 130
 
129 131
 target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT})
130 132
 target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT})
@@ -197,3 +199,4 @@ target_link_libraries (mpr121-example mpr121 ${CMAKE_THREAD_LIBS_INIT})
197 199
 target_link_libraries (ublox6-example ublox6 ${CMAKE_THREAD_LIBS_INIT})
198 200
 target_link_libraries (yg1006-example yg1006 ${CMAKE_THREAD_LIBS_INIT})
199 201
 target_link_libraries (wt5001-example wt5001 ${CMAKE_THREAD_LIBS_INIT})
202
+target_link_libraries (ppd42ns-example ppd42ns ${CMAKE_THREAD_LIBS_INIT})

+ 52
- 0
examples/javascript/ppd42ns.js View File

@@ -0,0 +1,52 @@
1
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
2
+/*jshint unused:true */
3
+/*global */
4
+/*
5
+* Author: Zion Orent <zorent@ics.com>
6
+* Copyright (c) 2014 Intel Corporation.
7
+*
8
+* Permission is hereby granted, free of charge, to any person obtaining
9
+* a copy of this software and associated documentation files (the
10
+* "Software"), to deal in the Software without restriction, including
11
+* without limitation the rights to use, copy, modify, merge, publish,
12
+* distribute, sublicense, and/or sell copies of the Software, and to
13
+* permit persons to whom the Software is furnished to do so, subject to
14
+* the following conditions:
15
+*
16
+* The above copyright notice and this permission notice shall be
17
+* included in all copies or substantial portions of the Software.
18
+*
19
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+*/
27
+
28
+// Load dust sensor module
29
+var dustSensor = require('jsupm_ppd42ns');
30
+// Instantiate a dust sensor on digital pin D8
31
+var myDustSensor = new dustSensor.PPD42NS(8);
32
+
33
+var data;
34
+
35
+// Continue until user ends program
36
+var notice = "This program will give readings ";
37
+notice += "every 30 seconds until you stop it"
38
+console.log(notice);
39
+while(1)
40
+{
41
+	data = myDustSensor.getData();
42
+	console.log("Low pulse occupancy: " + data.lowPulseOccupancy);
43
+	console.log("Ratio: " + data.ratio);
44
+	console.log("Concentration: " + data.concentration);
45
+}
46
+
47
+// Print message when exiting
48
+process.on('SIGINT', function()
49
+{
50
+	console.log("Exiting...");
51
+	process.exit(0);
52
+});

+ 63
- 0
examples/ppd42ns.cxx View File

@@ -0,0 +1,63 @@
1
+/*
2
+ * Author: Zion Orent <zorent@ics.com>
3
+ * Copyright (c) 2014 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <iostream>
27
+#include <signal.h>
28
+#include "ppd42ns.h"
29
+
30
+using namespace std;
31
+
32
+int shouldRun = true;
33
+
34
+void sig_handler(int signo)
35
+{
36
+	if (signo == SIGINT)
37
+		shouldRun = false;
38
+}
39
+
40
+
41
+int main ()
42
+{
43
+	signal(SIGINT, sig_handler);
44
+
45
+//! [Interesting]
46
+	// Instantiate a dust sensor on GPIO pin D8
47
+	upm::PPD42NS* dust = new upm::PPD42NS(8);
48
+	dustData data;
49
+	cout << "This program will give readings every 30 seconds until you stop it" << endl;
50
+	while (shouldRun)
51
+	{
52
+		data = dust->getData();
53
+		cout << "Low pulse occupancy: " << data.lowPulseOccupancy << endl;
54
+		cout << "Ratio: " << data.ratio << endl;
55
+		cout << "Concentration: " << data.concentration << endl;
56
+	}
57
+//! [Interesting]
58
+
59
+	cout << "Exiting" << endl;
60
+
61
+	delete dust;
62
+	return 0;
63
+}

+ 5
- 0
src/ppd42ns/CMakeLists.txt View File

@@ -0,0 +1,5 @@
1
+set (libname "ppd42ns")
2
+set (libdescription "upm ppd42ns dust sensor module")
3
+set (module_src ${libname}.cxx)
4
+set (module_h ${libname}.h)
5
+upm_module_init()

+ 8
- 0
src/ppd42ns/jsupm_ppd42ns.i View File

@@ -0,0 +1,8 @@
1
+%module jsupm_ppd42ns
2
+%include "../upm.i"
3
+
4
+%{
5
+    #include "ppd42ns.h"
6
+%}
7
+
8
+%include "ppd42ns.h"

+ 129
- 0
src/ppd42ns/ppd42ns.cxx View File

@@ -0,0 +1,129 @@
1
+/*
2
+ * Author: Zion Orent <sorent@ics.com>
3
+ * Copyright (c) 2014 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <iostream>
26
+#include <stddef.h>
27
+#include <stdio.h>
28
+#include <time.h>
29
+#include <math.h>
30
+#include <sys/sysinfo.h>
31
+#include "ppd42ns.h"
32
+
33
+using namespace upm;
34
+
35
+PPD42NS::PPD42NS(int pin)
36
+{
37
+    m_gpio = mraa_gpio_init(pin);
38
+    mraa_gpio_dir(m_gpio, MRAA_GPIO_IN);
39
+}
40
+
41
+PPD42NS::~PPD42NS()
42
+{
43
+    mraa_gpio_close(m_gpio);
44
+}
45
+
46
+dustData PPD42NS::getData()
47
+{
48
+	dustData data;
49
+	struct timespec printData_start={0,0};
50
+	struct timespec printData_now={0,0};
51
+	clock_gettime(CLOCK_MONOTONIC, &printData_start);
52
+	clock_gettime(CLOCK_MONOTONIC, &printData_now);
53
+	double low_pulse_occupancy = 0;
54
+	double pulse_check_time = 30;
55
+	
56
+	// Keep reading dust data until 30 seconds have passed
57
+	double start_time, end_time;
58
+	while (m_timediff(printData_start, printData_now) < pulse_check_time)
59
+	{
60
+		start_time = m_timediff(printData_start, printData_now);
61
+		end_time = pulse_check_time - start_time;
62
+		low_pulse_occupancy += pulseIn_polyfill(0, end_time);
63
+		clock_gettime(CLOCK_MONOTONIC, &printData_now);
64
+	}
65
+
66
+	// Store dust data
67
+	double ratio = low_pulse_occupancy / (pulse_check_time * 1000 * 10.0);  // Integer percentage 0=>100
68
+	double concentration = (1.1 * pow(ratio,3)) - (3.8 * pow(ratio, 2)) + (520 * ratio) + 0.62; // using spec sheet curve
69
+	data.lowPulseOccupancy = (int)low_pulse_occupancy;
70
+	data.ratio = ratio;
71
+	data.concentration = concentration;
72
+
73
+	return data;
74
+}
75
+
76
+
77
+// Mimicking Arduino's pulseIn function
78
+//	return how long it takes a pin to go from HIGH to LOW or LOW to HIGH
79
+double PPD42NS::pulseIn_polyfill(bool high_low_value, double end_time)
80
+{
81
+	struct timespec pulseIn_start={0,0};
82
+	struct timespec pulseIn_now={0,0};
83
+	struct timespec pulsetime_start={0,0};
84
+	struct timespec pulsetime_end={0,0};
85
+
86
+	int pin_val = 5; // some non-zero, non-1 number
87
+	bool started_timing = false;
88
+	bool ended_timing = false;
89
+	clock_gettime(CLOCK_MONOTONIC, &pulseIn_start);
90
+
91
+	// run through this loop until either:
92
+	//	a) we detect a change in pulse
93
+	//	b) we've hit 30 seconds
94
+	while (!ended_timing && (m_timediff(pulseIn_start, pulseIn_now) < end_time))
95
+	{
96
+		pin_val = (bool)mraa_gpio_read(m_gpio);
97
+		if (pin_val == high_low_value && !started_timing)
98
+		{
99
+			clock_gettime(CLOCK_MONOTONIC, &pulsetime_start);
100
+			started_timing = true;
101
+			//std::cout << "Started counting pulse change" << std::endl;
102
+			usleep(50);
103
+		}
104
+		else if (started_timing && pin_val != high_low_value)
105
+		{
106
+			clock_gettime(CLOCK_MONOTONIC, &pulsetime_end);
107
+			ended_timing = true;
108
+			//std::cout << "Ended counting pulse change" << (m_timediff(pulseIn_start, pulseIn_now)) << std::endl;
109
+		}
110
+		else
111
+			usleep(50);
112
+		clock_gettime(CLOCK_MONOTONIC, &pulseIn_now);
113
+	}
114
+
115
+	double low_pulse_occupancy = 0;
116
+
117
+	// if we ended due to detecting a pulse change and not due to hitting 30 seconds
118
+	if (started_timing && ended_timing)
119
+		low_pulse_occupancy = m_timediff(pulsetime_start, pulsetime_end);
120
+	//std::cout << "Low pulse occupancy is " << low_pulse_occupancy << " seconds" << std::endl;
121
+
122
+	return (low_pulse_occupancy * 1000000); // convert to microseconds
123
+}
124
+
125
+double PPD42NS::m_timediff(timespec time1, timespec time2)
126
+{
127
+	return ((double)time2.tv_sec + 1.0e-9*time2.tv_nsec) - 
128
+			((double)time1.tv_sec + 1.0e-9*time1.tv_nsec);
129
+}

+ 78
- 0
src/ppd42ns/ppd42ns.h View File

@@ -0,0 +1,78 @@
1
+/*
2
+ * Author: Zion Orent <sorent@ics.com>
3
+ * Copyright (c) 2014 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+#pragma once
25
+
26
+#include <string>
27
+#include <time.h>
28
+#include <mraa/aio.h>
29
+
30
+typedef struct
31
+{
32
+	int lowPulseOccupancy;
33
+	double ratio;
34
+	double concentration;
35
+} dustData;
36
+
37
+namespace upm {
38
+
39
+  /**
40
+   * @brief C++ API for the Dust Sensor
41
+   *
42
+   * UPM module for the Dust Sensor
43
+   *
44
+   * @ingroup gpio
45
+   * @snippet ppd42ns.cxx Interesting
46
+   */
47
+  class PPD42NS {
48
+  public:
49
+    /**
50
+     * Dust Sensor Constructor
51
+     *
52
+     * @param pin digital pin to use
53
+     */
54
+    PPD42NS(int pin);
55
+    /**
56
+     * Dust Sensor Destructor
57
+     */
58
+    ~PPD42NS();
59
+    /**
60
+     * Print dust concentration
61
+     *
62
+     * @return struct dustData  contains data from dust sensor
63
+     */
64
+     dustData getData();
65
+
66
+  private:
67
+        mraa_gpio_context m_gpio;
68
+		/**
69
+		 * Return the amount of time it takes a pin to go from HIGH to LOW or LOW to HIGH
70
+		 *
71
+		 * @param highLowValue int do we measure from HIGH to LOW or LOW to HIGH. highLowValue is "from" value
72
+		 */
73
+		double pulseIn_polyfill(bool highLowValue, double endTime);
74
+		double m_timediff(timespec time1, timespec time2);
75
+	};
76
+}
77
+
78
+

+ 9
- 0
src/ppd42ns/pyupm_ppd42ns.i View File

@@ -0,0 +1,9 @@
1
+%module pyupm_ppd42ns
2
+%include "../upm.i"
3
+
4
+%feature("autodoc", "3");
5
+
6
+%include "ppd42ns.h"
7
+%{
8
+    #include "ppd42ns.h"
9
+%}