gobot.io/x/gobot@v1.16.0/drivers/aio/temperature_sensor_driver.go (about)

     1  package aio
     2  
     3  import (
     4  	"math"
     5  	"time"
     6  
     7  	"gobot.io/x/gobot"
     8  )
     9  
    10  const kelvinOffset = 273.15
    11  
    12  type TemperatureSensorNtcConf struct {
    13  	TC0 int     // °C
    14  	R0  float64 // same unit as resistance of NTC (Ohm is recommended)
    15  	B   float64 // 2000..5000K
    16  	TC1 int     // used if B is not given, °C
    17  	R1  float64 // used if B is not given, same unit as R0 needed
    18  	t0  float64
    19  	r   float64
    20  }
    21  
    22  // TemperatureSensorDriver represents an Analog Sensor
    23  type TemperatureSensorDriver struct {
    24  	*AnalogSensorDriver
    25  }
    26  
    27  // NewTemperatureSensorDriver is a gobot driver for analog temperature sensors
    28  // with a polling interval 10 Milliseconds given an AnalogReader and pin.
    29  // For further details please refer to AnalogSensorDriver.
    30  // Linear scaling and NTC scaling is supported.
    31  //
    32  // Optionally accepts:
    33  // 	time.Duration: Interval at which the sensor is polled for new information (given 0 switch the polling off)
    34  //
    35  // Adds the following API Commands:
    36  // 	"Read"      - See AnalogDriverSensor.Read
    37  // 	"ReadValue" - See AnalogDriverSensor.ReadValue
    38  func NewTemperatureSensorDriver(a AnalogReader, pin string, v ...time.Duration) *TemperatureSensorDriver {
    39  	ad := NewAnalogSensorDriver(a, pin, v...)
    40  
    41  	d := &TemperatureSensorDriver{AnalogSensorDriver: ad}
    42  	d.SetName(gobot.DefaultName("TemperatureSensor"))
    43  
    44  	return d
    45  }
    46  
    47  // SetNtcSaler sets a function for typical NTC scaling the read value.
    48  // The read value is related to the voltage over the thermistor in an series connection to a resistor.
    49  // If the thermistor is connected to ground, the reverse flag must be set to true.
    50  // This means the voltage decreases when temperature gets higher.
    51  // Currently no negative values are supported.
    52  func (t *TemperatureSensorDriver) SetNtcScaler(vRef uint, rOhm uint, reverse bool, ntc TemperatureSensorNtcConf) {
    53  	t.SetScaler(TemperatureSensorNtcScaler(vRef, rOhm, reverse, ntc))
    54  }
    55  
    56  // SetLinearScaler sets a function for linear scaling the read value.
    57  // This can be applied for some silicon based PTC sensors or e.g. PT100,
    58  // and in a small temperature range also for NTC.
    59  func (t *TemperatureSensorDriver) SetLinearScaler(fromMin, fromMax int, toMin, toMax float64) {
    60  	t.SetScaler(AnalogSensorLinearScaler(fromMin, fromMax, toMin, toMax))
    61  }
    62  
    63  func TemperatureSensorNtcScaler(vRef uint, rOhm uint, reverse bool, ntc TemperatureSensorNtcConf) func(input int) (value float64) {
    64  	ntc.initialize()
    65  	return (func(input int) (value float64) {
    66  		if input < 0 {
    67  			input = 0
    68  		}
    69  		rTherm := temperaturSensorGetResistance(uint(input), vRef, rOhm, reverse)
    70  		temp := ntc.getTemp(rTherm)
    71  		return temp
    72  	})
    73  }
    74  
    75  // getResistance calculates the value of the series thermistor by given value
    76  // and reference value (e.g. the voltage value over the complete series circuit)
    77  // The unit of the returned thermistor value equals the given series resistor unit.
    78  func temperaturSensorGetResistance(value uint, vRef uint, rSeries uint, reverse bool) float64 {
    79  	if value > vRef {
    80  		value = vRef
    81  	}
    82  	valDiff := vRef - value
    83  	if reverse {
    84  		//        rSeries  thermistor
    85  		// vRef o--|==|--o--|=/=|----| GND
    86  		//               |-> value <-|
    87  		if value == 0 {
    88  			// prevent jump to -273.15
    89  			value = 1
    90  		}
    91  		return float64(rSeries*value) / float64(valDiff)
    92  	}
    93  
    94  	//      thermistor  rSeries
    95  	// vRef o--|=/=|--o--|==|-----| GND
    96  	//                |-> value <-|
    97  	if valDiff == 0 {
    98  		// prevent jump to -273.15
    99  		valDiff = 1
   100  	}
   101  	return float64(rSeries*valDiff) / float64(value)
   102  }
   103  
   104  // getTemp calculates the temperature from the given resistance of the NTC resistor
   105  func (n *TemperatureSensorNtcConf) getTemp(rntc float64) float64 {
   106  	// 1/T = 1/T0 + 1/B * ln(R/R0)
   107  	//
   108  	// B/T = B/T0 + ln(R/R0) = k, B/T0 = r
   109  	// T = B/k, Tc = T - 273
   110  
   111  	k := n.r + math.Log(rntc/n.R0)
   112  	return n.B/k - kelvinOffset
   113  }
   114  
   115  // initialize is used to calculate some constants for the NTC algorithm.
   116  // If B is unknown (given as 0), the function needs a second pair to calculate
   117  // B from the both pairs (R1, TC1), (R0, TC0)
   118  func (n *TemperatureSensorNtcConf) initialize() {
   119  	n.t0 = float64(n.TC0) + kelvinOffset
   120  	if n.B <= 0 {
   121  		//B=[ln(R0)-ln(R1)]/(1/T0-1/T1)
   122  		T1 := float64(n.TC1) + kelvinOffset
   123  		n.B = (1/n.t0 - 1/T1)
   124  		n.B = (math.Log(n.R0) - math.Log(n.R1)) / n.B // 2000K...5000K
   125  	}
   126  	n.r = n.B / n.t0
   127  }