Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1d4e83a2ea |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -164,6 +164,13 @@ esp_err_t rotary_encoder_get_state(const rotary_encoder_info_t * info, rotary_en
|
||||
*/
|
||||
esp_err_t rotary_encoder_reset(rotary_encoder_info_t * info);
|
||||
|
||||
/**
|
||||
* @brief Set the current position of the rotary encoder to passed value.
|
||||
* @param[in] info Pointer to initialised rotary encoder info structure.
|
||||
* @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.
|
||||
*/
|
||||
esp_err_t rotary_encoder_set_position(rotary_encoder_info_t * info, uint32_t posNew);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -343,3 +343,20 @@ esp_err_t rotary_encoder_reset(rotary_encoder_info_t * info)
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t rotary_encoder_set_position(rotary_encoder_info_t * info, uint32_t posNew)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
if (info)
|
||||
{
|
||||
ESP_LOGI(TAG, "changing rotary encoder position from %d to %d steps", info->state.position, posNew);
|
||||
info->state.position = posNew;
|
||||
info->state.direction = ROTARY_ENCODER_DIRECTION_NOT_SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "info is NULL");
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return err;
|
||||
}
|
@ -101,30 +101,6 @@
|
||||
//options affecting movement are currently defined in guide-stepper.cpp
|
||||
|
||||
|
||||
//---------------------------
|
||||
//------- cable guide -------
|
||||
//---------------------------
|
||||
// default axis coordinates the guide changes direction (winding width)
|
||||
#define GUIDE_MIN_MM 0 // TODO add feature so guide stays at zero for some steps (negative MIN_MM?), currently seems appropriate for even winding
|
||||
#define GUIDE_MAX_MM 90 // 95 still to long at max pos - actual reel is 110, but currently guide turned out to stay at max position for too long, due to cable running diagonal from guide to reel
|
||||
|
||||
// tolerance added to last stored position at previous shutdown.
|
||||
// When calibrating at startup the stepper moves for that sum to get track of zero position (ensure crashes into hardware limit for at least some time)
|
||||
#define AUTO_HOME_TRAVEL_ADD_TO_LAST_POS_MM 20
|
||||
#define MAX_TOTAL_AXIS_TRAVEL_MM 103 // max possible travel distance, needed as fallback for auto-home
|
||||
#define LAYER_THICKNESS_MM 5 // height of one cable layer on reel -> increase in radius every layer
|
||||
#define D_CABLE 6 // determines winds per layer / guide speed
|
||||
#define D_REEL 160 // start diameter of empty reel
|
||||
|
||||
// max winding width that can be set using potentiometer (SET+PRESET1 buttons)
|
||||
#define MAX_SELECTABLE_WINDING_WIDTH_MM 100;
|
||||
// max target length that can be selected using potentiometer (SET button)
|
||||
#define MAX_SELECTABLE_LENGTH_POTI_MM 100000
|
||||
|
||||
// calculate new winding width each time target length changes, according to custom thresholds defined in guide-stepper.cpp
|
||||
// if not defined, winding width is always GUIDE_MAX_MM even for short lengths
|
||||
#define DYNAMIC_WINDING_WIDTH_ENABLED
|
||||
|
||||
|
||||
//--------------------------
|
||||
//------ calibration -------
|
||||
|
@ -24,6 +24,7 @@ extern "C"
|
||||
#include "guide-stepper.hpp"
|
||||
#include "global.hpp"
|
||||
#include "control.hpp"
|
||||
#include "shutdown.hpp"
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
@ -54,10 +55,6 @@ static uint32_t timestamp_cut_lastBeep = 0;
|
||||
static uint32_t autoCut_delayMs = 2500; //TODO add this to config
|
||||
static bool autoCutEnabled = false; //store state of toggle switch (no hotswitch)
|
||||
|
||||
//user interface
|
||||
static uint32_t timestamp_lastWidthSelect = 0;
|
||||
//ignore new set events for that time after last value set using poti
|
||||
#define DEAD_TIME_POTI_SET_VALUE 1000
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
@ -161,8 +158,14 @@ void task_control(void *pvParameter)
|
||||
//currently show name and date and scrolling 'hello'
|
||||
display_ShowWelcomeMsg(two7SegDisplays);
|
||||
|
||||
//-- set initial winding width for default length --
|
||||
guide_setWindingWidth(guide_targetLength2WindingWidth(lengthTarget));
|
||||
//-- consider previous length from nvs --
|
||||
//read stored length from last shutdown
|
||||
int encoderPosLastShutdown = nvsReadLastEncoderSteps();
|
||||
// apply stored length when significant
|
||||
if (encoderPosLastShutdown > 2*ENCODER_STEPS_PER_METER){
|
||||
encoder_setPos(encoderPosLastShutdown);
|
||||
ESP_LOGW(TAG, "set encoder to last known steps %d (from last shutdown)", encoderPosLastShutdown);
|
||||
}
|
||||
|
||||
// ##############################
|
||||
// ######## control loop ########
|
||||
@ -259,44 +262,13 @@ void task_control(void *pvParameter)
|
||||
buzzer.beep(3, 100, 60);
|
||||
}
|
||||
|
||||
//##### SET switch + Potentiometer #####
|
||||
//## set winding-width (SET+PRESET1+POTI) ##
|
||||
// set winding width (axis travel) with poti position
|
||||
// when SET and PRESET1 button are pressed
|
||||
if (SW_SET.state == true && SW_PRESET1.state == true) {
|
||||
timestamp_lastWidthSelect = esp_log_timestamp();
|
||||
//##### SET switch #####
|
||||
//set target length to poti position when SET switch is pressed
|
||||
if (SW_SET.state == true) {
|
||||
//read adc
|
||||
potiRead = gpio_readAdc(ADC_CHANNEL_POTI); //0-4095
|
||||
//scale to target length range
|
||||
uint8_t windingWidthNew = (float)potiRead / 4095 * MAX_SELECTABLE_WINDING_WIDTH_MM;
|
||||
//apply hysteresis and round to whole meters //TODO optimize this
|
||||
if (windingWidthNew % 5 < 2) { //round down if remainder less than 2mm
|
||||
ESP_LOGD(TAG, "Poti input = %d -> rounding down", windingWidthNew);
|
||||
windingWidthNew = (windingWidthNew/5 ) * 5; //round down
|
||||
} else if (windingWidthNew % 5 > 4 ) { //round up if remainder more than 4mm
|
||||
ESP_LOGD(TAG, "Poti input = %d -> rounding up", windingWidthNew);
|
||||
windingWidthNew = (windingWidthNew/5 + 1) * 5; //round up
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Poti input = %d -> hysteresis", windingWidthNew);
|
||||
windingWidthNew = guide_getWindingWidth();
|
||||
}
|
||||
//update target width and beep when effectively changed
|
||||
if (windingWidthNew != guide_getWindingWidth()) {
|
||||
//TODO update at button release only?
|
||||
guide_setWindingWidth(windingWidthNew);
|
||||
ESP_LOGW(TAG, "Changed winding width to %d mm", windingWidthNew);
|
||||
buzzer.beep(1, 30, 10);
|
||||
}
|
||||
}
|
||||
|
||||
//## set target length (SET+POTI) ##
|
||||
//set target length to poti position when only SET button is pressed and certain dead time passed after last setWindingWidth (SET and PRESET1 button) to prevent set target at release
|
||||
// FIXME: when going to edit the winding width (SET+PRESET1) sometimes the target-length also updates when initially pressing SET -> update only at actual poti change (works sometimes)
|
||||
else if (SW_SET.state == true && (esp_log_timestamp() - timestamp_lastWidthSelect > DEAD_TIME_POTI_SET_VALUE)) {
|
||||
//read adc
|
||||
potiRead = gpio_readAdc(ADC_CHANNEL_POTI); //0-4095
|
||||
//scale to target length range
|
||||
int lengthTargetNew = (float)potiRead / 4095 * MAX_SELECTABLE_LENGTH_POTI_MM;
|
||||
int lengthTargetNew = (float)potiRead / 4095 * 50000;
|
||||
//apply hysteresis and round to whole meters //TODO optimize this
|
||||
if (lengthTargetNew % 1000 < 200) { //round down if less than .2 meter
|
||||
ESP_LOGD(TAG, "Poti input = %d -> rounding down", lengthTargetNew);
|
||||
@ -312,7 +284,6 @@ void task_control(void *pvParameter)
|
||||
if (lengthTargetNew != lengthTarget) {
|
||||
//TODO update lengthTarget only at button release?
|
||||
lengthTarget = lengthTargetNew;
|
||||
guide_setWindingWidth(guide_targetLength2WindingWidth(lengthTarget));
|
||||
ESP_LOGI(TAG, "Changed target length to %d mm", lengthTarget);
|
||||
buzzer.beep(1, 25, 10);
|
||||
}
|
||||
@ -328,22 +299,19 @@ void task_control(void *pvParameter)
|
||||
|
||||
|
||||
//##### target length preset buttons #####
|
||||
if (controlState != systemState_t::MANUAL && SW_SET.state == false) { //dont apply preset length while controlling motor with preset buttons
|
||||
if (controlState != systemState_t::MANUAL) { //dont apply preset length while controlling motor with preset buttons
|
||||
if (SW_PRESET1.risingEdge) {
|
||||
lengthTarget = 5000;
|
||||
guide_setWindingWidth(guide_targetLength2WindingWidth(lengthTarget));
|
||||
buzzer.beep(lengthTarget/1000, 25, 30);
|
||||
displayBot.blink(2, 100, 100, "S0LL ");
|
||||
}
|
||||
else if (SW_PRESET2.risingEdge) {
|
||||
lengthTarget = 10000;
|
||||
guide_setWindingWidth(guide_targetLength2WindingWidth(lengthTarget));
|
||||
buzzer.beep(lengthTarget/1000, 25, 30);
|
||||
displayBot.blink(2, 100, 100, "S0LL ");
|
||||
}
|
||||
else if (SW_PRESET3.risingEdge) {
|
||||
lengthTarget = 15000;
|
||||
guide_setWindingWidth(guide_targetLength2WindingWidth(lengthTarget));
|
||||
buzzer.beep(lengthTarget/1000, 25, 30);
|
||||
displayBot.blink(2, 100, 100, "S0LL ");
|
||||
}
|
||||
@ -517,10 +485,6 @@ void task_control(void *pvParameter)
|
||||
if (controlState == systemState_t::AUTO_CUT_WAITING) {
|
||||
displayTop.blinkStrings(" CUT 1N ", " ", 70, 30);
|
||||
}
|
||||
//setting winding width: blink info message
|
||||
else if (SW_SET.state && SW_PRESET1.state){
|
||||
displayTop.blinkStrings("SET WIND", " WIDTH ", 900, 900);
|
||||
}
|
||||
//otherwise show current position
|
||||
else {
|
||||
sprintf(buf_tmp, "1ST %5.4f", (float)lengthNow/1000);
|
||||
@ -535,8 +499,17 @@ void task_control(void *pvParameter)
|
||||
//--------------------------
|
||||
//run handle function
|
||||
displayBot.handle();
|
||||
//setting target length: blink target length
|
||||
if (SW_SET.state == true) {
|
||||
sprintf(buf_tmp, "S0LL%5.3f", (float)lengthTarget/1000);
|
||||
displayBot.blinkStrings(buf_tmp, "S0LL ", 300, 100);
|
||||
}
|
||||
//manual state: blink "manual"
|
||||
else if (controlState == systemState_t::MANUAL) {
|
||||
displayBot.blinkStrings(" MANUAL ", buf_disp2, 400, 800);
|
||||
}
|
||||
//notify that cutter is active
|
||||
if (cutter_isRunning()) {
|
||||
else if (cutter_isRunning()) {
|
||||
displayBot.blinkStrings("CUTTING]", "CUTTING[", 100, 100);
|
||||
}
|
||||
//show ms countdown to cut when pending
|
||||
@ -545,20 +518,6 @@ void task_control(void *pvParameter)
|
||||
//displayBot.showString(buf_disp2); //TODO:blink "erreicht" overrides this. for now using blink as workaround
|
||||
displayBot.blinkStrings(buf_disp2, buf_disp2, 100, 100);
|
||||
}
|
||||
//manual state: blink "manual"
|
||||
else if (controlState == systemState_t::MANUAL) {
|
||||
displayBot.blinkStrings(" MANUAL ", buf_disp2, 400, 800);
|
||||
}
|
||||
//setting winding width: blink currently set windingWidth
|
||||
else if (SW_SET.state && SW_PRESET1.state){
|
||||
sprintf(buf_tmp, " %03d mm", guide_getWindingWidth());
|
||||
displayBot.blinkStrings(buf_tmp, " ", 300, 100);
|
||||
}
|
||||
//setting target length: blink target length
|
||||
else if (SW_SET.state == true) {
|
||||
sprintf(buf_tmp, "S0LL%5.3f", (float)lengthTarget/1000);
|
||||
displayBot.blinkStrings(buf_tmp, "S0LL ", 300, 100);
|
||||
}
|
||||
//otherwise show target length
|
||||
else {
|
||||
//sprintf(buf_disp2, "%06.1f cm", (float)lengthTarget/10); //cm
|
||||
|
@ -77,3 +77,12 @@ void encoder_reset(){
|
||||
rotary_encoder_reset(&encoder);
|
||||
return;
|
||||
}
|
||||
|
||||
//========================
|
||||
//==== encoder_setPos ====
|
||||
//========================
|
||||
//set encoder position to certain Steps
|
||||
void encoder_setPos(uint32_t posNew){
|
||||
rotary_encoder_set_position(&encoder, posNew);
|
||||
return;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
extern "C" {
|
||||
#include <freertos/task.h>
|
||||
#include "freertos/queue.h"
|
||||
}
|
||||
|
||||
|
||||
@ -36,3 +37,7 @@ int encoder_getLenMm();
|
||||
//--- encoder_reset ---
|
||||
//reset counted steps / length to 0
|
||||
void encoder_reset();
|
||||
|
||||
//--- encoder_setPos ---
|
||||
//set encoder position to certain Steps
|
||||
void encoder_setPos(uint32_t posNew);
|
@ -6,7 +6,6 @@ extern "C"
|
||||
#include "esp_log.h"
|
||||
#include "driver/adc.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
}
|
||||
|
||||
#include "stepper.hpp"
|
||||
@ -24,23 +23,35 @@ extern "C"
|
||||
//--- configuration ---
|
||||
//---------------------
|
||||
//also see config.h
|
||||
//for pin definitions and guide parameters
|
||||
//for pin definition
|
||||
|
||||
// configure testing modes
|
||||
#define STEPPER_TEST_TRAVEL 65 // mm
|
||||
|
||||
#define MIN_MM 0 //TODO add feature so guide stays at zero for some steps (negative MIN_MM?), currently seems appropriate for even winding
|
||||
#define MAX_MM 95 //actual reel is 110, but currently guide turned out to stay at max position for too long
|
||||
#define POS_MAX_STEPS MAX_MM * STEPPER_STEPS_PER_MM
|
||||
#define POS_MIN_STEPS MIN_MM * STEPPER_STEPS_PER_MM
|
||||
|
||||
//tolerance added to last stored position at previous shutdown.
|
||||
//When calibrating at startup the stepper moves for that sum to get track of zero position (ensure crashes into hardware limit for at least some time)
|
||||
#define AUTO_HOME_TRAVEL_ADD_TO_LAST_POS_MM 20
|
||||
#define MAX_TOTAL_AXIS_TRAVEL_MM 103 //max possible travel distance, needed for auto-home
|
||||
|
||||
// speeds for testing with potentiometer (test task only)
|
||||
#define SPEED_MIN 2.0 // mm/s
|
||||
#define SPEED_MAX 70.0 // mm/s
|
||||
//note: actual speed is currently defined in config.h with STEPPER_SPEED_DEFAULT
|
||||
|
||||
#define LAYER_THICKNESS_MM 5 //height of one cable layer on reel -> increase in radius
|
||||
#define D_CABLE 6
|
||||
#define D_REEL 160
|
||||
#define PI 3.14159
|
||||
|
||||
|
||||
//simulate encoder with reset button to test stepper ctl task
|
||||
//note STEPPER_TEST has to be defined as well
|
||||
//#define STEPPER_SIMULATE_ENCODER
|
||||
|
||||
#define PI 3.14159
|
||||
//#define POS_MAX_STEPS GUIDE_MAX_MM * STEPPER_STEPS_PER_MM //note replaced with posMaxSteps
|
||||
#define POS_MIN_STEPS GUIDE_MIN_MM * STEPPER_STEPS_PER_MM
|
||||
|
||||
|
||||
//----------------------
|
||||
//----- variables ------
|
||||
//----------------------
|
||||
@ -53,15 +64,14 @@ static uint32_t posNow = 0;
|
||||
|
||||
static int layerCount = 0;
|
||||
|
||||
// store optimal distance traveled when homing (determined by last pos in nvs)
|
||||
static int homeTravelDistance = MAX_TOTAL_AXIS_TRAVEL_MM;
|
||||
// track if already homed (either homes at startup or at first reset when there is still cable on the reel)
|
||||
static bool axisIsHomed = false;
|
||||
|
||||
// queue for sending commands to task handling guide movement
|
||||
static QueueHandle_t queue_commandsGuideTask;
|
||||
|
||||
// mutex to prevent multiple axis to config variables also accessed/modified by control task
|
||||
SemaphoreHandle_t configVariables_mutex = xSemaphoreCreateMutex();
|
||||
|
||||
// configured winding width: position the axis returns again in steps
|
||||
static uint32_t posMaxSteps = GUIDE_MAX_MM * STEPPER_STEPS_PER_MM; //assign default width
|
||||
|
||||
|
||||
//----------------------
|
||||
//----- functions ------
|
||||
@ -77,73 +87,18 @@ int guide_getAxisPosSteps(){
|
||||
}
|
||||
|
||||
|
||||
//=============================
|
||||
//=== guide_setWindingWidth ===
|
||||
//=============================
|
||||
// set custom winding width (axis position the guide returns in mm)
|
||||
void guide_setWindingWidth(uint8_t maxPosMm)
|
||||
{
|
||||
if (xSemaphoreTake(configVariables_mutex, portMAX_DELAY) == pdTRUE) // mutex to prevent multiple access by control and stepper-ctl task
|
||||
{
|
||||
posMaxSteps = maxPosMm * STEPPER_STEPS_PER_MM;
|
||||
ESP_LOGI(TAG, "set winding width / max pos to %dmm", maxPosMm);
|
||||
xSemaphoreGive(configVariables_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=======================================
|
||||
//=== guide_targetLength2WindingWidth ===
|
||||
//=======================================
|
||||
// calculate dynamic winding width in mm from cable length in mm
|
||||
uint8_t guide_targetLength2WindingWidth(int lenMm)
|
||||
{
|
||||
#ifdef DYNAMIC_WINDING_WIDTH_ENABLED
|
||||
uint8_t width;
|
||||
//--- config ---
|
||||
// define thresholds for winding widths according to target length:
|
||||
if (lenMm <= 5000) // 0-5m
|
||||
width = 15;
|
||||
else if (lenMm <= 10000) // 6-10m
|
||||
width = 25;
|
||||
else if (lenMm <= 15000) // 11-15m
|
||||
width = 30;
|
||||
else if (lenMm <= 25000) // 16-25m
|
||||
width = 65;
|
||||
else // >25m
|
||||
width = GUIDE_MAX_MM;
|
||||
ESP_LOGW(TAG, "length2width: calculated windingWidth=%dmm from targetLength=%dm", width, lenMm);
|
||||
return width;
|
||||
#else
|
||||
ESP_LOGD(TAG, "length2width: dynamic windingWidh not enabled, stay at GUIDE_MAX=%d", GUIDE_MAX_MM);
|
||||
return GUIDE_MAX_MM;
|
||||
#endif
|
||||
//TODO update winding width here as well already?
|
||||
}
|
||||
|
||||
|
||||
//=============================
|
||||
//=== guide_getWindingWidth ===
|
||||
//=============================
|
||||
// get currently configured winding width (axis position at which the guide returns in mm)
|
||||
uint8_t guide_getWindingWidth()
|
||||
{
|
||||
if (xSemaphoreTake(configVariables_mutex, portMAX_DELAY) == pdTRUE) // mutex to prevent multiple access by control and stepper-ctl task
|
||||
{
|
||||
uint8_t returnValue = posMaxSteps / STEPPER_STEPS_PER_MM;
|
||||
xSemaphoreGive(configVariables_mutex);
|
||||
return returnValue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//==========================
|
||||
//==== guide_moveToZero ====
|
||||
//==========================
|
||||
//tell stepper-control task to move cable guide to zero position
|
||||
void guide_moveToZero(){
|
||||
bool valueToSend = true; // or false
|
||||
//home axis first if not done already at startup
|
||||
if (!axisIsHomed){
|
||||
ESP_LOGW(TAG, "moveToZero: Axis not homed yet due to high previous length -> homing now");
|
||||
stepper_home(homeTravelDistance);
|
||||
axisIsHomed = true;
|
||||
}
|
||||
bool valueToSend = true; // or false - currently not relevant
|
||||
xQueueSend(queue_commandsGuideTask, &valueToSend, portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "sending command to stepper_ctl task via queue");
|
||||
}
|
||||
@ -157,12 +112,6 @@ void travelSteps(int stepsTarget){
|
||||
//TODO simplify this function, one simple calculation of new position?
|
||||
//with new custom driver no need to detect direction change
|
||||
|
||||
// cancel when width is zero or no steps received
|
||||
if (posMaxSteps == 0 || stepsTarget == 0){
|
||||
ESP_LOGD(TAG, "travelSteps: MaxSteps or stepsTarget = 0 -> nothing to do");
|
||||
return;
|
||||
}
|
||||
|
||||
int stepsToGo, remaining;
|
||||
|
||||
stepsToGo = abs(stepsTarget);
|
||||
@ -175,12 +124,11 @@ void travelSteps(int stepsTarget){
|
||||
while (stepsToGo != 0){
|
||||
//--- currently moving right ---
|
||||
if (currentAxisDirection == AXIS_MOVING_RIGHT){ //currently moving right
|
||||
if (xSemaphoreTake(configVariables_mutex, portMAX_DELAY) == pdTRUE) { //prevent multiple acces on posMaxSteps by control-task
|
||||
remaining = posMaxSteps - posNow; //calc remaining distance fom current position to limit
|
||||
remaining = POS_MAX_STEPS - posNow; //calc remaining distance fom current position to limit
|
||||
if (stepsToGo > remaining){ //new distance will exceed limit
|
||||
stepper_setTargetPosSteps(posMaxSteps); //move to limit
|
||||
stepper_setTargetPosSteps(POS_MAX_STEPS); //move to limit
|
||||
stepper_waitForStop(1000);
|
||||
posNow = posMaxSteps;
|
||||
posNow = POS_MAX_STEPS;
|
||||
currentAxisDirection = AXIS_MOVING_LEFT; //change current direction for next iteration
|
||||
//increment/decrement layer count depending on current cable direction
|
||||
layerCount += (stepsTarget > 0) - (stepsTarget < 0);
|
||||
@ -194,8 +142,6 @@ void travelSteps(int stepsTarget){
|
||||
posNow += stepsToGo;
|
||||
stepsToGo = 0; //finished, reset target length (could as well exit loop/break)
|
||||
}
|
||||
xSemaphoreGive(configVariables_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
//--- currently moving left ---
|
||||
@ -230,6 +176,32 @@ void travelSteps(int stepsTarget){
|
||||
}
|
||||
|
||||
|
||||
//------------------------
|
||||
//---- lengthToLayers ----
|
||||
//------------------------
|
||||
// calculate cable layers on reel from a certain cable length
|
||||
// TODO: currently assumes windingWidth is constant (MAX_MM)
|
||||
uint16_t lengthToLayers(float lengthMm){
|
||||
float windingWidth = MAX_MM;
|
||||
uint16_t layerCount = 0;
|
||||
//cable length required for one layer
|
||||
float lenNextLayer = (PI * D_REEL) * (windingWidth / D_CABLE);
|
||||
uint32_t lengthRemaining = lengthMm;
|
||||
|
||||
while (lengthRemaining >= lenNextLayer){
|
||||
float lenThisLayer = lenNextLayer;
|
||||
lengthRemaining -= lenThisLayer;
|
||||
layerCount++;
|
||||
|
||||
float currentDiameter = D_REEL + LAYER_THICKNESS_MM * 2 * layerCount;
|
||||
lenNextLayer = (PI * currentDiameter) * windingWidth/D_CABLE;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "lengthToLayers: calculated %d layers from length=%.1fm, windWidth=%.1fmm, D-cable=%dmm, D-start=%dmm", layerCount, lengthMm/1000, windingWidth, D_CABLE, D_REEL);
|
||||
return layerCount;
|
||||
}
|
||||
|
||||
|
||||
//------------------
|
||||
//---- travelMm ----
|
||||
//------------------
|
||||
@ -367,9 +339,10 @@ void task_stepper_ctl(void *pvParameter)
|
||||
|
||||
|
||||
|
||||
//initialize stepper at task start
|
||||
//-- initialize stepper --
|
||||
init_stepper();
|
||||
//define zero-position
|
||||
|
||||
//-- consider axis-position at last shutdown --
|
||||
// use last known position stored at last shutdown to reduce time crashing into hardware limit
|
||||
int posLastShutdown = nvsReadLastAxisPosSteps();
|
||||
if (posLastShutdown >= 0)
|
||||
@ -378,26 +351,28 @@ void task_stepper_ctl(void *pvParameter)
|
||||
posLastShutdown / STEPPER_STEPS_PER_MM,
|
||||
AUTO_HOME_TRAVEL_ADD_TO_LAST_POS_MM);
|
||||
// home considering last position and offset, but limit to max distance possible
|
||||
stepper_home(MIN((posLastShutdown/STEPPER_STEPS_PER_MM + AUTO_HOME_TRAVEL_ADD_TO_LAST_POS_MM), MAX_TOTAL_AXIS_TRAVEL_MM));
|
||||
homeTravelDistance = MIN((posLastShutdown/STEPPER_STEPS_PER_MM + AUTO_HOME_TRAVEL_ADD_TO_LAST_POS_MM), MAX_TOTAL_AXIS_TRAVEL_MM);
|
||||
}
|
||||
else { // default to max travel when read from nvs failed
|
||||
stepper_home(MAX_TOTAL_AXIS_TRAVEL_MM);
|
||||
homeTravelDistance = MAX_TOTAL_AXIS_TRAVEL_MM; //note: is default value anyways
|
||||
}
|
||||
|
||||
//-- consider measured length at last shutdown --
|
||||
//read length at last power-off
|
||||
int encoderPosLastShutdown = nvsReadLastEncoderSteps();
|
||||
// when significant length stored: calculate layer count, dont home stepper yet (only at next RESET button press)
|
||||
if (encoderPosLastShutdown > 2*ENCODER_STEPS_PER_METER){
|
||||
layerCount = lengthToLayers((float)encoderPosLastShutdown/ENCODER_STEPS_PER_METER * 1000);
|
||||
ESP_LOGW(TAG, "last stored length is %.1fm -> set layer count to %d", (float)encoderPosLastShutdown/ENCODER_STEPS_PER_METER, layerCount);
|
||||
}
|
||||
else { //last stored length is not significant: home stepper
|
||||
stepper_home(homeTravelDistance);
|
||||
axisIsHomed = true;
|
||||
}
|
||||
|
||||
//repeatedly read changes in measured cable length and move axis accordingly
|
||||
while(1){
|
||||
|
||||
// guide is disabled when posMaxSteps is zero:
|
||||
if (posMaxSteps == 0)
|
||||
{
|
||||
// move to starting position
|
||||
stepper_setTargetPosSteps(0);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "posMaxSteps is zero -> guide disabled, doing nothing");
|
||||
// stop loop iteration
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef STEPPER_SIMULATE_ENCODER
|
||||
//TESTING - simulate encoder using switch
|
||||
SW_RESET.handle();
|
||||
|
@ -15,16 +15,6 @@ void task_stepper_ctl(void *pvParameter);
|
||||
//tell stepper-control task to move cable guide to zero position
|
||||
void guide_moveToZero();
|
||||
|
||||
|
||||
// return local variable posNow that stores the current position of cable guide axis in steps
|
||||
// needed by shutdown to store last axis position in nvs
|
||||
int guide_getAxisPosSteps();
|
||||
|
||||
// set custom winding width (axis position the guide returns in mm)
|
||||
void guide_setWindingWidth(uint8_t maxPosMm);
|
||||
|
||||
// get currently configured winding width (axis position the guide returns in mm)
|
||||
uint8_t guide_getWindingWidth();
|
||||
|
||||
// calculate dynamic winding width in mm from cable length in mm according to fixed thresholds
|
||||
uint8_t guide_targetLength2WindingWidth(int lenMm);
|
@ -11,6 +11,7 @@ extern "C"
|
||||
}
|
||||
|
||||
#include "config.h"
|
||||
#include "encoder.hpp"
|
||||
#include "shutdown.hpp"
|
||||
|
||||
#include "guide-stepper.hpp"
|
||||
@ -34,10 +35,28 @@ void nvsWriteLastAxisPos(uint32_t value)
|
||||
ESP_LOGE(TAG, "nvs: failed committing updates");
|
||||
else
|
||||
ESP_LOGI(TAG, "nvs: successfully committed updates");
|
||||
ESP_LOGW(TAG, "updated value in nvs to %d", value);
|
||||
ESP_LOGW(TAG, "updated value 'lastPosSteps' in nvs to %d", value);
|
||||
}
|
||||
|
||||
|
||||
// store a u32 value in nvs as "lastEncoderSteps"
|
||||
// TODO remove duplicate code
|
||||
void nvsWriteLastEncoderSteps(uint32_t value)
|
||||
{
|
||||
// update nvs value
|
||||
esp_err_t err = nvs_set_u32(nvsHandle, "lastEncoderSteps", value);
|
||||
if (err != ESP_OK)
|
||||
ESP_LOGE(TAG, "nvs: failed writing");
|
||||
err = nvs_commit(nvsHandle);
|
||||
if (err != ESP_OK)
|
||||
ESP_LOGE(TAG, "nvs: failed committing updates");
|
||||
else
|
||||
ESP_LOGI(TAG, "nvs: successfully committed updates");
|
||||
ESP_LOGW(TAG, "updated value 'lastEncoderSteps' in nvs to %d", value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// read "lastPosSteps" from nvs, returns -1 if failed
|
||||
int nvsReadLastAxisPosSteps()
|
||||
@ -61,6 +80,29 @@ int nvsReadLastAxisPosSteps()
|
||||
}
|
||||
|
||||
|
||||
// read "lastEncoderSteps" from nvs, returns -1 if failed
|
||||
// TODO remove duplicate code
|
||||
int nvsReadLastEncoderSteps()
|
||||
{
|
||||
uint32_t valueRead;
|
||||
esp_err_t err = nvs_get_u32(nvsHandle, "lastEncoderSteps", &valueRead);
|
||||
switch (err)
|
||||
{
|
||||
case ESP_OK:
|
||||
ESP_LOGW(TAG, "Successfully read value %d from nvs", valueRead);
|
||||
return valueRead;
|
||||
break;
|
||||
case ESP_ERR_NVS_NOT_FOUND:
|
||||
ESP_LOGE(TAG, "nvs: the value '%s' is not initialized yet", "lastEncoderSteps");
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Error (%s) reading nvs!", esp_err_to_name(err));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// task that repeatedly checks supply voltage (12V) and saves certain values to nvs in case of power off detected
|
||||
// note: with the 2200uF capacitor in the 12V supply and measuring if 12V start do drop here, there is more than enough time to take action until the 3v3 regulator turns off
|
||||
@ -101,7 +143,8 @@ void task_shutDownDetection(void *pvParameter)
|
||||
// write to nvs and log once at change to below
|
||||
if (!voltageBelowThreshold){
|
||||
nvsWriteLastAxisPos(guide_getAxisPosSteps());
|
||||
ESP_LOGE(TAG, "voltage now below threshold! now=%d threshold=%d -> wrote last axis-pos to nvs", adc_reading, ADC_LOW_VOLTAGE_THRESHOLD);
|
||||
nvsWriteLastEncoderSteps(encoder_getSteps());
|
||||
ESP_LOGE(TAG, "voltage now below threshold! now=%d threshold=%d -> wrote last axis-pos and encoder-steps to nvs", adc_reading, ADC_LOW_VOLTAGE_THRESHOLD);
|
||||
voltageBelowThreshold = true;
|
||||
}
|
||||
}
|
||||
|
@ -5,3 +5,6 @@ void task_shutDownDetection(void *pvParameter);
|
||||
// read last axis position in steps from nvs
|
||||
// returns -1 when reading from nvs failed
|
||||
int nvsReadLastAxisPosSteps();
|
||||
|
||||
// read last encoder steps from nvs
|
||||
int nvsReadLastEncoderSteps();
|
Loading…
x
Reference in New Issue
Block a user