Home | History | Annotate | Download | only in otp538u
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2015 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 <string>
     27 #include <stdexcept>
     28 
     29 #include "otp538u.h"
     30 
     31 #include "thermopile_vt_table.h"
     32 #include "thermister_rt_table.h"
     33 
     34 using namespace upm;
     35 using namespace std;
     36 
     37 OTP538U::OTP538U(int pinA, int pinO, float aref)
     38 {
     39   // this is the internal voltage reference on the Grove IR temp
     40   // sensor module
     41   m_vref = 2.5;
     42 
     43   // analog reference in use
     44   m_aref = aref;
     45 
     46   // This is the value of the output resistor of the Grove IR
     47   // temp sensor's SIG2 output (ambient)
     48   m_vResistance = 2000000;      // 2M ohms
     49 
     50   // This was the default offset voltage in the seeedstudio code.  You
     51   // can adjust as neccessary depending on your calibration.
     52   m_offsetVoltage = 0.014;
     53 
     54   // We need around 1mV resolution, so use 12 bit resolution (4096)
     55   // with a default aref of 5.0.
     56   m_adcResolution = 4096;
     57 
     58   if ( !(m_aioA = mraa_aio_init(pinA)) )
     59     {
     60       throw std::invalid_argument(std::string(__FUNCTION__) +
     61                                   ": mraa_gpio_init(pinA) failed, invalid pin?");
     62       return;
     63     }
     64 
     65   // enable 12 bit resolution
     66   mraa_aio_set_bit(m_aioA, 12);
     67 
     68   if ( !(m_aioO = mraa_aio_init(pinO)) )
     69     {
     70       throw std::invalid_argument(std::string(__FUNCTION__) +
     71                                   ": mraa_gpio_init(pinO) failed, invalid pin?");
     72       return;
     73     }
     74 
     75   // enable 12 bit resolution
     76   mraa_aio_set_bit(m_aioO, 12);
     77 }
     78 
     79 OTP538U::~OTP538U()
     80 {
     81   mraa_aio_close(m_aioA);
     82   mraa_aio_close(m_aioO);
     83 }
     84 
     85 float OTP538U::ambientTemperature()
     86 {
     87   const int samples = 5;
     88   int val = 0;
     89   float temp = 0;
     90   float res;
     91 
     92   for (int i=0; i<samples; i++)
     93     {
     94       val = mraa_aio_read(m_aioA);
     95       temp += val;
     96       usleep(10000);
     97     }
     98 
     99   temp = temp / samples;
    100   temp = temp * m_aref / m_adcResolution;
    101 
    102   // compute the resistance of the thermistor
    103   res = m_vResistance * temp / (m_vref - temp);
    104 
    105   // look it up in the thermistor (RT) resistence/temperature table
    106   int rawslot;
    107   int j;
    108   for (j=0; j<otp538u_rt_table_max; j++)
    109     if (otp538u_rt_table[j] < res)
    110       {
    111         rawslot = j;
    112         break;
    113       }
    114 
    115   if (j >= otp538u_rt_table_max)
    116     {
    117       throw std::out_of_range(std::string(__FUNCTION__) +
    118                               ": ambient temperature out of range.");
    119       return 0;
    120     }
    121 
    122   // we need to compensate for the fact that we are supporting
    123   // temperature values less than 0 (-20C), so adjust correspondingly
    124   // so that we obtain the correct temperature 'slot'.  This will be
    125   // our base temperature.
    126   int slot = rawslot - 20;
    127 
    128   // too cold
    129   if (slot < 0)
    130     {
    131       throw std::out_of_range(std::string(__FUNCTION__) +
    132                               ": ambient temperature out of range.");
    133       return 0;
    134     }
    135 
    136   // now compute the ambient temperature
    137   float ambientTemp = slot - 1 +
    138     (otp538u_rt_table[rawslot - 1]-res) / (otp538u_rt_table[rawslot - 1] -
    139                                            otp538u_rt_table[rawslot]);
    140 
    141   return ambientTemp;
    142 }
    143 
    144 float OTP538U::objectTemperature()
    145 {
    146   const int samples = 5;
    147   const float reference_vol= 0.5; // what is this value? (from seeedstudio)
    148   const float tempIncrement=10;
    149   int val = 0;
    150   float temp = 0;
    151   float ambTemp = ambientTemperature();
    152 
    153   for (int i=0; i<samples; i++)
    154     {
    155       val = mraa_aio_read(m_aioO);
    156       temp += val;
    157       usleep(10000);
    158     }
    159 
    160   temp = temp / samples;
    161 
    162   float temp1 = temp * m_aref / m_adcResolution;
    163   float sensorVolts = temp1 - (reference_vol + m_offsetVoltage);
    164   // cout << "Sensor Voltage: " << sensorVolts << endl;
    165 
    166   // search the VT (voltage/temperature) table to find the object
    167   // temperature.
    168   int slot;
    169   // add +2 to compensate for the -20C and -10C slots below zero
    170   int voltOffset = int(ambTemp / 10) + 1 + 2;
    171   float voltage = sensorVolts * 10.0;
    172   for (slot=0; slot<(otp538u_vt_table_max - 1); slot++)
    173     {
    174       if ( (voltage > otp538u_vt_table[slot][voltOffset]) &&
    175            (voltage < otp538u_vt_table[slot+1][voltOffset]) )
    176         {
    177           break;
    178         }
    179     }
    180 
    181   if (slot >= (otp538u_vt_table_max - 1))
    182     {
    183       throw std::out_of_range(std::string(__FUNCTION__) +
    184                               ": object temperature out of range.");
    185       return 0;
    186     }
    187 
    188   float objTemp = (float(tempIncrement) * voltage) /
    189     ( otp538u_vt_table[slot + 1][voltOffset] -
    190       otp538u_vt_table[slot][voltOffset] );
    191 
    192   //  cout << "TABLE VALUE [" << slot << "][" <<
    193   //    voltOffset << "] = " << otp538u_vt_table[slot][voltOffset] << endl;
    194 
    195   return (ambTemp + objTemp);
    196 }
    197