Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve filament sensor PCB upgrade logic #3155

Open
wants to merge 6 commits into
base: MK3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 90 additions & 85 deletions Firmware/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9679,42 +9679,94 @@ static void handleSafetyTimer()
#endif //SAFETYTIMER

#ifdef IR_SENSOR_ANALOG
#define FS_CHECK_COUNT 16
/// Switching mechanism of the fsensor type.
/// Called from 2 spots which have a very similar behavior
/// 1: ClFsensorPCB::_Old -> ClFsensorPCB::_Rev04 and print _i("FS v0.4 or newer")
/// 2: ClFsensorPCB::_Rev04 -> oFsensorPCB=ClFsensorPCB::_Old and print _i("FS v0.3 or older")
void manage_inactivity_IR_ANALOG_Check(uint16_t &nFSCheckCount, ClFsensorPCB isVersion, ClFsensorPCB switchTo, const char *statusLineTxt_P) {
bool bTemp = (!CHECK_ALL_HEATERS);
bTemp = bTemp && (menu_menu == lcd_status_screen);
bTemp = bTemp && ((oFsensorPCB == isVersion) || (oFsensorPCB == ClFsensorPCB::_Undef));
bTemp = bTemp && fsensor_enabled;
if (bTemp) {
nFSCheckCount++;
if (nFSCheckCount > FS_CHECK_COUNT) {
nFSCheckCount = 0; // not necessary
oFsensorPCB = switchTo;
void manage_inactivity_IR_ANALOG_CheckPCB()
{
static uint16_t minVolt = Voltage2Raw(6.F), maxVolt = 0;
static ClFsensorPCB nFsensorPCB = oFsensorPCB;
static uint16_t nFSCheckCount = FS_CHECK_COUNT;

// only attempt detection when cold and idling in the status screen
if (!fsensor_enabled || CHECK_ALL_HEATERS || menu_menu != lcd_status_screen)
return;

// detect min-max, some long term sliding window for filtration may be added
// avoiding floating point operations, thus computing in raw
if( current_voltage_raw_IR > maxVolt )maxVolt = current_voltage_raw_IR;
if( current_voltage_raw_IR < minVolt )minVolt = current_voltage_raw_IR;

#if 0 // Start: IR Sensor debug info
{ // debug print
static uint16_t lastVolt = ~0U;
if( current_voltage_raw_IR != lastVolt ){
printf_P(PSTR("fs volt=%4.2fV (min=%4.2f max=%4.2f)\n"), Raw2Voltage(current_voltage_raw_IR), Raw2Voltage(minVolt), Raw2Voltage(maxVolt) );
lastVolt = current_voltage_raw_IR;
}
}
#endif // End: IR Sensor debug info

//! The trouble is, I can hold the filament in the hole in such a way, that it creates the exact voltage
//! to be detected as the new fsensor
//! We can either fake it by extending the detection window to a looooong time
//! or do some other countermeasures
ClFsensorPCB tempFsensorPCB;
const char *statusLineTxt_P;

//! what we want to detect:
//! if minvolt gets below ~0.3V, it means there is an old fsensor
//! if maxvolt gets above 4.6V, it means we either have an old fsensor or broken cables/fsensor
//! So I'm waiting for a situation, when minVolt gets to range <0, 1.5> and maxVolt gets into range <3.0, 5>
//! If and only if minVolt is in range <0.3, 1.5> and maxVolt is in range <3.0, 4.6>, I'm considering a situation with the new fsensor
if( minVolt >= IRsensor_Ldiode_TRESHOLD && minVolt <= IRsensor_Lmax_TRESHOLD
&& maxVolt >= IRsensor_Hmin_TRESHOLD && maxVolt <= IRsensor_Hopen_TRESHOLD
){
tempFsensorPCB = ClFsensorPCB::_Rev04;
statusLineTxt_P = _i("FS v0.4 or newer"); ////MSG_FS_V_04_OR_NEWER c=18
}
//! If and only if minVolt is in range <0.0, 0.3> and maxVolt is in range <4.6, 5.0V>, I'm considering a situation with the old fsensor
//! Note, we are not relying on one voltage here - getting just +5V can mean an old fsensor or a broken new sensor - that's why
//! we need to have both voltages detected correctly to allow switching back to the old fsensor.
else if( minVolt < IRsensor_Ldiode_TRESHOLD
&& maxVolt > IRsensor_Hopen_TRESHOLD && maxVolt <= IRsensor_VMax_TRESHOLD
){
tempFsensorPCB = ClFsensorPCB::_Old;
statusLineTxt_P = _i("FS v0.3 or older"); ////MSG_FS_V_03_OR_OLDER c=18
}
//! Ambiguous range
else
{
tempFsensorPCB = ClFsensorPCB::_Undef;
}

if (tempFsensorPCB != ClFsensorPCB::_Undef)
{
--oFSCheckCount;

if (tempFsensorPCB != nFsensorPCB)
{
// latest detection changed, reset internal counters
nFsensorPCB = tempFsensorPCB;
nFSCheckCount = FS_CHECK_COUNT;
}
else if(!--nFSCheckCount)
{
// consistent PCB match, set detected sensor type and stop attempts
oFSCheckCount = 0;
oFsensorPCB = tempFsensorPCB;
eeprom_update_byte((uint8_t *)EEPROM_FSENSOR_PCB, (uint8_t)oFsensorPCB);
printf_IRSensorAnalogBoardChange();
lcd_setstatuspgm(statusLineTxt_P);
}
} else {
nFSCheckCount = 0;
}
}
#endif

void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h
{
#ifdef FILAMENT_SENSOR
bool bInhibitFlag = false;
#ifdef IR_SENSOR_ANALOG
static uint16_t nFSCheckCount=0;
#endif // IR_SENSOR_ANALOG
bool bInhibitFlag = false;

if (mmu_enabled == false)
{
//-// if (mcode_in_progress != 600) //M600 not in progress
if (!PRINTER_ACTIVE) bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); //Block Filament sensor actions if PRINTER is not active and Support::SensorInfo menu active
#ifdef IR_SENSOR_ANALOG
bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Block Filament sensor actions if Settings::HWsetup::FSdetect menu active
Expand All @@ -9723,80 +9775,33 @@ static uint16_t nFSCheckCount=0;
{
if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal) && ! eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE))
{
// idling: housekeeping and autoload checks
#ifdef IR_SENSOR_ANALOG
static uint16_t minVolt = Voltage2Raw(6.F), maxVolt = 0;
// detect min-max, some long term sliding window for filtration may be added
// avoiding floating point operations, thus computing in raw
if( current_voltage_raw_IR > maxVolt )maxVolt = current_voltage_raw_IR;
if( current_voltage_raw_IR < minVolt )minVolt = current_voltage_raw_IR;

#if 0 // Start: IR Sensor debug info
{ // debug print
static uint16_t lastVolt = ~0U;
if( current_voltage_raw_IR != lastVolt ){
printf_P(PSTR("fs volt=%4.2fV (min=%4.2f max=%4.2f)\n"), Raw2Voltage(current_voltage_raw_IR), Raw2Voltage(minVolt), Raw2Voltage(maxVolt) );
lastVolt = current_voltage_raw_IR;
}
}
#endif // End: IR Sensor debug info
//! The trouble is, I can hold the filament in the hole in such a way, that it creates the exact voltage
//! to be detected as the new fsensor
//! We can either fake it by extending the detection window to a looooong time
//! or do some other countermeasures

//! what we want to detect:
//! if minvolt gets below ~0.3V, it means there is an old fsensor
//! if maxvolt gets above 4.6V, it means we either have an old fsensor or broken cables/fsensor
//! So I'm waiting for a situation, when minVolt gets to range <0, 1.5> and maxVolt gets into range <3.0, 5>
//! If and only if minVolt is in range <0.3, 1.5> and maxVolt is in range <3.0, 4.6>, I'm considering a situation with the new fsensor
if( minVolt >= IRsensor_Ldiode_TRESHOLD && minVolt <= IRsensor_Lmax_TRESHOLD
&& maxVolt >= IRsensor_Hmin_TRESHOLD && maxVolt <= IRsensor_Hopen_TRESHOLD
){
manage_inactivity_IR_ANALOG_Check(nFSCheckCount, ClFsensorPCB::_Old, ClFsensorPCB::_Rev04, _i("FS v0.4 or newer") ); ////MSG_FS_V_04_OR_NEWER c=18
}
//! If and only if minVolt is in range <0.0, 0.3> and maxVolt is in range <4.6, 5.0V>, I'm considering a situation with the old fsensor
//! Note, we are not relying on one voltage here - getting just +5V can mean an old fsensor or a broken new sensor - that's why
//! we need to have both voltages detected correctly to allow switching back to the old fsensor.
else if( minVolt < IRsensor_Ldiode_TRESHOLD
&& maxVolt > IRsensor_Hopen_TRESHOLD && maxVolt <= IRsensor_VMax_TRESHOLD
){
manage_inactivity_IR_ANALOG_Check(nFSCheckCount, ClFsensorPCB::_Rev04, oFsensorPCB=ClFsensorPCB::_Old, _i("FS v0.3 or older")); ////MSG_FS_V_03_OR_OLDER c=18
}
if (oFSCheckCount)
{
// Attempt to detect an upgrade of the filament sensor PCB
manage_inactivity_IR_ANALOG_CheckPCB();
}
#endif // IR_SENSOR_ANALOG
if (fsensor_check_autoload())
{
#ifdef PAT9125
fsensor_autoload_check_stop();
#endif //PAT9125
//-// if (degHotend0() > EXTRUDE_MINTEMP)
if(0)
{
Sound_MakeCustom(50,1000,false);
loading_flag = true;
enquecommand_front_P((PSTR("M701")));
}
else
{
/*
lcd_update_enable(false);
show_preheat_nozzle_warning();
lcd_update_enable(true);
*/
eFilamentAction=FilamentAction::AutoLoad;
bFilamentFirstRun=false;
if(target_temperature[0]>=EXTRUDE_MINTEMP){
bFilamentPreheatState=true;
// mFilamentItem(target_temperature[0],target_temperature_bed);
menu_submenu(mFilamentItemForce);
} else {
menu_submenu(lcd_generic_preheat_menu);
lcd_timeoutToStatus.start();
}
}
eFilamentAction=FilamentAction::AutoLoad;
bFilamentFirstRun=false;
if(target_temperature[0]>=EXTRUDE_MINTEMP){
bFilamentPreheatState=true;
menu_submenu(mFilamentItemForce);
} else {
menu_submenu(lcd_generic_preheat_menu);
lcd_timeoutToStatus.start();
}
}
}
else
{
// printing: runout detection
#ifdef PAT9125
fsensor_autoload_check_stop();
#endif //PAT9125
Expand Down
5 changes: 5 additions & 0 deletions Firmware/fsensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ uint16_t fsensor_oq_sh_sum;
#ifdef IR_SENSOR_ANALOG
ClFsensorPCB oFsensorPCB;
ClFsensorActionNA oFsensorActionNA;
uint16_t oFSCheckCount = FS_CHECK_COUNT * 3;
bool bIRsensorStateFlag=false;
unsigned long nIRsensorLastTime;
#endif //IR_SENSOR_ANALOG
Expand Down Expand Up @@ -208,6 +209,10 @@ void fsensor_init(void)
oFsensorPCB = (ClFsensorPCB)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_PCB);
oFsensorActionNA = (ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA);

// disable checking for PCB updates if already at the newest version
if(oFsensorPCB == ClFsensorPCB::_Newest)
oFSCheckCount = 0;

// If the fsensor is not responding even at the start of the printer,
// set this flag accordingly to show N/A in Settings->Filament sensor.
// This is even valid for both fsensor board revisions (0.3 or older and 0.4).
Expand Down
17 changes: 8 additions & 9 deletions Firmware/fsensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,18 @@ extern uint8_t fsensor_log;
//! @}
#endif //PAT9125

#define VOLT_DIV_REF 5

#ifdef IR_SENSOR_ANALOG
#define IR_SENSOR_STEADY 10 // [ms]

// number of required consistent consecutive filament sensor check attempts
#define FS_CHECK_COUNT 16
// number of remaining filament sensor checks to be done
extern uint16_t oFSCheckCount;

enum class ClFsensorPCB:uint_least8_t
{
_Old=0,
_Rev04=1,
_Rev04=1, _Newest=1,
_Undef=EEPROM_EMPTY_VALUE
};

Expand All @@ -107,12 +110,8 @@ extern ClFsensorActionNA oFsensorActionNA;
extern const char* FsensorIRVersionText();

extern bool fsensor_IR_check();
constexpr uint16_t Voltage2Raw(float V){
return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F;
}
constexpr float Raw2Voltage(uint16_t raw){
return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) );
}

