change measurement method to resistor divider, slightly questionable and off by 10 degrees but that's probably good enough for baking bread

fake-chip
Ondřej Hruška 1 year ago
parent 84532fd339
commit f093936970
  1. 25
      BluepillTrouba.ioc
  2. 1
      Core/Inc/stm32f1xx_it.h
  3. 2
      Core/Src/adc.c
  4. 195
      Core/Src/app.c
  5. 4
      Core/Src/main.c
  6. 2
      Core/Src/stm32f1xx_hal_timebase_tim.c
  7. 15
      Core/Src/stm32f1xx_it.c
  8. 5
      Core/Src/tim.c
  9. 6
      Makefile

@ -11,10 +11,10 @@ ADC1.Rank-0\#ChannelRegularConversion=1
ADC1.Rank-1\#ChannelRegularConversion=2
ADC1.Rank-2\#ChannelRegularConversion=3
ADC1.Rank-3\#ChannelRegularConversion=4
ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_239CYCLES_5
ADC1.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_239CYCLES_5
ADC1.SamplingTime-2\#ChannelRegularConversion=ADC_SAMPLETIME_239CYCLES_5
ADC1.SamplingTime-3\#ChannelRegularConversion=ADC_SAMPLETIME_239CYCLES_5
ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_41CYCLES_5
ADC1.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_41CYCLES_5
ADC1.SamplingTime-2\#ChannelRegularConversion=ADC_SAMPLETIME_41CYCLES_5
ADC1.SamplingTime-3\#ChannelRegularConversion=ADC_SAMPLETIME_41CYCLES_5
ADC1.master=1
Dma.ADC1.0.Direction=DMA_PERIPH_TO_MEMORY
Dma.ADC1.0.Instance=DMA1_Channel1
@ -105,6 +105,7 @@ NVIC.SavedSvcallIrqHandlerGenerated=true
NVIC.SavedSystickIrqHandlerGenerated=true
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:true
NVIC.TIM1_UP_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
NVIC.TIM4_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.TimeBase=TIM1_UP_IRQn
NVIC.TimeBaseIP=TIM1
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:true
@ -207,18 +208,19 @@ ProjectManager.TargetToolchain=Makefile
ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_IWDG_Init-IWDG-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_ADC1_Init-ADC1-false-HAL-true,6-MX_SPI1_Init-SPI1-false-HAL-true,7-MX_DMA_Init-DMA-false-HAL-true,8-MX_TIM4_Init-TIM4-false-HAL-true,9-MX_TIM2_Init-TIM2-false-HAL-true
RCC.ADCFreqValue=12000000
RCC.ADCPresc=RCC_ADCPCLK2_DIV6
RCC.ADCFreqValue=2250000
RCC.ADCPresc=RCC_ADCPCLK2_DIV8
RCC.AHBFreq_Value=72000000
RCC.APB1CLKDivider=RCC_HCLK_DIV2
RCC.APB1Freq_Value=36000000
RCC.APB1TimFreq_Value=72000000
RCC.APB2Freq_Value=72000000
RCC.APB2TimFreq_Value=72000000
RCC.APB2CLKDivider=RCC_HCLK_DIV4
RCC.APB2Freq_Value=18000000
RCC.APB2TimFreq_Value=36000000
RCC.FCLKCortexFreq_Value=72000000
RCC.FamilyName=M
RCC.HCLKFreq_Value=72000000
RCC.IPParameters=ADCFreqValue,ADCPresc,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,PLLSourceVirtual,RTCClockSelection,RTCFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value,VCOOutput2Freq_Value
RCC.IPParameters=ADCFreqValue,ADCPresc,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,PLLSourceVirtual,RTCClockSelection,RTCFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value,VCOOutput2Freq_Value
RCC.MCOFreq_Value=72000000
RCC.PLLCLKFreq_Value=72000000
RCC.PLLMCOFreq_Value=36000000
@ -242,7 +244,7 @@ SH.S_TIM4_CH1.ConfNb=1
SH.S_TIM4_CH2.0=TIM4_CH2,Encoder_Interface
SH.S_TIM4_CH2.ConfNb=1
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_8
SPI1.CalculateBaudRate=9.0 MBits/s
SPI1.CalculateBaudRate=2.25 MBits/s
SPI1.Direction=SPI_DIRECTION_2LINES
SPI1.IPParameters=VirtualType,Mode,Direction,BaudRatePrescaler,CalculateBaudRate
SPI1.Mode=SPI_MODE_MASTER
@ -251,7 +253,8 @@ TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM2.IPParameters=Channel-PWM Generation1 CH1,Prescaler
TIM2.Prescaler=2
TIM4.IC2Filter=15
TIM4.IPParameters=IC2Filter
TIM4.IPParameters=IC2Filter,Prescaler
TIM4.Prescaler=0
USART1.IPParameters=VirtualMode,Mode
USART1.Mode=MODE_TX_RX
USART1.VirtualMode=VM_ASYNC

