split stepper conf

This commit is contained in:
leo 2023-09-19 17:56:31 +02:00
parent ffaa78798e
commit 8a099f5c21
Signed by: leo
GPG Key ID: 0DD993BFB2B307DB
6 changed files with 57 additions and 46 deletions

View File

@ -31,7 +31,9 @@ typedef struct{
int32_t steps_counter; int32_t steps_counter;
uint8_t stop_at_limit; // boolean to stop at stop_steps uint8_t stop_at_limit; // boolean to stop at stop_steps
int32_t stop_steps; // position to stop at int32_t stop_steps; // position to stop at
} pse_stepper_status;
typedef struct{
GPIO_TypeDef* EN_GPIO_Port; // Pin definitions GPIO_TypeDef* EN_GPIO_Port; // Pin definitions
uint16_t EN_GPIO_Pin; uint16_t EN_GPIO_Pin;
GPIO_TypeDef* DIR_GPIO_Port; GPIO_TypeDef* DIR_GPIO_Port;
@ -59,12 +61,13 @@ typedef struct{
pse_syringe* syringe; // associated syringe pse_syringe* syringe; // associated syringe
pse_stepper_conf* stepper_conf; // hardware configuration for the associated stepper pse_stepper_conf* stepper_conf; // hardware configuration for the associated stepper
pse_home_display* home_display; // Widgets for updating the home screen pse_home_display* home_display; // Widgets for updating the home screen
pse_stepper_status* stepper_status; // stepper position/speed status
int32_t start_pos; // movement start position for volume calculation int32_t start_pos; // movement start position for volume calculation
uint32_t nL_per_step; // pL delivered per step uint32_t nL_per_step; // pL delivered per step
} pse_unit; } pse_unit;
void load_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* stepper_confs, pse_home_display* home_displays, uint8_t unit_num, uint16_t ws_ind); void load_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* stepper_confs, pse_stepper_status* stepper_status, pse_home_display* home_displays, uint8_t unit_num, uint16_t ws_ind);
void load_units_short(pse_unit* units, uint8_t unit_num, uint16_t ws_ind); void load_units_short(pse_unit* units, uint8_t unit_num, uint16_t ws_ind);
void save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind); void save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind);

View File

@ -16,12 +16,12 @@
#define PSE_STEPPER_JOG_PRESC 64 // jog step frequency 50kHz #define PSE_STEPPER_JOG_PRESC 64 // jog step frequency 50kHz
#define PSE_STEPPER_JOG_PERIOD 25 // 64Mhz / 64 / 10 / 2 #define PSE_STEPPER_JOG_PERIOD 25 // 64Mhz / 64 / 10 / 2
void pse_sp_start_axis(pse_stepper_conf* conf); void pse_sp_start_axis(pse_stepper_conf* conf, pse_stepper_status* status);
void pse_sp_stop_axis(pse_stepper_conf* conf); void pse_sp_stop_axis(pse_stepper_conf* conf);
void pse_sp_set_dir(pse_stepper_conf* conf, int dir); void pse_sp_set_dir(pse_stepper_conf* conf, int dir);
int pse_sp_get_dir(pse_stepper_conf* conf); int pse_sp_get_dir(pse_stepper_conf* conf);
void pse_stepper_planer_tick(pse_unit* unit); void pse_stepper_planer_tick(pse_unit* unit);
void pse_sp_jog_speed(pse_stepper_conf* conf, int status); void pse_sp_jog_speed(pse_stepper_conf* conf, pse_stepper_status* sta, int status);
void pse_sp_set_dir_all(pse_unit* units, int unit_num, int dir); void pse_sp_set_dir_all(pse_unit* units, int unit_num, int dir);
void pse_sp_start_all(pse_unit* units, int unit_num); void pse_sp_start_all(pse_unit* units, int unit_num);

View File