#include "temperature.h"
constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982
constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910
constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821
Expand Down
9 changes: 9 additions & 0 deletions Firmware/temperature.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@

#endif //SYSTEM_TIMER_2

// voltage conversion functions
#define VOLT_DIV_REF 5

constexpr uint16_t Voltage2Raw(float V){
return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F;
}
constexpr float Raw2Voltage(uint16_t raw){
return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) );
}

// public functions
void tp_init(); //initialize the heating
Expand Down
3 changes: 2 additions & 1 deletion Firmware/ultralcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7301,7 +7301,7 @@ void lcd_belttest()
#ifdef IR_SENSOR_ANALOG
// called also from marlin_main.cpp
void printf_IRSensorAnalogBoardChange(){
printf_P(PSTR("Filament sensor board change detected: revision%S\n"), FsensorIRVersionText());
printf_P(PSTR("Filament sensor board change detected: revision %S\n"), FsensorIRVersionText());
}

static bool lcd_selftest_IRsensor(bool bStandalone)
Expand All @@ -7327,6 +7327,7 @@ static bool lcd_selftest_IRsensor(bool bStandalone)
}
if((bPCBrev04 ? 1 : 0) != (uint8_t)oFsensorPCB){ // safer then "(uint8_t)bPCBrev04"
oFsensorPCB=bPCBrev04 ? ClFsensorPCB::_Rev04 : ClFsensorPCB::_Old;
oFSCheckCount = 0;
printf_IRSensorAnalogBoardChange();
eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB);
}
Expand Down