diff --git a/Firmware/Configuration.h b/Firmware/Configuration.h index 8d241bb0..9d087442 100644 --- a/Firmware/Configuration.h +++ b/Firmware/Configuration.h @@ -16,8 +16,8 @@ extern uint16_t nPrinterType; extern PGM_P sPrinterName; // Firmware version -#define FW_VERSION "3.9.0-RC2" -#define FW_COMMIT_NR 3398 +#define FW_VERSION "3.9.0-RC3" +#define FW_COMMIT_NR 3401 // FW_VERSION_UNKNOWN means this is an unofficial build. // The firmware should only be checked into github with this symbol. #define FW_DEV_VERSION FW_VERSION_UNKNOWN diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 0c4e574b..e03e1cd5 100755 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -9448,13 +9448,13 @@ static void handleSafetyTimer() } #endif //SAFETYTIMER -#define FS_CHECK_COUNT 15 +#define FS_CHECK_COUNT 250 void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument set in Marlin.h { #ifdef FILAMENT_SENSOR bool bInhibitFlag; #ifdef IR_SENSOR_ANALOG -static uint8_t nFSCheckCount=0; +static uint16_t nFSCheckCount=0; #endif // IR_SENSOR_ANALOG if (mmu_enabled == false) @@ -9474,25 +9474,53 @@ static uint8_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)) { #ifdef IR_SENSOR_ANALOG - bool bTemp=current_voltage_raw_IR>IRsensor_Hmin_TRESHOLD; - bTemp=bTemp&¤t_voltage_raw_IR maxVolt )maxVolt = current_voltage_raw_IR; + if( current_voltage_raw_IR < minVolt )minVolt = current_voltage_raw_IR; + +#if 0 + { // 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 + // 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.6V, 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, 0.7> and maxVolt gets into range <4.4, 5> + // If and only if minVolt is in range <0.6, 0.7> and maxVolt is in range <4.4, 4.5>, I'm considering a situation with the new fsensor + // otherwise, I don't care + + if( minVolt >= Voltage2Raw(0.3F) && minVolt <= Voltage2Raw(0.5F) + && maxVolt >= Voltage2Raw(4.2F) && maxVolt <= Voltage2Raw(4.6F) + ){ + bool bTemp = (!CHECK_ALL_HEATERS); + bTemp = bTemp && (menu_menu==lcd_status_screen); + bTemp = bTemp && ((oFsensorPCB==ClFsensorPCB::_Old)||(oFsensorPCB==ClFsensorPCB::_Undef)); + bTemp = bTemp && fsensor_enabled; + if(bTemp){ nFSCheckCount++; - if(nFSCheckCount>FS_CHECK_COUNT) - { + if(nFSCheckCount>FS_CHECK_COUNT){ nFSCheckCount=0; // not necessary oFsensorPCB=ClFsensorPCB::_Rev04; eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB); printf_IRSensorAnalogBoardChange(true); lcd_setstatuspgm(_i("FS v0.4 or newer")); } - } - else nFSCheckCount=0; + } else { + nFSCheckCount=0; + } + } #endif // IR_SENSOR_ANALOG if (fsensor_check_autoload()) { diff --git a/Firmware/fsensor.cpp b/Firmware/fsensor.cpp index 0acb9e28..edb2fa89 100755 --- a/Firmware/fsensor.cpp +++ b/Firmware/fsensor.cpp @@ -174,39 +174,46 @@ void fsensor_init(void) { #ifdef PAT9125 uint8_t pat9125 = pat9125_init(); - printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125); + printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125); #endif //PAT9125 - uint8_t fsensor = eeprom_read_byte((uint8_t*)EEPROM_FSENSOR); + uint8_t fsensor_enabled = eeprom_read_byte((uint8_t*)EEPROM_FSENSOR); fsensor_autoload_enabled=eeprom_read_byte((uint8_t*)EEPROM_FSENS_AUTOLOAD_ENABLED); - fsensor_not_responding = false; + fsensor_not_responding = false; #ifdef PAT9125 uint8_t oq_meassure_enabled = eeprom_read_byte((uint8_t*)EEPROM_FSENS_OQ_MEASS_ENABLED); fsensor_oq_meassure_enabled = (oq_meassure_enabled == 1)?true:false; - fsensor_set_axis_steps_per_unit(cs.axis_steps_per_unit[E_AXIS]); - - if (!pat9125) - { - fsensor = 0; //disable sensor + fsensor_set_axis_steps_per_unit(cs.axis_steps_per_unit[E_AXIS]); + + if (!pat9125){ + fsensor_enabled = 0; //disable sensor fsensor_not_responding = true; } #endif //PAT9125 #ifdef IR_SENSOR_ANALOG - bIRsensorStateFlag=false; - oFsensorPCB=(ClFsensorPCB)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_PCB); - oFsensorActionNA=(ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA); + bIRsensorStateFlag=false; + oFsensorPCB = (ClFsensorPCB)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_PCB); + oFsensorActionNA = (ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA); + + // 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). + // Must be done after reading what type of fsensor board we have + fsensor_not_responding = ! fsensor_IR_check(); #endif //IR_SENSOR_ANALOG - if (fsensor) + if (fsensor_enabled){ fsensor_enable(false); // (in this case) EEPROM update is not necessary - else + } else { fsensor_disable(false); // (in this case) EEPROM update is not necessary + } printf_P(PSTR("FSensor %S"), (fsensor_enabled?PSTR("ENABLED"):PSTR("DISABLED"))); #ifdef IR_SENSOR_ANALOG - printf_P(PSTR(" (sensor board revision: %S)\n"),(oFsensorPCB==ClFsensorPCB::_Rev04) ? MSG_04_OR_NEWER : MSG_03_OR_OLDER); + printf_P(PSTR(" (sensor board revision:%S)\n"), (oFsensorPCB==ClFsensorPCB::_Rev04) ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER)); #else //IR_SENSOR_ANALOG printf_P(PSTR("\n")); #endif //IR_SENSOR_ANALOG - if (check_for_ir_sensor()) ir_sensor_detected = true; - + if (check_for_ir_sensor()){ + ir_sensor_detected = true; + } } bool fsensor_enable(bool bUpdateEEPROM) @@ -691,12 +698,16 @@ void fsensor_update(void) ADCSRB=nMUX2; ENABLE_TEMPERATURE_INTERRUPT(); // end of sequence for ... - if((oFsensorPCB==ClFsensorPCB::_Rev04)&&((nADC*OVERSAMPLENR)>((int)IRsensor_Hopen_TRESHOLD))) + // Detection of correct function of fsensor v04 - it must NOT read >4.6V + // If it does, it means a disconnected cables or faulty board + if( (oFsensorPCB == ClFsensorPCB::_Rev04) && ( (nADC*OVERSAMPLENR) > IRsensor_Hopen_TRESHOLD ) ) { fsensor_disable(); fsensor_not_responding = true; printf_P(PSTR("IR sensor not responding (%d)!\n"),1); - if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause) + if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause) + + // if we are printing and FS action is set to "Pause", force pause the print if(oFsensorActionNA==ClFsensorActionNA::_Pause) lcd_pause_print(); } @@ -720,14 +731,27 @@ void fsensor_update(void) } #ifdef IR_SENSOR_ANALOG -bool fsensor_IR_check() -{ -uint16_t volt_IR_int; -bool bCheckResult; +/// This is called only upon start of the printer or when switching the fsensor ON in the menu +/// We cannot do temporal window checks here (aka the voltage has been in some range for a period of time) +bool fsensor_IR_check(){ + if( IRsensor_Lmax_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_Hmin_TRESHOLD ){ + // If the voltage is in forbidden range, the fsensor is ok, but the lever is mounted improperly. + // Or the user is so creative so that he can hold a piece of fillament in the hole in such a genius way, + // that the IR fsensor reading is within 1.5 and 3V ... this would have been highly unusual + // and would have been considered more like a sabotage than normal printer operation + printf_P(PSTR("fsensor in forbidden range 1.5-3V - bad lever\n")); + return false; + } + + if( oFsensorPCB == ClFsensorPCB::_Rev04 ){ + // newer IR sensor cannot normally produce 4.6-5V, this is considered a failure/bad mount + if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){ + printf_P(PSTR("fsensor v0.4 in fault range 4.6-5V - unconnected\n")); + return false; + } + } -volt_IR_int=current_voltage_raw_IR; -bCheckResult=(volt_IR_int<((int)IRsensor_Lmax_TRESHOLD))||(volt_IR_int>((int)IRsensor_Hmin_TRESHOLD)); -bCheckResult=bCheckResult&&(!((oFsensorPCB==ClFsensorPCB::_Rev04)&&(volt_IR_int>((int)IRsensor_Hopen_TRESHOLD)))); -return(bCheckResult); + // otherwise the IR fsensor is considered working correctly + return true; } #endif //IR_SENSOR_ANALOG diff --git a/Firmware/temperature.cpp b/Firmware/temperature.cpp index 7ca035f7..f6f8f320 100755 --- a/Firmware/temperature.cpp +++ b/Firmware/temperature.cpp @@ -74,7 +74,7 @@ int current_voltage_raw_bed = 0; #endif #ifdef IR_SENSOR_ANALOG -int current_voltage_raw_IR = 0; +uint16_t current_voltage_raw_IR = 0; #endif //IR_SENSOR_ANALOG int current_temperature_bed_raw = 0; diff --git a/Firmware/temperature.h b/Firmware/temperature.h index 5fb62d58..7b7637b1 100755 --- a/Firmware/temperature.h +++ b/Firmware/temperature.h @@ -79,7 +79,7 @@ extern int current_voltage_raw_bed; #endif #ifdef IR_SENSOR_ANALOG -extern int current_voltage_raw_IR; +extern uint16_t current_voltage_raw_IR; #endif //IR_SENSOR_ANALOG #if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1 diff --git a/Firmware/ultralcd.cpp b/Firmware/ultralcd.cpp index a6a37cb4..4c1be6ae 100755 --- a/Firmware/ultralcd.cpp +++ b/Firmware/ultralcd.cpp @@ -1981,8 +1981,7 @@ static void lcd_menu_voltages() lcd_home(); lcd_printf_P(PSTR(" PWR: %4.1fV\n" " BED: %4.1fV"), volt_pwr, volt_bed); #ifdef IR_SENSOR_ANALOG - float volt_IR = VOLT_DIV_REF * ((float)current_voltage_raw_IR / (1023 * OVERSAMPLENR)); - lcd_printf_P(PSTR("\n IR : %3.1fV"),volt_IR); + lcd_printf_P(PSTR("\n IR : %3.1fV"), Raw2Voltage(current_voltage_raw_IR)); #endif //IR_SENSOR_ANALOG menu_back_if_clicked(); } @@ -2169,10 +2168,10 @@ static void lcd_support_menu() switch(oFsensorPCB) { case ClFsensorPCB::_Old: - MENU_ITEM_BACK_P(MSG_03_OR_OLDER); + MENU_ITEM_BACK_P(_T(MSG_03_OR_OLDER)); break; case ClFsensorPCB::_Rev04: - MENU_ITEM_BACK_P(MSG_04_OR_NEWER); + MENU_ITEM_BACK_P(_T(MSG_04_OR_NEWER)); break; case ClFsensorPCB::_Undef: default: @@ -7512,37 +7511,33 @@ void lcd_belttest() #ifdef IR_SENSOR_ANALOG // called also from marlin_main.cpp void printf_IRSensorAnalogBoardChange(bool bPCBrev04){ - printf_P(PSTR("Filament sensor board change detected: revision %S\n"), bPCBrev04 ? MSG_04_OR_NEWER : MSG_03_OR_OLDER); + printf_P(PSTR("Filament sensor board change detected: revision%S\n"), bPCBrev04 ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER)); } static bool lcd_selftest_IRsensor(bool bStandalone) { - bool bAction; bool bPCBrev04; uint16_t volt_IR_int; - float volt_IR; - volt_IR_int=current_voltage_raw_IR; - bPCBrev04=(volt_IR_int<((int)IRsensor_Hopen_TRESHOLD)); - volt_IR=VOLT_DIV_REF*((float)volt_IR_int/(1023*OVERSAMPLENR)); - printf_P(PSTR("Measured filament sensor high level: %4.2fV\n"),volt_IR); - if(volt_IR_int < ((int)IRsensor_Hmin_TRESHOLD)){ + volt_IR_int = current_voltage_raw_IR; + bPCBrev04=(volt_IR_int < IRsensor_Hopen_TRESHOLD); + printf_P(PSTR("Measured filament sensor high level: %4.2fV\n"), Raw2Voltage(volt_IR_int) ); + if(volt_IR_int < IRsensor_Hmin_TRESHOLD){ if(!bStandalone) lcd_selftest_error(TestError::FsensorLevel,"HIGH",""); return(false); } lcd_show_fullscreen_message_and_wait_P(_i("Insert the filament (do not load it) into the extruder and then press the knob.")); - volt_IR_int=current_voltage_raw_IR; - volt_IR=VOLT_DIV_REF*((float)volt_IR_int/(1023*OVERSAMPLENR)); - printf_P(PSTR("Measured filament sensor low level: %4.2fV\n"),volt_IR); - if(volt_IR_int > ((int)IRsensor_Lmax_TRESHOLD)){ + volt_IR_int = current_voltage_raw_IR; + printf_P(PSTR("Measured filament sensor low level: %4.2fV\n"), Raw2Voltage(volt_IR_int)); + if(volt_IR_int > (IRsensor_Lmax_TRESHOLD)){ if(!bStandalone) lcd_selftest_error(TestError::FsensorLevel,"LOW",""); return(false); } - if((bPCBrev04?1:0)!=(uint8_t)oFsensorPCB){ // safer then "(uint8_t)bPCBrev04" + if((bPCBrev04 ? 1 : 0) != (uint8_t)oFsensorPCB){ // safer then "(uint8_t)bPCBrev04" printf_IRSensorAnalogBoardChange(bPCBrev04); - oFsensorPCB=bPCBrev04?ClFsensorPCB::_Rev04:ClFsensorPCB::_Old; + oFsensorPCB=bPCBrev04 ? ClFsensorPCB::_Rev04 : ClFsensorPCB::_Old; eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB); } return(true); @@ -7558,10 +7553,14 @@ static void lcd_detect_IRsensor(){ return; } bAction = lcd_selftest_IRsensor(true); - if(bAction) + if(bAction){ lcd_show_fullscreen_message_and_wait_P(_i("Sensor verified, remove the filament now.")); - else + // the fsensor board has been successfully identified, any previous "not responding" may be cleared now + fsensor_not_responding = false; + } else { lcd_show_fullscreen_message_and_wait_P(_i("Verification failed, remove the filament and try again.")); + // here it is unclear what to to with the fsensor_not_responding flag + } bMenuFSDetect=false; // de-inhibits some code inside "manage_inactivity()" } #endif //IR_SENSOR_ANALOG diff --git a/Firmware/ultralcd.h b/Firmware/ultralcd.h index 70584d6e..d68ab14b 100755 --- a/Firmware/ultralcd.h +++ b/Firmware/ultralcd.h @@ -259,10 +259,19 @@ void lcd_wizard(WizState state); #define VOLT_DIV_REF 5 #ifdef IR_SENSOR_ANALOG -#define IRsensor_Hmin_TRESHOLD (3.0*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~3.0V (0.6*Vcc) -#define IRsensor_Lmax_TRESHOLD (1.5*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~1.5V (0.3*Vcc) -#define IRsensor_Hopen_TRESHOLD (4.6*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k) -#define IRsensor_Ldiode_TRESHOLD (0.3*1023*OVERSAMPLENR/VOLT_DIV_REF) // ~0.3V +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) ); +} +constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821 +constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910 +constexpr uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059 +constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982 +constexpr uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368 + + #endif //IR_SENSOR_ANALOG #endif //ULTRALCD_H