otp538u: Initial implementation

This module was tested on the Grove non-contact IR Temperature
Sensor.  The tables included are only valid for a distance of 9cm.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Zion Orent <zorent@ics.com>
Signed-off-by: John Van Drasek <john.r.van.drasek@intel.com>
This commit is contained in:
Jon Trulson 2015-02-05 11:38:05 -07:00 committed by John Van Drasek
parent 1f3d074261
commit f13216752e
10 changed files with 640 additions and 0 deletions

View File

@ -85,6 +85,7 @@ add_executable (cjq4435-example cjq4435.cxx)
add_executable (adxl335-example adxl335.cxx)
add_executable (hmtrp-example hmtrp.cxx)
add_executable (nunchuck-example nunchuck.cxx)
add_executable (otp538u-example otp538u.cxx)
include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@ -155,6 +156,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/cjq4435)
include_directories (${PROJECT_SOURCE_DIR}/src/adxl335)
include_directories (${PROJECT_SOURCE_DIR}/src/hmtrp)
include_directories (${PROJECT_SOURCE_DIR}/src/nunchuck)
include_directories (${PROJECT_SOURCE_DIR}/src/otp538u)
target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT})
@ -243,3 +245,4 @@ target_link_libraries (cjq4435-example cjq4435 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (adxl335-example adxl335 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (hmtrp-example hmtrp ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (nunchuck-example nunchuck ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (otp538u-example otp538u ${CMAKE_THREAD_LIBS_INIT})

View File

@ -0,0 +1,64 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Zion Orent <zorent@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.
*/
// analog voltage, usually 3.3 or 5.0
var OTP538U_AREF = 5.0;
var tempIRSensor_lib = require('jsupm_otp538u');
// Instantiate a OTP538U on analog pins A0 and A1
// A0 is used for the Ambient Temperature and A1 is used for the
// Object temperature.
var tempIRSensor_obj = new tempIRSensor_lib.OTP538U(0, 1, OTP538U_AREF);
function checkTemp()
{
var outputStr = "Ambient temp: " +
roundNum(tempIRSensor_obj.ambientTemperature(), 2) +
" C, Object temp: " +
roundNum(tempIRSensor_obj.objectTemperature(), 2) +
" C";
console.log(outputStr);
}
var myInterval = setInterval(checkTemp, 1000);
function roundNum(num, decimalPlaces)
{
var extraNum = (1 / (Math.pow(10, decimalPlaces) * 1000));
return (Math.round((num + extraNum) *
(Math.pow(10, decimalPlaces))) / Math.pow(10, decimalPlaces));
}
// When exiting: clear interval and print message
process.on('SIGINT', function()
{
clearInterval(myInterval);
console.log("Exiting...");
process.exit(0);
});

71
examples/otp538u.cxx Normal file
View File

@ -0,0 +1,71 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 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 <iostream>
#include <iomanip>
#include <signal.h>
#include "otp538u.h"
using namespace std;
bool shouldRun = true;
// analog voltage, usually 3.3 or 5.0
#define OTP538U_AREF 5.0
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main()
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a OTP538U on analog pins A0 and A1
// A0 is used for the Ambient Temperature and A1 is used for the
// Object tempewrature.
upm::OTP538U *temps = new upm::OTP538U(0, 1, OTP538U_AREF);
// Output ambient and object temperatures
while (shouldRun)
{
cout << "Ambient temp: " << std::fixed << setprecision(2)
<< temps->ambientTemperature()
<< " C, Object temp: " << temps->objectTemperature()
<< " C" << endl;
sleep(1);
}
//! [Interesting]
cout << "Exiting" << endl;
delete temps;
return 0;
}

View File

@ -0,0 +1,5 @@
set (libname "otp538u")
set (libdescription "upm otp538u IR temperature sensor")
set (module_src ${libname}.cxx)
set (module_h ${libname}.h)
upm_module_init()

View File

@ -0,0 +1,8 @@
%module jsupm_otp538u
%include "../upm.i"
%{
#include "otp538u.h"
%}
%include "otp538u.h"

189
src/otp538u/otp538u.cxx Normal file
View File

@ -0,0 +1,189 @@
/*
* 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 "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)) )
{
cerr << __FUNCTION__ << ": mraa_aio_init() failed" << endl;
return;
}
// enable 12 bit resolution
mraa_aio_set_bit(m_aioA, 12);
if ( !(m_aioO = mraa_aio_init(pinO)) )
{
cerr << __FUNCTION__ << ": mraa_aio_init() failed" << endl;
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)
{
cerr << __FUNCTION__ << ": ambient temperature out of range." << endl;
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)
{
cerr << __FUNCTION__ << ": ambient temperature out of range." << endl;
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; slot++)
{
if ( (voltage > otp538u_vt_table[slot][voltOffset]) &&
(voltage < otp538u_vt_table[slot+1][voltOffset]) )
{
break;
}
}
if (slot >= (otp538u_vt_table_max - 1))
{
cerr << __FUNCTION__ << ": object temperature out of range." << endl;
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);
}

141
src/otp538u/otp538u.h Normal file
View File

@ -0,0 +1,141 @@
/*
* 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.
*/
#pragma once
#include <string>
#include <mraa/aio.h>
namespace upm {
/**
* @brief C++ API for the OTP538U IR Temperature Sensor
*
* UPM module for the OTP538U IR Temperature Sensor
*
* This module was tested with the Grove IR non-contact temperature
* sensor.
*
* The sensor provides 2 analog outputs - one for the thermistor
* that measures ambient temperature, and another for the thermopile
* that measures object temperature.
*
* Much of the code depends on analyzing the SeeedStudio examples
* and circuit design. As a result, there are several 'magic'
* numbers that were derived from their circuit design. By default,
* these values will be used.
*
* The tables used came from the datasheets "538U VT
* Table__20_200(v1.3).pdf" and "538RT_table.pdf".
*
* These tables assume the object to be measured is 9cm (3.54
* inches) from the sensor.
*
* @ingroup grove analog
* @defgroup otp538u libupm-otp538u
* @snippet otp538u.cxx Interesting
*/
class OTP538U {
public:
/**
* OTP538U sensor constructor
*
* @param pinA analog pin to use for Ambient temperature
* @param pinO analog pin to use for Object temperature
* @param aref analog reference voltage, default 5.0
*/
OTP538U(int pinA, int pinO, float aref = 5.0);
/**
* OTP538U Destructor
*/
~OTP538U();
/**
* Get the ambient temperature in C
*
* @return the ambient temperature
*/
float ambientTemperature();
/**
* Get the object temperature in C
*
* @return the object's temperature
*/
float objectTemperature();
/**
* Set the offset voltage
*
* The Seeedstudio wiki gives an example on calibrating the sensor
* and calculating the offset voltage to apply. Currently, the
* default value is set, but you can use the function to set one
* of your own.
*
* @param vOffset the desired offset voltage
*/
void setVoltageOffset(float vOffset) { m_offsetVoltage = vOffset; };
/**
* Set the output resistance value
*
* The Seeedstudio wiki example uses a value, 2000000 in one of
* the equations used to calculate a voltage. The value is the
* resistance of a resistor they use in the output stage of their
* SIG2 output. This was 'decoded' by looking at the eagle files
* containing their schematics for this device.
*
* @param outResistance value of output resistor, default 2M Ohm.
*/
void setOutputResistence(int outResistance) {
m_vResistance = outResistance; };
/**
* Set the voltage reference of the internal seedstudio voltage
* regulator on the sensor board.
*
* The Seeedstudio wiki example uses a value, 2.5 in one of the
* equations used to calculate the resistance of the ambient
* thermistor. The value is the voltage of an internal voltage
* regulator used in the sensor board. This was 'decoded' by
* looking at the eagle files containing their schematics for this
* device.
*
* @param vref internal sensor voltage reference, default 2.5
*/
void setVRef(float vref) { m_vref = vref; };
private:
float m_vref;
float m_aref;
int m_vResistance;
float m_offsetVoltage;
int m_adcResolution;
mraa_aio_context m_aioA;
mraa_aio_context m_aioO;
};
}

View File

@ -0,0 +1,9 @@
%module pyupm_otp538u
%include "../upm.i"
%feature("autodoc", "3");
%include "otp538u.h"
%{
#include "otp538u.h"
%}

View File

@ -0,0 +1,46 @@
/*
* 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.
*/
// This table was taken from the 538RT_table.pdf datasheet. It maps
// resistance values to ambient temperatures starting at -20C and
// going to 200C in increments of 1C
static const int otp538u_rt_table_max = 121;
static int otp538u_rt_table[otp538u_rt_table_max] = {
919730, 869299, 821942, 777454, 735644, 696336, 659365, 624578, 591834,
561002, 531958, 504588, 478788, 454457, 431504, 409843, 389394, 370082,
351839, 334598, 318300, 302903, 288329, 274533, 261471, 249100, 237381,
226276, 215750, 205768, 196300, 187316, 178788, 170691, 163002, 155700,
148766, 142183, 135936, 130012, 124400, 119038, 113928, 109059, 104420,
100000, 95788, 91775, 87950, 84305, 80830, 77517, 74357, 71342, 68466,
65720, 63098, 60595, 58202, 55916, 53730, 51645, 49652, 47746, 45924,
44180, 42511, 40912, 39380, 37910, 36500, 35155, 33866, 32631, 31446,
30311, 29222, 28177, 27175, 26213, 25290, 24403, 23554, 22738, 21955,
21202, 20479, 19783, 19115, 18472, 17854, 17260, 16688, 16138, 15608,
15098, 14608, 14135, 13680, 13242, 12819, 12412, 12020, 11642, 11278,
10926, 10587, 10260, 9945, 9641, 9347, 9063, 8789, 8525, 8270, 8023,
7785, 7555, 7333, 7118, 6911
};

View File

@ -0,0 +1,104 @@
/*
* 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.
*/
// This table was taken from the 538U VT Table__20_200(v1.3).pdf
// datasheet, but the 25C column has been removed for consistency.
static const int otp538u_vt_table_max = 23;
// Thermister temperature (C)
// { -20 -10 0 10 20 30 40 50 60 70 80 90 100 }
static float otp538u_vt_table[otp538u_vt_table_max][13] = {
// object temp (C)
{0.000, -0.246, -0.523, -0.832, -1.177, -1.559, // -20C
-1.981, -2.446, -2.957, -3.516, -4.126, -4.791, -5.513},
{0.243, 0.000, -0.274, -0.580, -0.922, -1.301, // -10
-1.721, -2.183, -2.691, -3.247, -3.854, -4.516, -5.236},
{0.511, 0.271, 0.000, -0.303, -0.642, -1.018, // 0
-1.434, -1.894, -2.398, -2.951, -3.556, -4.215, -4.931},
{0.804, 0.567, 0.300, 0.000, -0.335, -0.708, // 10
-1.121, -1.577, -2.078, -2.628, -3.229, -3.884, -4.597},
{1.125, 0.891, 0.628, 0.331, 0.000, -0.369, // 20
-0.778, -1.230, -1.728, -2.274, -2.871, -3.523, -4.232},
{1.474, 1.244, 0.985, 0.692, 0.365, 0.000, // 30
-0.405, -0.853, -1.347, -1.889, -2.482, -3.130, -3.835},
{1.852, 1.628, 1.372, 1.084, 0.761, 0.401, // 40
0.000, -0.444, -0.933, -1.470, -2.059, -2.702, -3.403},
{2.263, 2.043, 1.792, 1.509, 1.191, 0.835, // 50
0.439, 0.000, -0.484, -1.017, -1.601, -2.240, -2.936},
{2.706, 2.491, 2.246, 1.968, 1.655, 1.304, // 60
0.913, 0.479, 0.000, -0.528, -1.107, -1.740, -2.431},
{3.184, 2.975, 2.735, 2.462, 2.155, 1.809, // 70
1.424, 0.996, 0.522, 0.000, -0.573, -1.201, -1.887},
{3.698, 3.495, 3.261, 2.994, 2.692, 2.353, // 80
1.974, 1.552, 1.084, 0.568, 0.000, -0.622, -1.301},
{4.250, 4.053, 3.825, 3.565, 3.270, 2.937, // 90
2.564, 2.148, 1.687, 1.177, 0.616, 0.000, -0.673},
{4.841, 4.651, 4.430, 4.177, 3.888, 3.562, // 100
3.196, 2.787, 2.332, 1.829, 1.275, 0.666, 0.000},
{5.473, 5.290, 5.076, 4.830, 4.549, 4.231, // 110
3.872, 3.470, 3.023, 2.527, 1.980, 1.379, 0.720},
{6.147, 5.972, 5.767, 5.528, 5.255, 4.944, // 120
4.593, 4.199, 3.760, 3.272, 2.733, 2.139, 1.488},
{6.866, 6.699, 6.502, 6.272, 6.007, 5.705, // 130
5.362, 4.976, 4.545, 4.066, 3.535, 2.950, 2.307},
{7.631, 7.473, 7.285, 7.064, 6.808, 6.514, // 140
6.180, 5.803, 5.381, 4.910, 4.388, 3.812, 3.178},
{8.444, 8.295, 8.116, 7.905, 7.658, 7.373, // 150
7.049, 6.682, 6.269, 5.807, 5.295, 4.728, 4.103},
{9.306, 9.167, 8.998, 8.796, 8.560, 8.285, // 160
7.971, 7.613, 7.211, 6.759, 6.257, 5.700, 5.085},
{10.219, 10.091, 9.933, 9.741, 9.515, 9.251, // 170
8.947, 8.601, 8.208, 7.768, 7.276, 6.729, 6.125},
{11.185, 11.068, 10.921, 10.741, 10.526, 10.274, // 180
9.981, 9.645, 9.264, 8.835, 8.354, 7.818, 7.226},
{12.206, 12.101, 11.966, 11.798, 11.595, 11.354, // 190
11.073, 10.749, 10.380, 9.962, 9.493, 8.969, 8.388},
{13.284, 13.191, 13.068, 12.913, 12.722, 12.494, // 200
12.225, 11.914, 11.557, 11.152, 10.695, 10.184, 9.616}
};