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