Add temperature profile executer and add shell command
This commit is contained in:
parent
1b4eba1871
commit
1ecd5edd93
@ -51,6 +51,8 @@ CFILES += safety/safety-adc.c safety/safety-controller.c safety/watchdog.c safet
|
||||
CFILES += hw-version-detect.c
|
||||
CFILES += config-parser/config-parser.c config-parser/temp-profile-parser.c
|
||||
CFILES += updater/updater.c
|
||||
CFILES += temp-profile-executer.c
|
||||
|
||||
INCLUDEPATH += -Iconfig-parser/include
|
||||
|
||||
CFILES += base64-lib/src/base64-lib.c
|
||||
|
@ -108,27 +108,37 @@ static int parse_line(char *line, struct pl_command *cmd)
|
||||
const char * const delim = " \t";
|
||||
const struct pl_command_list_map *map;
|
||||
char *endptr;
|
||||
struct pl_command c;
|
||||
|
||||
if (!line || !cmd)
|
||||
return -1000;
|
||||
|
||||
token = strtok(line, delim);
|
||||
|
||||
if (!token) {
|
||||
/* Empty line or command line */
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (token && token_idx <= PROFILE_LANG_MAX_NUM_ARGS) {
|
||||
switch (token_idx) {
|
||||
case 0:
|
||||
map = string_to_command(token);
|
||||
cmd->cmd = map->command;
|
||||
c.cmd = map->command;
|
||||
break;
|
||||
default:
|
||||
if (!map) {
|
||||
/* No valid command found */
|
||||
return -1;
|
||||
}
|
||||
cmd->params[token_idx - 1] = strtof(token, &endptr);
|
||||
c.params[token_idx - 1] = strtof(token, &endptr);
|
||||
if (endptr == token) {
|
||||
/* Invalid parameter */
|
||||
return -2;
|
||||
}
|
||||
if (token_idx > map->expected_param_count)
|
||||
return -3;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -136,6 +146,12 @@ static int parse_line(char *line, struct pl_command *cmd)
|
||||
token_idx++;
|
||||
}
|
||||
|
||||
if (token_idx - 1 < map->expected_param_count) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
memcpy(cmd, &c, sizeof(struct pl_command));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -180,12 +196,14 @@ enum pl_ret_val temp_profile_parse_from_file(const char *filename,
|
||||
|
||||
/* Parse the line */
|
||||
res = parse_line(workbuff, &cmd_list[cmd_idx]);
|
||||
if (res) {
|
||||
if (res < 0) {
|
||||
ret = PL_RET_SCRIPT_ERR;
|
||||
goto exit_close;
|
||||
} else if (res == 0) {
|
||||
cmd_idx++;
|
||||
*cmds_parsed= cmd_idx;
|
||||
}
|
||||
cmd_idx++;
|
||||
*cmds_parsed= cmd_idx;
|
||||
|
||||
|
||||
} while (!f_eof(&script_file));
|
||||
|
||||
|
@ -35,8 +35,6 @@ void oven_driver_set_power(uint8_t power);
|
||||
|
||||
void oven_driver_disable(void);
|
||||
|
||||
void oven_pid_ack_errors(void);
|
||||
|
||||
void oven_pid_init(struct pid_controller *controller_to_copy);
|
||||
|
||||
void oven_pid_handle(void);
|
||||
|
@ -0,0 +1,52 @@
|
||||
/* Reflow Oven Controller
|
||||
*
|
||||
* Copyright (C) 2021 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 __TEMP_PROFILE_EXECUTER_H__
|
||||
#define __TEMP_PROFILE_EXECUTER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <reflow-controller/config-parser/temp-profile-parser.h>
|
||||
|
||||
#define MAX_PROFILE_LENGTH 50
|
||||
|
||||
enum tpe_status {
|
||||
TPE_OFF,
|
||||
TPE_RUNNING,
|
||||
TPE_ABORT,
|
||||
};
|
||||
|
||||
struct tpe_current_state {
|
||||
enum tpe_status status;
|
||||
float setpoint;
|
||||
uint64_t start_timestamp;
|
||||
uint32_t step;
|
||||
uint32_t profile_steps;
|
||||
enum pl_command_type current_command;
|
||||
};
|
||||
|
||||
enum pl_ret_val temp_profile_executer_start(const char *filename);
|
||||
|
||||
int temp_profile_executer_handle(void);
|
||||
|
||||
const struct tpe_current_state *temp_profile_executer_status(void);
|
||||
|
||||
int temp_profile_executer_stop(void);
|
||||
|
||||
#endif /* __TEMP_PROFILE_EXECUTER_H__ */
|
@ -46,7 +46,7 @@
|
||||
#include <reflow-controller/safety/safety-memory.h>
|
||||
#include <reflow-controller/safety/fault.h>
|
||||
#include <reflow-controller/updater/updater.h>
|
||||
|
||||
#include <reflow-controller/temp-profile-executer.h>
|
||||
#include <reflow-controller/settings/spi-eeprom.h>
|
||||
|
||||
static void setup_nvic_priorities(void)
|
||||
@ -253,6 +253,9 @@ int main(void)
|
||||
menu_wait_request = gui_handle();
|
||||
handle_shell_uart_input(shell_handle);
|
||||
|
||||
/* Execute current profile step, if a profile is active */
|
||||
temp_profile_executer_handle();
|
||||
|
||||
safety_controller_handle();
|
||||
if (oven_pid_get_status() == OVEN_PID_RUNNING) {
|
||||
oven_pid_handle();
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <reflow-controller/safety/fault.h>
|
||||
#include <reflow-controller/safety/safety-memory.h>
|
||||
#include <reflow-controller/hw-version-detect.h>
|
||||
#include <reflow-controller/temp-profile-executer.h>
|
||||
|
||||
#ifndef GIT_VER
|
||||
#define GIT_VER "VERSION NOT SET"
|
||||
@ -683,6 +684,58 @@ shellmatta_retCode_t shell_cmd_overtemp_cfg(const shellmatta_handle_t handle, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
shellmatta_retCode_t shell_cmd_execute(const shellmatta_handle_t handle, const char *args, uint32_t len)
|
||||
{
|
||||
enum pl_ret_val res;
|
||||
const struct tpe_current_state *state;
|
||||
static bool running = false;
|
||||
char *data;
|
||||
uint32_t dlen;
|
||||
|
||||
shellmatta_read(handle, &data, &dlen);
|
||||
|
||||
if (!running) {
|
||||
res = temp_profile_executer_start("profile.tpr");
|
||||
|
||||
if (res != PL_RET_SUCCESS) {
|
||||
switch (res) {
|
||||
case PL_RET_DISK_ERR:
|
||||
shellmatta_printf(handle, "Error reading file\r\n");
|
||||
break;
|
||||
case PL_RET_LIST_FULL:
|
||||
shellmatta_printf(handle, "Script too long!\r\n");
|
||||
break;
|
||||
case PL_RET_SCRIPT_ERR:
|
||||
shellmatta_printf(handle, "Error in script\r\n");
|
||||
break;
|
||||
default:
|
||||
shellmatta_printf(handle, "Unspecified error occured\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return SHELLMATTA_ERROR;
|
||||
}
|
||||
running = true;
|
||||
} else {
|
||||
state = temp_profile_executer_status();
|
||||
if (state->status != TPE_RUNNING) {
|
||||
shellmatta_printf(handle, "Profile executed.\r\n");
|
||||
running = false;
|
||||
if(state->status == TPE_ABORT) {
|
||||
shellmatta_printf(handle, "Profile execution aborted!\r\n");
|
||||
}
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
if (dlen > 0 && *data == '\x03') {
|
||||
temp_profile_executer_stop();
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return SHELLMATTA_CONTINUE;
|
||||
}
|
||||
|
||||
//typedef struct shellmatta_cmd
|
||||
//{
|
||||
// char *cmd; /**< command name */
|
||||
@ -692,7 +745,7 @@ shellmatta_retCode_t shell_cmd_overtemp_cfg(const shellmatta_handle_t handle, co
|
||||
// shellmatta_cmdFct_t cmdFct; /**< pointer to the cmd callack function */
|
||||
// struct shellmatta_cmd *next; /**< pointer to next command or NULL */
|
||||
//} shellmatta_cmd_t;
|
||||
static shellmatta_cmd_t cmd[20] = {
|
||||
static shellmatta_cmd_t cmd[21] = {
|
||||
{
|
||||
.cmd = "version",
|
||||
.cmdAlias = "ver",
|
||||
@ -852,6 +905,14 @@ static shellmatta_cmd_t cmd[20] = {
|
||||
.helpText = "Overtemperature Config",
|
||||
.usageText = "",
|
||||
.cmdFct = shell_cmd_overtemp_cfg,
|
||||
.next = &cmd[20],
|
||||
},
|
||||
{
|
||||
.cmd = "execute",
|
||||
.cmdAlias = NULL,
|
||||
.helpText = "Execute Temp Profile",
|
||||
.usageText = "",
|
||||
.cmdFct = shell_cmd_execute,
|
||||
.next = NULL,
|
||||
}
|
||||
};
|
||||
|
216
stm-firmware/temp-profile-executer.c
Normal file
216
stm-firmware/temp-profile-executer.c
Normal file
@ -0,0 +1,216 @@
|
||||
/* Reflow Oven Controller
|
||||
*
|
||||
* Copyright (C) 2021 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/temp-profile-executer.h>
|
||||
#include <reflow-controller/systick.h>
|
||||
#include <helper-macros/helper-macros.h>
|
||||
#include <reflow-controller/oven-driver.h>
|
||||
#include <reflow-controller/temp-converter.h>
|
||||
#include <reflow-controller/adc-meas.h>
|
||||
#include <reflow-controller/digio.h>
|
||||
|
||||
static struct tpe_current_state IN_SECTION(.ccm.data) state = {
|
||||
.status = TPE_OFF,
|
||||
.start_timestamp = 0,
|
||||
};
|
||||
static bool IN_SECTION(.ccm.bss) pid_should_run;
|
||||
struct pid_controller IN_SECTION(.ccm.bss) pid;
|
||||
|
||||
static struct pl_command IN_SECTION(.ccm.bss) cmd_list[MAX_PROFILE_LENGTH];
|
||||
|
||||
static void abort(void)
|
||||
{
|
||||
temp_profile_executer_stop();
|
||||
state.status = TPE_ABORT;
|
||||
}
|
||||
|
||||
enum pl_ret_val temp_profile_executer_start(const char *filename)
|
||||
{
|
||||
uint32_t parsed_count = 0;
|
||||
enum pl_ret_val res;
|
||||
|
||||
state.setpoint = 0.0f;
|
||||
state.start_timestamp = 0ULL;
|
||||
state.setpoint = 0.0f;
|
||||
state.step = 0;
|
||||
state.profile_steps = 0;
|
||||
|
||||
oven_pid_stop();
|
||||
pid_should_run = false;
|
||||
|
||||
res = temp_profile_parse_from_file(filename, cmd_list, MAX_PROFILE_LENGTH, &parsed_count);
|
||||
if (res == PL_RET_SUCCESS) {
|
||||
state.profile_steps = parsed_count;
|
||||
state.status = TPE_RUNNING;
|
||||
state.start_timestamp = systick_get_global_tick();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool cmd_wait_temp(struct pl_command *cmd, bool cmd_continue)
|
||||
{
|
||||
(void)cmd_continue;
|
||||
float resistance;
|
||||
int res;
|
||||
float temp;
|
||||
|
||||
res = adc_pt1000_get_current_resistance(&resistance);
|
||||
if (res < 0) {
|
||||
abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
(void)temp_converter_convert_resistance_to_temp(resistance, &temp);
|
||||
|
||||
if (ABS(cmd->params[0] - temp) < 3.0f)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool cmd_wait_time(struct pl_command *cmd, bool cmd_continue)
|
||||
{
|
||||
static uint64_t temp_tick = 0UL;
|
||||
|
||||
if (cmd_continue) {
|
||||
if (systick_ticks_have_passed(temp_tick,
|
||||
(uint64_t)(cmd->params[0] * 1000.0f)))
|
||||
return true;
|
||||
} else {
|
||||
temp_tick = systick_get_global_tick();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void reactivate_pid_if_suspended(void)
|
||||
{
|
||||
if (oven_pid_get_status() == OVEN_PID_DEACTIVATED)
|
||||
oven_pid_init(&pid);
|
||||
|
||||
pid_should_run = true;
|
||||
}
|
||||
|
||||
static bool cmd_set_temp(struct pl_command *cmd, bool cmd_continue)
|
||||
{
|
||||
(void)cmd_continue;
|
||||
|
||||
reactivate_pid_if_suspended();
|
||||
oven_pid_set_target_temperature(cmd->params[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int temp_profile_executer_handle(void)
|
||||
{
|
||||
struct pl_command *current_cmd;
|
||||
static uint64_t last_tick = 0UL;
|
||||
bool advance;
|
||||
static bool cmd_continue = false;
|
||||
uint32_t next_step;
|
||||
|
||||
|
||||
if (state.status != TPE_RUNNING)
|
||||
return -1;
|
||||
if (oven_pid_get_status() == OVEN_PID_ABORTED && pid_should_run) {
|
||||
abort();
|
||||
oven_pid_stop();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (systick_ticks_have_passed(last_tick, 100)) {
|
||||
current_cmd = &cmd_list[state.step];
|
||||
next_step = state.step;
|
||||
|
||||
switch (current_cmd->cmd) {
|
||||
case PL_WAIT_FOR_TIME:
|
||||
advance = cmd_wait_time(current_cmd, cmd_continue);
|
||||
break;
|
||||
case PL_WAIT_FOR_TEMP:
|
||||
advance = cmd_wait_temp(current_cmd, cmd_continue);
|
||||
break;
|
||||
case PL_SET_TEMP:
|
||||
advance = cmd_set_temp(current_cmd, cmd_continue);
|
||||
break;
|
||||
case PL_LOUDSPEAKER_SET:
|
||||
loudspeaker_set((uint16_t)current_cmd->params[0]);
|
||||
advance = true;
|
||||
break;
|
||||
case PL_OFF:
|
||||
oven_pid_stop();
|
||||
pid_should_run = false;
|
||||
advance = true;
|
||||
break;
|
||||
case PL_PID_CONF:
|
||||
pid_init(&pid, current_cmd->params[0], /* Kd */
|
||||
current_cmd->params[1], /* Ki */
|
||||
current_cmd->params[2], /* Kp */
|
||||
0.0f, 0.0f,
|
||||
current_cmd->params[3], /* Int max */
|
||||
current_cmd->params[4], /* Kd tau */
|
||||
current_cmd->params[5]); /* Period */
|
||||
oven_pid_init(&pid);
|
||||
advance = true;
|
||||
pid_should_run = true;
|
||||
break;
|
||||
case PL_SET_RAMP:
|
||||
advance = true;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
advance = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (advance)
|
||||
next_step++;
|
||||
|
||||
if (next_step != state.step) {
|
||||
state.step = next_step;
|
||||
if (next_step >= state.profile_steps) {
|
||||
(void)temp_profile_executer_stop();
|
||||
} else {
|
||||
cmd_continue = false;
|
||||
}
|
||||
} else {
|
||||
cmd_continue = true;
|
||||
}
|
||||
last_tick = systick_get_global_tick();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct tpe_current_state *temp_profile_executer_status(void)
|
||||
{
|
||||
return &state;
|
||||
}
|
||||
|
||||
int temp_profile_executer_stop(void)
|
||||
{
|
||||
if (state.status == TPE_RUNNING) {
|
||||
state.status = TPE_OFF;
|
||||
oven_pid_stop();
|
||||
}
|
||||
|
||||
loudspeaker_set(0);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user