Skip to content

Commit

Permalink
ppd42ns: C implementation; C++ wraps C
Browse files Browse the repository at this point in the history
Signed-off-by: Jon Trulson <jtrulson@ics.com>
  • Loading branch information
jontrulson committed Nov 2, 2016
1 parent 8f6442e commit 1f954a8
Show file tree
Hide file tree
Showing 13 changed files with 466 additions and 193 deletions.
37 changes: 20 additions & 17 deletions examples/c++/ppd42ns.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,34 @@ int shouldRun = true;

void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
if (signo == SIGINT)
shouldRun = false;
}


int main ()
{
signal(SIGINT, sig_handler);
signal(SIGINT, sig_handler);

//! [Interesting]
// Instantiate a dust sensor on GPIO pin D8
upm::PPD42NS* dust = new upm::PPD42NS(8);
upm::dustData data;
cout << "This program will give readings every 30 seconds until you stop it" << endl;
while (shouldRun)
{
data = dust->getData();
cout << "Low pulse occupancy: " << data.lowPulseOccupancy << endl;
cout << "Ratio: " << data.ratio << endl;
cout << "Concentration: " << data.concentration << endl;
}
// Instantiate a dust sensor on GPIO pin D8
upm::PPD42NS* dust = new upm::PPD42NS(8);
ppd42ns_dust_data data;
cout << "This program will give readings every 30 seconds until "
<< "you stop it"
<< endl;
while (shouldRun)
{
data = dust->getData();
cout << "Low pulse occupancy: " << data.lowPulseOccupancy << endl;
cout << "Ratio: " << data.ratio << endl;
cout << "Concentration: " << data.concentration << endl;
cout << endl;
}
//! [Interesting]

cout << "Exiting" << endl;
cout << "Exiting" << endl;

delete dust;
return 0;
delete dust;
return 0;
}
1 change: 1 addition & 0 deletions examples/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ add_example (linefinder)
add_example (uln200xa)
add_example (mma7660)
add_example (buzzer)
add_example (ppd42ns)

# Custom examples
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)
Expand Down
66 changes: 66 additions & 0 deletions examples/c/ppd42ns.c
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;
}
30 changes: 15 additions & 15 deletions examples/java/PPD42NSSample.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@

public class PPD42NSSample {

public static void main(String[] args) throws InterruptedException {
// ! [Interesting]
// Instantiate a dust sensor on GPIO pin D8
upm_ppd42ns.PPD42NS dust = new upm_ppd42ns.PPD42NS(8);
upm_ppd42ns.dustData data;
public static void main(String[] args) throws InterruptedException {
// ! [Interesting]
// Instantiate a dust sensor on GPIO pin D8
upm_ppd42ns.PPD42NS dust = new upm_ppd42ns.PPD42NS(8);
upm_ppd42ns.ppd42ns_dust_data data;

System.out.println("This program will give readings every 30 seconds until you stop it");
System.out.println("This program will give readings every 30 seconds until you stop it");

while (true) {
data = dust.getData();
while (true) {
data = dust.getData();

System.out.println("Low pulse occupancy: " + data.getLowPulseOccupancy());
System.out.println("Ratio: " + data.getRatio());
System.out.println("Concentration: " + data.getConcentration());
}
// ! [Interesting]
}
System.out.println("Low pulse occupancy: " + data.getLowPulseOccupancy());
System.out.println("Ratio: " + data.getRatio());
System.out.println("Concentration: " + data.getConcentration());
}
// ! [Interesting]
}

}
}
14 changes: 9 additions & 5 deletions src/ppd42ns/CMakeLists.txt
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)
5 changes: 3 additions & 2 deletions src/ppd42ns/javaupm_ppd42ns.i
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
%module javaupm_ppd42ns
%include "../upm.i"

%include "ppd42ns_data.h"
%include "ppd42ns.hpp"
%{
#include "ppd42ns.hpp"
%}

%include "ppd42ns.hpp"

%pragma(java) jniclasscode=%{
static {
Expand All @@ -16,4 +17,4 @@
System.exit(1);
}
}
%}
%}
3 changes: 2 additions & 1 deletion src/ppd42ns/jsupm_ppd42ns.i
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"
167 changes: 167 additions & 0 deletions src/ppd42ns/ppd42ns.c
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;
}
Loading

0 comments on commit 1f954a8

Please sign in to comment.