Compare commits
No commits in common. "77701636b53c4561a97779ca53492175a6876d26" and "dae0fbcbdaa0b0bd9212348c323dfa8683b46ce4" have entirely different histories.
77701636b5
...
dae0fbcbda
@ -166,12 +166,9 @@ u8g2_t* display_init(void)
|
|||||||
#elif SSD1312_96X16 && SSD1312_96X16 == 1
|
#elif SSD1312_96X16 && SSD1312_96X16 == 1
|
||||||
// NOTE: display size is wrong, hardware is 96x16, but driver is configured for 120x28
|
// NOTE: display size is wrong, hardware is 96x16, but driver is configured for 120x28
|
||||||
u8g2_Setup_ssd1312_i2c_120x28_f(&u8g2, U8G2_R0, u8x8_byte_i2c, u8x8_gpio_and_delay);
|
u8g2_Setup_ssd1312_i2c_120x28_f(&u8g2, U8G2_R0, u8x8_byte_i2c, u8x8_gpio_and_delay);
|
||||||
#else
|
|
||||||
static_assert(0, "unsupported display size");
|
|
||||||
#endif
|
#endif
|
||||||
// TODO: log errors and return NULL on failure
|
// TODO: log errors and return NULL on failure
|
||||||
u8g2_InitDisplay(&u8g2);
|
u8g2_InitDisplay(&u8g2);
|
||||||
u8g2_SetPowerSave(&u8g2, 0);
|
u8g2_SetPowerSave(&u8g2, 0);
|
||||||
u8g2_SetContrast(&u8g2, 255);
|
|
||||||
return &u8g2;
|
return &u8g2;
|
||||||
}
|
}
|
||||||
|
|||||||
60
fw/main.c
60
fw/main.c
@ -28,12 +28,11 @@
|
|||||||
// constants
|
// constants
|
||||||
// LUT for converting NTC readings to degrees kelvin
|
// LUT for converting NTC readings to degrees kelvin
|
||||||
// Nominal: 1kOhm, Beta: 3380, Step: 64
|
// Nominal: 1kOhm, Beta: 3380, Step: 64
|
||||||
|
// TODO: Since the board temperature is almost always in the 300-200K range add
|
||||||
|
// more steps in order to better represent that interval
|
||||||
const uint8_t ntc_step_size = 64;
|
const uint8_t ntc_step_size = 64;
|
||||||
const int16_t ntc_lut[] = {
|
const int16_t ntc_table[64] = {
|
||||||
1316, 197, 155, 133, 119, 108, 100, 93, 87, 82, 77, 73, 69, 66, 63, 60,
|
1180, 197, 155, 133, 119, 108, 100, 93, 87, 82, 77, 73, 69, 66, 63, 60, 57, 54, 52, 50, 47, 45, 43, 41, 39, 37, 35, 34, 32, 30, 28, 27, 25, 23, 22, 20, 19, 17, 15, 14, 12, 11, 9, 7, 6, 4, 2, 0, -1, -3, -5, -7, -9, -11, -14, -16, -19, -22, -25, -28, -33, -38, -44, -55
|
||||||
57, 54, 52, 50, 47, 45, 43, 41, 39, 37, 35, 34, 32, 30, 28, 27,
|
|
||||||
25, 23, 22, 20, 19, 17, 15, 14, 12, 11, 9, 7, 6, 4, 2, 0,
|
|
||||||
-1, -3, -5, -7, -9, -11, -14, -16, -19, -22, -25, -28, -32, -38, -44, -55
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -51,8 +50,8 @@ static inline int16_t get_temp_k(uint16_t adc_reading)
|
|||||||
if (adc_reading > 4095) return 0;
|
if (adc_reading > 4095) return 0;
|
||||||
uint8_t index = adc_reading / ntc_step_size;
|
uint8_t index = adc_reading / ntc_step_size;
|
||||||
uint8_t remainder = adc_reading % ntc_step_size;
|
uint8_t remainder = adc_reading % ntc_step_size;
|
||||||
int16_t temp_base = index < 64 ? ntc_lut[index] : 0;
|
int16_t temp_base = index < 64 ? ntc_table[index] : 0;
|
||||||
int16_t temp_next = index < 63 ? ntc_lut[index + 1] : temp_base;
|
int16_t temp_next = index < 63 ? ntc_table[index + 1] : temp_base;
|
||||||
return temp_base + ((temp_next - temp_base) * remainder)/ntc_step_size;
|
return temp_base + ((temp_next - temp_base) * remainder)/ntc_step_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,31 +136,6 @@ void EXTI15_8_IRQHandler(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Procedure to get hardware I2C working on the CH32X035F8U6
|
|
||||||
static inline void setup_i2c(void)
|
|
||||||
{
|
|
||||||
// Order here matters, first initialize the AFIO and I2C subsystems then
|
|
||||||
// change register values, do that the other way around and the configuration
|
|
||||||
// wont take effect
|
|
||||||
// Enable AFIO (Alternate Function IO)
|
|
||||||
RCC->APB2PCENR |= RCC_AFIOEN;
|
|
||||||
// Init I2C
|
|
||||||
i2c_init(I2C_TARGET, FUNCONF_SYSTEM_CORE_CLOCK, 100000);
|
|
||||||
|
|
||||||
// To utilize the I2C bus we need to disable SWD first, since the pins overlap
|
|
||||||
AFIO->PCFR1 &= ~(0b0111 << 24);
|
|
||||||
AFIO->PCFR1 |= 0b0100 << 24;
|
|
||||||
|
|
||||||
// Map SCL to PC18 and SDA to PC19
|
|
||||||
AFIO->PCFR1 |= 0b0101 << 2;
|
|
||||||
// Manually set the I2C pins to Alternate Function IO, CNF=10b, MODE=10b
|
|
||||||
GPIOC->CFGXR &= ~((0xF << 8) | (0xF << 12)); // first clear the bits
|
|
||||||
// then set them
|
|
||||||
GPIOC->CFGXR |= 0b1010 << 8; // PC18
|
|
||||||
GPIOC->CFGXR |= 0b1010 << 12; // PC19
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__((noreturn)) int main(void)
|
__attribute__((noreturn)) int main(void)
|
||||||
{
|
{
|
||||||
SystemInit();
|
SystemInit();
|
||||||
@ -190,7 +164,27 @@ __attribute__((noreturn)) int main(void)
|
|||||||
|
|
||||||
Delay_Ms(5000);
|
Delay_Ms(5000);
|
||||||
|
|
||||||
setup_i2c();
|
/* -------- Code to get hardware I2C working on the CH32X035F8U6 -------- */
|
||||||
|
// Order here matters, first initialize the AFIO and I2C subsystems then
|
||||||
|
// change register values, do that the other way around and the configuration
|
||||||
|
// wont take effect
|
||||||
|
// Enable AFIO (Alternate Function IO)
|
||||||
|
RCC->APB2PCENR |= RCC_AFIOEN;
|
||||||
|
// Init I2C
|
||||||
|
i2c_init(I2C_TARGET, FUNCONF_SYSTEM_CORE_CLOCK, 100000);
|
||||||
|
|
||||||
|
// To utilize the I2C bus we need to disable SWD first, since the pins overlap
|
||||||
|
AFIO->PCFR1 &= ~(0b0111 << 24);
|
||||||
|
AFIO->PCFR1 |= 0b0100 << 24;
|
||||||
|
|
||||||
|
// Map SCL to PC18 and SDA to PC19
|
||||||
|
AFIO->PCFR1 |= 0b0101 << 2;
|
||||||
|
// Manually set the I2C pins to Alternate Function IO, CNF=10b, MODE=10b
|
||||||
|
GPIOC->CFGXR &= ~((0xF << 8) | (0xF << 12)); // first clear the bits
|
||||||
|
// then set them
|
||||||
|
GPIOC->CFGXR |= 0b1010 << 8; // PC18
|
||||||
|
GPIOC->CFGXR |= 0b1010 << 12; // PC19
|
||||||
|
|
||||||
|
|
||||||
// Configure the IO as an interrupt.
|
// Configure the IO as an interrupt.
|
||||||
// PIN_ENC_B is on port B, channel 11
|
// PIN_ENC_B is on port B, channel 11
|
||||||
|
|||||||
@ -1,59 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
# Script to generate NTC lookup table
|
|
||||||
# ^ Vcc
|
|
||||||
# |
|
|
||||||
# [RES]
|
|
||||||
# |
|
|
||||||
# +-- Vadc
|
|
||||||
# |
|
|
||||||
# [NTC]
|
|
||||||
# |
|
|
||||||
# _|_ GND
|
|
||||||
# ///
|
|
||||||
|
|
||||||
adc_res = 12
|
|
||||||
ntc_value = 10_000 # at 25°C
|
|
||||||
resistor_value = 10_000
|
|
||||||
ntc_beta = 3380 # at 25°C
|
|
||||||
steps = 64
|
|
||||||
|
|
||||||
# NTC resistance to temperature (°C) conversion
|
|
||||||
def resistance_to_t(ntc_r):
|
|
||||||
# Standard B-parameter equation
|
|
||||||
# T = 1 / (1/T0 + 1/B * ln(R/R0))
|
|
||||||
inv_t = 1/(25 + 273.15) + math.log(ntc_r/ntc_value)/ntc_beta
|
|
||||||
return 1/inv_t - 273.15
|
|
||||||
|
|
||||||
# Resistor divider percentage to NTC resistance conversion
|
|
||||||
# x = NTC / (NTC + RES) => NTC = RES * x / (1 - x)
|
|
||||||
def x_to_r(x):
|
|
||||||
x = max(0.0001, min(0.9999, x))
|
|
||||||
return resistor_value * x / (1 - x)
|
|
||||||
|
|
||||||
# Use 4096 for cleaner divisions
|
|
||||||
adc_max = 2**adc_res
|
|
||||||
step_size = adc_max // steps
|
|
||||||
|
|
||||||
values = []
|
|
||||||
for i in range(steps):
|
|
||||||
adc_val = i * step_size
|
|
||||||
x = adc_val / adc_max
|
|
||||||
r = x_to_r(adc_val / adc_max)
|
|
||||||
t = resistance_to_t(r)
|
|
||||||
values.append(int(round(t)))
|
|
||||||
|
|
||||||
def to_c_array(values, ctype="float", name="table", formatter=str, colcount=8):
|
|
||||||
# apply formatting to each element
|
|
||||||
values = [formatter(v) for v in values]
|
|
||||||
# split into rows with up to `colcount` elements per row
|
|
||||||
rows = [values[i:i+colcount] for i in range(0, len(values), colcount)]
|
|
||||||
# separate elements with commas, separate rows with newlines
|
|
||||||
body = ',\n '.join([', '.join(r) for r in rows])
|
|
||||||
# assemble components into the complete string
|
|
||||||
return '{} {}[] = {{\n {}}};'.format(ctype, name, body)
|
|
||||||
|
|
||||||
print("uint8_t ntc_step_size = {};".format(int(step_size)))
|
|
||||||
print(to_c_array(values, ctype="int16_t", name="ntc_lut", formatter=str, colcount=16))
|
|
||||||
Loading…
x
Reference in New Issue
Block a user