Skip to content

Instantly share code, notes, and snippets.

@iwanders
Last active August 29, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iwanders/44671b3cf09afe390d3e to your computer and use it in GitHub Desktop.
Save iwanders/44671b3cf09afe390d3e to your computer and use it in GitHub Desktop.
[Teensy] Script used to relate analogRead(39) with input voltage.
#!/usr/bin/env python2
"""
Script to relate Teensy 3.0 analogRead(39) values to the input voltage.
That's the original purpose atleast, it could probably be used to create
polynomials for any file in which holds measurements of: "x y" per line.
Datafiles included here:
https://gist.github.com/iwanders/44671b3cf09afe390d3e
"""
import os
import numpy as np
import matplotlib.pyplot as plt
def parse_file(f):
d = [] # data list.
with open(f, 'r') as f:
lines = f.readlines()
for line in lines:
line = line.strip() # strip newlines.
if (line.startswith('#')): # skip comments.
continue
a = line.split(" ") # split on spaces
if (len(a) < 2): # remove empty line.
continue
# get values from start and end of line, interpret as float.
reading = (float(a[0]), float(a[-1]))
d.append(reading)
return d
# sort the data on the first column.
def order_data(d):
return sorted(d, key=lambda x: x[0])
# swap the first and second column.
def swap_cols(d):
nd = []
for r in d:
nd.append((r[1], r[0]))
return nd
def perform_analysis(path, interval=(1500, 3100), xlim=(1200, 3100),
ylim=(1500, 4500),
image_path=None, plot_this_poly=None,
plot_ADC_inversion=True):
plt.clf()
d = parse_file(path)
plt.xlim(xlim)
plt.ylim(ylim)
# order on readings (as we use this as x)
d = swap_cols(d)
d = order_data(d)
d = swap_cols(d)
d = np.array(d)
v = d[:, 0]*1000 # millivolt
r = d[:, 1] # reading
# draw measurement scatter plot in green
plt.scatter(r, v, c=(0.25, 1, 0.25), alpha=0.7, label="Measurements")
# resample:
x_r = np.arange(interval[0], interval[1], 100)
y_r = np.interp(x_r, r, v)
plt.scatter(x_r, y_r, c=(1, 0.25, 0.25), alpha=0.7, label="Resampled")
# cubic polynomial
p_values_2, residuals_2, _, _, _ = np.polyfit(x_r, y_r, 2, full=True)
print("Coefficients P_2: %s" % p_values_2)
# print("Residuals: %s" % residuals_2)
float_values = np.polyval(p_values_2, x_r)
plt.plot(x_r, float_values, c=(0.5, 1, 0.2), label="Quadratic poly")
# quadratic polynomial
p_values_3, residuals_3, _, _, _ = np.polyfit(x_r, y_r, 3, full=True)
print("Coefficients P_3: %s" % p_values_3)
# print("Residuals: %s" % residuals_3)
float_values = np.polyval(p_values_3, x_r)
plt.plot(x_r, float_values, c=(0.5, 0.2, 1), label="Cubic poly")
if (plot_this_poly):
integer_values = plot_this_poly(x_r)
plt.plot(x_r, integer_values, c="k", linestyle='--',
label="Integer poly", linewidth=2)
diff = np.sqrt(np.mean(np.power(float_values - integer_values, 2)))
print("Signed difference: %f" % diff)
if (plot_ADC_inversion):
cal_pos = 3.3 * 1000.0;
analogread_at_3v3 = np.interp(np.array([cal_pos]), v[::-1], r[::-1])
#(1474*3.33/4096 = 1.198344 v)
vref = ((analogread_at_3v3[0] * cal_pos) / 4096.0)
#Vcc=1.198344*4096/analogRead(39)
Vcc = vref * (4096.0 / x_r)
plt.scatter(analogread_at_3v3,[cal_pos], c="m", marker='x',
label="AD@3.3v:{:.2f}, vref:{:.2f}".format(analogread_at_3v3[0],vref), linewidth=2, s=50)
plt.plot(x_r, Vcc, c="g", linestyle='--',
label="({:.2f} * 4096)/x".format(vref), linewidth=2)
plt.xlim(xlim[0], xlim[1])
plt.xlabel('analogRead(39), res=12bit, avg=32')
plt.title(os.path.basename(path))
plt.ylabel('Input voltage measured [V]')
plt.legend()
# plt.show()
if (image_path):
plt.savefig(image_path, bbox_inches='tight', dpi=150)
def tainting_type(f):
def foo(x):
x = np.array(x, dtype=f)
return x.astype(f, casting='no')
return foo
uint32_t = tainting_type(np.uint32)
int32_t = tainting_type(np.int32)
def integer_poly_vin_T30():
coeffs = np.array([4.79305738e-04, 3.18084349e+00, 7.22111948e+03])
# x is in [1400, 3000]
uint32_t_max = 2**32 - 1
x_max = 3000
# calculate scale such that it does not overflow.
scale = uint32_t_max / (coeffs[0] * x_max**2 + coeffs[2])
print("Scale: {}".format(scale))
c_scaled = [uint32_t(coeffs[i]*scale) for i in (0, 1, 2)]
print("C0: {}".format(c_scaled[0]))
print("C1: {}".format(c_scaled[1]))
print("C2: {}".format(c_scaled[2]))
print("Calculation in C:")
print("output = ({C0:}*x*x + {C2:} - {C1:} * x) / {scale:};".format(**{
"C0": c_scaled[0],
"C1": c_scaled[1],
"C2": c_scaled[2],
"scale": uint32_t(scale)}))
def foo(x):
xi = uint32_t(x)
return uint32_t((uint32_t(uint32_t(c_scaled[0] * xi**2) +
uint32_t(c_scaled[2])) - uint32_t(c_scaled[1] * xi))
/ uint32_t(scale))
return foo
def integer_poly_vin_T31():
coeffs = np.array([ 4.80021836e-04, 3.17930738e+00, 7.23180952e+03])
# x is in [1400, 3000]
uint32_t_max = 2**32 - 1
x_max = 3000
# calculate scale such that it does not overflow.
scale = uint32_t_max / (coeffs[0] * x_max**2 + coeffs[2])
print("Scale: {}".format(scale))
c_scaled = [uint32_t(coeffs[i]*scale) for i in (0, 1, 2)]
print("C0: {}".format(c_scaled[0]))
print("C1: {}".format(c_scaled[1]))
print("C2: {}".format(c_scaled[2]))
print("Calculation in C:")
print("output = ({C0:}*x*x + {C2:} - {C1:} * x) / {scale:};".format(**{
"C0": c_scaled[0],
"C1": c_scaled[1],
"C2": c_scaled[2],
"scale": uint32_t(scale)}))
def foo(x):
xi = uint32_t(x)
return uint32_t((uint32_t(uint32_t(c_scaled[0] * xi**2) +
uint32_t(c_scaled[2])) - uint32_t(c_scaled[1] * xi))
/ uint32_t(scale))
return foo
def integer_poly_3v3_TLC():
coeffs = np.array([ 7.75866783e-04, 4.17213376e+00, 7.27723148e+03])
# x is in [1400, 3000]
uint32_t_max = 2**32 - 1
x_max = 2600
# calculate scale such that it does not overflow.
scale = uint32_t_max / (coeffs[0] * x_max**2 + coeffs[2])
print("Scale: {}".format(scale))
c_scaled = [uint32_t(coeffs[i]*scale) for i in (0, 1, 2)]
print("C0: {}".format(c_scaled[0]))
print("C1: {}".format(c_scaled[1]))
print("C2: {}".format(c_scaled[2]))
print("Calculation in C:")
print("output = ({C0:}*x*x + {C2:} - {C1:} * x) / {scale:};".format(**{
"C0": c_scaled[0],
"C1": c_scaled[1],
"C2": c_scaled[2],
"scale": uint32_t(scale)}))
def foo(x):
xi = uint32_t(x)
return uint32_t((uint32_t(uint32_t(c_scaled[0] * xi**2) +
uint32_t(c_scaled[2])) - uint32_t(c_scaled[1] * xi))
/ uint32_t(scale))
return foo
def integer_poly_vin_TLC():
coeffs = np.array([ 7.53720089e-04, 4.06922934e+00, 7.19510440e+03])
# x is in [1400, 3000]
uint32_t_max = 2**32 - 1
x_max = 2700
# calculate scale such that it does not overflow.
scale = uint32_t_max / (coeffs[0] * x_max**2 + coeffs[2])
print("Scale: {}".format(scale))
c_scaled = [uint32_t(coeffs[i]*scale) for i in (0, 1, 2)]
print("C0: {}".format(c_scaled[0]))
print("C1: {}".format(c_scaled[1]))
print("C2: {}".format(c_scaled[2]))
print("Calculation in C:")
print("output = ({C0:}*x*x + {C2:} - {C1:} * x) / {scale:};".format(**{
"C0": c_scaled[0],
"C1": c_scaled[1],
"C2": c_scaled[2],
"scale": uint32_t(scale)}))
def foo(x):
xi = uint32_t(x)
return uint32_t((uint32_t(uint32_t(c_scaled[0] * xi**2) +
uint32_t(c_scaled[2])) - uint32_t(c_scaled[1] * xi))
/ uint32_t(scale))
return foo
if __name__ == "__main__":
print("Analysing 3v3 input measurements.")
perform_analysis("to_3v3.txt",
interval=(1252, 3000),
image_path=os.path.join("to_3v3.png"))
print("\nAnalysing Vin input measurements.")
perform_analysis("to_Vin.txt",image_path="to_Vin.png",
plot_this_poly=integer_poly_vin_T30())
print("\nAnalysing 3v3 input measurements, T3.1")
perform_analysis("to_Vin_T3.1.txt",image_path="to_Vin_T3.1.png",
plot_this_poly=integer_poly_vin_T31())
print("\nAnalysing Vin input measurements, Teensy LC")
perform_analysis("to_Vin_LC.txt",image_path="to_Vin_LC.png",
interval=(1246,2500),
xlim=(1200,2600),
plot_this_poly=integer_poly_vin_TLC())
print("\nAnalysing 3v3 input measurements, Teensy LC")
perform_analysis("to_3v3_LC.txt",image_path="to_3v3_LC.png",
interval=(1150,2510),
xlim=(1100,2600),
plot_this_poly=integer_poly_3v3_TLC())
#Supply to 3.3v:
#Volt Reading
3.75 1310
3.66 1343
3.58 1373
3.35 1467
3.22 1530
2.99 1639
3.45 1425
3.07 1601
2.67 1842
2.26 2186
1.98 2498
1.90 2597
1.70 2911
1.65 3000
1.69 2931
1.92 2583
2.45 2012
2.62 1888
3.33 1474
3.69 1333
3.74 1314
3.78 1299
3.50 1405
3.57 1379
2.95 1662
2.71 1812
2.38 2070
1.89 2609
2.47 1996
3.68 1336
3.53 1393
3.38 1456
3.10 1593
2.49 1978
2.21 2236
1.88 2634
2.54 1940
2.70 1823
3.16 1553
3.46 1422
3.04 1621
3.18 1549
3.50 1404
3.87 1273
3.93 1252
#Supply to Vin:
# analogReference(INTERNAL);
# analogReadResolution(12);
# analogReadAveraging(32);
# PMC_REGSC |= PMC_REGSC_BGBE;
#Volt Reading
3.55 1151
3.27 1252
3.09 1329
2.82 1452
2.68 1528
2.50 1645
2.24 1839
2.03 2026
1.81 2270
1.75 2350
1.65 2493
1.64 2510
# shuts down around here...
1.69 2436
1.87 2203
1.92 2151
1.97 2096
2.10 1960
2.33 1764
2.44 1684
2.51 1637
2.55 1611
2.62 1566
2.74 1494
2.93 1397
3.01 1362
3.12 1315
3.23 1264
3.31 1235
3.34 1224
3.41 1200
3.45 1187
#Supply to Vin:
#Volt Reading
3.43 1562
3.37 1596
3.71 1468
3.23 1677
3.05 1782
2.88 1908
2.60 2146
2.21 2598
4.98 1464
5.35 1460
5.58 1455
5.20 1462
4.74 1465
4.61 1465
4.41 1466
4.17 1466
3.91 1466
3.59 1489
3.31 1624
#Second batch of measurements
2.30 2456
2.88 1899
3.06 1778
3.27 1652
2.68 2066
2.16 2667
2.75 2002
2.27 2527
1.97 2982
2.14 2695
2.47 2282
2.29 2503
2.15 2675
2.07 2802
2.86 1916
2.02 2901
2.59 2154
2.36 2402
#Supply to Vin:
# analogReference(INTERNAL);
# analogReadResolution(12);
# analogReadAveraging(32);
# PMC_REGSC |= PMC_REGSC_BGBE;
#Volt Reading
1.69 2495
1.76 2392
1.79 2354
1.92 2180
1.99 2105
2.06 2024
2.20 1896
2.32 1799
2.42 1717
2.55 1626
2.63 1577
2.74 1505
2.87 1440
3.03 1369
3.10 1332
3.20 1291
3.34 1246
3.40 1245
3.72 1245
3.79 1245
4.00 1245
4.34 1245
4.59 1244
4.87 1232
5.04 1241
5.43 1234
#Supply to Vin:
#Volt Reading
3.35 1610
2.87 1927
2.48 2289
2.00 2988
2.19 2652
2.43 2344
2.93 1882
3.42 1586
3.90 1469
4.28 1469
3.70 1469
3.54 1519
4.78 1467
3.94 1469
3.62 1483
3.40 1593
3.07 1784
2.91 1895
2.62 2151
3.87 1469
2.91 1896
2.03 2928
2.37 2405
2.62 2144
2.57 2197
2.13 2740
2.01 2974
2.13 2744
2.25 2567
2.71 2061
3.11 1754
3.15 1731
3.19 1703
3.38 1593
3.69 1469
3.26 1660
2.33 2450
2.18 2663
2.17 2677
2.25 2557
2.03 2918
2.07 2839
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment