Optimize filament sensor implementation

- remove virtual methods (we only have one fsensor implementation at a time)
- comment out some of the debugging texts
- remove volatile and replace them with proper synchronized access to relevant variables
This commit is contained in:
D.R.racer 2022-08-24 10:07:24 +02:00
parent 2662e09f1e
commit 70532333dc
2 changed files with 74 additions and 107 deletions

View File

@ -41,9 +41,9 @@ FSensorBlockRunout::~FSensorBlockRunout() { }
void Filament_sensor::setEnabled(bool enabled) { void Filament_sensor::setEnabled(bool enabled) {
eeprom_update_byte((uint8_t *)EEPROM_FSENSOR, enabled); eeprom_update_byte((uint8_t *)EEPROM_FSENSOR, enabled);
if (enabled) { if (enabled) {
init(); fsensor.init();
} else { } else {
deinit(); fsensor.deinit();
} }
} }
@ -89,16 +89,16 @@ bool Filament_sensor::checkFilamentEvents() {
return false; return false;
} }
bool newFilamentPresent = getFilamentPresent(); bool newFilamentPresent = fsensor.getFilamentPresent();
if (oldFilamentPresent != newFilamentPresent) { if (oldFilamentPresent != newFilamentPresent) {
oldFilamentPresent = newFilamentPresent; oldFilamentPresent = newFilamentPresent;
eventBlankingTimer.start(); eventBlankingTimer.start();
if (newFilamentPresent) { // filament insertion if (newFilamentPresent) { // filament insertion
puts_P(PSTR("filament inserted")); // puts_P(PSTR("filament inserted"));
triggerFilamentInserted(); triggerFilamentInserted();
postponedLoadEvent = true; postponedLoadEvent = true;
} else { // filament removal } else { // filament removal
puts_P(PSTR("filament removed")); // puts_P(PSTR("filament removed"));
triggerFilamentRemoved(); triggerFilamentRemoved();
} }
return true; return true;
@ -111,7 +111,7 @@ void Filament_sensor::triggerFilamentInserted() {
&& (eFilamentAction == FilamentAction::None) && (eFilamentAction == FilamentAction::None)
&& (! MMU2::mmu2.Enabled() ) // quick and dirty hack to prevent spurious runouts while the MMU is in charge && (! MMU2::mmu2.Enabled() ) // quick and dirty hack to prevent spurious runouts while the MMU is in charge
&& !( && !(
moves_planned() moves_planned() != 0
|| IS_SD_PRINTING || IS_SD_PRINTING
|| usb_timer.running() || usb_timer.running()
|| (lcd_commands_type == LcdCommands::Layer1Cal) || (lcd_commands_type == LcdCommands::Layer1Cal)
@ -129,7 +129,7 @@ void Filament_sensor::triggerFilamentRemoved() {
&& (eFilamentAction == FilamentAction::None) && (eFilamentAction == FilamentAction::None)
&& !saved_printing && !saved_printing
&& ( && (
moves_planned() moves_planned() != 0
|| IS_SD_PRINTING || IS_SD_PRINTING
|| usb_timer.running() || usb_timer.running()
|| (lcd_commands_type == LcdCommands::Layer1Cal) || (lcd_commands_type == LcdCommands::Layer1Cal)
@ -175,16 +175,16 @@ void Filament_sensor::triggerError() {
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG) #if (FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
void IR_sensor::init() { void IR_sensor::init() {
if (state == State::error) { if (state == State::error) {
deinit(); // deinit first if there was an error. fsensor.deinit(); // deinit first if there was an error.
} }
puts_P(PSTR("fsensor::init()")); // puts_P(PSTR("fsensor::init()"));
SET_INPUT(IR_SENSOR_PIN); // input mode SET_INPUT(IR_SENSOR_PIN); // input mode
WRITE(IR_SENSOR_PIN, 1); // pullup WRITE(IR_SENSOR_PIN, 1); // pullup
settings_init(); // also sets the state to State::initializing settings_init(); // also sets the state to State::initializing
} }
void IR_sensor::deinit() { void IR_sensor::deinit() {
puts_P(PSTR("fsensor::deinit()")); // puts_P(PSTR("fsensor::deinit()"));
SET_INPUT(IR_SENSOR_PIN); // input mode SET_INPUT(IR_SENSOR_PIN); // input mode
WRITE(IR_SENSOR_PIN, 0); // no pullup WRITE(IR_SENSOR_PIN, 0); // no pullup
state = State::disabled; state = State::disabled;
@ -194,16 +194,12 @@ bool IR_sensor::update() {
switch (state) { switch (state) {
case State::initializing: case State::initializing:
state = State::ready; // the IR sensor gets ready instantly as it's just a gpio read operation. state = State::ready; // the IR sensor gets ready instantly as it's just a gpio read operation.
oldFilamentPresent = // initialize the current filament state so that we don't create a switching event right after the sensor is ready.
getFilamentPresent(); // initialize the current filament state so that we don't create a switching event right after the sensor is ready. oldFilamentPresent = fsensor.getFilamentPresent();
// fallthru [[fallthrough]];
case State::ready: { case State::ready: {
postponedLoadEvent = false; postponedLoadEvent = false;
bool event = checkFilamentEvents(); return checkFilamentEvents();
; //
return event;
} break; } break;
case State::disabled: case State::disabled:
case State::error: case State::error:
@ -213,7 +209,7 @@ bool IR_sensor::update() {
return false; return false;
} }
bool IR_sensor::getFilamentPresent() { return !READ(IR_SENSOR_PIN); }
#ifdef FSENSOR_PROBING #ifdef FSENSOR_PROBING
bool IR_sensor::probeOtherType() { return pat9125_probe(); } bool IR_sensor::probeOtherType() { return pat9125_probe(); }
@ -224,16 +220,15 @@ void IR_sensor::settings_init() { Filament_sensor::settings_init_common(); }
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG) #if (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
void IR_sensor_analog::init() { void IR_sensor_analog::init() {
IR_sensor::init(); IR_sensor::init();
settings_init(); IR_sensor::settings_init();
sensorRevision = (SensorRevision)eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_PCB);
} }
void IR_sensor_analog::deinit() { IR_sensor::deinit(); }
bool IR_sensor_analog::update() { bool IR_sensor_analog::update() {
bool event = IR_sensor::update(); bool event = IR_sensor::update();
if (state == State::ready) { if (state == State::ready) {
if (voltReady) { if (getVoltReady()) {
voltReady = false; clearVoltReady();
uint16_t volt = getVoltRaw(); uint16_t volt = getVoltRaw();
// printf_P(PSTR("newVoltRaw:%u\n"), volt / OVERSAMPLENR); // printf_P(PSTR("newVoltRaw:%u\n"), volt / OVERSAMPLENR);
@ -282,14 +277,7 @@ void IR_sensor_analog::voltUpdate(uint16_t raw) { // to be called from the ADC I
} }
uint16_t IR_sensor_analog::getVoltRaw() { uint16_t IR_sensor_analog::getVoltRaw() {
uint16_t newVoltRaw; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { return voltRaw; }
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { newVoltRaw = voltRaw; }
return newVoltRaw;
}
void IR_sensor_analog::settings_init() {
IR_sensor::settings_init();
sensorRevision = (SensorRevision)eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_PCB);
} }
const char *IR_sensor_analog::getIRVersionText() { const char *IR_sensor_analog::getIRVersionText() {
@ -349,6 +337,14 @@ bool IR_sensor_analog::checkVoltage(uint16_t raw) {
return true; return true;
} }
bool IR_sensor_analog::getVoltReady() const {
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ return voltReady; }
}
void IR_sensor_analog::clearVoltReady(){
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ voltReady = false; }
}
void IR_sensor_analog::IR_ANALOG_Check(SensorRevision isVersion, SensorRevision switchTo) { void IR_sensor_analog::IR_ANALOG_Check(SensorRevision isVersion, SensorRevision switchTo) {
bool bTemp = (!CHECK_ALL_HEATERS); bool bTemp = (!CHECK_ALL_HEATERS);
bTemp = bTemp && (menu_menu == lcd_status_screen); bTemp = bTemp && (menu_menu == lcd_status_screen);
@ -383,7 +379,7 @@ void PAT9125_sensor::init() {
if (state == State::error) { if (state == State::error) {
deinit(); // deinit first if there was an error. deinit(); // deinit first if there was an error.
} }
puts_P(PSTR("fsensor::init()")); // puts_P(PSTR("fsensor::init()"));
settings_init(); // also sets the state to State::initializing settings_init(); // also sets the state to State::initializing
@ -402,7 +398,7 @@ void PAT9125_sensor::init() {
} }
void PAT9125_sensor::deinit() { void PAT9125_sensor::deinit() {
puts_P(PSTR("fsensor::deinit()")); // puts_P(PSTR("fsensor::deinit()"));
; // ; //
state = State::disabled; state = State::disabled;
filter = 0; filter = 0;
@ -459,15 +455,13 @@ void PAT9125_sensor::setJamDetectionEnabled(bool state, bool updateEEPROM) {
} }
void PAT9125_sensor::settings_init() { void PAT9125_sensor::settings_init() {
puts_P(PSTR("settings_init")); // puts_P(PSTR("settings_init"));
Filament_sensor::settings_init_common(); Filament_sensor::settings_init_common();
setJamDetectionEnabled(eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_JAM_DETECTION)); setJamDetectionEnabled(eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_JAM_DETECTION));
} }
int16_t PAT9125_sensor::getStepCount() { int16_t PAT9125_sensor::getStepCount() {
int16_t st_cnt; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { return stepCount; }
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { st_cnt = stepCount; }
return st_cnt;
} }
void PAT9125_sensor::resetStepCount() { void PAT9125_sensor::resetStepCount() {

View File

@ -20,17 +20,17 @@ public:
~FSensorBlockRunout(); ~FSensorBlockRunout();
}; };
/// Base class Filament sensor
///
/// Ideally, there could have been a nice class hierarchy of filament sensor types with common functionality
/// extracted into this base class.
/// But:
/// - virtual methods take more space
/// - we don't need to switch among different filament sensors at runtime
/// Therefore the class hierarchy carefully avoids using virtual methods and doesn't look too fancy.
#ifdef FILAMENT_SENSOR #ifdef FILAMENT_SENSOR
class Filament_sensor { class Filament_sensor {
public: public:
virtual void init() = 0;
virtual void deinit() = 0;
virtual bool update() = 0;
virtual bool getFilamentPresent() = 0;
#ifdef FSENSOR_PROBING
virtual bool probeOtherType() = 0; //checks if the wrong fsensor type is detected.
#endif
enum class State : uint8_t { enum class State : uint8_t {
disabled = 0, disabled = 0,
initializing, initializing,
@ -44,41 +44,22 @@ public:
_Undef = EEPROM_EMPTY_VALUE _Undef = EEPROM_EMPTY_VALUE
}; };
void setEnabled(bool enabled); static void setEnabled(bool enabled);
void setAutoLoadEnabled(bool state, bool updateEEPROM = false); void setAutoLoadEnabled(bool state, bool updateEEPROM = false);
bool getAutoLoadEnabled() const { return autoLoadEnabled; }
bool getAutoLoadEnabled() {
return autoLoadEnabled;
}
void setRunoutEnabled(bool state, bool updateEEPROM = false); void setRunoutEnabled(bool state, bool updateEEPROM = false);
bool getRunoutEnabled() const { return runoutEnabled; }
bool getRunoutEnabled() {
return runoutEnabled;
}
void setActionOnError(SensorActionOnError state, bool updateEEPROM = false); void setActionOnError(SensorActionOnError state, bool updateEEPROM = false);
SensorActionOnError getActionOnError() const { return sensorActionOnError; }
SensorActionOnError getActionOnError() { bool getFilamentLoadEvent() const { return postponedLoadEvent; }
return sensorActionOnError;
}
bool getFilamentLoadEvent() { bool isError() const { return state == State::error; }
return postponedLoadEvent; bool isReady() const { return state == State::ready; }
} bool isEnabled() const { return state != State::disabled; }
bool isError() {
return state == State::error;
}
bool isReady() {
return state == State::ready;
}
bool isEnabled() {
return state != State::disabled;
}
protected: protected:
void settings_init_common(); void settings_init_common();
@ -89,7 +70,7 @@ protected:
void triggerFilamentRemoved(); void triggerFilamentRemoved();
void filAutoLoad(); static void filAutoLoad();
void filRunout(); void filRunout();
@ -107,12 +88,12 @@ protected:
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG) #if (FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
class IR_sensor: public Filament_sensor { class IR_sensor: public Filament_sensor {
public: public:
void init() override; void init();
void deinit() override; void deinit();
bool update()override ; bool update();
bool getFilamentPresent()override; bool getFilamentPresent() const { return !READ(IR_SENSOR_PIN); }
#ifdef FSENSOR_PROBING #ifdef FSENSOR_PROBING
bool probeOtherType()override; static bool probeOtherType(); //checks if the wrong fsensor type is detected.
#endif #endif
void settings_init(); void settings_init();
}; };
@ -127,14 +108,11 @@ constexpr static float Raw2Voltage(uint16_t raw) {
class IR_sensor_analog: public IR_sensor { class IR_sensor_analog: public IR_sensor {
public: public:
void init()override; void init();
void deinit()override; bool update();
bool update()override;
void voltUpdate(uint16_t raw); void voltUpdate(uint16_t raw);
uint16_t getVoltRaw(); uint16_t __attribute__((noinline)) getVoltRaw();
void settings_init();
enum class SensorRevision : uint8_t { enum class SensorRevision : uint8_t {
_Old = 0, _Old = 0,
@ -142,17 +120,12 @@ public:
_Undef = EEPROM_EMPTY_VALUE _Undef = EEPROM_EMPTY_VALUE
}; };
SensorRevision getSensorRevision() { SensorRevision getSensorRevision() const { return sensorRevision; }
return sensorRevision;
}
const char* getIRVersionText(); const char* __attribute__((noinline)) getIRVersionText();
void setSensorRevision(SensorRevision rev, bool updateEEPROM = false); void setSensorRevision(SensorRevision rev, bool updateEEPROM = false);
bool checkVoltage(uint16_t raw);
// Voltage2Raw is not constexpr :/
constexpr static uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982 constexpr static uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982
constexpr static uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910 constexpr static uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910
constexpr static uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821 constexpr static uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821
@ -161,8 +134,14 @@ public:
private: private:
SensorRevision sensorRevision; SensorRevision sensorRevision;
volatile bool voltReady; //this gets set by the adc ISR
volatile uint16_t voltRaw; bool voltReady; // set by the adc ISR, therefore avoid accessing the variable directly but use getVoltReady()
bool getVoltReady()const;
void clearVoltReady();
uint16_t voltRaw; // set by the adc ISR, therefore avoid accessing the variable directly but use getVoltRaw()
bool checkVoltage(uint16_t raw);
uint16_t minVolt = Voltage2Raw(6.F); uint16_t minVolt = Voltage2Raw(6.F);
uint16_t maxVolt = 0; uint16_t maxVolt = 0;
uint16_t nFSCheckCount; uint16_t nFSCheckCount;
@ -181,22 +160,16 @@ private:
#if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125) #if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
class PAT9125_sensor: public Filament_sensor { class PAT9125_sensor: public Filament_sensor {
public: public:
void init()override; void init();
void deinit()override; void deinit();
bool update()override; bool update();
bool getFilamentPresent() override{ bool getFilamentPresent() const { return filterFilPresent; }
return filterFilPresent;
}
#ifdef FSENSOR_PROBING #ifdef FSENSOR_PROBING
bool probeOtherType() override; bool probeOtherType(); //checks if the wrong fsensor type is detected.
#endif #endif
void setJamDetectionEnabled(bool state, bool updateEEPROM = false); void setJamDetectionEnabled(bool state, bool updateEEPROM = false);
bool getJamDetectionEnabled() const { return jamDetection; }
bool getJamDetectionEnabled() {
return jamDetection;
}
void stStep(bool rev) { //from stepper isr void stStep(bool rev) { //from stepper isr
stepCount += rev ? -1 : 1; stepCount += rev ? -1 : 1;
@ -212,7 +185,7 @@ private:
bool jamDetection; bool jamDetection;
int16_t oldPos; int16_t oldPos;
volatile int16_t stepCount; int16_t stepCount;
int16_t chunkSteps; int16_t chunkSteps;
uint8_t jamErrCnt; uint8_t jamErrCnt;