Add preliminary safety ADC which measures the Controller temperature and checks the reference voltage against the STM's internal reference voltage
This commit is contained in:
parent
dc8beefb63
commit
e97092042b
@ -46,6 +46,7 @@ CFILES += ui/lcd.c ui/menu.c
|
|||||||
CFILES += fatfs/diskio.c fatfs/ff.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c
|
CFILES += fatfs/diskio.c fatfs/ff.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c
|
||||||
CFILES += pid-controller.c oven-driver.c
|
CFILES += pid-controller.c oven-driver.c
|
||||||
CFILES += settings/settings.c settings/settings-sd-card.c
|
CFILES += settings/settings.c settings/settings-sd-card.c
|
||||||
|
CFILES += safety-adc.c
|
||||||
|
|
||||||
DEFINES += -DDEBUGBUILD
|
DEFINES += -DDEBUGBUILD
|
||||||
|
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
/* Reflow Oven Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of the Reflow Oven Controller Project.
|
||||||
|
*
|
||||||
|
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with the reflow oven controller project.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SAFETY_ADC_HWCFG_H__
|
||||||
|
#define __SAFETY_ADC_HWCFG_H__
|
||||||
|
|
||||||
|
#include <stm32/stm32f4xx.h>
|
||||||
|
|
||||||
|
#define SAFETY_ADC_ADC_PERIPHERAL ADC1
|
||||||
|
#define SAFETY_ADC_ADC_RCC_MASK RCC_APB2ENR_ADC1EN
|
||||||
|
#define TEMP_CHANNEL_NUM (16)
|
||||||
|
#define INT_REF_CHANNEL_NUM (17)
|
||||||
|
|
||||||
|
#endif /* __SAFETY_ADC_HWCFG_H__ */
|
64
stm-firmware/include/reflow-controller/safety-adc.h
Normal file
64
stm-firmware/include/reflow-controller/safety-adc.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* Reflow Oven Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of the Reflow Oven Controller Project.
|
||||||
|
*
|
||||||
|
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with the reflow oven controller project.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SAFETY_ADC_H__
|
||||||
|
#define __SAFETY_ADC_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define SAFETY_ADC_FRAC_BITS (8)
|
||||||
|
#define SAFETY_ADC_VREF_VOLT (2.5)
|
||||||
|
#define SAFETY_ADC_VREF_TOL (0.25)
|
||||||
|
#define SAFETY_ADC_VREF_INT ()
|
||||||
|
|
||||||
|
|
||||||
|
enum safety_adc_meas_channel {SAFETY_ADC_MEAS_VREF, SAFETY_ADC_MEAS_TEMP};
|
||||||
|
enum safety_adc_check_result {
|
||||||
|
SAFETY_ADC_CHECK_OK = 0UL,
|
||||||
|
SAFETY_ADC_CHECK_VREF_LOW = (1U<<0),
|
||||||
|
SAFETY_ADC_CHECK_VREF_HIGH = (1U<<1),
|
||||||
|
SAFETY_ADC_CHECK_TEMP_LOW = (1U<<2),
|
||||||
|
SAFETY_ADC_CHECK_TEMP_HIGH = (1U<<3),
|
||||||
|
};
|
||||||
|
|
||||||
|
void safety_adc_init();
|
||||||
|
|
||||||
|
void safety_adc_deinit();
|
||||||
|
|
||||||
|
void safety_adc_trigger_meas(enum safety_adc_meas_channel measurement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Poll ADC result.
|
||||||
|
* @param results adc results
|
||||||
|
* @return 1 if measurement successful, 0 if not ready, -1 if ADC aborted or not started
|
||||||
|
*/
|
||||||
|
int safety_adc_poll_result(uint16_t *adc_result);
|
||||||
|
|
||||||
|
enum safety_adc_check_result safety_adc_check_results(uint16_t vref_result, uint16_t temp_result,
|
||||||
|
float *vref_calculated, float *temp_calculated);
|
||||||
|
|
||||||
|
enum safety_adc_check_result handle_safety_adc();
|
||||||
|
|
||||||
|
float safety_adc_get_temp();
|
||||||
|
|
||||||
|
float safety_adc_get_vref();
|
||||||
|
|
||||||
|
#endif /* __SAFETY_ADC_H__ */
|
@ -47,6 +47,7 @@
|
|||||||
#include <helper-macros/helper-macros.h>
|
#include <helper-macros/helper-macros.h>
|
||||||
#include <reflow-controller/button.h>
|
#include <reflow-controller/button.h>
|
||||||
#include <reflow-controller/oven-driver.h>
|
#include <reflow-controller/oven-driver.h>
|
||||||
|
#include <reflow-controller/safety-adc.h>
|
||||||
#include <fatfs/ff.h>
|
#include <fatfs/ff.h>
|
||||||
|
|
||||||
static void setup_nvic_priorities()
|
static void setup_nvic_priorities()
|
||||||
@ -142,12 +143,10 @@ static bool mount_sd_card_if_avail(bool mounted)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t handle_pid_controller(struct pid_controller *pid, float target_temperature,
|
static inline int32_t handle_pid_controller(struct pid_controller *pid, float target_temperature,
|
||||||
float current_pt1000_resistance)
|
float current_temperature)
|
||||||
{
|
{
|
||||||
float current_temperature;
|
|
||||||
int32_t pid_out;
|
int32_t pid_out;
|
||||||
|
|
||||||
(void)temp_converter_convert_resistance_to_temp(current_pt1000_resistance, (float *)¤t_temperature);
|
|
||||||
pid_out = (int32_t)pid_sample(pid, target_temperature - current_temperature);
|
pid_out = (int32_t)pid_sample(pid, target_temperature - current_temperature);
|
||||||
|
|
||||||
/* Blink green LED */
|
/* Blink green LED */
|
||||||
@ -179,6 +178,7 @@ static inline void setup_system()
|
|||||||
rotary_encoder_setup();
|
rotary_encoder_setup();
|
||||||
button_init();
|
button_init();
|
||||||
lcd_init();
|
lcd_init();
|
||||||
|
safety_adc_init();
|
||||||
|
|
||||||
uart_gpio_config();
|
uart_gpio_config();
|
||||||
setup_sell_uart(&shell_uart);
|
setup_sell_uart(&shell_uart);
|
||||||
@ -198,6 +198,8 @@ static void handle_shell_uart_input(shellmatta_handle_t shell_handle)
|
|||||||
shell_handle_input(shell_handle, uart_input, uart_input_len);
|
shell_handle_input(shell_handle, uart_input, uart_input_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
bool sd_card_mounted = false;
|
bool sd_card_mounted = false;
|
||||||
@ -209,6 +211,8 @@ int main()
|
|||||||
uint64_t display_timestamp = 0ULL;
|
uint64_t display_timestamp = 0ULL;
|
||||||
char disp[4][21] = {0};
|
char disp[4][21] = {0};
|
||||||
enum lcd_fsm_ret lcd_ret = LCD_FSM_NOP;
|
enum lcd_fsm_ret lcd_ret = LCD_FSM_NOP;
|
||||||
|
int temp_status;
|
||||||
|
float current_temp;
|
||||||
|
|
||||||
target_temperature = 25.0f;
|
target_temperature = 25.0f;
|
||||||
|
|
||||||
@ -228,15 +232,25 @@ int main()
|
|||||||
pt1000_value_status = adc_pt1000_get_current_resistance(&pt1000_value);
|
pt1000_value_status = adc_pt1000_get_current_resistance(&pt1000_value);
|
||||||
|
|
||||||
if (systick_ticks_have_passed(pid_timestamp, 250)) {
|
if (systick_ticks_have_passed(pid_timestamp, 250)) {
|
||||||
|
|
||||||
|
(void)handle_safety_adc();
|
||||||
|
|
||||||
pid_timestamp = systick_get_global_tick();
|
pid_timestamp = systick_get_global_tick();
|
||||||
|
|
||||||
|
temp_status = temp_converter_convert_resistance_to_temp(pt1000_value,
|
||||||
|
¤t_temp);
|
||||||
|
|
||||||
if (pt1000_value_status >= 0 && pid_controller_active)
|
if (pt1000_value_status >= 0 && pid_controller_active)
|
||||||
pid_controller_output = handle_pid_controller(&pid, target_temperature, pt1000_value);
|
pid_controller_output = handle_pid_controller(&pid, target_temperature, current_temp);
|
||||||
|
|
||||||
/* Blink red led in case of temp error */
|
/* Blink red led in case of temp error */
|
||||||
if (pt1000_value_status < 0)
|
if (pt1000_value_status < 0)
|
||||||
led_set(0, !led_get(0));
|
led_set(0, !led_get(0));
|
||||||
else
|
else
|
||||||
led_set(0, 0);
|
led_set(0, 0);
|
||||||
|
|
||||||
|
snprintf(&disp[3][0], 17, "Temp: %s%.1f C", (temp_status == 0 ? "" : temp_status < 0 ? "<" : ">")
|
||||||
|
, current_temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle error in case PID controller should be active, but temperature measurement failed */
|
/* Handle error in case PID controller should be active, but temperature measurement failed */
|
||||||
|
153
stm-firmware/safety-adc.c
Normal file
153
stm-firmware/safety-adc.c
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/* Reflow Oven Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
|
||||||
|
*
|
||||||
|
* This file is part of the Reflow Oven Controller Project.
|
||||||
|
*
|
||||||
|
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with the reflow oven controller project.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <reflow-controller/safety-adc.h>
|
||||||
|
#include <reflow-controller/periph-config/safety-adc-hwcfg.h>
|
||||||
|
|
||||||
|
#include <stm-periph/clock-enable-manager.h>
|
||||||
|
|
||||||
|
void safety_adc_init()
|
||||||
|
{
|
||||||
|
rcc_manager_enable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(SAFETY_ADC_ADC_RCC_MASK));
|
||||||
|
|
||||||
|
/* Enable temperature and VREFINT measurement */
|
||||||
|
ADC->CCR |= ADC_CCR_TSVREFE;
|
||||||
|
|
||||||
|
/* Set sample time for channels 16 and 17 */
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->SMPR1 |= ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16;
|
||||||
|
|
||||||
|
/* Standard sequence. One measurement */
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->SQR1 = 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void safety_adc_deinit()
|
||||||
|
{
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->CR1 = 0UL;
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->CR2 = 0UL;
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->SMPR1 = 0UL;
|
||||||
|
rcc_manager_enable_clock(&RCC->APB1ENR, BITMASK_TO_BITNO(RCC_APB2ENR_ADC2EN));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum safety_adc_check_result safety_adc_check_results(uint16_t vref_result, uint16_t temp_result,
|
||||||
|
float *vref_calculated, float *temp_calculated)
|
||||||
|
{
|
||||||
|
enum safety_adc_check_result res = SAFETY_ADC_CHECK_OK;
|
||||||
|
|
||||||
|
|
||||||
|
if (vref_calculated) {
|
||||||
|
*vref_calculated = (1210.0 * 4095) / (float)vref_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp_calculated) {
|
||||||
|
*temp_calculated = (((float)temp_result / 4095.0f * 2500.0f - 760.0f) / 2.5f) + 25.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int safety_adc_poll_result(uint16_t *adc_result)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!adc_result)
|
||||||
|
return -1000;
|
||||||
|
|
||||||
|
if (!(SAFETY_ADC_ADC_PERIPHERAL->CR2 & ADC_CR2_ADON)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SAFETY_ADC_ADC_PERIPHERAL->SR & ADC_SR_EOC) {
|
||||||
|
*adc_result = (uint16_t)SAFETY_ADC_ADC_PERIPHERAL->DR;
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->CR2 &= ~ADC_CR2_ADON;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void safety_adc_trigger_meas(enum safety_adc_meas_channel measurement)
|
||||||
|
{
|
||||||
|
switch (measurement) {
|
||||||
|
case SAFETY_ADC_MEAS_TEMP:
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->SQR3 = TEMP_CHANNEL_NUM;
|
||||||
|
break;
|
||||||
|
case SAFETY_ADC_MEAS_VREF:
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->SQR3 = INT_REF_CHANNEL_NUM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->CR2 |= ADC_CR2_ADON;
|
||||||
|
SAFETY_ADC_ADC_PERIPHERAL->CR2 |= ADC_CR2_SWSTART;
|
||||||
|
}
|
||||||
|
|
||||||
|
static volatile uint16_t safety_vref_meas_raw;
|
||||||
|
static volatile bool safety_vref_valid = false;
|
||||||
|
static volatile uint16_t safety_temp_meas_raw;
|
||||||
|
static volatile bool safety_temp_valid = false;
|
||||||
|
static float safety_vref;
|
||||||
|
static float safety_temp;
|
||||||
|
|
||||||
|
enum safety_adc_check_result handle_safety_adc()
|
||||||
|
{
|
||||||
|
static enum safety_adc_meas_channel safety_meas_channel = SAFETY_ADC_MEAS_VREF;
|
||||||
|
uint16_t result;
|
||||||
|
int poll_status;
|
||||||
|
|
||||||
|
poll_status = safety_adc_poll_result(&result);
|
||||||
|
|
||||||
|
if (poll_status < 0) {
|
||||||
|
safety_adc_trigger_meas(safety_meas_channel);
|
||||||
|
} else if (poll_status > 0) {
|
||||||
|
switch (safety_meas_channel) {
|
||||||
|
case SAFETY_ADC_MEAS_TEMP:
|
||||||
|
safety_temp_meas_raw = result;
|
||||||
|
safety_temp_valid = true;
|
||||||
|
safety_meas_channel = SAFETY_ADC_MEAS_VREF;
|
||||||
|
break;
|
||||||
|
case SAFETY_ADC_MEAS_VREF:
|
||||||
|
safety_vref_meas_raw = result;
|
||||||
|
safety_vref_valid = true;
|
||||||
|
safety_meas_channel = SAFETY_ADC_MEAS_TEMP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
safety_meas_channel = SAFETY_ADC_MEAS_VREF;
|
||||||
|
return -2000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safety_temp_valid && safety_vref_valid) {
|
||||||
|
return safety_adc_check_results(safety_vref_meas_raw, safety_temp_meas_raw, &safety_vref, &safety_temp);
|
||||||
|
} else {
|
||||||
|
return SAFETY_ADC_CHECK_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float safety_adc_get_temp()
|
||||||
|
{
|
||||||
|
return safety_temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
float safety_adc_get_vref()
|
||||||
|
{
|
||||||
|
return safety_vref;
|
||||||
|
}
|
@ -35,6 +35,7 @@
|
|||||||
#include <fatfs/ff.h>
|
#include <fatfs/ff.h>
|
||||||
#include <reflow-controller/stack-check.h>
|
#include <reflow-controller/stack-check.h>
|
||||||
#include <reflow-controller/rotary-encoder.h>
|
#include <reflow-controller/rotary-encoder.h>
|
||||||
|
#include <reflow-controller/safety-adc.h>
|
||||||
|
|
||||||
#ifndef GIT_VER
|
#ifndef GIT_VER
|
||||||
#define GIT_VER "VERSION NOT SET"
|
#define GIT_VER "VERSION NOT SET"
|
||||||
@ -342,6 +343,18 @@ static shellmatta_retCode_t shell_cmd_cat(const shellmatta_handle_t handle, cons
|
|||||||
return SHELLMATTA_OK;
|
return SHELLMATTA_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static shellmatta_retCode_t shell_cmd_safety_adc(const shellmatta_handle_t handle, const char *arguments,
|
||||||
|
uint32_t length)
|
||||||
|
{
|
||||||
|
(void)length;
|
||||||
|
(void)arguments;
|
||||||
|
|
||||||
|
shellmatta_printf(handle, "VREF:\t%8.2f\tmV\r\n", safety_adc_get_vref());
|
||||||
|
shellmatta_printf(handle, "TEMP:\t%8.2f\tdeg. Celsius\r\n", safety_adc_get_temp());
|
||||||
|
|
||||||
|
return SHELLMATTA_OK;
|
||||||
|
}
|
||||||
|
|
||||||
//typedef struct shellmatta_cmd
|
//typedef struct shellmatta_cmd
|
||||||
//{
|
//{
|
||||||
// char *cmd; /**< command name */
|
// char *cmd; /**< command name */
|
||||||
@ -352,7 +365,7 @@ static shellmatta_retCode_t shell_cmd_cat(const shellmatta_handle_t handle, cons
|
|||||||
// struct shellmatta_cmd *next; /**< pointer to next command or NULL */
|
// struct shellmatta_cmd *next; /**< pointer to next command or NULL */
|
||||||
//} shellmatta_cmd_t;
|
//} shellmatta_cmd_t;
|
||||||
|
|
||||||
static shellmatta_cmd_t cmd[13] = {
|
static shellmatta_cmd_t cmd[14] = {
|
||||||
{
|
{
|
||||||
.cmd = "version",
|
.cmd = "version",
|
||||||
.cmdAlias = "ver",
|
.cmdAlias = "ver",
|
||||||
@ -455,8 +468,16 @@ static shellmatta_cmd_t cmd[13] = {
|
|||||||
.helpText = "Print file contents",
|
.helpText = "Print file contents",
|
||||||
.usageText = "cat <path>",
|
.usageText = "cat <path>",
|
||||||
.cmdFct = shell_cmd_cat,
|
.cmdFct = shell_cmd_cat,
|
||||||
|
.next = &cmd[13],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.cmd = "safety-adc",
|
||||||
|
.cmdAlias = NULL,
|
||||||
|
.helpText = "",
|
||||||
|
.usageText = "",
|
||||||
|
.cmdFct = shell_cmd_safety_adc,
|
||||||
.next = NULL,
|
.next = NULL,
|
||||||
}
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user