Skip to content

Instantly share code, notes, and snippets.

@jaggzh
Last active October 29, 2023 22:45
Show Gist options
  • Save jaggzh/b76b555afc8143935bd5b365bf53143d to your computer and use it in GitHub Desktop.
Save jaggzh/b76b555afc8143935bd5b365bf53143d to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
# CC-By 2023 jaggz.h {over at} gmail.com
# https://github.com/jaggzh/
#
# Gist URL:
# https://gist.github.com/jaggzh/b76b555afc8143935bd5b365bf53143d
#
# Outputs values for command-line provided resistances or temperatures
# Usage: therm [options] <values> [options]
# eg: therm <resistance>k [<resistance2>k ...]
# therm <temperature>f [...]
# therm <temperature>c [...]
# (multiple temperatures or resistances may be given)
# -v -- increase verbosity
# -h -- help
# -d # -- Show temperature/resistance differences in clusters of #
# -D -- Dump table
use v5.36;
use utf8;
my %data;
my $deg = "\x{00B0}";
my @uinputs; # User-provided Resistances and Temperatures
my $verbose=0;
my $opt_help=0;
my $opt_diff=0;
my $opt_dump=0;
binmode *STDOUT, ":encoding(UTF-8)";
# BG
our $bgbla="\033[40m"; our $bgred="\033[41m"; our $bggre="\033[42m";
our $bgbro="\033[43m"; our $bgblu="\033[44m"; our $bgmag="\033[45m";
our $bgcya="\033[46m"; our $bggra="\033[47m";
# FG
our $bla="\033[30m"; our $red="\033[31m"; our $gre="\033[32m";
our $bro="\033[33m"; our $blu="\033[34m"; our $mag="\033[35m";
our $cya="\033[36m"; our $gra="\033[37m";
# Bright FG (FG with intensity)
our $bbla="\033[30;1m"; our $bred="\033[31;1m"; our $bgre="\033[32;1m";
our $yel="\033[33;1m"; our $bblu="\033[34;1m"; our $bmag="\033[35;1m";
our $bcya="\033[36;1m"; our $whi="\033[37;1m";
# Other...
our $rst="\033[0m"; our $inv="\033[7m";
our $cll="\033[2K"; our $cllr="\033[K"; our $cls="\033[2J"; our $clsb="\033[J";
our $ahome = "\033[1H";
sub getopts {
for (my $i=0; $i < @ARGV; $i++) {
my $opt = $ARGV[$i];
if ($opt eq '-v') {
$verbose++;
} elsif ($opt eq '-h') {
$opt_help=1;
} elsif ($opt eq '-D') {
$opt_dump=1;
} elsif ($opt eq '-d') {
$opt = $ARGV[++$opt];
if (!defined $opt || $opt =~ /^\d+$/) {
say STDERR "-d requires a number";
exit 1;
}
$opt_diff=$opt;
} else {
push @uinputs, $opt;
}
}
if ($opt_diff || $opt_dump) {
if (@uinputs) {
say STDERR "Can't use -d or -D along with values to look up";
exit 1;
}
} elsif (!@uinputs || $opt_help) {
usage();
exit();
}
}
sub usage {
print <<~'EOT';
Usage: therm [options] <values> [options]
eg: therm <resistance>k [<resistance2>k ...]
therm <temperature>f [...]
therm <temperature>c [...]
(multiple temperatures or resistances may be given)
-v -- increase verbosity
-h -- help
-d # -- Show temp/res differences in clusters of # (not implemented)
-D -- Dump table
EOT
print_datainfo();
}
sub print_datainfo {
print <<~'EOT';
Reprap Hotend Thermistor NTC 3950 100K with 1M Cable
- Standard resistance: R25(25): 1.5K, 2K, 5K, 10K, 20K, 30K, 47K, 50K, 100K, 200K, 500K, etc
- Resistance tolerance: ±1%, ±2%, ±3%
- B-value R25/50: 3435K, 3600K, 3950K, 3990K, 4100K, 4200K, etc
- B-value accuracy: ±1%
- Operating temperature: -40~+300℃C
- Power dissipation coefficient: >= 5 mW/℃C (in static air)
- Max. rated power: 45mW
- Thermal time constant: <=7S (in static air)
- Temperature coefficient of resistance: -2~-5%/℃C
- It is recommended to use: R25℃C = 100K, B25/50 = 3950K±1%
R@25℃C 100KΩ±1% B@25℃C/50℃C 3950±1%
EOT
}
sub loaddata {
while (<DATA>) {
chomp;
my ($temp, $rmax, $rnor, $rmin) = split;
$data{$temp} = [$rmax, $rnor, $rmin];
}
}
sub interpolate_temps {
my ($r, $temp1, $temp2) = @_;
my ($rmax1, $rnor1, $rmin1) = @{$data{$temp1}};
my ($rmax2, $rnor2, $rmin2) = @{$data{$temp2}};
# Interpolating temperature based on resistance
my $max_temp = $temp1 + ($r - $rmax1) * ($temp2 - $temp1) / ($rmax2 - $rmax1);
my $nor_temp = $temp1 + ($r - $rnor1) * ($temp2 - $temp1) / ($rnor2 - $rnor1);
my $min_temp = $temp1 + ($r - $rmin1) * ($temp2 - $temp1) / ($rmin2 - $rmin1);
return ($max_temp, $nor_temp, $min_temp);
}
sub interpolate_kohms {
my ($temp, $temp1, $temp2) = @_;
my ($rmax1, $rnor1, $rmin1) = @{$data{$temp1}};
my ($rmax2, $rnor2, $rmin2) = @{$data{$temp2}};
my $max_r = $rmax1 + ($temp - $temp1) * ($rmax2 - $rmax1) / ($temp2 - $temp1);
my $nor_r = $rnor1 + ($temp - $temp1) * ($rnor2 - $rnor1) / ($temp2 - $temp1);
my $min_r = $rmin1 + ($temp - $temp1) * ($rmin2 - $rmin1) / ($temp2 - $temp1);
return ($max_r, $nor_r, $min_r);
}
sub c_to_f {
my $c = shift;
return $c * 9/5 + 32;
}
sub f_to_c {
my $c = shift;
return ($c-32)*5/9;
}
sub resistance_from_temp {
my ($temp, $unit) = @_;
$temp = ($temp - 32) * 5/9 if lc($unit) eq 'f'; # Convert Fahrenheit to Celsius
my $prevtemp = (sort {$a <=> $b} keys %data)[0]; # Start with the lowest temperature
foreach my $curtemp (sort {$a <=> $b} keys %data) {
if ($verbose) {
say "Scanning C $curtemp < C: $temp";
say " (Row is: ", join(', ', @{$data{$curtemp}});
}
if ($temp <= $curtemp) {
if ($verbose) {
say "Interpolating between: $prevtemp, $temp, and $curtemp:";
}
my ($rmax, $rnor, $rmin) = interpolate_kohms($temp, $prevtemp, $curtemp);
return ($rmax, $rnor, $rmin);
}
$prevtemp = $curtemp;
}
}
sub output {
my ($r) = @_;
my $previous_temp = (sort {$a <=> $b} keys %data)[0]; # Start with the lowest temperature
foreach my $temp (sort {$a <=> $b} keys %data) {
if ($verbose) {
say "Scanning R $data{$temp}[1] < R: $r";
say " (Row is: ", join(', ', @{$data{$temp}});
}
if ($r >= $data{$temp}->[1]) {
say '';
printf "Requested resistance: $bmag%.2f kOhm$rst\n", $r;
say " Reached temperature at RNorm ", $data{$temp}->[1]
if $verbose;
say " Previous row ${previous_temp}${deg}C ",
join(', ', @{$data{$previous_temp}});
say " Next row ${temp}${deg}C ",
join(', ', @{$data{$temp}});
my ($max, $nor, $min) = interpolate_temps($r, $previous_temp, $temp);
say '';
printf " %-5s %-5s %-5s\n",
'Max', 'Norm', 'Min';
printf "${deg}C %5.2f %5.2f %5.2f\n",
$max, $nor, $min;
printf "${deg}F %5.2f %5.2f %5.2f\n",
c_to_f($max), c_to_f($nor), c_to_f($min);
last;
}
$previous_temp = $temp;
}
}
sub procinputs {
for my $input (@uinputs) {
if ($input =~ /^\d+(\.\d+)?k$/i) { # Matches 50.2k or 50k
$input =~ s/k//i;
output($input);
} elsif ($input =~ /^\d+(\.\d+)?$/) { # Matches 50200 or 50200.3
$input /= 1000; # Change to k
output($input);
} elsif ($input =~ /^(\d+(\.\d+)?)([fc])$/i) { # Matches 25.5c or 77.9f
my $temp = $1;
my $unit = lc($3);
my ($tempc, $tempf);
if ($unit eq 'f') {
$tempc = f_to_c($temp);
$tempf = $temp;
} elsif ($unit eq 'c') {
$tempc = $temp;
$tempf = c_to_f($temp);
}
my ($rmax, $rnor, $rmin) = resistance_from_temp($temp, $unit);
say '';
say sprintf "For temperature $bmag%.3f ${deg}F (%.3f ${deg}C)$rst:", $tempf, $tempc;
say " Resistances:";
say sprintf " Min: %6.3f kOhm", $rmin;
say sprintf " Normal: %6.3f kOhm", $rnor;
say sprintf " Max: %6.3f kOhm", $rmax;
} else {
say STDERR "Invalid resistance value '$input'";
exit 1;
}
}
}
sub dumpdata {
foreach my $temp (sort {$a <=> $b} keys %data) {
say join("\t", $temp, @{$data{$temp}});
}
}
sub main {
getopts();
loaddata();
if ($opt_dump) {
dumpdata();
} elsif ($opt_diff) {
say "we should diff here, but we haven't made it yet."
} else {
procinputs();
}
}
main();
# T Rmax Rnor Rmin
__DATA__
-30 1805.1971 1733.2000 1663.6657
-29 1693.5863 1630.4080 1569.3019
-28 1593.9380 1534.4770 1476.9663
-27 1500.8930 1444.9030 1390.7495
-26 1413.9673 1361.2200 1310.2028
-25 1329.1367 1283.0000 1238.3016
-24 1252.8144 1209.3270 1167.1953
-23 1181.4336 1140.4240 1100.6928
-22 1114.6401 1075.9490 1038.4640
-21 1052.1085 1015.5880 980.2059
-20 990.8617 959.0500 928.1695
-19 936.0641 906.0117 876.8390
-18 884.6914 856.2883 828.7167
-17 836.5067 809.6506 783.5807
-16 791.2910 765.8865 741.2257
-15 746.7035 724.8000 703.4662
-14 706.3711 685.6507 665.4693
-13 668.5024 648.8929 629.7934
-12 632.9310 614.3649 596.2817
-11 599.5024 581.9169 564.7888
-10 566.5131 551.4100 536.6581
-9 537.0073 522.6908 508.7073
-8 509.2437 495.6674 482.4068
-7 483.1082 470.2286 457.6486
-6 458.4948 446.2714 434.3323
-5 434.1442 423.7000 413.4672
-4 411.9667 402.0560 392.3459
-3 391.0739 381.6658 372.4482
-2 371.3832 362.4488 353.6953
-1 352.8178 344.3301 336.0142
0 334.4393 327.2400 320.1638
1 317.8826 311.0397 304.3138
2 302.2571 295.7506 289.3553
3 287.5046 281.3157 275.2325
4 273.5710 267.6820 261.8936
5 259.7533 254.8000 249.9157
6 247.2985 242.5827 237.9326
7 235.5234 231.0321 226.6034
8 224.3869 220.1080 215.8887
9 213.8504 209.7724 205.7513
10 203.3838 199.9900 196.6338
11 193.7916 190.5578 187.3599
12 184.7142 181.6319 178.5838
13 176.1211 173.1822 170.2759
14 167.9835 165.1804 162.4083
15 159.8962 157.6000 155.3211
16 152.6170 150.4253 148.2502
17 145.7160 143.6234 141.5466
18 139.1712 137.1726 135.1891
19 132.9622 131.0528 129.1578
20 126.7793 125.2450 123.7170
21 121.1240 119.6582 118.1984
22 115.7568 114.3559 112.9608
23 110.6613 109.3221 107.9884
24 105.6340 104.5415 103.4506
25 101.0000 100.0000 99.0000
26 96.8195 95.8191 94.8195
27 92.8384 91.8392 90.8415
28 89.0074 88.0494 87.0928
29 85.3582 84.4395 83.5222
30 81.9874 81.0000 80.0167
31 78.5700 77.6238 76.6815
32 75.3161 74.4091 73.5058
33 72.2170 71.3472 70.4812
34 69.2643 68.4301 67.5994
35 66.5901 65.6500 64.7167
36 63.8857 62.9838 62.0884
37 61.3075 60.4420 59.5827
38 58.8489 58.0181 57.1933
39 56.5037 55.7060 54.9141
40 54.3774 53.5000 52.6316
41 52.2133 51.3708 50.5370
42 50.1482 49.3391 48.5382
43 48.1771 47.3998 46.6304
44 46.2952 45.5483 44.8090
45 44.5864 43.7800 42.9836
46 42.8302 42.0555 41.2905
47 41.1535 40.4092 39.6741
48 39.5522 38.8369 38.1304
49 38.0227 37.3350 36.6558
50 36.6326 35.8999 35.1785
51 35.3225 34.6160 33.9204
52 34.0669 33.3855 32.7147
53 32.8632 32.2059 31.5588
54 31.7091 31.0748 30.4504
55 30.6600 29.9900 29.3318
56 29.5510 28.9053 28.2709
57 28.4885 27.8660 27.2545
58 27.4703 26.8700 26.2803
59 26.4943 25.9153 25.3466
60 25.6058 25.0000 24.4063
61 24.6941 24.1099 23.5373
62 23.8200 23.2565 22.7042
63 22.9818 22.4381 21.9052
64 22.1778 21.6531 21.1389
65 21.4449 20.9000 20.3669
66 20.7000 20.1741 19.6595
67 19.9852 19.4774 18.9806
68 19.2990 18.8087 18.3289
69 18.6402 18.1666 17.7032
70 18.0391 17.5500 17.0723
71 17.4182 16.9459 16.4847
72 16.8220 16.3659 15.9204
73 16.2495 15.8089 15.3786
74 15.6996 15.2739 14.8582
75 15.1975 14.7600 14.3337
76 14.7046 14.2813 13.8688
77 14.2303 13.8206 13.4215
78 13.7739 13.3774 12.9910
79 13.3346 12.9507 12.5767
80 12.9333 12.5400 12.1575
81 12.5153 12.1347 11.7646
82 12.1130 11.7447 11.3865
83 11.7259 11.3694 11.0225
84 11.3532 11.0080 10.6722
85 11.0123 10.6600 10.3179
86 10.6655 10.3243 9.9930
87 10.3315 10.0010 9.6800
88 10.0097 9.6895 9.3785
89 9.6996 9.3893 9.0880
90 9.4159 9.1000 8.7939
91 9.1231 8.8171 8.5205
92 8.8410 8.5444 8.2571
93 8.5691 8.2816 8.0031
94 8.3069 8.0283 7.7583
95 8.0667 7.7840 7.5105
96 7.8282 7.5538 7.2884
97 7.5979 7.3316 7.0740
98 7.3756 7.1172 6.8670
99 7.1610 6.9100 6.6672
100 6.9643 6.7100 6.4644
101 6.7739 6.5265 6.2876
102 6.5896 6.3490 6.1166
103 6.4113 6.1772 5.9511
104 6.2388 6.0109 5.7909
105 6.0808 5.8500 5.6274
106 5.9075 5.6832 5.4669
107 5.7400 5.5221 5.3119
108 5.5780 5.3663 5.1620
109 5.4214 5.2156 5.0171
110 5.2777 5.0700 4.8700
111 5.1310 4.9291 4.7346
112 4.9892 4.7928 4.6037
113 4.8519 4.6610 4.4771
114 4.7192 4.5334 4.3546
115 4.5973 4.4100 4.2299
116 4.4729 4.2906 4.1154
117 4.3524 4.1751 4.0046
118 4.2358 4.0632 3.8973
119 4.1229 3.9549 3.7934
120 4.0192 3.8500 3.6877
121 3.9054 3.7410 3.5833
122 3.7954 3.6357 3.4824
123 3.6891 3.5338 3.3848
124 3.5862 3.4353 3.2904
125 3.4915 3.3400 3.1947
126 3.4027 3.2550 3.1135
127 3.3166 3.1726 3.0346
128 3.2330 3.0927 2.9582
129 3.1520 3.0152 2.8841
130 3.0776 2.9400 2.8084
131 2.9974 2.8634 2.7353
132 2.9198 2.7893 2.6644
133 2.8445 2.7173 2.5957
134 2.7715 2.6476 2.5291
135 2.7043 2.5800 2.4613
136 2.6355 2.5144 2.3987
137 2.5688 2.4507 2.3380
138 2.5041 2.3890 2.2791
139 2.4413 2.3291 2.2220
140 2.3834 2.2710 2.1637
141 2.3231 2.2135 2.1089
142 2.2645 2.1577 2.0557
143 2.2077 2.1035 2.0041
144 2.1525 2.0510 1.9541
145 2.1016 2.0000 1.9031
146 2.0504 1.9513 1.8567
147 2.0007 1.9040 1.8117
148 1.9524 1.8580 1.7680
149 1.9055 1.8134 1.7255
150 1.8624 1.7700 1.6822
151 1.8222 1.7319 1.6459
152 1.7832 1.6947 1.6106
153 1.7451 1.6586 1.5763
154 1.7080 1.6233 1.5428
155 1.6739 1.5890 1.5083
156 1.6349 1.5520 1.4732
157 1.5970 1.5160 1.4391
158 1.5602 1.4811 1.4059
159 1.5244 1.4471 1.3736
160 1.4914 1.4140 1.3406
161 1.4568 1.3812 1.3095
162 1.4233 1.3494 1.2793
163 1.3906 1.3184 1.2500
164 1.3588 1.2883 1.2214
165 1.3294 1.2590 1.1923
166 1.2988 1.2301 1.1649
167 1.2691 1.2019 1.1382
168 1.2402 1.1745 1.1123
169 1.2121 1.1479 1.0871
170 1.1861 1.1220 1.0613
171 1.1582 1.0956 1.0363
172 1.1310 1.0699 1.0120
173 1.1046 1.0449 0.9884
174 1.0790 1.0206 0.9654
175 1.0551 0.9970 0.9419
176 1.0326 0.9757 0.9218
177 1.0107 0.9550 0.9023
178 0.9893 0.9348 0.8832
179 0.9685 0.9151 0.8646
180 0.9493 0.8960 0.8457
181 0.9271 0.8750 0.8258
182 0.9056 0.8547 0.8067
183 0.8846 0.8349 0.7880
184 0.8643 0.8157 0.7699
185 0.8453 0.7970 0.7514
186 0.8279 0.7806 0.7360
187 0.8110 0.7646 0.7209
188 0.7944 0.7490 0.7062
189 0.7783 0.7338 0.6918
190 0.7633 0.7190 0.6771
191 0.7463 0.7029 0.6619
192 0.7297 0.6873 0.6472
193 0.7136 0.6721 0.6329
194 0.6979 0.6574 0.6191
195 0.6835 0.6430 0.6049
196 0.6698 0.6302 0.5928
197 0.6566 0.6177 0.5811
198 0.6436 0.6055 0.5696
199 0.6309 0.5936 0.5584
200 0.6192 0.5820 0.5469
201 0.6082 0.5717 0.5373
202 0.5976 0.5617 0.5279
203 0.5872 0.5519 0.5187
204 0.5769 0.5423 0.5096
205 0.5677 0.5330 0.5004
206 0.5565 0.5225 0.4905
207 0.5455 0.5122 0.4808
208 0.5349 0.5022 0.4715
209 0.5245 0.4925 0.4624
210 0.5149 0.4830 0.4529
211 0.5046 0.4733 0.4438
212 0.4945 0.4639 0.4350
213 0.4847 0.4547 0.4264
214 0.4751 0.4457 0.4180
215 0.4664 0.4370 0.4095
216 0.4572 0.4284 0.4014
217 0.4482 0.4200 0.3935
218 0.4395 0.4118 0.3859
219 0.4309 0.4038 0.3784
220 0.4230 0.3960 0.3707
221 0.4149 0.3884 0.3636
222 0.4070 0.3810 0.3566
223 0.3994 0.3739 0.3500
224 0.3918 0.3668 0.3434
225 0.3850 0.3600 0.3366
226 0.3778 0.3533 0.3304
227 0.3708 0.3467 0.3242
228 0.3639 0.3403 0.3182
229 0.3573 0.3341 0.3124
230 0.3510 0.3280 0.3065
231 0.3446 0.3220 0.3009
232 0.3383 0.3161 0.2953
233 0.3322 0.3104 0.2900
234 0.3262 0.3048 0.2848
235 0.3206 0.2993 0.2794
236 0.3149 0.2940 0.2744
237 0.3094 0.2888 0.2696
238 0.3038 0.2836 0.2647
239 0.2984 0.2786 0.2601
240 0.2934 0.2737 0.2553
241 0.2883 0.2689 0.2508
242 0.2832 0.2642 0.2464
243 0.2783 0.2596 0.2421
244 0.2735 0.2551 0.2379
245 0.2690 0.2507 0.2337
246 0.2644 0.2464 0.2296
247 0.2599 0.2422 0.2257
248 0.2554 0.2380 0.2218
249 0.2511 0.2340 0.2181
250 0.2471 0.2300 0.2141
251 0.2430 0.2262 0.2106
252 0.2388 0.2223 0.2070
253 0.2348 0.2186 0.2035
254 0.2309 0.2150 0.2002
255 0.2273 0.2114 0.1966
256 0.2235 0.2079 0.1934
257 0.2199 0.2045 0.1902
258 0.2162 0.2011 0.1871
259 0.2127 0.1978 0.1840
260 0.2094 0.1946 0.1808
261 0.2060 0.1914 0.1779
262 0.2026 0.1883 0.1750
263 0.1994 0.1853 0.1722
264 0.1962 0.1823 0.1694
265 0.1932 0.1794 0.1666
266 0.1901 0.1765 0.1639
267 0.1871 0.1737 0.1613
268 0.1842 0.1710 0.1588
269 0.1813 0.1683 0.1563
270 0.1785 0.1656 0.1536
271 0.1757 0.1630 0.1512
272 0.1729 0.1604 0.1488
273 0.1702 0.1579 0.1465
274 0.1676 0.1555 0.1443
275 0.1652 0.1531 0.1419
276 0.1626 0.1507 0.1397
277 0.1601 0.1484 0.1375
278 0.1576 0.1461 0.1354
279 0.1553 0.1439 0.1334
280 0.1530 0.1417 0.1312
281 0.1508 0.1396 0.1293
282 0.1485 0.1375 0.1273
283 0.1462 0.1354 0.1254
284 0.1441 0.1334 0.1235
285 0.1420 0.1314 0.1216
286 0.1400 0.1295 0.1198
287 0.1378 0.1275 0.1180
288 0.1359 0.1257 0.1163
289 0.1338 0.1238 0.1145
290 0.1320 0.1220 0.1128
291 0.1301 0.1202 0.1111
292 0.1282 0.1185 0.1095
293 0.1264 0.1168 0.1080
294 0.1245 0.1151 0.1064
295 0.1228 0.1134 0.1047
296 0.1211 0.1118 0.1033
297 0.1193 0.1102 0.1018
298 0.1176 0.1086 0.1003
299 0.1160 0.1071 0.0989
300 0.1145 0.1056 0.0974
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment