/** * Main task */ #include #include #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "app.h" #include "ufb/framebuffer.h" #include "iwdg.h" #include "tim.h" #include "adc.h" #include "oled.h" // TODO averaging 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 static struct App { float oven_temp; float soc_temp; float v_sensor; float v_current_reference; float sensor_current; float r_sensor; uint16_t wheel; bool push; } s_app = {}; #define TSENSE_LOOKUP_LEN 101 #define TSENSE_T_STEP 5.0f #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 }; static float r_to_c(float r){ // TODO use binary search.. lol for (int i = 1; i < TSENSE_LOOKUP_LEN; i++) { float cur = TSENSE_LOOKUP[i]; if (cur >= r) { float prev = TSENSE_LOOKUP[i-1]; float ratio = (r - prev) / (cur - prev); return TSENSE_T_MIN + ((float) i + ratio) * TSENSE_T_STEP; } } return TSENSE_T_MAX; } void calculate_analog_values() { /* 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; const float avg_slope = 4.3f; const float v25 = 1.43f; const float v_tsen = (float) adc_values_snapshot[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.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); } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { // notify memcpy((void*) adc_values_snapshot, (const void*) adc_values, 8); } static void hw_init() { /* Start periodic reading of the ADC channels */ HAL_ADC_Start_DMA(&hadc1, (uint32_t*)(void*)adc_values, 4); /* Enable the rotary encoder */ HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL); /* Enable buzzer PWM */ HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); /* Prepare the framebuffer and OLED interface */ oled_init(); fb_clear(); } void app_main_task(void *argument) { hw_init(); /* Infinite loop */ bool invert = 0; for(;;) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); s_app.wheel = htim4.Instance->CNT; s_app.push = 0 == HAL_GPIO_ReadPin(KNOB_PUSH_GPIO_Port, KNOB_PUSH_Pin); 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 ); invert = !invert; fb_clear(); if (s_app.push) { fb_rect(s_app.wheel % FBW, 0, 15, 15, 1); } else { if (invert) { fb_frame(s_app.wheel % FBW, 0, 15, 15, 2, 1); } else { fb_frame(s_app.wheel % FBW, 0, 15, 15, 1, 1); } } fb_blit(); vTaskDelay(250); // beep htim2.Instance->ARR = 12000 + (int16_t)s_app.wheel * 100; htim2.Instance->CCR1 = htim2.Instance->ARR/2; vTaskDelay(50); htim2.Instance->ARR = 0; // feed dogs HAL_IWDG_Refresh(&hiwdg); } }