-
Notifications
You must be signed in to change notification settings - Fork 410
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ppd42ns: C implementation; C++ wraps C
Signed-off-by: Jon Trulson <jtrulson@ics.com>
- Loading branch information
1 parent
8f6442e
commit 1f954a8
Showing
13 changed files
with
466 additions
and
193 deletions.
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
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
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,66 @@ | ||
/* | ||
* Author: Jon Trulson <jtrulson@ics.com> | ||
* Copyright (c) 2016 Intel Corporation. | ||
* | ||
* 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. | ||
*/ | ||
|
||
#include <unistd.h> | ||
#include <stdio.h> | ||
#include <signal.h> | ||
|
||
#include <ppd42ns.h> | ||
|
||
int shouldRun = true; | ||
|
||
void sig_handler(int signo) | ||
{ | ||
if (signo == SIGINT) | ||
shouldRun = false; | ||
} | ||
|
||
|
||
int main() | ||
{ | ||
signal(SIGINT, sig_handler); | ||
|
||
//! [Interesting] | ||
// Instantiate a dust sensor on GPIO pin D8 | ||
ppd42ns_context dust = ppd42ns_init(8); | ||
|
||
ppd42ns_dust_data data; | ||
printf("This program will give readings every 30 seconds until " | ||
"you stop it\n"); | ||
|
||
while (shouldRun) | ||
{ | ||
data = ppd42ns_get_data(dust); | ||
printf("Low pulse occupancy: %d\n", data.lowPulseOccupancy); | ||
printf("Ratio: %f\n", data.ratio); | ||
printf("Concentration: %f\n\n", data.concentration); | ||
} | ||
|
||
printf("Exiting...\n"); | ||
|
||
ppd42ns_close(dust); | ||
|
||
//! [Interesting] | ||
return 0; | ||
} |
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
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,5 +1,9 @@ | ||
set (libname "ppd42ns") | ||
set (libdescription "Ppd42ns dust sensor module") | ||
set (module_src ${libname}.cxx) | ||
set (module_hpp ${libname}.hpp) | ||
upm_module_init("-lrt") | ||
upm_mixed_module_init (NAME ppd42ns | ||
DESCRIPTION "PPD42NS Dust Sensor" | ||
C_HDR ppd42ns.h ppd42ns_data.h | ||
C_SRC ppd42ns.c | ||
CPP_HDR ppd42ns.hpp | ||
CPP_SRC ppd42ns.cxx | ||
CPP_WRAPS_C | ||
REQUIRES mraa) | ||
target_link_libraries(${libnamec} m) |
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
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,8 +1,9 @@ | ||
%module jsupm_ppd42ns | ||
%include "../upm.i" | ||
|
||
%include "ppd42ns_data.h" | ||
%include "ppd42ns.hpp" | ||
%{ | ||
#include "ppd42ns.hpp" | ||
%} | ||
|
||
%include "ppd42ns.hpp" |
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,167 @@ | ||
/* | ||
* Author: Jon Trulson <jtrulson@ics.com> | ||
* Copyright (c) 2016 Intel Corporation. | ||
* | ||
* Rewritten Based on original C++ driver written by: | ||
* Author: Zion Orent <sorent@ics.com> | ||
* Copyright (c) 2014 Intel Corporation. | ||
* | ||
* 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. | ||
*/ | ||
|
||
#include <assert.h> | ||
#include <stddef.h> | ||
#include <stdio.h> | ||
|
||
#include <upm_math.h> | ||
#include <upm_utilities.h> | ||
|
||
#include "ppd42ns.h" | ||
|
||
// Returns the amount of time it takes a pin to go from HIGH to LOW or | ||
// from LOW to HIGH | ||
static uint32_t ppd42ns_pulse_in(const ppd42ns_context dev, | ||
bool high_low_value); | ||
|
||
ppd42ns_context ppd42ns_init(int pin) | ||
{ | ||
ppd42ns_context dev = | ||
(ppd42ns_context)malloc(sizeof(struct _ppd42ns_context)); | ||
|
||
if (!dev) | ||
return NULL; | ||
|
||
dev->gpio = NULL; | ||
|
||
// make sure MRAA is initialized | ||
int mraa_rv; | ||
if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) | ||
{ | ||
printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); | ||
ppd42ns_close(dev); | ||
return NULL; | ||
} | ||
|
||
// MRAA contexts... | ||
if ( !(dev->gpio = mraa_gpio_init(pin)) ) | ||
{ | ||
printf("%s: mraa_gpio_init() failed\n", | ||
__FUNCTION__); | ||
ppd42ns_close(dev); | ||
return NULL; | ||
} | ||
|
||
mraa_gpio_dir(dev->gpio, MRAA_GPIO_IN); | ||
|
||
return dev; | ||
} | ||
|
||
void ppd42ns_close(ppd42ns_context dev) | ||
{ | ||
assert(dev != NULL); | ||
|
||
if (dev->gpio) | ||
mraa_gpio_close(dev->gpio); | ||
} | ||
|
||
ppd42ns_dust_data ppd42ns_get_data(const ppd42ns_context dev) | ||
{ | ||
assert(dev != NULL); | ||
|
||
ppd42ns_dust_data data; | ||
|
||
// in ms, 30 seconds | ||
const int pulse_check_time = 30000; | ||
// loop timer | ||
upm_clock_t max_loop_time; | ||
|
||
unsigned int low_pulse_occupancy = 0; | ||
|
||
upm_clock_init(&max_loop_time); | ||
|
||
do { | ||
low_pulse_occupancy += ppd42ns_pulse_in(dev, 0); | ||
} while (upm_elapsed_ms(&max_loop_time) < pulse_check_time); | ||
|
||
// Store dust data | ||
// Integer percentage 0=>100 | ||
double ratio = (float)low_pulse_occupancy | ||
/ ((float)pulse_check_time * 10.0); | ||
|
||
// using spec sheet curve | ||
double concentration = (1.1 * pow(ratio,3)) - (3.8 * pow(ratio, 2)) | ||
+ (520 * ratio) + 0.62; | ||
|
||
data.lowPulseOccupancy = low_pulse_occupancy; | ||
data.ratio = ratio; | ||
data.concentration = concentration; | ||
|
||
return data; | ||
} | ||
|
||
|
||
// Mimicking Arduino's pulseIn function | ||
// return how long it takes a pin to go from HIGH to LOW or LOW to HIGH | ||
static uint32_t ppd42ns_pulse_in(const ppd42ns_context dev, | ||
bool high_low_value) | ||
{ | ||
assert(dev != NULL); | ||
|
||
// we run for no more than 1 second at a time | ||
upm_clock_t max_time; | ||
upm_clock_t pulse_time; | ||
uint32_t total_pulse_time = 0; | ||
|
||
upm_clock_init(&max_time); | ||
bool pin_level; | ||
bool is_timing = false; | ||
|
||
do { | ||
pin_level = (bool)mraa_gpio_read(dev->gpio); | ||
|
||
if (!is_timing && pin_level == high_low_value) | ||
{ | ||
// level is desired level, but not currently timing | ||
upm_clock_init(&pulse_time); | ||
is_timing = true; | ||
} | ||
else if (is_timing && pin_level != high_low_value) | ||
{ | ||
// we started timing, but level changed | ||
total_pulse_time += upm_elapsed_us(&pulse_time); | ||
is_timing = false; | ||
} | ||
else | ||
{ | ||
// not timing and/or level is not equal to desired level | ||
// so we "wait". | ||
upm_delay_us(10); | ||
} | ||
} while (upm_elapsed_ms(&max_time) < 1000); // 1 second | ||
|
||
if (is_timing) | ||
{ | ||
// if we were still timing when the loop expired, add the | ||
// accumulated time. | ||
total_pulse_time += upm_elapsed_us(&pulse_time); | ||
} | ||
|
||
return total_pulse_time; | ||
} |
Oops, something went wrong.