d6t: initial implementation of Omron Thermal Sensor d6t\n\r\n\r

Signed-off-by: omron-ankit <ankit.juneja@omron.com>
This commit is contained in:
omron-ankit 2019-08-07 18:22:53 +00:00
parent 6bf21a23e7
commit d7eac4a878
6 changed files with 1283 additions and 0 deletions

407
examples/c++/d6t.cxx Normal file
View File

@ -0,0 +1,407 @@
/*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* 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.
*/
/* standard headers */
#include <iostream>
#include <signal.h>
#include <upm_utilities.h>
#include <sys/time.h>
#include <iomanip>
#include <cmath>
/* omron sensor header */
#include "d6t.hpp"
using namespace upm;
using namespace std;
volatile sig_atomic_t flag = true;
/**
* 1) Using first macro, call displayTemperature() method call and
* display the temperature
* 2) Using second macro, call API
* getTemperature(float *ptat, float* temperatureData,
* uint8_t length, uint8_t *pec);
* 3) Using third macro, call API
* getTemperature(float &ptat, std::vector<float> &temperatureData,
* uint8_t &pec);
*/
#define DISP_TEMP_API
#define DISP_TEMP_API_USING_ARRAY
#define DISP_TEMP_API_USING_VECTOR
/**
* delay values channel 1
*/
float channel_1_delay_values[]=
{0.4, 0.8, 1.6, 3.2, 6.4, 12.5, 25, 50, 100, 200, 400, 800, 1600, 3200, 0.4, 0.8, 1.6, 3.2, 6.4, 12.5, 25, 50, 100, 200, 400, 800, 1600, 3200};
/**
* delay values channel 8
*/
double channel_8_delay_values[]=
{1, 2, 4, 8, 16, 32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 1, 2, 4, 8, 16, 32, 64, 125, 250, 500, 1000, 2000, 4000, 8000};
/**
* delay values channel 16
*/
double channel_16_delay_values[]=
{43, 86, 130, 172, 215, 258, 300, 344, 386, 420, 472, 514, 558, 600, 642, 685, 728, 772, 814, 856, 900, 942, 986, 1028, 1070, 1114, 1156, 1200, 1242, 1284, 1328, 1370};
void
sig_handler(int signum)
{
// Check for Abort signal
if(signum == SIGABRT){
cout << "abort signal" << endl;
}
// Check for Interrupt signal
if (signum == SIGINT || signum == SIGTERM){
cout << "exit" << endl;
flag = false;
exit(1);
}
}
int
main(int argc, char** argv)
{
char option = 0;
int bus = D6T_DEFAULT_I2C_BUS_NUM;
uint32_t sleep_time = 1000;
int interval_value;
uint32_t intervalValueMS = 0;
uint8_t addr = D6T_DEFAULT_I2C_ADDR;
D6T_SENSOR_TYPES_T s_type;
TemperatureUnit iTempscale = TemperatureUnit::CELSIUS;
int ret = D6T_STATUS_FAILURE;
uint8_t iInput;
signal(SIGINT, sig_handler);
// Print sensor for selection
cout << "************************************************************\r\n";
cout << "Please select type of thermal sensor \r\n";
cout << "1) 1X1 Channel\r\n";
cout << "2) 1X8 Channel\r\n";
cout << "3) 4X4 Channel\r\n";
cout << "************************************************************\r\n";
cin >> iInput;
// Update sensor type variable
switch(iInput){
case '1':
s_type = D6T_1X1_CHANNEL;
break;
case '2':
s_type = D6T_1X8_CHANNEL;
break;
case '3':
s_type = D6T_4X4_CHANNEL;
break;
default:
cout << "Invalid Selection\r\n";
exit(1);
}
// Print Temperature scale for selection
cout << "************************************************************\r\n";
cout << "Please select Temperature scale \r\n";
cout << "1) CELCIUS\r\n";
cout << "2) FAHRENHEIT\r\n";
cout << "3) KELVIN\r\n";
cout << "************************************************************\r\n";
cin >> iInput;
// Update Temperature scale variable
switch(iInput){
case '1':
iTempscale = TemperatureUnit::CELSIUS;
break;
case '2':
iTempscale = TemperatureUnit::FAHRENHEIT;
break;
case '3':
iTempscale = TemperatureUnit::KELVIN;
break;
default:
cout << "Invalid Selection\r\n";
exit(1);
}
// Instantiate a D6T sensor on I2C using bus and address.
D6T sensor(s_type,bus,addr);
uint8_t Interval = 0;
// Get current interval setting
sensor.getMeasurementInterval(Interval);
if(s_type == D6T_4X4_CHANNEL){
// Print for measurement value
cout << "************************************************************\r\n";
cout << "Please select interval measurement value between 1 to 32 \r\n";
cout << "Current Measurement Interval value is : " << unsigned(Interval) << endl;
cout << "************************************************************\r\n";
cout << "1 : 43 ms\r\n";
cout << "2 : 86 ms\r\n";
cout << "3 : 130 ms\r\n";
cout << "4 : 172 ms\r\n";
cout << "5 : 215 ms\r\n";
cout << "6 : 258 ms\r\n";
cout << "7 : 300 ms(Recommended)\r\n";
cout << "8 : 344 ms\r\n";
cout << "9 : 386 ms\r\n";
cout << "10 : 420 ms\r\n";
cout << "11 : 472 ms\r\n";
cout << "12 : 514 ms\r\n";
cout << "13 : 558 ms\r\n";
cout << "14 : 600 ms\r\n";
cout << "15 : 642 ms\r\n";
cout << "16 : 685 ms\r\n";
cout << "17 : 728 ms\r\n";
cout << "18 : 772 ms\r\n";
cout << "19 : 814 ms\r\n";
cout << "20 : 856 ms\r\n";
cout << "21 : 900 ms\r\n";
cout << "22 : 942 ms\r\n";
cout << "23 : 986 ms\r\n";
cout << "24 : 1028 ms\r\n";
cout << "25 : 1070 ms\r\n";
cout << "26 : 1114 ms\r\n";
cout << "27 : 1156 ms\r\n";
cout << "28 : 1200 ms\r\n";
cout << "29 : 1242 ms\r\n";
cout << "30 : 1284 ms\r\n";
cout << "31 : 1328 ms\r\n";
cout << "32 : 1370 ms\r\n";
cout << "************************************************************\r\n";
cin >> interval_value;
// Inteval Value
intervalValueMS = channel_16_delay_values[interval_value - 1];
}else{
// Print for measurement value
cout << "************************************************************\r\n";
cout << "Please select interval measurement value between 1 to 28 \r\n";
cout << "Current Measurement Interval value is : " << unsigned(Interval) << endl;
cout << "************************************************************\r\n";
if(s_type == D6T_1X1_CHANNEL){
cout << "1 : 8 ms\r\n";
cout << "2 : 8.5 ms\r\n";
cout << "3 : 10 ms\r\n";
cout << "4 : 12 ms\r\n";
cout << "5 : 15 ms\r\n";
cout << "6 : 20 ms\r\n";
cout << "7 : 35 ms\r\n";
cout << "8 : 55 ms\r\n";
cout << "9 : 100 ms\r\n";
cout << "10 : 200 ms\r\n";
cout << "11 : 400 ms\r\n";
cout << "12 : 800 ms\r\n";
cout << "13 : 1600 ms\r\n";
cout << "14 : 3200 ms\r\n";
cout << "15 : 8 ms(2 times average)\r\n";
cout << "16 : 8.5 ms(2 times average)\r\n";
cout << "17 : 10 ms(2 times average)\r\n";
cout << "18 : 12 ms(2 times average)\r\n";
cout << "19 : 15 ms(2 times average)\r\n";
cout << "20 : 20 ms(2 times average)\r\n";
cout << "21 : 35 ms(2 times average)\r\n";
cout << "22 : 55 ms(2 times average)\r\n";
cout << "23 : 100 ms(2 times average)(Recommended)\r\n";
cout << "24 : 200 ms(2 times average)\r\n";
cout << "25 : 400 ms(2 times average)\r\n";
cout << "26 : 800 ms(2 times average)\r\n";
cout << "27 : 1600 ms(2 times average)\r\n";
cout << "28 : 3200 ms(2 times average)\r\n";
cout << "************************************************************\r\n";
cin >> interval_value;
// Inteval Value
intervalValueMS = ceil(channel_1_delay_values[interval_value - 1]);
}else{
cout << "1 : 9 ms\r\n";
cout << "2 : 10 ms\r\n";
cout << "3 : 12 ms\r\n";
cout << "4 : 16 ms\r\n";
cout << "5 : 24 ms\r\n";
cout << "6 : 40 ms\r\n";
cout << "7 : 70 ms\r\n";
cout << "8 : 140 ms\r\n";
cout << "9 : 250 ms\r\n";
cout << "10 : 500 ms\r\n";
cout << "11 : 1000 ms\r\n";
cout << "12 : 2000 ms\r\n";
cout << "13 : 4000 ms\r\n";
cout << "14 : 8000 ms\r\n";
cout << "15 : 9 ms(2 times average)\r\n";
cout << "16 : 10 ms(2 times average)\r\n";
cout << "17 : 12 ms(2 times average)\r\n";
cout << "18 : 16 ms(2 times average)\r\n";
cout << "19 : 24 ms(2 times average)\r\n";
cout << "20 : 40 ms(2 times average)\r\n";
cout << "21 : 70 ms(2 times average)\r\n";
cout << "22 : 140 ms(2 times average)\r\n";
cout << "23 : 250 ms(2 times average)(Recommended)\r\n";
cout << "24 : 500 ms(2 times average)\r\n";
cout << "25 : 1000 ms(2 times average)\r\n";
cout << "26 : 2000 ms(2 times average)\r\n";
cout << "27 : 4000 ms(2 times average)\r\n";
cout << "28 : 8000 ms(2 times average)\r\n";
cout << "************************************************************\r\n";
cin >> interval_value;
// Inteval Value
intervalValueMS = channel_8_delay_values[interval_value - 1];
}
}
while(true){
// Print for enter sleep time
cout << "************************************************************\r\n";
cout << "Please enter display sleep time in ms \r\n";
cout << "Value entered should be greater than or equal to the sensor measurement interval\r\n";
cout << "************************************************************\r\n";
// Update sleep time variable
cin >> sleep_time;
//Compare sleep time interval with sensor measurement interval
if(sleep_time >= intervalValueMS){
break;
}else{
cout << "ERROR: Please enter the value greater than or equal to sensor measurement interval" << endl;
}
}
//set interval value
ret = sensor.setMeasurementInterval(interval_value);
// Display error message if measurement interval set fail
if(ret != D6T_STATUS_SUCCESS){
cout << "Measurement interval set fail" << endl;
return ret;
}
// Set temperature scale
ret = sensor.setTemperatureScale(iTempscale);
// Display error message if temperature scale set fail
if(ret != D6T_STATUS_SUCCESS){
cout << "Temperature scale set fail" << endl;
return ret;
}
//Get Temperature scale
sensor.getTemperatureScale(iTempscale);
//Print temperature scale
if(iTempscale == TemperatureUnit::CELSIUS){
cout << "Temperature scale - CELSIUS\r\n";
}
else if(iTempscale == TemperatureUnit::FAHRENHEIT){
cout << "Temperature scale - FAHRENHEIT\r\n";
}
else if(iTempscale == TemperatureUnit::KELVIN){
cout << "Temperature scale - KELVIN\r\n";
}else{
cout << "Temperature scale set fail\r\n";
}
// Variables declaration
float ptat;
float temperatureData[s_type];
vector<float> VtemperatureData;
uint8_t pec;
D6T_STATUS_T returnValue;
uint8_t counter;
// Data and Time
char dateAndTime[30];
struct timeval value;
time_t curtime;
// Print the Temperature, PTAT, and PEC values
// every perticular time as configure in sleep time
while(flag)
{
gettimeofday(&value, NULL);
curtime=value.tv_sec;
strftime(dateAndTime,30,"[%F %T.",localtime(&curtime));
cout << dateAndTime << std::setfill('0') << std::setw(3) << value.tv_usec/1000 << "] ";
#ifdef DISP_TEMP_API
sensor.displayTemperature();
#elif defined (DISP_TEMP_API_USING_ARRAY)
//Get current thermal sensor temperature values
returnValue = sensor.getTemperature(&ptat, temperatureData, s_type, &pec);
if(D6T_STATUS_SUCCESS != returnValue){
std::cout << "displayTemperature failed with error code: " << returnValue << std::endl;
}
//Print values
cout << "TEMP_DATA: ";
for(counter = 0; counter < s_type; counter ++) {
cout << temperatureData[counter] << " ";
}
cout << "PTAT: " << ptat;
cout << " PEC: " << (unsigned) pec << endl;
#elif defined (DISP_TEMP_API_USING_VECTOR)
returnValue = sensor.getTemperature(ptat, VtemperatureData, pec);
if(D6T_STATUS_SUCCESS != returnValue){
std::cout << "displayTemperature failed with error code: " << returnValue << std::endl;
return returnValue;
}
//Print values
cout << "TEMP_DATA: ";
for(counter = 0; counter < s_type; counter ++) {
cout << VtemperatureData[counter] << " ";
}
cout << "PTAT: " << ptat;
cout << " PEC: " << (unsigned) pec << endl;
//Clear Vector
VtemperatureData.clear();
#endif
//Delay
upm_delay_ms(sleep_time);
}
return 0;
}

