From cc8894f703a90f4acb4dd1988cfdba6fa5a9e1b6 Mon Sep 17 00:00:00 2001 From: Moritz Ruffer Date: Fri, 4 Apr 2025 22:10:22 +0200 Subject: [PATCH] feat: add code for lookup table generation --- AMS_Master_Code/temp_gen_adbms.py | 89 +++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 AMS_Master_Code/temp_gen_adbms.py diff --git a/AMS_Master_Code/temp_gen_adbms.py b/AMS_Master_Code/temp_gen_adbms.py new file mode 100644 index 0000000..dbf5cf9 --- /dev/null +++ b/AMS_Master_Code/temp_gen_adbms.py @@ -0,0 +1,89 @@ +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 \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) +