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 }