-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathautocal.py
executable file
·153 lines (112 loc) · 4.21 KB
/
autocal.py
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
##
## This CircuitPython code auto-calibrates the reference resistors and
## RTD Harness for the attached SenseTemp or SenseTemp TEC PCB.
##
## Before running auto_calibrate() or auto_calibrate_loop(),
## YOU MUST have all four RTD elements at the same temperature.
## The recommended way of doing this is to press all four onto
## a large body of metal with compliant material.
##
## If pressing them with your fingers, that complaint material
## must have enough thermal resistance to insulate the sensor
## elemets from the heat generated by your fingers.
##
## SenseTemp : https://www.crowdsupply.com/capable-robot-components/sensetemp
##
## CircuitPython Imports
import digitalio
import analogio
import pulseio
import busio
import board
## Local Imports
import adafruit_max31865 as max31865
def mean(data):
return sum(data)/float(len(data))
def _ss(data):
c = mean(data)
ss = sum((x-c)**2 for x in data)
return ss
def stddev(data, ddof=0):
ss = _ss(data)
pvar = ss/(len(data)-ddof)
return pvar**0.5
RTD_NOMINAL = 1000.0 ## Resistance of RTD at 0C
RTD_REFERENCE = 4300.0 ## Value of reference resistor on PCB
import adafruit_onewire.bus as onewire_bus
bus = onewire_bus.OneWireBus(board.D12)
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
## Create SPI Chip Select pins
cs1 = digitalio.DigitalInOut(board.D10)
cs2 = digitalio.DigitalInOut(board.D9)
cs3 = digitalio.DigitalInOut(board.D6)
cs4 = digitalio.DigitalInOut(board.D5)
css = [cs1, cs2, cs3, cs4]
sensors = []
## Create array for the RTD sensors on the SenseTemp Wing
for idx, cs in enumerate(css):
cs.switch_to_output(digitalio.DriveMode.PUSH_PULL)
sensors.append(
max31865.MAX31865(
spi, cs,
wires = 4,
rtd_nominal = RTD_NOMINAL,
ref_resistor = RTD_REFERENCE
)
)
def collect_samples(count):
idx = 0
readings = [[], [], [], []]
while idx < count:
idx += 1
for ch, sensor in enumerate(sensors):
readings[ch].append(sensor.temperature)
return readings
def auto_calibrate(count=10, reset=True):
if reset:
for sensor in sensors:
sensor.ref_resistor = RTD_REFERENCE
presample = collect_samples(count)
readings = [mean(channel) for channel in presample]
print("Means : %s" % " ".join(["%.3f" % f for f in readings]))
overall_mean = mean(readings)
overall_limit = stddev(readings)
print("Overall Range : %.3f" % (max(readings)-min(readings)))
print("Overall Mean : %.3f" % overall_mean)
print("Overall STD : %.3f" % overall_limit)
for ch, reading in enumerate(readings):
if reading > overall_mean + overall_limit or reading < overall_mean - overall_limit:
error = reading - overall_mean
idx = 0
print("CH%d is outlier at %.3f" % (ch+1, reading))
print(" %d %.3f %.3f %.3f" % (idx, sensors[ch].ref_resistor, reading, error))
while abs(error) > overall_limit*0.25:
idx += 1
if idx > 15:
break
step = error * -2.0
sensors[ch].ref_resistor += step
reading = sensors[ch].temperature
error = reading - overall_mean
print(" %d %.3f %.3f %.3f" % (idx, sensors[ch].ref_resistor, reading, error))
postsample = collect_samples(count)
readings = [mean(channel) for channel in postsample]
print("Means : %s" % " ".join(["%.3f" % f for f in readings]))
print("Resistors : %s" % " ".join(["%.1f" % s.ref_resistor for s in sensors]))
overall_mean = mean(readings)
overall_limit = stddev(readings)
print("Overall Range : %.3f" % (max(readings)-min(readings)))
print("Overall Mean : %.3f" % overall_mean)
print("Overall STD : %.3f" % overall_limit)
return presample, postsample
def auto_calibrate_loop(times=4, sample_count=20):
idx = 0
reset = True
while idx < times:
if idx > 0:
reset = False
print()
print("Calibration Cycle %d" % idx)
auto_calibrate(count=sample_count, reset=reset)
idx += 1
return [s.ref_resistor for s in sensors]