ams-master/AMS_Master_Code/temp_gen_adbms.py

90 lines
2.7 KiB
Python

import numpy as np
import matplotlib.pyplot as plt # Import matplotlib for plotting
# Constants
NTC_A1 = 0.003354016
NTC_B1 = 0.000300131
NTC_C1 = 5.08516E-06
NTC_D1 = 2.18765E-07
LOW_TEMP = 0
HIGH_TEMP = 70
N = 16 # Number of bits
VREF = 3.0
RESOLUTION = 0.01 # temp is in 0.01°C
TEMP_CONV = 1/RESOLUTION
CELSIUS_TO_KELVIN = 273.15
def calc_temp_c(adc_voltage):
log_ohms = np.log(1 / ((VREF / adc_voltage) - 1))
temperature = 1 / (
NTC_A1 +
NTC_B1 * log_ohms +
NTC_C1 * log_ohms**2 +
NTC_D1 * log_ohms**3
) - CELSIUS_TO_KELVIN
return temperature
def calc_voltage(adc_code):
return adc_code * 150e-6 + 1.5 # Convert ADC ADBMS code to voltage
def temp_table(adc_codes):
temp = []
for adc_code in adc_codes: # Signed 16-bit ADC range
adc_voltage = calc_voltage(adc_code)
try:
temperature = calc_temp_c(adc_voltage)
except (ValueError, ZeroDivisionError):
temperature = None # Handle invalid calculations gracefully
temp.append(temperature)
return np.array(temp)
def make_c_code(temp_values, low_t_adc, high_t_adc):
# generate C code of an array and put into code.c file
with open("tempTable.h", "w") as f:
f.write("#include <stdint.h>\nconst uint16_t ADC2TEMP[] = {\n")
for temp in temp_values:
f.write(f" {(int)(temp*TEMP_CONV)}")
if temp != temp_values[-1]:
f.write(",")
f.write("};")
with open("tempCalc.c", "w") as f:
f.write("""#include "tempTable.h"
static inline uint16_t ntc_mv_to_celsius(int16_t adc) {
// Out of bounds checking --> done by OV/UV setting of the BMS?
if (adc < """ + str(int(low_t_adc)) + """ || adc > """ + str(int(high_t_adc)) + """) {
return -1;
}
return ADC2TEMP[adc + """ + str(-int(low_t_adc)) + """];
}
""")
if __name__ == "__main__":
adc_codes = np.linspace(-2**(N - 1), 2**(N - 1) - 1, 2**N)
temp_values = temp_table(adc_codes)
bool_vec = (temp_values >= LOW_TEMP) & (temp_values <= HIGH_TEMP)
low_t_adc = adc_codes[bool_vec][0]
high_t_adc = adc_codes[bool_vec][-1]
print(f"ADC code for {LOW_TEMP}°C: {low_t_adc}")
print(f"ADC code for {HIGH_TEMP}°C: {high_t_adc}")
plt.figure(figsize=(10, 6))
plt.plot(adc_codes[bool_vec], temp_values[bool_vec], "b", label="0°C to 70°C")
# plt.plot(adc_codes, temp_values, "r")
# plt.xlim([-10000, 10000])
plt.title("ADC Code to Temperature Conversion")
plt.xlabel("ADC Code")
plt.ylabel("Temperature (°C)")
plt.grid(True)
plt.legend()
plt.show()
make_c_code(temp_values[bool_vec], low_t_adc, high_t_adc)