5
src/d6t/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
set (libname "d6t")
set (libdescription "Mems Thermal Sensors")
set (module_src "${libname}.cxx" "d6t.cxx")
set (module_hpp "${libname}.hpp" "d6t.hpp")
upm_module_init(mraa)

536
src/d6t/d6t.cxx Normal file
View File

@ -0,0 +1,536 @@
/*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* 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 <stdexcept>
#include <stdio.h>
#include <iomanip>
#include <string.h>
#include "d6t.hpp"
using namespace upm;
/**
* Measurement interval values for 1 Channel Sensor
*/
uint8_t D6T::intervalValues1Channel[D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH][D6T_1AND8_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH]={
{0x80, 0xD2, 0x79},{0x80, 0xD3, 0x7E},{0x80, 0xD4, 0x6B},{0x80, 0xD5, 0x6C},
{0x80, 0xD6, 0x65},{0x80, 0xD7, 0x62},{0x80, 0xD8, 0x4F},{0x80, 0xD9, 0x48},
{0x80, 0xDA, 0x41},{0x80, 0xDB, 0x46},{0x80, 0xDC, 0x53},{0x80, 0xDD, 0x54},
{0x80, 0xDE, 0x5D},{0x80, 0xDF, 0x5A},{0x90, 0xD2, 0x2E},{0x90, 0xD3, 0x29},
{0x90, 0xD4, 0x3C},{0x90, 0xD5, 0x3B},{0x90, 0xD6, 0x32},{0x90, 0xD7, 0x35},
{0x90, 0xD8, 0x18},{0x90, 0xD9, 0x1F},{0x90, 0xDA, 0x16},{0x90, 0xDB, 0x11},
{0x90, 0xDC, 0x04},{0x90, 0xDD, 0x03},{0x90, 0xDE, 0x0A},{0x90, 0xDF, 0x0D}};
/**
* Measurement interval values for 8 Channel Sensor
*/
uint8_t D6T::intervalValues8Channel[D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH][D6T_1AND8_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH]={
{0x80, 0x32, 0xD7},{0x80, 0x33, 0xD0},{0x80, 0x34, 0xC5},{0x80, 0x35, 0xC2},
{0x80, 0x36, 0xCB},{0x80, 0x37, 0xCC},{0x80, 0x38, 0xE1},{0x80, 0x39, 0xE6},
{0x80, 0x3A, 0xEF},{0x80, 0x3B, 0xE8},{0x80, 0x3C, 0xFD},{0x80, 0x3D, 0xFA},
{0x80, 0x3E, 0xF3},{0x80, 0x3F, 0xF4},{0x90, 0x32, 0x80},{0x90, 0x33, 0x87},
{0x90, 0x34, 0x92},{0x90, 0x35, 0x95},{0x90, 0x36, 0x9C},{0x90, 0x37, 0x9B},
{0x90, 0x38, 0xB6},{0x90, 0x39, 0xB1},{0x90, 0x3A, 0xB8},{0x90, 0x3B, 0xBF},
{0x90, 0x3C, 0xAA},{0x90, 0x3D, 0xAD},{0x90, 0x3E, 0xA4},{0x90, 0x3F, 0xA3}};
/**
* Measurement interval values for 16 Channel Sensor
*/
uint8_t D6T::intervalValues16Channel[D6T_16_CHANNEL_VALUE_BUFFER_ROW_LENGTH][D6T_16_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH]={
{0x01,0x00},{0x02,0x00},{0x03,0x00},{0x04,0x00},{0x05,0x00},{0x06,0x00},
{0x07,0x00},{0x08,0x00},{0x09,0x00},{0x0A,0x00},{0x0B,0x00},{0x0C,0x00},
{0x0D,0x00},{0x0E,0x00},{0x0F,0x00},{0x10,0x00},{0x11,0x00},{0x12,0x00},
{0x13,0x00},{0x14,0x00},{0x15,0x00},{0x16,0x00},{0x17,0x00},{0x18,0x00},
{0x19,0x00},{0x1A,0x00},{0x1B,0x00},{0x1C,0x00},{0x1D,0x00},{0x1E,0x00},
{0x1F,0x00},{0x20,0x00}};
/**
* Measurement interval bytes write pattern
* for 1 and 8 channel sensor
*/
uint8_t D6T::intervalBytePattern1And8Channel[D6T_1AND8_CHANNEL_REG_PATTERN_ROW_LENGTH][D6T_1AND8_CHANNEL_REG_PATTERN_COLUMN_LENGTH]={
{0x02, 0x00, 0x01, 0xEE},
{0x05, 0x90, 0x3F, 0xA3},
{0x03, 0x00, 0x03, 0x8B},
{0x03, 0x00, 0x07, 0x97},
{0x02, 0x00, 0x00, 0xE9}};
/**
* Measurement interval bytes write pattern
* for 16 channel sensor
*/
uint8_t D6T::intervalBytePattern16Channel[D6T_16_CHANNEL_REG_PATTERN_ROW_LENGTH][D6T_16_CHANNEL_REG_PATTERN_COLUMN_LENGTH]={
{0x50, 0x52, 0x45, 0x4C, 0x45, 0x41, 0x53, 0x45, 0x00},
{0x42, 0x14, 0x00},
{0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
D6T::D6T(D6T_SENSOR_TYPES_T type, int bus,uint8_t address): m_bus(bus), m_address(address) {
//Create I2c object
m_i2c = new mraa::I2c(m_bus);
//Check for I2c object created well or not
if(m_i2c->address(m_address) != mraa::SUCCESS){
throw std::invalid_argument(std::string(__FUNCTION__) + ": I2c.address() failed");
}
//Set default Temperature scale to celsius
m_tempScale = upm::TemperatureUnit::CELSIUS;
//Set sensor type
d6t_sensor_type = type;
setSensorType(type);
//Set default floating point precision
std::cout << std::fixed << std::setprecision(2);
}
D6T::~D6T() {
//Delete I2c instance
delete m_i2c;
//Delete buffer
delete m_buf;
}
D6T_STATUS_T D6T::getTemperature(float *ptat, float* temperatureData, uint8_t length, uint8_t *pec) {
D6T_STATUS_T ret;
uint8_t counter = 0;
//Input arguments validation
if(NULL == ptat || NULL == temperatureData || NULL == pec){
return D6T_STATUS_INVALID_INPUT;
}
//Get updated temperature
try{
ret = getUpdatedTemperature();
//Check return value
if(ret != D6T_STATUS_SUCCESS){
std::cerr << "Get Temperature data failed " << std::endl;
return ret;
}
}catch(const std::runtime_error& e) {
std::cerr << "Error while handling: " << e.what() << std::endl;
return ret;
}
//Copy temperature data
for(counter = 0; counter < length; counter ++) {
temperatureData[counter] = (((m_buf[(counter*2) + 3] * 256) + m_buf[(counter *2) + 2]) / 10.0);
if(m_tempScale != upm::TemperatureUnit::CELSIUS){
temperatureData[counter] = convertCelsiusTo(temperatureData[counter],m_tempScale);
}
}
*ptat = (((m_buf[1] * 256) + m_buf[0]) / 10.0);
*pec = m_buf[d6t_sensor_data_length -1];
return D6T_STATUS_SUCCESS;
}
D6T_STATUS_T D6T::getTemperature(float &ptat, std::vector<float> &temperatureData, uint8_t &pec)
{
D6T_STATUS_T ret;
uint8_t counter = 0;
//Get updated temperature
try{
ret = getUpdatedTemperature();
//Check return value
if(ret != D6T_STATUS_SUCCESS){
std::cerr << "Error while handling: " << std::endl;
return ret;
}
}catch(const std::runtime_error& e) {
std::cerr << "Error while handling: " << e.what() << std::endl;
return ret;
}
//temporary variable
float tmpData = 0;
//Copy temperature data
for(counter = 0; counter < d6t_sensor_type ; counter ++) {
tmpData = ((((m_buf[(counter*2) + 3] * 256) + m_buf[(counter *2) + 2]) / 10.0));
if(m_tempScale != upm::TemperatureUnit::CELSIUS){
tmpData = convertCelsiusTo(tmpData,m_tempScale);
}
temperatureData.push_back(tmpData);
}
ptat = (((m_buf[1] * 256) + m_buf[0]) / 10.0);
pec = m_buf[d6t_sensor_data_length - 1];
return D6T_STATUS_SUCCESS;
}
D6T_STATUS_T D6T::getTemperatureScale(TemperatureUnit &unit)
{
unit = m_tempScale;
return D6T_STATUS_SUCCESS;
}
D6T_STATUS_T D6T::setTemperatureScale(TemperatureUnit unit)
{
m_tempScale = unit;
return D6T_STATUS_SUCCESS;
}
D6T_STATUS_T D6T::getSensorType(D6T_SENSOR_TYPES_T &type)
{
type = d6t_sensor_type;
return D6T_STATUS_SUCCESS;
}
D6T_STATUS_T D6T::setSensorType(D6T_SENSOR_TYPES_T type)
{
D6T_STATUS_T returnValue = D6T_STATUS_SUCCESS;
// Set sensor type
d6t_sensor_type = type;
switch(type)
{
case D6T_1X1_CHANNEL:
d6t_sensor_data_length = D6T_1X1_CHANNEL_BUFFER_LENGTH;
break;
case D6T_1X8_CHANNEL:
d6t_sensor_data_length = D6T_1X8_CHANNEL_BUFFER_LENGTH;
break;
case D6T_4X4_CHANNEL:
d6t_sensor_data_length = D6T_4X4_CHANNEL_BUFFER_LENGTH;
break;
default:
returnValue = D6T_STATUS_INVALID_SENSOR_TYPE;
return returnValue;
}
// Memory Allocation
m_buf = new uint8_t[d6t_sensor_data_length];
// Check Memory Allocation
if(m_buf == NULL){
throw std::runtime_error(std::string(__FUNCTION__) +
": Allocation failed" );
}
return returnValue;
}
D6T_STATUS_T D6T::displayTemperature()
{
float ptat;
float temperatureData[d6t_sensor_type];
uint8_t pec;
D6T_STATUS_T returnValue;
uint8_t counter;
//Get current thermal sensor temperature values
returnValue = getTemperature(&ptat, temperatureData, d6t_sensor_type, &pec);
//Check return value
if(D6T_STATUS_SUCCESS != returnValue){
std::cout << "displayTemperature failed with error code: " << returnValue << std::endl;
return returnValue;
}
//Print values
std::cout << "TEMP_DATA: ";
for(counter = 0; counter < d6t_sensor_type; counter++) {
std::cout << temperatureData[counter] << " ";
}
std::cout << "PTAT: " << ptat;
std::cout << " PEC: " << unsigned(pec) << std::endl;
return D6T_STATUS_SUCCESS;
}
D6T_STATUS_T D6T::getUpdatedTemperature()
{
mraa::Result returnValue;
//Check memory allocated for data
if(m_buf == NULL){
throw std::runtime_error(std::string(__FUNCTION__) +
": Sensor channel type not set" );
}
//Make sensor ready to read data
if((returnValue = m_i2c->writeByte(D6T_SENSOR_DATA_READ_CMD)) != mraa::SUCCESS){
throw std::runtime_error(std::string(__FUNCTION__) +
": I2c.writeByte() failed" );
}
//Read sensor data
if (!m_i2c->read(m_buf, d6t_sensor_data_length)){
throw std::runtime_error(std::string(__FUNCTION__) +
": I2c.read() failed");
}
//Validate PEC value
if(checkPEC(m_buf, d6t_sensor_data_length - 1)){
return D6T_STATUS_PEC_FAILURE;
}
return D6T_STATUS_SUCCESS;
}
uint8_t D6T::calculateCrc(uint8_t data)
{
uint8_t index;
uint8_t temp;
//CRC method
for(index=0;index<8;index++){
temp = data;
data <<= 1;
if(temp & 0x80) data ^= 0x07;
}
return data;
}
bool D6T::checkPEC(uint8_t *buf , uint8_t count)
{
uint8_t crc;
uint8_t i;
uint8_t defaulut_value = 0x14;
//Calculate CRC
crc = calculateCrc(defaulut_value);
crc = calculateCrc(0x4C ^ crc );
crc = calculateCrc(0x15 ^ crc );
for(i=0;i<count;i++){
crc = calculateCrc( buf[i] ^ crc );
}
return (crc == buf[count]);
}
D6T_STATUS_T D6T::getMeasurementInterval(uint8_t &value)
{
D6T_STATUS_T returnValue = D6T_STATUS_SUCCESS;
uint8_t count;
uint8_t tempByte[2];
switch(d6t_sensor_type)
{
case D6T_1X1_CHANNEL:
try{
//Get register values
returnValue = getMeasurementSettingRegisterValue(intervalBytePattern1And8Channel[1][0],tempByte);
//Check return value
if(returnValue != D6T_STATUS_SUCCESS){
std::cerr << "Error while handling: " << std::endl;
return returnValue;
}
}catch(const std::runtime_error& e){
std::cerr << "Error while handling: " << e.what() << std::endl;
return returnValue;
}
//Find register value from buffer
for(count = 0; count < D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH; count++){
if(memcmp(intervalValues1Channel[count],tempByte,sizeof(tempByte)) == 0){
value = count + 1;
break;
}
}
//Return invalid measurement interval
if(count == D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH){
return D6T_STATUS_INVALID_MEASURMENT_INTERVAL;
}
break;
case D6T_1X8_CHANNEL:
try{
//Get register values
returnValue = getMeasurementSettingRegisterValue(intervalBytePattern1And8Channel[1][0],tempByte);
//Check return value
if(returnValue != D6T_STATUS_SUCCESS){
std::cerr << "Error while handling: " << std::endl;
return returnValue;
}
}catch(const std::runtime_error& e){
std::cerr << "Error while handling: " << e.what() << std::endl;
return returnValue;
}
//Find register value from buffer
for(count = 0; count < D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH; count++){
if(memcmp(intervalValues8Channel[count],tempByte,sizeof(tempByte)) == 0){
value = count + 1;
break;
}
}
//Return invalid measurement interval
if(count == D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH){
return D6T_STATUS_INVALID_MEASURMENT_INTERVAL;
}
break;
case D6T_4X4_CHANNEL:
try{
//Unlock register
if((m_i2c->write(intervalBytePattern16Channel[0],D6T_16_CHANNEL_REG_PATTERN_COLUMN_LENGTH)) != mraa::SUCCESS)
{
throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write failed");
}
//Get register values
returnValue = getMeasurementSettingRegisterValue(D6T_16_CHANNEL_WRITE_ADDR_READ_REG_VALUE,tempByte);
//Check return value
if(returnValue != D6T_STATUS_SUCCESS){
std::cerr << "Fail to get measurement interval register value" << std::endl;
return returnValue;
}
//Lock register
if((m_i2c->write(intervalBytePattern16Channel[2],D6T_16_CHANNEL_REG_PATTERN_COLUMN_LENGTH)) != mraa::SUCCESS)
{
throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write failed");
}
}catch(const std::runtime_error& e){
std::cerr << "Error while handling: " << e.what() << std::endl;
return returnValue;
}
//Find register value from buffer
for(count = 0; count < D6T_16_CHANNEL_VALUE_BUFFER_ROW_LENGTH; count++){
if(memcmp(intervalValues16Channel[count],tempByte,1) == 0){
value = count + 1;
break;
}
}
//Return invalid measurement interval
if(count == D6T_16_CHANNEL_VALUE_BUFFER_ROW_LENGTH){
return D6T_STATUS_INVALID_MEASURMENT_INTERVAL;
}
break;
default:
returnValue = D6T_STATUS_INVALID_SENSOR_TYPE;
return returnValue;
}
return D6T_STATUS_SUCCESS;
}
D6T_STATUS_T D6T::setMeasurementInterval(uint8_t value)
{
D6T_STATUS_T returnValue = D6T_STATUS_SUCCESS;
switch(d6t_sensor_type)
{
case D6T_1X1_CHANNEL:
//Copy interval values
intervalBytePattern1And8Channel[1][1] = intervalValues1Channel[value - 1][0];
intervalBytePattern1And8Channel[1][2] = intervalValues1Channel[value - 1][1];
intervalBytePattern1And8Channel[1][3] = intervalValues1Channel[value - 1][2];
//Write interval setting
for(int i = 0;i < D6T_1AND8_CHANNEL_REG_PATTERN_ROW_LENGTH; i++)
{
if((m_i2c->write(intervalBytePattern1And8Channel[i],D6T_1AND8_CHANNEL_REG_PATTERN_COLUMN_LENGTH)) != mraa::SUCCESS){
throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write failed");
}
}
break;
case D6T_1X8_CHANNEL:
//Copy interval values
intervalBytePattern1And8Channel[1][1] = intervalValues8Channel[value - 1][0];
intervalBytePattern1And8Channel[1][2] = intervalValues8Channel[value - 1][1];
intervalBytePattern1And8Channel[1][3] = intervalValues8Channel[value - 1][2];
//Write inteval setting
for(int i = 0;i < D6T_1AND8_CHANNEL_REG_PATTERN_ROW_LENGTH; i++)
{
if((m_i2c->write(intervalBytePattern1And8Channel[i],D6T_1AND8_CHANNEL_REG_PATTERN_COLUMN_LENGTH)) != mraa::SUCCESS){
throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write failed");
}
}
break;
case D6T_4X4_CHANNEL:
//Copy inteval values
intervalBytePattern16Channel[1][1] = intervalValues16Channel[value - 1][0];
intervalBytePattern16Channel[1][2] = intervalValues16Channel[value - 1][1];
//Write inteval setting
for(int i = 0;i < D6T_16_CHANNEL_REG_PATTERN_ROW_LENGTH; i++)
{
if((m_i2c->write(intervalBytePattern16Channel[i],i==1?D6T_16_CHANNEL_REG_PATTERN_ROW_LENGTH:D6T_16_CHANNEL_REG_PATTERN_COLUMN_LENGTH)) != mraa::SUCCESS){
throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.write failed");
}
}
break;
default:
returnValue = D6T_STATUS_INVALID_SENSOR_TYPE;
return returnValue;
}
return returnValue;
}
D6T_STATUS_T D6T::getMeasurementSettingRegisterValue(uint8_t r_addr, uint8_t* data)
{
D6T_STATUS_T returnValue = D6T_STATUS_SUCCESS;
if(data == NULL)
return D6T_STATUS_INVALID_INPUT;
//Write register
if((m_i2c->writeByte(r_addr)) != mraa::SUCCESS){
throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.writeByte failed");
}
//Read values
if (!m_i2c->read(data, 2)){
throw std::runtime_error(std::string(__FUNCTION__) + ": I2c.read() failed");
}
return returnValue;
}

280
src/d6t/d6t.hpp Normal file
View File

@ -0,0 +1,280 @@
/*
* Author: Hiroyuki Mino <omronsupportupm@omron.com>
* Copyright (c) 2019 Omron Electronic Components - Americas
*
* 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 <iostream> //Required for c++ standard IO
#include "mraa/i2c.hpp" //Required for MRAA I2c operations
#include <interfaces/iTemperature.hpp> //Required to Temperature Unit functionality
#include <vector>
/**
* MACROS and enum
*/
#define D6T_DEFAULT_I2C_BUS_NUM 6
#define D6T_DEFAULT_I2C_ADDR 0x0a
#define D6T_SENSOR_DATA_READ_CMD 0x4C
#define D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH 28
#define D6T_1AND8_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH 3
#define D6T_16_CHANNEL_VALUE_BUFFER_ROW_LENGTH 32
#define D6T_16_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH 2
#define D6T_1AND8_CHANNEL_REG_PATTERN_ROW_LENGTH 5
#define D6T_1AND8_CHANNEL_REG_PATTERN_COLUMN_LENGTH 4
#define D6T_16_CHANNEL_REG_PATTERN_ROW_LENGTH 3
#define D6T_16_CHANNEL_REG_PATTERN_COLUMN_LENGTH 9
#define D6T_16_CHANNEL_WRITE_ADDR_READ_REG_VALUE 0x62
/**
* D6T_STATUS enum
* An Enum contains status code of operations
*/
typedef enum D6T_STATUS{
D6T_STATUS_FAILURE = 0,
D6T_STATUS_SUCCESS =1,
D6T_STATUS_I2C_NOT_INITED,
D6T_STATUS_I2C_WRITE_FAILED,
D6T_STATUS_I2C_READ_FAILED,
D6T_STATUS_INVALID_SENSOR_TYPE,
D6T_STATUS_MEMORY_ALLOCATION_FAIL,
D6T_STATUS_PEC_FAILURE,
D6T_STATUS_INVALID_MEASURMENT_INTERVAL,
D6T_STATUS_INVALID_INPUT,
}D6T_STATUS_T;
/**
* D6T_SENSOR_TYPES enum
* An Enum contains TYPES of D6T sensors
*/
typedef enum D6T_SENSOR_TYPES{
D6T_1X1_CHANNEL = 1,
D6T_1X8_CHANNEL = 8,
D6T_4X4_CHANNEL = 16,
}D6T_SENSOR_TYPES_T;
/**
* D6T_SENSOR_BUFFER_LENGTH enum
* An enum contains Length of BUFFER
*/
typedef enum D6T_SENSOR_BUFFER_LENGTH{
D6T_1X1_CHANNEL_BUFFER_LENGTH = 5,
D6T_1X8_CHANNEL_BUFFER_LENGTH = 19,
D6T_4X4_CHANNEL_BUFFER_LENGTH = 35,
}D6T_SENSOR_BUFFER_LENGTH_T;
/*=========================================================================*/
namespace upm {
/**
* @brief Mems Thermal Sensors
* @defgroup d6t libupm-d6t
* @ingroup --add group
*/
/**
* @library d6t
* @sensor d6t
* @comname Omron Mems thermal sensors
* @type --add type
* @man omron
* @con I2C
* @web --add weblink
*
* @brief API for the Omron Mems thermal sensors interface
*
* It is connected via a I2C Interface.
*
* @snippet d6t.cxx Interesting
*/
class D6T : virtual private iTemperature{
public :
/**
* D6T constructor
*
* @param type D6T sensor type
* @param bus I2c bus the sensor is attached to. Default is 6.
* @param address I2c address Optional device address. Default is 0x0a.
*/
D6T(D6T_SENSOR_TYPES_T type, int bus = D6T_DEFAULT_I2C_BUS_NUM,uint8_t address = D6T_DEFAULT_I2C_ADDR);
/**
* D6T destructor
*/
~D6T();
/**
* Get thermal sensor temperature data.
* User can call this API at interval greater than or equal to sensor measurement interval.
*
* @param ptat Reference temperature data stored in the sensor
* @param temperatureData Temperature data for each pixel. Sufficient memory should be allocated on app side.
* @param length Length of temperatureData. This values is used to fillup temperatureData.
* @param pec Packet error check code
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T getTemperature(float *ptat, float* temperatureData, uint8_t length, uint8_t *pec);
/**
* Get thermal sensor temperature data.
* User can call this API at interval greater than or equal to sensor measurement interval.
*
* @param ptat Reference temperature data stored in the sensor
* @param temperatureData Temperature data for each pixel.
* @param pec Packet error check code
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T getTemperature(float &ptat, std::vector<float> &temperatureData, uint8_t &pec);
/**
* Get the thermal sensor temperature unit.
*
* @param unit Temperature scale unit
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T getTemperatureScale(TemperatureUnit &unit);
/**
* Set the thermal sensor temperature unit.
*
* @param unit Temperature scale unit
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T setTemperatureScale(TemperatureUnit unit);
/**
* Display thermal sensor data with PTAT, P0 to P15 and PEC values.
*
* User can call this API at interval greater than or equal to sensor measurement interval.
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T displayTemperature();
/**
* Set the thermal sensor type.
*
* @param type Sensor type
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T setSensorType(D6T_SENSOR_TYPES_T type);
/**
* Get the thermal sensor type.
*
* @param type Sensor type
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T getSensorType(D6T_SENSOR_TYPES_T &type);
/**
* Get Measurement Interval time.
*
* @param value Interval value
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T getMeasurementInterval(uint8_t &value);
/**
* Set Measurement Interval time.
*
* @param value Interval value
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T setMeasurementInterval(uint8_t value);
private:
int m_bus;
int m_address;
upm::TemperatureUnit m_tempScale;
D6T_SENSOR_TYPES_T d6t_sensor_type;
D6T_SENSOR_BUFFER_LENGTH_T d6t_sensor_data_length;
uint8_t *m_buf = NULL;
mraa::I2c* m_i2c;
static uint8_t intervalValues1Channel[D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH][D6T_1AND8_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH];
static uint8_t intervalValues8Channel[D6T_1AND8_CHANNEL_VALUE_BUFFER_ROW_LENGTH][D6T_1AND8_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH];
static uint8_t intervalValues16Channel[D6T_16_CHANNEL_VALUE_BUFFER_ROW_LENGTH][D6T_16_CHANNEL_VALUE_BUFFER_COLUMN_LENGTH];
static uint8_t intervalBytePattern1And8Channel[D6T_1AND8_CHANNEL_REG_PATTERN_ROW_LENGTH][D6T_1AND8_CHANNEL_REG_PATTERN_COLUMN_LENGTH];
static uint8_t intervalBytePattern16Channel[D6T_16_CHANNEL_REG_PATTERN_ROW_LENGTH][D6T_16_CHANNEL_REG_PATTERN_COLUMN_LENGTH];
/**
* Returns the temperature. This method is not publicly accessible.
*
* @return Dummy value
*/
virtual float getTemperature(){return 0.0;}
/**
* Returns the updated temperature. This method is not publicly accessible.
*
* @return One of the D6T_STATUS_T values
*/
virtual D6T_STATUS_T getUpdatedTemperature();
/**
* Calculate CRC for given data.
*
* @param data Sensor PEC data
*
* @return CRC value
*/
uint8_t calculateCrc(uint8_t data);
/**
* Get the thermal sensor type.
*
* @param buf Sensor data buffer
* @param len Sensor data buffer length
*
* @return Return success or Failure
*/
bool checkPEC(uint8_t *buf , uint8_t count);
/**
* Get register value of measurement interval.
*
* @param r_addr Address of register
* @param data Interval setting register values
*
* @return One of the D6T_STATUS_T values
*/
D6T_STATUS_T getMeasurementSettingRegisterValue(uint8_t r_addr, uint8_t* data);
/*
* Copy Constructor
*/
D6T(const D6T&);
/**
* Operator Overloading
*/
D6T& operator=(const D6T&);
};
}

19
src/d6t/d6t.i Normal file
View File

@ -0,0 +1,19 @@
#ifdef SWIGPYTHON
%module (package="upm") d6t
#endif
%include "../common_top.i"
/* BEGIN Java syntax ------------------------------------------------------- */
#ifdef SWIGJAVA
JAVA_JNI_LOADLIBRARY(javaupm_d6t)
#endif
/* END Java syntax */
/* BEGIN Common SWIG syntax ------------------------------------------------- */
%{
#include "d6t.hpp"
%}
%include "d6t.hpp"
/* END Common SWIG syntax */

36
src/d6t/d6t.json Normal file
View File

@ -0,0 +1,36 @@
{
"Library": "d6t",
"Description": "Omron MEMS D6T Thermal Sensor",
"Sensor Class": {
"d6t": {
"Name": "API for D6T Sensor",
"Description": "This is the UPM Module for Omron MEMS D6T Thermal Sensor",
"Aliases": [""],
"Categories": [""],
"Connections": ["I2C"],
"Project Type": ["sensor"],
"Manufacturers": ["Omron"],
"Image": "",
"Examples": {
"C++": ["d6t.cxx"]
},
"Specifications": {
"Baud Rate": {
"unit" : "",
"default": ""
}
},
"Platforms": {
"Intel Edison": {
"Notes": [""]
}
},
"Urls": {
"Product Pages": ["https://www.components.omron.com/product-detail?partId=396"],
"Datasheets": ["https://omronfs.omron.com/en_US/ecb/products/pdf/en_D6T_catalog.pdf"]
}
}
}
}