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