@ -16,7 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static void generate_default_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* stepper_confs, pse_home_display* home_displays, uint8_t unit_num){ static void generate_default_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* stepper_confs,pse_stepper_status* stepper_status, pse_home_display* home_displays, uint8_t unit_num){
for(int i = 0; i < unit_num; i++){ for(int i = 0; i < unit_num; i++){
units[i] = (pse_unit){ units[i] = (pse_unit){
.enabled = i%2, .enabled = i%2,
@ -25,8 +25,9 @@ static void generate_default_units(pse_unit* units, pse_syringe* syringes, pse_s
.volume = 0, .volume = 0,
.set_volume = 0, .set_volume = 0,
.syringe = &syringes[i], .syringe = &syringes[i],
.stepper_conf = &stepper_confs[i], .stepper_conf = &stepper_confs[i],
.home_display = &home_displays[i], .stepper_status = &stepper_status[i],
.home_display = &home_displays[i],
}; };
syringes[i] = (pse_syringe){ syringes[i] = (pse_syringe){
.name = "Test", .name = "Test",
@ -39,7 +40,7 @@ static void generate_default_units(pse_unit* units, pse_syringe* syringes, pse_s
// Load units from file // Load units from file
// Units configuration are saved as binary, in the order [pse_unit, pse_syringe, pse_stepper_conf] with each unit back to back // Units configuration are saved as binary, in the order [pse_unit, pse_syringe, pse_stepper_conf] with each unit back to back
// In case of any error fallback to a default configuration // In case of any error fallback to a default configuration
void load_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* stepper_confs, pse_home_display* home_displays, uint8_t unit_num, uint16_t ws_ind){ void load_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* stepper_confs, pse_stepper_status* stepper_status, pse_home_display* home_displays, uint8_t unit_num, uint16_t ws_ind){
// Open save file // Open save file
FIL saveFile; FIL saveFile;
@ -54,7 +55,7 @@ void load_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* steppe
if(f_open(&saveFile, filename, FA_READ) != FR_OK){ if(f_open(&saveFile, filename, FA_READ) != FR_OK){
lv_obj_t * mbox1 = lv_msgbox_create(NULL, "Error", "Could not load configuration from SD card", NULL, true); lv_obj_t * mbox1 = lv_msgbox_create(NULL, "Error", "Could not load configuration from SD card", NULL, true);
lv_obj_center(mbox1); lv_obj_center(mbox1);
generate_default_units(units, syringes, stepper_confs, home_displays, unit_num); generate_default_units(units, syringes, stepper_confs, stepper_status, home_displays, unit_num);
free(filename); free(filename);
return; return;
} }
@ -68,12 +69,13 @@ void load_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* steppe
units[i].syringe = &syringes[i]; units[i].syringe = &syringes[i];
units[i].stepper_conf = &stepper_confs[i]; units[i].stepper_conf = &stepper_confs[i];
units[i].home_display = &home_displays[i]; units[i].home_display = &home_displays[i];
units[i].stepper_status = &stepper_status[i];
res += f_read(&saveFile, units[i].syringe, sizeof(pse_syringe), &bytesRead); res += f_read(&saveFile, units[i].syringe, sizeof(pse_syringe), &bytesRead);
res += f_read(&saveFile, units[i].stepper_conf, sizeof(pse_stepper_conf), &bytesRead); res += f_read(&saveFile, units[i].stepper_status, sizeof(pse_stepper_status), &bytesRead);
if(res != FR_OK){ if(res != FR_OK){
generate_default_units(units, syringes, stepper_confs, home_displays, unit_num); generate_default_units(units, syringes, stepper_confs, stepper_status, home_displays, unit_num);
return; return;
} }
} }
@ -82,7 +84,7 @@ void load_units(pse_unit* units, pse_syringe* syringes, pse_stepper_conf* steppe
} }
void load_units_short(pse_unit* units, uint8_t unit_num, uint16_t ws_ind){ void load_units_short(pse_unit* units, uint8_t unit_num, uint16_t ws_ind){
load_units(units, units->syringe, units->stepper_conf, units->home_display, unit_num, ws_ind); load_units(units, units->syringe, units->stepper_conf, units->stepper_status , units->home_display, unit_num, ws_ind);
} }
void save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind){ void save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind){
@ -112,7 +114,7 @@ void save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind){
UINT bytesRead; UINT bytesRead;
res = f_write(&saveFile, &units[i], sizeof(units[i]), &bytesRead); res = f_write(&saveFile, &units[i], sizeof(units[i]), &bytesRead);
res += f_write(&saveFile, units[i].syringe, sizeof(pse_syringe), &bytesRead); res += f_write(&saveFile, units[i].syringe, sizeof(pse_syringe), &bytesRead);
res += f_write(&saveFile, units[i].stepper_conf, sizeof(pse_stepper_conf), &bytesRead); res += f_write(&saveFile, units[i].stepper_status, sizeof(pse_stepper_status), &bytesRead);
if(res != FR_OK){ if(res != FR_OK){
return; return;
@ -124,7 +126,7 @@ void save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind){
} }
void pse_unit_compute_volume_delivered(pse_unit* unit){ void pse_unit_compute_volume_delivered(pse_unit* unit){
unit->volume = (int64_t)1 * (unit->stepper_conf->steps_counter - unit->start_pos) * unit->nL_per_step / 1000; unit->volume = (int64_t)1 * (unit->stepper_status->steps_counter - unit->start_pos) * unit->nL_per_step / 1000;
} }
void pse_unit_compute_volume_per_step(pse_unit* unit){ void pse_unit_compute_volume_per_step(pse_unit* unit){

View File

@ -38,10 +38,12 @@ static void back_button_handler(lv_event_t * e){
// set limit if volume defined // set limit if volume defined
if(c_pse_unit->set_volume != 0){ if(c_pse_unit->set_volume != 0){
c_pse_unit->stepper_conf->stop_at_limit = 1; if(c_pse_unit->nL_per_step == 0) return; // TODO: alert popup / better resolution
c_pse_unit->stepper_conf->stop_steps = (uint64_t)1000 * c_pse_unit->set_volume / c_pse_unit->nL_per_step; } if(c_pse_unit->flow == 0) return;
c_pse_unit->stepper_status->stop_at_limit = 1;
c_pse_unit->stepper_status->stop_steps = (uint64_t)1000 * c_pse_unit->set_volume / c_pse_unit->nL_per_step; }
else else
c_pse_unit->stepper_conf->stop_at_limit = 0; c_pse_unit->stepper_status->stop_at_limit = 0;
// go back to the main menu // go back to the main menu
Home_Screen_Gen(c_pse_units, c_pse_units_num, true); Home_Screen_Gen(c_pse_units, c_pse_units_num, true);
@ -167,12 +169,12 @@ static void jog_forward_button_handler(lv_event_t* e){
pse_unit* unit = lv_event_get_user_data(e); pse_unit* unit = lv_event_get_user_data(e);
if(code == LV_EVENT_PRESSED) { if(code == LV_EVENT_PRESSED) {
pse_sp_jog_speed(unit->stepper_conf, 1); pse_sp_jog_speed(unit->stepper_conf, unit->stepper_status, 1);
pse_sp_set_dir(unit->stepper_conf, 1); pse_sp_set_dir(unit->stepper_conf, 1);
pse_sp_start_axis(unit->stepper_conf); pse_sp_start_axis(unit->stepper_conf, unit->stepper_status);
} }
else if(code == LV_EVENT_RELEASED){ else if(code == LV_EVENT_RELEASED){
pse_sp_jog_speed(unit->stepper_conf, 0); pse_sp_jog_speed(unit->stepper_conf, unit->stepper_status, 0);
pse_sp_stop_axis(unit->stepper_conf); pse_sp_stop_axis(unit->stepper_conf);
} }
} }
@ -182,12 +184,12 @@ static void jog_backward_button_handler(lv_event_t* e){
pse_unit* unit = lv_event_get_user_data(e); pse_unit* unit = lv_event_get_user_data(e);
if(code == LV_EVENT_PRESSED) { if(code == LV_EVENT_PRESSED) {
pse_sp_jog_speed(unit->stepper_conf, 1); pse_sp_jog_speed(unit->stepper_conf, unit->stepper_status, 1);
pse_sp_set_dir(unit->stepper_conf, 0); pse_sp_set_dir(unit->stepper_conf, 0);
pse_sp_start_axis(unit->stepper_conf); pse_sp_start_axis(unit->stepper_conf, unit->stepper_status);
} }
else if(code == LV_EVENT_RELEASED){ else if(code == LV_EVENT_RELEASED){
pse_sp_jog_speed(unit->stepper_conf, 0); pse_sp_jog_speed(unit->stepper_conf, unit->stepper_status, 0);
pse_sp_stop_axis(unit->stepper_conf); pse_sp_stop_axis(unit->stepper_conf);
} }
} }
@ -197,7 +199,7 @@ static void set_home_button_handler(lv_event_t* e){
pse_unit* unit = lv_event_get_user_data(e); pse_unit* unit = lv_event_get_user_data(e);
if(code == LV_EVENT_CLICKED) { if(code == LV_EVENT_CLICKED) {
unit->stepper_conf->steps_counter = 0; unit->stepper_status->steps_counter = 0;
} }
} }

View File

@ -95,12 +95,13 @@ static void unit_home_handler(lv_event_t * e){
if(code == LV_EVENT_CLICKED) { if(code == LV_EVENT_CLICKED) {
pse_unit* unit = lv_event_get_user_data(e); pse_unit* unit = lv_event_get_user_data(e);
pse_stepper_conf* c = unit->stepper_conf; pse_stepper_conf* c = unit->stepper_conf;
if(c->steps_counter == 0) return; pse_stepper_status* s = unit->stepper_status;
c->stop_at_limit = 1; if(s->steps_counter == 0) return;
c->stop_steps = 0; s->stop_at_limit = 1;
pse_sp_jog_speed(c, 1); s->stop_steps = 0;
pse_sp_set_dir(c, c->steps_counter < 0); pse_sp_jog_speed(c, s, 1);
pse_sp_start_axis(c); pse_sp_set_dir(c, s->steps_counter < 0);
pse_sp_start_axis(c, s);
} }
} }

View File

@ -15,17 +15,18 @@
void pse_stepper_planer_tick(pse_unit* unit){ void pse_stepper_planer_tick(pse_unit* unit){
pse_stepper_conf* c = unit->stepper_conf; pse_stepper_conf* c = unit->stepper_conf;
pse_stepper_status* s = unit->stepper_status;
HAL_GPIO_TogglePin(c->STEP_GPIO_Port, c->STEP_GPIO_Pin); HAL_GPIO_TogglePin(c->STEP_GPIO_Port, c->STEP_GPIO_Pin);
c->steps_counter += (pse_sp_get_dir(c)?1:-1) * HAL_GPIO_ReadPin(c->STEP_GPIO_Port, c->STEP_GPIO_Pin); s->steps_counter += (pse_sp_get_dir(c)?1:-1) * HAL_GPIO_ReadPin(c->STEP_GPIO_Port, c->STEP_GPIO_Pin);
if(c->stop_at_limit && c->steps_counter == c->stop_steps){ if(s->stop_at_limit && s->steps_counter == s->stop_steps){
pse_sp_jog_speed(c, 0); pse_sp_jog_speed(c, s, 0);
pse_sp_stop_axis(c); pse_sp_stop_axis(c);
} }
} }
void pse_sp_start_axis(pse_stepper_conf* conf){ void pse_sp_start_axis(pse_stepper_conf* conf, pse_stepper_status* status){
if(conf->stop_at_limit && conf->steps_counter == conf->stop_steps) return; if(status->stop_at_limit && status->steps_counter == status->stop_steps) return;
HAL_GPIO_WritePin(conf->EN_GPIO_Port, conf->EN_GPIO_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(conf->EN_GPIO_Port, conf->EN_GPIO_Pin, GPIO_PIN_RESET);
HAL_TIM_Base_Start_IT(conf->tim); HAL_TIM_Base_Start_IT(conf->tim);
@ -61,6 +62,8 @@ static uint16_t int_sqrt(uint32_t s){
void pse_stepper_planer_compute_sps(pse_unit* unit){ void pse_stepper_planer_compute_sps(pse_unit* unit){
pse_stepper_conf* c = unit->stepper_conf; pse_stepper_conf* c = unit->stepper_conf;
pse_stepper_status* s = unit->stepper_status;
// magic constants are used to approximate pi and other multiplicatives constant as a rationnal // magic constants are used to approximate pi and other multiplicatives constant as a rationnal
uint64_t numerator = (uint64_t)14323 * unit->syringe->diameter * unit->syringe->diameter * PSE_STEPPER_TIMER_CLOCK * PSE_STEPPER_SCREW_PITCH; uint64_t numerator = (uint64_t)14323 * unit->syringe->diameter * unit->syringe->diameter * PSE_STEPPER_TIMER_CLOCK * PSE_STEPPER_SCREW_PITCH;
uint64_t denominator = (uint64_t)607887 * unit->flow * PSE_STEPPER_STEPS_PER_ROTATION; uint64_t denominator = (uint64_t)607887 * unit->flow * PSE_STEPPER_STEPS_PER_ROTATION;
@ -77,17 +80,17 @@ void pse_stepper_planer_compute_sps(pse_unit* unit){
} }
if(res < 65536){ if(res < 65536){
c->tim_presc = 0; s->tim_presc = 0;
c->tim_period = res - 1; s->tim_period = res - 1;
__HAL_TIM_SET_AUTORELOAD(c->tim, c->tim_period); __HAL_TIM_SET_AUTORELOAD(c->tim, s->tim_period);
__HAL_TIM_SET_PRESCALER(c->tim, c->tim_presc); __HAL_TIM_SET_PRESCALER(c->tim, s->tim_presc);
} }
else{ else{
uint16_t sqrt = int_sqrt(res); uint16_t sqrt = int_sqrt(res);
c->tim_presc = sqrt - 1; s->tim_presc = sqrt - 1;
c->tim_period = sqrt; s->tim_period = sqrt;
__HAL_TIM_SET_AUTORELOAD(c->tim, c->tim_period); __HAL_TIM_SET_AUTORELOAD(c->tim, s->tim_period);
__HAL_TIM_SET_PRESCALER(c->tim, c->tim_presc); __HAL_TIM_SET_PRESCALER(c->tim, s->tim_presc);
} }
} }
@ -100,7 +103,7 @@ void pse_sp_set_dir_all(pse_unit* units, int units_num, int dir){
void pse_sp_start_all(pse_unit* units, int units_num){ void pse_sp_start_all(pse_unit* units, int units_num){
for(int i = 0; i < units_num; i++){ for(int i = 0; i < units_num; i++){
if(units[i].enabled){ if(units[i].enabled){
pse_sp_start_axis(units[i].stepper_conf); pse_sp_start_axis(units[i].stepper_conf, units[i].stepper_status);
} }
} }
} }
@ -111,13 +114,13 @@ void pse_sp_stop_all(pse_unit* units, int units_num){
} }
} }
void pse_sp_jog_speed(pse_stepper_conf* conf, int status){ void pse_sp_jog_speed(pse_stepper_conf* conf, pse_stepper_status* sta, int status){
if(status){ if(status){
__HAL_TIM_SET_AUTORELOAD(conf->tim, PSE_STEPPER_JOG_PERIOD); __HAL_TIM_SET_AUTORELOAD(conf->tim, PSE_STEPPER_JOG_PERIOD);
__HAL_TIM_SET_PRESCALER(conf->tim, PSE_STEPPER_JOG_PRESC); __HAL_TIM_SET_PRESCALER(conf->tim, PSE_STEPPER_JOG_PRESC);
} }
else{ else{
__HAL_TIM_SET_AUTORELOAD(conf->tim, conf->tim_period); __HAL_TIM_SET_AUTORELOAD(conf->tim, sta->tim_period);
__HAL_TIM_SET_PRESCALER(conf->tim, conf->tim_presc); __HAL_TIM_SET_PRESCALER(conf->tim, sta->tim_presc);
} }
} }