enc03r: C port; FTI; C++ wraps C

The API for this driver has changed.  See docs/apichanges.md.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2017-01-27 17:58:35 -07:00
parent f914159e21
commit 1bbb9386b7
15 changed files with 758 additions and 165 deletions

View File

@ -4,9 +4,16 @@ API Changes {#apichanges}
Here's a list of other API changes made to the library that break source/binary Here's a list of other API changes made to the library that break source/binary
compatibility between releases: compatibility between releases:
* **enc03r** This driver no longer supports the value() function. In
addition, an update() function has been added. This function must be
called prior to calling angularVelocity(). angularVelocity() no
longer accepts an argument. Additional functions have been added,
however they do not affect compatibility with previous versions.
* **ds18b20** The C++ interface init() function has been deprecated. * **ds18b20** The C++ interface init() function has been deprecated.
It is still present, but currently does nothing. It will be removed It is still present, but currently does nothing. It will be removed
in a future release. in a future release.
* **grove<name>** Starting with UPM 1.0 the Grove libraries have been renamed * **grove<name>** Starting with UPM 1.0 the Grove libraries have been renamed
from *upm-grove<name>* to simply *upm-<name>*. Class names also match this new from *upm-grove<name>* to simply *upm-<name>*. Class names also match this new
format, with old classes marked as deprecated throughout the documentation. format, with old classes marked as deprecated throughout the documentation.
@ -14,27 +21,35 @@ compatibility between releases:
groveelectromagnet, groveemg, grovegprs, grovegsr, grovelinefinder, grovemd, groveelectromagnet, groveemg, grovegprs, grovegsr, grovelinefinder, grovemd,
grovemoisture, groveo2, grovescam, grovespeaker, groveultrasonic, grovevdiv, grovemoisture, groveo2, grovescam, grovespeaker, groveultrasonic, grovevdiv,
grovewater, grovewfs. grovewater, grovewfs.
* **grove** As of UPM 1.0 the Grove classes for sensors in the starter kit are * **grove** As of UPM 1.0 the Grove classes for sensors in the starter kit are
being separated into individual libraries. The old classes will be deprecated being separated into individual libraries. The old classes will be deprecated
over time and eventually removed. Corresponding libraries have the grove over time and eventually removed. Corresponding libraries have the grove
prefix removed. Affected classes are GroveButton, GroveLed, GroveLight, prefix removed. Affected classes are GroveButton, GroveLed, GroveLight,
GroveRelay, GroveRotary, GroveSlide and GroveTemp. GroveRelay, GroveRotary, GroveSlide and GroveTemp.
* The **ublox6** driver has been replaced with a generic implementation called * The **ublox6** driver has been replaced with a generic implementation called
nmea_gps as of UPM 1.0. This driver should handle all generic serial GPS nmea_gps as of UPM 1.0. This driver should handle all generic serial GPS
devices that output NMEA data going forward. This new driver has been tested devices that output NMEA data going forward. This new driver has been tested
with ublox6, DFRobot VK2828U7 (ublox7) and ublox LEA-6H GPS devices. with ublox6, DFRobot VK2828U7 (ublox7) and ublox LEA-6H GPS devices.
* **grove** Binary compatibility was broken for the GroveTemp class as of UPM * **grove** Binary compatibility was broken for the GroveTemp class as of UPM
v0.7.3. C++ code using this class has to be recompiled. v0.7.3. C++ code using this class has to be recompiled.
* There were frequent misspellings of the word *Celsius* in the UPM * There were frequent misspellings of the word *Celsius* in the UPM
code. In some cases, these were in method names, which will cause code. In some cases, these were in method names, which will cause
some API compatibility issues. These have all been corrected for UPM some API compatibility issues. These have all been corrected for UPM
versions after v.0.7.2. versions after v.0.7.2.
* Our **C++ header files** changed their extension from *.h* to *.hpp* in * Our **C++ header files** changed their extension from *.h* to *.hpp* in
version 0.7.0, Intel provided examples and code samples also reflect this version 0.7.0, Intel provided examples and code samples also reflect this
change but you will need to modify your `#include` directives in existing change but you will need to modify your `#include` directives in existing
code. code.
* **my9221**, **groveledbar** and **grovecircularled** are now all part of the * **my9221**, **groveledbar** and **grovecircularled** are now all part of the
same library (my9221) and new functionality was added going to v.0.5.1. same library (my9221) and new functionality was added going to v.0.5.1.
* **stepmotor** driver API was changed significantly from v.0.4.1 to v.0.5.0. * **stepmotor** driver API was changed significantly from v.0.4.1 to v.0.5.0.
* **eboled** library was greatly improved in version 0.4.0 and the `draw()` * **eboled** library was greatly improved in version 0.4.0 and the `draw()`
function was removed in favor of a more complete GFX library implementation. function was removed in favor of a more complete GFX library implementation.

View File

@ -1,6 +1,6 @@
/* /*
* Author: Jon Trulson <jtrulson@ics.com> * Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation. * Copyright (c) 2014-2017 Intel Corporation.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@ -36,44 +36,45 @@ bool shouldRun = true;
void sig_handler(int signo) void sig_handler(int signo)
{ {
if (signo == SIGINT) if (signo == SIGINT)
shouldRun = false; shouldRun = false;
} }
int main() int main()
{ {
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);
//! [Interesting] //! [Interesting]
// Instantiate a ENC03R on analog pin A0 // Instantiate a ENC03R on analog pin A0
upm::ENC03R *gyro = new upm::ENC03R(0); upm::ENC03R *gyro = new upm::ENC03R(0);
// The first thing we need to do is calibrate the sensor.
cout << "Please place the sensor in a stable location, and do not" << endl;
cout << "move it while calibration takes place." << endl;
cout << "This may take a couple of minutes." << endl;
gyro->calibrate(CALIBRATION_SAMPLES); // The first thing we need to do is calibrate the sensor.
cout << "Calibration complete. Reference value: " cout << "Please place the sensor in a stable location, and do not" << endl;
<< gyro->calibrationValue() << endl; cout << "move it while calibration takes place." << endl;
cout << "This may take a couple of minutes." << endl;
// Read the input and print both the raw value and the angular velocity, gyro->calibrate(CALIBRATION_SAMPLES);
// waiting 0.1 seconds between readings cout << "Calibration complete. Reference value: "
while (shouldRun) << gyro->calibrationValue() << endl;
// Read the input and print both the raw value and the angular velocity,
// waiting 0.1 seconds between readings
while (shouldRun)
{ {
unsigned int val = gyro->value(); gyro->update();
double av = gyro->angularVelocity(val);
cout << "Raw value: " << val << ", " cout << "Angular velocity: "
<< "angular velocity: " << av << " deg/s" << endl; << gyro->angularVelocity()
<< " deg/s"
usleep(100000); << endl;
usleep(100000);
} }
//! [Interesting] //! [Interesting]
cout << "Exiting" << endl; cout << "Exiting" << endl;
delete gyro; delete gyro;
return 0; return 0;
} }

View File

@ -147,6 +147,7 @@ add_example (speaker)
add_example (cjq4435) add_example (cjq4435)
add_example (hmc5883l) add_example (hmc5883l)
add_example (wfs) add_example (wfs)
add_example (enc03r)
# Custom examples # Custom examples
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)

90
examples/c/enc03r.c Normal file
View File

@ -0,0 +1,90 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014-2017 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 <upm_utilities.h>
#include <upm_platform.h>
#include "enc03r.h"
bool shouldRun = true;
// The number of samples used for calibration
#if defined(UPM_PLATFORM_ZEPHYR)
# define CALIBRATION_SAMPLES 500
#else
# define CALIBRATION_SAMPLES 1000
#endif
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a ENC03R on analog pin A0
enc03r_context sensor = enc03r_init(0, 5.0);
if (!sensor)
{
printf("%s: enc03r_init() failed\n", __FUNCTION__);
return 1;
}
// The first thing we need to do is calibrate the sensor.
printf("Please place the sensor in a stable location, and do not\n");
printf("move it while calibration takes place.\n");
printf("This may take a little time to complete.\n");
enc03r_calibrate(sensor, CALIBRATION_SAMPLES);
printf("Calibration complete. Reference value: %f\n\n",
enc03r_calibration_value(sensor));
// Read the input and print both the raw value and the angular velocity,
// waiting 0.1 seconds between readings
while (shouldRun)
{
enc03r_update(sensor);
printf("Angular velocity: %f deg/s\n",
enc03r_angular_velocity(sensor));
upm_delay_ms(100);
}
printf("Exiting\n");
enc03r_close(sensor);
//! [Interesting]
return 0;
}

View File

@ -22,7 +22,7 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
//NOT TESTED!!!
public class ENC03RSample { public class ENC03RSample {
private static final long CALIBRATION_SAMPLES = 1000; private static final long CALIBRATION_SAMPLES = 1000;
@ -42,14 +42,15 @@ public class ENC03RSample {
// Read the input and print both the raw value and the angular velocity, // Read the input and print both the raw value and the angular velocity,
// waiting 1 second between readings // waiting 1 second between readings
while (true) { while (true) {
long val = gyro.value(); gyro.update();
double av = gyro.angularVelocity(val);
System.out.println("Raw value: " + val + ", angular velocity: " + av + " deg/s"); System.out.println("Angular velocity: "
+ gyro.angularVelocity()
+ " deg/s");
Thread.sleep(1000); Thread.sleep(100);
} }
// ! [Interesting] // ! [Interesting]
} }
} }

View File

@ -30,8 +30,8 @@ var myGyro = new analogGyro.ENC03R(0);
var CALIBRATION_SAMPLES = 1000; var CALIBRATION_SAMPLES = 1000;
console.log("Please place the sensor in a stable location,\n" + console.log("Please place the sensor in a stable location,\n" +
"and do not move it while calibration takes place.\n" + "and do not move it while calibration takes place.\n" +
"This may take a couple of minutes."); "This may take a couple of minutes.");
myGyro.calibrate(CALIBRATION_SAMPLES); myGyro.calibrate(CALIBRATION_SAMPLES);
console.log("Calibration complete. Reference value: " + console.log("Calibration complete. Reference value: " +
@ -41,23 +41,22 @@ console.log("Calibration complete. Reference value: " +
// waiting 0.1 seconds between readings // waiting 0.1 seconds between readings
setInterval(function() setInterval(function()
{ {
var gyroVal = myGyro.value(); myGyro.update();
var outputStr = "Raw value: " + gyroVal + ", " + var outputStr = "Angular velocity: " +
"angular velocity: " + roundNum(myGyro.angularVelocity(), 5) + " deg/s";
roundNum(myGyro.angularVelocity(gyroVal), 5) + " deg/s"; console.log(outputStr);
console.log(outputStr);
}, 100); }, 100);
function roundNum(num, decimalPlaces) function roundNum(num, decimalPlaces)
{ {
var extraNum = (1 / (Math.pow(10, decimalPlaces) * 1000)); var extraNum = (1 / (Math.pow(10, decimalPlaces) * 1000));
return (Math.round((num + extraNum) * (Math.pow(10, decimalPlaces))) / return (Math.round((num + extraNum) * (Math.pow(10, decimalPlaces))) /
Math.pow(10, decimalPlaces)); Math.pow(10, decimalPlaces));
} }
// Print message when exiting // Print message when exiting
process.on('SIGINT', function() process.on('SIGINT', function()
{ {
console.log("Exiting..."); console.log("Exiting...");
process.exit(0); process.exit(0);
}); });

View File

@ -55,10 +55,9 @@ def main():
print("Reference value: ", myAnalogGyro.calibrationValue()) print("Reference value: ", myAnalogGyro.calibrationValue())
while(1): while(1):
gyroVal = myAnalogGyro.value(); myAnalogGyro.update();
outputStr = ("Raw value: {0}, " outputStr = ("Angular velocity: {0}"
"angular velocity: {1}" " deg/s".format(myAnalogGyro.angularVelocity()))
" deg/s".format(gyroVal, myAnalogGyro.angularVelocity(gyroVal)))
print(outputStr) print(outputStr)
time.sleep(.1) time.sleep(.1)

View File

@ -0,0 +1,42 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 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.
*/
#ifndef UPM_GYROSCOPE_H_
#define UPM_GYROSCOPE_H_
#ifdef __cplusplus
extern "C" {
#endif
// Gyroscope function table
typedef struct _upm_gyroscope_ft {
upm_result_t (*upm_gyroscope_set_scale) (void* dev, float* scale);
upm_result_t (*upm_gyroscope_set_offset) (void* dev, float* offset);
upm_result_t (*upm_gyroscope_get_value) (void* dev, float* value);
} upm_gyroscope_ft;
#ifdef __cplusplus
}
#endif
#endif /* UPM_GYROSCOPE_H_ */

View File

@ -126,6 +126,7 @@ typedef struct _upm_sensor_ft* (*func_get_upm_sensor_ft)(upm_sensor_t sensor_typ
#include <fti/upm_rotaryencoder.h> #include <fti/upm_rotaryencoder.h>
#include <fti/upm_pressure.h> #include <fti/upm_pressure.h>
#include <fti/upm_compass.h> #include <fti/upm_compass.h>
#include <fti/upm_gyroscope.h>
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,5 +1,9 @@
set (libname "enc03r") upm_mixed_module_init (NAME enc03r
set (libdescription "Enc03r single axis analog gyro module") DESCRIPTION "Single-axis Analog Gyroscope"
set (module_src ${libname}.cxx) C_HDR enc03r.h
set (module_hpp ${libname}.hpp) C_SRC enc03r.c
upm_module_init() CPP_HDR enc03r.hpp
CPP_SRC enc03r.cxx
FTI_SRC enc03r_fti.c
CPP_WRAPS_C
REQUIRES mraa)

158
src/enc03r/enc03r.c Normal file
View File

@ -0,0 +1,158 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014-2017 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 <stdio.h>
#include <string.h>
#include <assert.h>
#include "enc03r.h"
enc03r_context enc03r_init(int pin, float aref)
{
// 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);
return NULL;
}
enc03r_context dev =
(enc03r_context)malloc(sizeof(struct _enc03r_context));
if (!dev)
return NULL;
// zero out context
memset((void *)dev, 0, sizeof(struct _enc03r_context));
dev->a_ref = aref;
if ( !(dev->aio = mraa_aio_init(pin)) )
{
printf("%s: mraa_aio_init() failed.\n", __FUNCTION__);
enc03r_close(dev);
return NULL;
}
dev->offset = 0.0;
dev->scale = 1.0;
dev->a_res = (float)(1 << mraa_aio_get_bit(dev->aio)) - 1.0;
dev->calibrationValue = 0.0;
return dev;
}
void enc03r_close(enc03r_context dev)
{
assert(dev != NULL);
if (dev->aio)
mraa_aio_close(dev->aio);
free(dev);
}
upm_result_t enc03r_update(enc03r_context dev)
{
assert(dev != NULL);
float val = (float)mraa_aio_read(dev->aio);
if (val < 0)
{
printf("%s: mraa_aio_read() failed\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
dev->normalized = val / dev->a_res;
// from seeed studio example
dev->angular_velocity =
((val - dev->calibrationValue) * (dev->a_ref * 1000.0)
/ dev->a_res / 0.67);
return UPM_SUCCESS;
}
upm_result_t enc03r_calibrate(const enc03r_context dev,
unsigned int samples)
{
assert(dev != NULL);
float total = 0.0;
for (int i=0; i<samples; i++)
{
int val = mraa_aio_read(dev->aio);
if (val < 0)
{
printf("%s: mraa_aio_read() failed\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
total += (float)val;
upm_delay_ms(2);
}
dev->calibrationValue = total / (float)samples;
return UPM_SUCCESS;
}
float enc03r_calibration_value(const enc03r_context dev)
{
assert(dev != NULL);
return dev->calibrationValue;
}
float enc03r_angular_velocity(const enc03r_context dev)
{
assert(dev != NULL);
return dev->angular_velocity * dev->scale + (dev->offset * dev->scale);
}
void enc03r_set_offset(const enc03r_context dev, float offset)
{
assert(dev != NULL);
dev->offset = offset;
}
void enc03r_set_scale(const enc03r_context dev, float scale)
{
assert(dev != NULL);
dev->scale = scale;
}
float enc03r_get_normalized(const enc03r_context dev)
{
assert(dev != NULL);
return dev->normalized;
}

View File

@ -1,6 +1,6 @@
/* /*
* Author: Jon Trulson <jtrulson@ics.com> * Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation. * Copyright (c) 2014-2017 Intel Corporation.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@ -31,52 +31,49 @@
using namespace upm; using namespace upm;
using namespace std; using namespace std;
ENC03R::ENC03R(int pin, float vref) ENC03R::ENC03R(int pin, float aref) :
m_enc03r(enc03r_init(pin, aref))
{ {
if ( !(m_aio = mraa_aio_init(pin)) ) if (!m_enc03r)
{ throw std::runtime_error(string(__FUNCTION__)
throw std::invalid_argument(std::string(__FUNCTION__) + + ": enc03r_init() failed");
": mraa_aio_init() failed, invalid pin?");
return;
}
m_vref = vref;
m_calibrationValue = 0;
} }
ENC03R::~ENC03R() ENC03R::~ENC03R()
{ {
mraa_aio_close(m_aio); enc03r_close(m_enc03r);
}
unsigned int ENC03R::value()
{
int x = mraa_aio_read(m_aio);
if (x == -1) throw std::out_of_range(std::string(__FUNCTION__) +
": Failed to do an aio read.");
return (unsigned int) x;
} }
void ENC03R::calibrate(unsigned int samples) void ENC03R::calibrate(unsigned int samples)
{ {
int val; if (enc03r_calibrate(m_enc03r, samples))
float total = 0.0; throw std::runtime_error(string(__FUNCTION__)
+ ": enc03r_calibrate() failed");
for (unsigned int i=0; i<samples; i++)
{
val = mraa_aio_read(m_aio);
if (val == -1) throw std::out_of_range(std::string(__FUNCTION__) +
": Failed to do an aio read.");
total += (float)val;
usleep(2000);
}
m_calibrationValue = total / (float)samples;
} }
double ENC03R::angularVelocity(unsigned int val) void ENC03R::update()
{ {
// from seeed studio example if (enc03r_update(m_enc03r))
//return (((double)(val-m_calibrationValue)*(m_vref*1000.0))/1023.0/0.67); throw std::runtime_error(string(__FUNCTION__)
return (((double)(val-m_calibrationValue)*(m_vref*1000.0))/685.41); + ": enc03r_update() failed");
}
float ENC03R::angularVelocity()
{
return enc03r_angular_velocity(m_enc03r);
}
void ENC03R::setOffset(float offset)
{
enc03r_set_offset(m_enc03r, offset);
}
void ENC03R::setScale(float scale)
{
enc03r_set_scale(m_enc03r, scale);
}
float ENC03R::getNormalized()
{
return enc03r_get_normalized(m_enc03r);
} }

159
src/enc03r/enc03r.h Normal file
View File

@ -0,0 +1,159 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014-2017 Intel Corporation.
emacs . *
* 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.
*/
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <mraa/aio.h>
#include <upm.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file enc03r.h
* @library enc03r
* @brief Generic API for AT command based UART devices
*
*/
/**
* Device context
*/
typedef struct _enc03r_context {
mraa_aio_context aio;
// determined by calibrate();
float calibrationValue;
// our computed value
float angular_velocity;
// analog reference voltage
float a_ref;
// analog ADC resolution (max value)
float a_res;
// offset
float offset;
// scale
float scale;
// normalized ADC value
float normalized;
} *enc03r_context;
/**
* ENC03R sensor constructor
*
* @param pin Analog pin to use
* @param vref Reference voltage to use; default is 5.0 V
* @return Device context
*/
enc03r_context enc03r_init(int pin, float aref);
/**
* ENC03R destructor
*
* @param dev Device context
*/
void enc03r_close(enc03r_context dev);
/**
* Update the internal state with the current reading. This
* function must be called prior to calling
* enc03r_angular_velocity().
*
* @param dev Device context
* @return UPM result
*/
upm_result_t enc03r_update(enc03r_context dev);
/**
* Calibrates the sensor by determining an analog reading over many
* samples with no movement of the sensor. This must be done
* before attempting to use the sensor.
*
* @param dev Device context
* @param samples Number of samples to use for calibration
* @return UPM result
*/
upm_result_t enc03r_calibrate(const enc03r_context dev,
unsigned int samples);
/**
* Returns the currently stored calibration value
*
* @param dev Device context
* @return Current calibration value
*/
float enc03r_calibration_value(const enc03r_context dev);
/**
* Return the computed Angular Velocity in degrees per second.
* You must have called encr03r_update() prior to calling this
* function.
*
* @param dev Device context
* @return Computed angular velocity
*/
float enc03r_angular_velocity(const enc03r_context dev);
/**
* Set sensor offset. The offste is applied to the return value
* before scaling. Default is 0.
*
* @param dev Device context
* @param scale Scale to apply to value
*/
void enc03r_set_offset(const enc03r_context dev, float offset);
/**
* Set sensor scale. The return value is scaled by this value
* before the offset is applied. Default is 1.0.
*
* @param dev Device context
* @param scale Offset to apply to value
*/
void enc03r_set_scale(const enc03r_context dev, float scale);
/**
* Get a normalized ADC value from the sensor. The return value
* will be between 0.0 (indicating no voltage) and 1.0 indicating
* max voltage (aref). encr03r_update() must be called prior to
* calling this function.
*
* @param dev Device context
* @return The normalized reading from the ADC.
*/
float enc03r_get_normalized(const enc03r_context dev);
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +1,6 @@
/* /*
* Author: Jon Trulson <jtrulson@ics.com> * Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation. * Copyright (c) 2014-2017 Intel Corporation.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@ -24,92 +24,116 @@
#pragma once #pragma once
#include <string> #include <string>
#include <mraa/aio.h> #include "enc03r.h"
namespace upm { namespace upm {
/** /**
* @brief ENC03R Single Axis Gyro library * @brief ENC03R Single Axis Gyro library
* @defgroup enc03r libupm-enc03r * @defgroup enc03r libupm-enc03r
* @ingroup seeed analog compass robok * @ingroup seeed analog compass robok
*/ */
/**
* @library enc03r
* @sensor enc03r
* @comname ENC03R Single Axis Gyro
* @altname Grove Single Axis Analog Gyro
* @type compass
* @man seeed
* @con analog
* @kit robok
*
* @brief API for the ENC03R Single Axis Analog Gyro
*
* UPM module for the ENC03R single axis analog gyro.
* This gyroscope measures x-axis angular velocity, that is
* how fast the sensor is rotating around the x-axis.
* Calibration of the sensor is necessary for accurate readings.
*
* @image html enc03r.jpg
* @snippet enc03r.cxx Interesting
*/
class ENC03R {
public:
/** /**
* ENC03R sensor constructor * @library enc03r
* @sensor enc03r
* @comname ENC03R Single Axis Gyro
* @altname Grove Single Axis Analog Gyro
* @type compass
* @man seeed
* @con analog
* @kit robok
* *
* @param pin Analog pin to use * @brief API for the ENC03R Single Axis Analog Gyro
* @param vref Reference voltage to use; default is 5.0 V
*/
ENC03R(int pin, float vref=5.0);
/**
* ENC03R destructor
*/
~ENC03R();
/**
* Calibrates the sensor by determining an analog reading over many
* samples with no movement of the sensor. This must be done
* before attempting to use the sensor.
* *
* @param samples Number of samples to use for calibration * UPM module for the ENC03R single axis analog gyro.
*/ * This gyroscope measures x-axis angular velocity, that is
void calibrate(unsigned int samples); * how fast the sensor is rotating around the x-axis.
* Calibration of the sensor is necessary for accurate readings.
/**
* Returns the raw value of the sensor
* *
* @return Raw value of the sensor * @image html enc03r.jpg
* @snippet enc03r.cxx Interesting
*/ */
unsigned int value(); class ENC03R {
public:
/** /**
* Returns the currently stored calibration value * ENC03R sensor constructor
* *
* @return Current calibration value * @param pin Analog pin to use
*/ * @param vref Reference voltage to use; default is 5.0 V
float calibrationValue() { return m_calibrationValue; }; */
ENC03R(int pin, float aref=5.0);
/** /**
* Computes angular velocity based on the value and stored calibration * ENC03R destructor
* reference. */
* ~ENC03R();
* @param val Value to use to compute angular velocity
* @return Computed angular velocity
*/
double angularVelocity(unsigned int val);
private: /**
// determined by calibrate(); * Calibrates the sensor by determining an analog reading over many
float m_calibrationValue; * samples with no movement of the sensor. This must be done
* before attempting to use the sensor.
*
* @param samples Number of samples to use for calibration
*/
void calibrate(unsigned int samples);
// reference voltage /**
float m_vref; * Update the internal state with the current reading. This
mraa_aio_context m_aio; * function must be called prior to calling
}; * angularVelocity().
*
* @param dev Device context
*/
void update();
/**
* Returns the currently stored calibration value
*
* @return Current calibration value
*/
float calibrationValue() { return enc03r_calibration_value(m_enc03r); };
/**
* Computes angular velocity based on the value and stored calibration
* reference.
*
* @param val Value to use to compute angular velocity
* @return Computed angular velocity
*/
float angularVelocity();
/**
* Set sensor offset. The offste is applied to the return value
* before scaling. Default is 0.
*
* @param scale Scale to apply to value
*/
void setOffset(float offset);
/**
* Set sensor scale. The return value is scaled by this value
* before the offset is applied. Default is 1.0.
*
* @param dev Device context
* @param scale Offset to apply to value
*/
void setScale(float scale);
/**
* Get a normalized ADC value from the sensor. The return
* value will be between 0.0 (indicating no voltage) and 1.0
* indicating max voltage (aref). update() must be called
* prior to calling this function.
*
* @return The normalized reading from the ADC.
*/
float getNormalized();
protected:
enc03r_context m_enc03r;
private:
};
} }

102
src/enc03r/enc03r_fti.c Normal file
View File

@ -0,0 +1,102 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 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 "enc03r.h"
#include "upm_fti.h"
/**
* This file implements the Function Table Interface (FTI) for this sensor
*/
const char upm_enc03r_name[] = "ENC03R";
const char upm_enc03r_description[] = "Analog Single Axis Gyroscope";
const upm_protocol_t upm_enc03r_protocol[] = {UPM_ANALOG};
const upm_sensor_t upm_enc03r_category[] = {UPM_GYROSCOPE};
// forward declarations
const void* upm_enc03r_get_ft(upm_sensor_t sensor_type);
void* upm_enc03r_init_name();
void upm_enc03r_close(void *dev);
upm_result_t upm_enc03r_get_value(void *dev, float *value);
const upm_sensor_descriptor_t upm_enc03r_get_descriptor()
{
upm_sensor_descriptor_t usd;
usd.name = upm_enc03r_name;
usd.description = upm_enc03r_description;
usd.protocol_size = 1;
usd.protocol = upm_enc03r_protocol;
usd.category_size = 1;
usd.category = upm_enc03r_category;
return usd;
}
static const upm_sensor_ft ft =
{
.upm_sensor_init_name = &upm_enc03r_init_name,
.upm_sensor_close = &upm_enc03r_close,
};
static const upm_gyroscope_ft gft =
{
.upm_gyroscope_get_value = &upm_enc03r_get_value
};
const void* upm_enc03r_get_ft(upm_sensor_t sensor_type)
{
switch(sensor_type)
{
case UPM_SENSOR:
return &ft;
case UPM_GYROSCOPE:
return &gft;
default:
return NULL;
}
}
void* upm_enc03r_init_name()
{
return NULL;
}
void upm_enc03r_close(void *dev)
{
enc03r_close((enc03r_context)dev);
}
upm_result_t upm_enc03r_get_value(void *dev, float *value)
{
if (enc03r_update((enc03r_context)dev))
return UPM_ERROR_OPERATION_FAILED;
value[0] = enc03r_angular_velocity((enc03r_context)dev);
value[1] = 0.0;
value[2] = 0.0;
return UPM_SUCCESS;
}