diff --git a/Core/Inc/PSE_unit.h b/Core/Inc/PSE_unit.h index 07213f6..1454db3 100644 --- a/Core/Inc/PSE_unit.h +++ b/Core/Inc/PSE_unit.h @@ -31,7 +31,9 @@ typedef struct{ int32_t steps_counter; uint8_t stop_at_limit; // boolean to stop at stop_steps int32_t stop_steps; // position to stop at +} pse_stepper_status; +typedef struct{ GPIO_TypeDef* EN_GPIO_Port; // Pin definitions uint16_t EN_GPIO_Pin; GPIO_TypeDef* DIR_GPIO_Port; @@ -59,12 +61,13 @@ typedef struct{ pse_syringe* syringe; // associated syringe pse_stepper_conf* stepper_conf; // hardware configuration for the associated stepper 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 uint32_t nL_per_step; // pL delivered per step } 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 save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind); diff --git a/Core/Inc/pse_stepper_planer.h b/Core/Inc/pse_stepper_planer.h index a4d3fe1..60162bc 100644 --- a/Core/Inc/pse_stepper_planer.h +++ b/Core/Inc/pse_stepper_planer.h @@ -16,12 +16,12 @@ #define PSE_STEPPER_JOG_PRESC 64 // jog step frequency 50kHz #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_set_dir(pse_stepper_conf* conf, int dir); int pse_sp_get_dir(pse_stepper_conf* conf); 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_start_all(pse_unit* units, int unit_num); diff --git a/Core/Src/PSE_unit.c b/Core/Src/PSE_unit.c index 20006eb..b264a88 100644 --- a/Core/Src/PSE_unit.c +++ b/Core/Src/PSE_unit.c @@ -16,7 +16,7 @@ #include #include -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++){ units[i] = (pse_unit){ .enabled = i%2, @@ -25,8 +25,9 @@ static void generate_default_units(pse_unit* units, pse_syringe* syringes, pse_s .volume = 0, .set_volume = 0, .syringe = &syringes[i], - .stepper_conf = &stepper_confs[i], - .home_display = &home_displays[i], + .stepper_conf = &stepper_confs[i], + .stepper_status = &stepper_status[i], + .home_display = &home_displays[i], }; syringes[i] = (pse_syringe){ .name = "Test", @@ -39,7 +40,7 @@ static void generate_default_units(pse_unit* units, pse_syringe* syringes, pse_s // 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 // 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 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){ lv_obj_t * mbox1 = lv_msgbox_create(NULL, "Error", "Could not load configuration from SD card", NULL, true); 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); 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].stepper_conf = &stepper_confs[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].stepper_conf, sizeof(pse_stepper_conf), &bytesRead); + res += f_read(&saveFile, units[i].stepper_status, sizeof(pse_stepper_status), &bytesRead); 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; } } @@ -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){ - 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){ @@ -112,7 +114,7 @@ void save_units(pse_unit* units, uint8_t unit_num, uint16_t ws_ind){ UINT 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].stepper_conf, sizeof(pse_stepper_conf), &bytesRead); + res += f_write(&saveFile, units[i].stepper_status, sizeof(pse_stepper_status), &bytesRead); if(res != FR_OK){ 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){ - 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){ diff --git a/Core/Src/PSE_unit_edit_screen.c b/Core/Src/PSE_unit_edit_screen.c index 2511aaa..19b05e0 100644 --- a/Core/Src/PSE_unit_edit_screen.c +++ b/Core/Src/PSE_unit_edit_screen.c @@ -38,10 +38,12 @@ static void back_button_handler(lv_event_t * e){ // set limit if volume defined if(c_pse_unit->set_volume != 0){ - c_pse_unit->stepper_conf->stop_at_limit = 1; - 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->nL_per_step == 0) return; // TODO: alert popup / better resolution + 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 - c_pse_unit->stepper_conf->stop_at_limit = 0; + c_pse_unit->stepper_status->stop_at_limit = 0; // go back to the main menu 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); 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_start_axis(unit->stepper_conf); + pse_sp_start_axis(unit->stepper_conf, unit->stepper_status); } 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); } } @@ -182,12 +184,12 @@ static void jog_backward_button_handler(lv_event_t* e){ pse_unit* unit = lv_event_get_user_data(e); 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_start_axis(unit->stepper_conf); + pse_sp_start_axis(unit->stepper_conf, unit->stepper_status); } 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); } } @@ -197,7 +199,7 @@ static void set_home_button_handler(lv_event_t* e){ pse_unit* unit = lv_event_get_user_data(e); if(code == LV_EVENT_CLICKED) { - unit->stepper_conf->steps_counter = 0; + unit->stepper_status->steps_counter = 0; } } diff --git a/Core/Src/home_screen.c b/Core/Src/home_screen.c index 4f80bdb..51caf24 100644 --- a/Core/Src/home_screen.c +++ b/Core/Src/home_screen.c @@ -95,12 +95,13 @@ static void unit_home_handler(lv_event_t * e){ if(code == LV_EVENT_CLICKED) { pse_unit* unit = lv_event_get_user_data(e); pse_stepper_conf* c = unit->stepper_conf; - if(c->steps_counter == 0) return; - c->stop_at_limit = 1; - c->stop_steps = 0; - pse_sp_jog_speed(c, 1); - pse_sp_set_dir(c, c->steps_counter < 0); - pse_sp_start_axis(c); + pse_stepper_status* s = unit->stepper_status; + if(s->steps_counter == 0) return; + s->stop_at_limit = 1; + s->stop_steps = 0; + pse_sp_jog_speed(c, s, 1); + pse_sp_set_dir(c, s->steps_counter < 0); + pse_sp_start_axis(c, s); } } diff --git a/Core/Src/pse_stepper_planer.c b/Core/Src/pse_stepper_planer.c index 1e45fe7..c178876 100644 --- a/Core/Src/pse_stepper_planer.c +++ b/Core/Src/pse_stepper_planer.c @@ -15,17 +15,18 @@ void pse_stepper_planer_tick(pse_unit* unit){ 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); - c->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){ - pse_sp_jog_speed(c, 0); + s->steps_counter += (pse_sp_get_dir(c)?1:-1) * HAL_GPIO_ReadPin(c->STEP_GPIO_Port, c->STEP_GPIO_Pin); + if(s->stop_at_limit && s->steps_counter == s->stop_steps){ + pse_sp_jog_speed(c, s, 0); pse_sp_stop_axis(c); } } -void pse_sp_start_axis(pse_stepper_conf* conf){ - if(conf->stop_at_limit && conf->steps_counter == conf->stop_steps) return; +void pse_sp_start_axis(pse_stepper_conf* conf, pse_stepper_status* status){ + 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_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){ 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 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; @@ -77,17 +80,17 @@ void pse_stepper_planer_compute_sps(pse_unit* unit){ } if(res < 65536){ - c->tim_presc = 0; - c->tim_period = res - 1; - __HAL_TIM_SET_AUTORELOAD(c->tim, c->tim_period); - __HAL_TIM_SET_PRESCALER(c->tim, c->tim_presc); + s->tim_presc = 0; + s->tim_period = res - 1; + __HAL_TIM_SET_AUTORELOAD(c->tim, s->tim_period); + __HAL_TIM_SET_PRESCALER(c->tim, s->tim_presc); } else{ uint16_t sqrt = int_sqrt(res); - c->tim_presc = sqrt - 1; - c->tim_period = sqrt; - __HAL_TIM_SET_AUTORELOAD(c->tim, c->tim_period); - __HAL_TIM_SET_PRESCALER(c->tim, c->tim_presc); + s->tim_presc = sqrt - 1; + s->tim_period = sqrt; + __HAL_TIM_SET_AUTORELOAD(c->tim, s->tim_period); + __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){ for(int i = 0; i < units_num; i++){ 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){ __HAL_TIM_SET_AUTORELOAD(conf->tim, PSE_STEPPER_JOG_PERIOD); __HAL_TIM_SET_PRESCALER(conf->tim, PSE_STEPPER_JOG_PRESC); } else{ - __HAL_TIM_SET_AUTORELOAD(conf->tim, conf->tim_period); - __HAL_TIM_SET_PRESCALER(conf->tim, conf->tim_presc); + __HAL_TIM_SET_AUTORELOAD(conf->tim, sta->tim_period); + __HAL_TIM_SET_PRESCALER(conf->tim, sta->tim_presc); } }