@ -54,6 +54,7 @@ void UsageFault_Handler(void);
void DebugMon_Handler(void);
void DMA1_Channel1_IRQHandler(void);
void TIM1_UP_IRQHandler(void);
void TIM4_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

@ -59,7 +59,7 @@ void MX_ADC1_Init(void)
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();

@ -15,22 +15,27 @@
#include "tim.h"
#include "adc.h"
#include "oled.h"
#include "ufb/fb_text.h"
// TODO averaging
/* DMA dest */
static volatile uint16_t adc_values[4];
static volatile uint16_t adc_values_snapshot[4];
const float r_current_sensor = 98.2f; // Ohm TODO measure
const float V_REFINT = 1.23f;
#define AVERAGEBUF_DEPTH 32
static struct App {
float oven_temp;
float soc_temp;
float v_sensor;
float v_current_reference;
float sensor_current;
float r_sensor;
// float v_current_reference;
// float sensor_current;
// float r_sensor;
uint16_t wheel;
bool push;
uint16_t adc_averagebuf[AVERAGEBUF_DEPTH * 4];
uint8_t averagebuf_ptr;
float adc_averages[4];
} s_app = {};
#define TSENSE_LOOKUP_LEN 101
@ -38,25 +43,117 @@ static struct App {
#define TSENSE_T_MIN 0.0f
#define TSENSE_T_MAX 500.0f
static const float TSENSE_LOOKUP[TSENSE_LOOKUP_LEN] = {
100.0f, 101.9527f, 103.9025f, 105.8495f, 107.7935f, 109.7347f, 111.6729f, 113.6083f, 115.5408f, 117.4704f, 119.3971f, 121.321f,
123.2419f, 125.16f, 127.0751f, 128.9874f, 130.8968f, 132.8033f, 134.7069f, 136.6077f, 138.5055f, 140.4005f, 142.2925f, 144.1817f,
146.068f, 147.9514f, 149.8319f, 151.7096f, 153.5843f, 155.4562f, 157.3251f, 159.1912f, 161.0544f, 162.9147f, 164.7721f, 166.6267f,
168.4783f, 170.3271f, 172.1729f, 174.0159f, 175.856f, 177.6932f, 179.5275f, 181.359f, 183.1875f, 185.0132f, 186.8359f, 188.6558f,
190.4728f, 192.2869f, 194.0981f, 195.9065f, 197.7119f, 199.5145f, 201.3141f, 203.1109f, 204.9048f, 206.6958f, 208.4839f, 210.2692f,
212.0515f, 213.831f, 215.6075f, 217.3812f, 219.152f, 220.9199f, 222.6849f, 224.4471f, 226.2063f, 227.9627f, 229.7161f, 231.4667f,
233.2144f, 234.9592f, 236.7011f, 238.4402f, 240.1763f, 241.9096f, 243.6399f, 245.3674f, 247.092f, 248.8137f, 250.5325f, 252.2485f,
253.9615f, 255.6717f, 257.3789f, 259.0833f, 260.7848f, 262.4834f, 264.1791f, 265.872f, 267.5619f, 269.249f, 270.9331f, 272.6144f,
274.2928f, 275.9683f, 277.6409f, 279.3107f, 280.9775f
0.092678405931418f,
0.0943174479327356f,
0.095948157844312f,
0.0975706768542549f,
0.0991848957506647f,
0.100791037522732f,
0.102388993070241f,
0.103978983136042f,
0.105560980458654f,
0.107135039851509f,
0.108701215616829f,
0.110259642413441f,
0.111810211533421f,
0.113353137226489f,
0.114888310929339f,
0.11641594480226f,
0.117936009906507f,
0.119448557132363f,
0.120953636903929f,
0.122451377845456f,
0.12394167187544f,
0.125424725109556f,
0.126900429638119f,
0.128368989630084f,
0.129830374697352f,
0.131284632150064f,
0.132731808872517f,
0.134172027901771f,
0.135605181883591f,
0.13703146935069f,
0.138450783142958f,
0.139863319976468f,
0.14126904821384f,
0.142668011892657f,
0.144060254660872f,
0.145445894373796f,
0.146824824486877f,
0.14819723645253f,
0.149563023938454f,
0.150922376699229f,
0.15227526202401f,
0.153621720954182f,
0.15496179417407f,
0.156295594725426f,
0.157623016940038f,
0.158944245649448f,
0.160259175412251f,
0.16156798947087f,
0.162870654195634f,
0.164167207880495f,
0.165457688491696f,
0.166742204592451f,
0.168020651444079f,
0.169293207677971f,
0.170559768793747f,
0.171820511933356f,
0.173075402684405f,
0.174324476817747f,
0.175567769803026f,
0.176805386030345f,
0.178037221732226f,
0.179263449725904f,
0.180483966491086f,
0.181698943447122f,
0.182908345518766f,
0.184112206156428f,
0.185310558533273f,
0.186503503145257f,
0.187690937227925f,
0.188873028139146f,
0.190049673368296f,
0.191221038959601f,
0.192387089280576f,
0.193547855644572f,
0.194703369109397f,
0.195853726532112f,
0.196998826174689f,
0.19813883026229f,
0.199273637315452f,
0.200403408323351f,
0.201528107189346f,
0.20264776325594f,
0.203762405629782f,
0.204872127762998f,
0.205976828960191f,
0.207076666615101f,
0.208171540293999f,
0.209261606226334f,
0.210346827933364f,
0.211427232937629f,
0.212502848543705f,
0.213573765013592f,
0.214639882704581f,
0.215701354457324f,
0.216758080892489f,
0.217810213752734f,
0.218857716249547f,
0.219900614222686f,
0.220938933310224f,
0.221972760781578f,
0.223001998051553f,
};
static float r_to_c(float r){
static float val_to_c(float val){
// TODO use binary search.. lol
for (int i = 1; i < TSENSE_LOOKUP_LEN; i++) {
float cur = TSENSE_LOOKUP[i];
if (cur >= r) {
if (cur >= val) {
float prev = TSENSE_LOOKUP[i-1];
float ratio = (r - prev) / (cur - prev);
float ratio = (val - prev) / (cur - prev);
return TSENSE_T_MIN + ((float) i + ratio) * TSENSE_T_STEP;
}
}
@ -64,32 +161,45 @@ static float r_to_c(float r){
}
void calculate_analog_values() {
uint32_t sums[4] = {};
for (int i = 0; i < AVERAGEBUF_DEPTH * 4; i += 4) {
sums[0] += s_app.adc_averagebuf[i];
sums[1] += s_app.adc_averagebuf[i + 1];
sums[2] += s_app.adc_averagebuf[i + 2];
sums[3] += s_app.adc_averagebuf[i + 3];
}
s_app.adc_averages[0] = (float)sums[0] / AVERAGEBUF_DEPTH;
s_app.adc_averages[1] = (float)sums[1] / AVERAGEBUF_DEPTH;
s_app.adc_averages[2] = (float)sums[2] / AVERAGEBUF_DEPTH;
s_app.adc_averages[3] = (float)sums[3] / AVERAGEBUF_DEPTH;
/* r_pt100, r_ref, internal_temp, v_ref_int */
uint16_t refint = adc_values_snapshot[3];
const float vrefint = 1.2f;
float scale = vrefint / (float)refint;
float refint = s_app.adc_averages[3];
float scale = V_REFINT / refint;
const float avg_slope = 4.3f;
const float avg_slope = 4.3f * scale;
const float v25 = 1.43f;
const float v_tsen = (float) adc_values_snapshot[2] * scale;
const float v_tsen = s_app.adc_averages[2] * scale;
s_app.soc_temp = (v25 - v_tsen) / avg_slope + 25.f;
s_app.v_sensor = (float)adc_values_snapshot[0] * scale;
s_app.v_current_reference = (float)(adc_values_snapshot[1] - adc_values_snapshot[0]) * scale;
s_app.v_sensor = s_app.adc_averages[0] * scale; // good for debug/tuning
s_app.sensor_current = s_app.v_current_reference / r_current_sensor;
s_app.r_sensor = s_app.v_sensor / s_app.sensor_current;
s_app.oven_temp = r_to_c(s_app.r_sensor);
// using a voltage divider, so assuming the reference resistor is measured well,
// we can just use the ratio and the exact voltage value is not important.
s_app.oven_temp = val_to_c(s_app.adc_averages[0] / s_app.adc_averages[1]);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
// notify
memcpy((void*) adc_values_snapshot, (const void*) adc_values, 8);
memcpy((void*) &s_app.adc_averagebuf[s_app.averagebuf_ptr * 4], (const void*) adc_values, 8);
s_app.averagebuf_ptr = (s_app.averagebuf_ptr + 1) % AVERAGEBUF_DEPTH;
}
static void hw_init()
{
HAL_ADCEx_Calibration_Start(&hadc1);
/* Start periodic reading of the ADC channels */
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)(void*)adc_values, 4);
@ -119,17 +229,14 @@ void app_main_task(void *argument)
calculate_analog_values();
printf("Knob %d (P=%d), ADC %d %d %d %d, oven %.2f°C, soc %.2f°C, vPt %.3fV, v_iref %.3f, I %.6fA, rPt %.2f Ohm \r\n",
(int) s_app.wheel, s_app.push,
adc_values[0], adc_values[1], adc_values[2], adc_values[3],
s_app.oven_temp,
s_app.soc_temp,
s_app.v_sensor,
s_app.v_current_reference,
s_app.sensor_current,
s_app.r_sensor
);
// printf("Knob %d (P=%d), ADC %.2f %.2f %.2f %.2f, oven %.2f°C, soc %.2f°C, divider %.3f V \r\n",
// (int) s_app.wheel, s_app.push,
// s_app.adc_averages[0], s_app.adc_averages[1], s_app.adc_averages[2], s_app.adc_averages[3],
//
// s_app.oven_temp,
// s_app.soc_temp,
// s_app.v_sensor
// );
invert = !invert;
@ -143,9 +250,15 @@ void app_main_task(void *argument)
fb_frame(s_app.wheel % FBW, 0, 15, 15, 1, 1);
}
}
char tmp[100];
sprintf(tmp, "%d°C", (int) s_app.oven_temp);
fb_text(0, 20, tmp, 0, 1);
fb_blit();
vTaskDelay(250);
vTaskDelay(100);
// beep
htim2.Instance->ARR = 12000 + (int16_t)s_app.wheel * 100;

@ -163,7 +163,7 @@ void SystemClock_Config(void)
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
@ -171,7 +171,7 @@ void SystemClock_Config(void)
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV8;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();

@ -57,7 +57,7 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Compute TIM1 clock */
uwTimclock = HAL_RCC_GetPCLK2Freq();
uwTimclock = 2*HAL_RCC_GetPCLK2Freq();
/* Compute the prescaler value to have TIM1 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);

@ -57,6 +57,7 @@
/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_adc1;
extern TIM_HandleTypeDef htim4;
extern TIM_HandleTypeDef htim1;
/* USER CODE BEGIN EV */
@ -190,6 +191,20 @@ void TIM1_UP_IRQHandler(void)
/* USER CODE END TIM1_UP_IRQn 1 */
}
/**
* @brief This function handles TIM4 global interrupt.
*/
void TIM4_IRQHandler(void)
{
/* USER CODE BEGIN TIM4_IRQn 0 */
/* USER CODE END TIM4_IRQn 0 */
HAL_TIM_IRQHandler(&htim4);
/* USER CODE BEGIN TIM4_IRQn 1 */
/* USER CODE END TIM4_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

@ -164,6 +164,9 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* TIM4 interrupt Init */
HAL_NVIC_SetPriority(TIM4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(TIM4_IRQn);
/* USER CODE BEGIN TIM4_MspInit 1 */
/* USER CODE END TIM4_MspInit 1 */
@ -230,6 +233,8 @@ void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* tim_encoderHandle)
*/
HAL_GPIO_DeInit(GPIOB, KNOB_B_Pin|KNOB_A_Pin);
/* TIM4 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM4_IRQn);
/* USER CODE BEGIN TIM4_MspDeInit 1 */
/* USER CODE END TIM4_MspDeInit 1 */

@ -1,5 +1,5 @@
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Wed Feb 22 23:22:04 CET 2023]
# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Thu Feb 23 00:46:03 CET 2023]
##########################################################################################################################
# ------------------------------------------------
@ -174,8 +174,8 @@ LDSCRIPT = STM32F103CBTx_FLASH.ld
# libraries
LIBS = -lc -lm -lnosys
LIBDIR =
LDFLAGS = $(MCU) -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
# -specs=nano.specs
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
#
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin

Loading…
Cancel
Save