summaryrefslogtreecommitdiff
path: root/peripheral/libupm/src/otp538u/otp538u.cxx
blob: 6231ae3806f13c10d26edd5e7cb6a8603be13430 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * Author: Jon Trulson <jtrulson@ics.com>
 * Copyright (c) 2015 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 <iostream>
#include <string>
#include <stdexcept>

#include "otp538u.h"

#include "thermopile_vt_table.h"
#include "thermister_rt_table.h"

using namespace upm;
using namespace std;

OTP538U::OTP538U(int pinA, int pinO, float aref)
{
  // this is the internal voltage reference on the Grove IR temp
  // sensor module
  m_vref = 2.5;

  // analog reference in use
  m_aref = aref;

  // This is the value of the output resistor of the Grove IR
  // temp sensor's SIG2 output (ambient)
  m_vResistance = 2000000;      // 2M ohms

  // This was the default offset voltage in the seeedstudio code.  You
  // can adjust as neccessary depending on your calibration.
  m_offsetVoltage = 0.014;

  // We need around 1mV resolution, so use 12 bit resolution (4096)
  // with a default aref of 5.0.
  m_adcResolution = 4096;

  if ( !(m_aioA = mraa_aio_init(pinA)) )
    {
      throw std::invalid_argument(std::string(__FUNCTION__) +
                                  ": mraa_gpio_init(pinA) failed, invalid pin?");
      return;
    }

  // enable 12 bit resolution
  mraa_aio_set_bit(m_aioA, 12);

  if ( !(m_aioO = mraa_aio_init(pinO)) )
    {
      throw std::invalid_argument(std::string(__FUNCTION__) +
                                  ": mraa_gpio_init(pinO) failed, invalid pin?");
      return;
    }

  // enable 12 bit resolution
  mraa_aio_set_bit(m_aioO, 12);
}

OTP538U::~OTP538U()
{
  mraa_aio_close(m_aioA);
  mraa_aio_close(m_aioO);
}

float OTP538U::ambientTemperature()
{
  const int samples = 5;
  int val = 0;
  float temp = 0;
  float res;

  for (int i=0; i<samples; i++)
    {
      val = mraa_aio_read(m_aioA);
      temp += val;
      usleep(10000);
    }

  temp = temp / samples;
  temp = temp * m_aref / m_adcResolution;

  // compute the resistance of the thermistor
  res = m_vResistance * temp / (m_vref - temp);

  // look it up in the thermistor (RT) resistence/temperature table
  int rawslot;
  int j;
  for (j=0; j<otp538u_rt_table_max; j++)
    if (otp538u_rt_table[j] < res)
      {
        rawslot = j;
        break;
      }

  if (j >= otp538u_rt_table_max)
    {
      throw std::out_of_range(std::string(__FUNCTION__) +
                              ": ambient temperature out of range.");
      return 0;
    }

  // we need to compensate for the fact that we are supporting
  // temperature values less than 0 (-20C), so adjust correspondingly
  // so that we obtain the correct temperature 'slot'.  This will be
  // our base temperature.
  int slot = rawslot - 20;
  
  // too cold
  if (slot < 0)
    {
      throw std::out_of_range(std::string(__FUNCTION__) +
                              ": ambient temperature out of range.");
      return 0;
    }

  // now compute the ambient temperature
  float ambientTemp = slot - 1 +
    (otp538u_rt_table[rawslot - 1]-res) / (otp538u_rt_table[rawslot - 1] - 
                                           otp538u_rt_table[rawslot]);
  
  return ambientTemp;
}

float OTP538U::objectTemperature()
{
  const int samples = 5;
  const float reference_vol= 0.5; // what is this value? (from seeedstudio)
  const float tempIncrement=10;
  int val = 0;
  float temp = 0;
  float ambTemp = ambientTemperature();
  
  for (int i=0; i<samples; i++)
    {
      val = mraa_aio_read(m_aioO);
      temp += val;
      usleep(10000);
    }

  temp = temp / samples;

  float temp1 = temp * m_aref / m_adcResolution;
  float sensorVolts = temp1 - (reference_vol + m_offsetVoltage);
  // cout << "Sensor Voltage: " << sensorVolts << endl;

  // search the VT (voltage/temperature) table to find the object
  // temperature.
  int slot;
  // add +2 to compensate for the -20C and -10C slots below zero
  int voltOffset = int(ambTemp / 10) + 1 + 2;
  float voltage = sensorVolts * 10.0;
  for (slot=0; slot<(otp538u_vt_table_max - 1); slot++)		
    {
      if ( (voltage > otp538u_vt_table[slot][voltOffset]) &&
           (voltage < otp538u_vt_table[slot+1][voltOffset]) )
        {
          break;
        }
    }

  if (slot >= (otp538u_vt_table_max - 1))
    {
      throw std::out_of_range(std::string(__FUNCTION__) +
                              ": object temperature out of range.");
      return 0;
    }

  float objTemp = (float(tempIncrement) * voltage) /
    ( otp538u_vt_table[slot + 1][voltOffset] - 
      otp538u_vt_table[slot][voltOffset] );    

  //  cout << "TABLE VALUE [" << slot << "][" <<
  //    voltOffset << "] = " << otp538u_vt_table[slot][voltOffset] << endl;

  return (ambTemp + objTemp);
}