Merge branch 'MK3' into MK3_NEW_SD_COMPILATION

This commit is contained in:
Alex Voinea 2020-09-12 08:28:13 +03:00
commit 6bc59197ad
No known key found for this signature in database
GPG key ID: F5034E7CFCF2F973
42 changed files with 1533 additions and 959 deletions

View file

@ -15,6 +15,9 @@ Please, before you create a new bug report, please make sure you searched in ope
**MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1]
**MMU upgrade firmware version [e.g. 1.0.6, 1.0.6-RC2, ...]
**SD card or USB/Octoprint**
Please let us know if you print via SD card or USB/Octoprint
**Describe the bug**
A clear and concise description of what the bug is.

View file

@ -16,8 +16,8 @@ extern uint16_t nPrinterType;
extern PGM_P sPrinterName;
// Firmware version
#define FW_VERSION "3.9.0-RC3"
#define FW_COMMIT_NR 3401
#define FW_VERSION "3.9.0"
#define FW_COMMIT_NR 3421
// 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

View file

@ -290,6 +290,7 @@
#define LA_K_DEF 0 // Default K factor (Unit: mm compression per 1mm/s extruder speed)
#define LA_K_MAX 10 // Maximum acceptable K factor (exclusive, see notes in planner.cpp:plan_buffer_line)
#define LA_LA10_MIN LA_K_MAX // Lin. Advance 1.0 threshold value (inclusive)
//#define LA_FLOWADJ // Adjust LA along with flow/M221 for uniform width
//#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility
//#define LA_LIVE_K // Allow adjusting K in the Tune menu
//#define LA_DEBUG // If enabled, this will generate debug information output over USB.
@ -438,6 +439,10 @@ const unsigned int dropsegments=5; //everything with less than this number of st
#undef BED_MINTEMP
#undef BED_MAXTEMP
#endif
#if TEMP_SENSOR_AMBIENT == 0
#undef AMBIENT_MINTEMP
#undef AMBIENT_MAXTEMP
#endif
#endif //__CONFIGURATION_ADV_H

View file

@ -1,5 +1,5 @@
#include "Dcodes.h"
//#include "Marlin.h"
#include "Marlin.h"
#include "Configuration.h"
#include "language.h"
#include "cmdqueue.h"
@ -226,9 +226,7 @@ void dcode_0()
LOG("D0 - Reset\n");
if (code_seen('B')) //bootloader
{
cli();
wdt_enable(WDTO_15MS);
while(1);
softReset();
}
else //reset
{
@ -252,8 +250,7 @@ void dcode_1()
cli();
for (int i = 0; i < 8192; i++)
eeprom_write_byte((unsigned char*)i, (unsigned char)0xff);
wdt_enable(WDTO_15MS);
while(1);
softReset();
}
/*!
@ -420,8 +417,7 @@ void dcode_5()
boot_dst_addr = (uint32_t)address;
boot_src_addr = (uint32_t)(&data);
bootapp_print_vars();
wdt_enable(WDTO_15MS);
while(1);
softReset();
}
while (count)
{
@ -467,8 +463,7 @@ void dcode_7()
boot_copy_size = (uint16_t)0xc00;
boot_src_addr = (uint32_t)0x0003e400;
boot_dst_addr = (uint32_t)0x0003f400;
wdt_enable(WDTO_15MS);
while(1);
softReset();
*/
}

View file

@ -299,7 +299,7 @@ extern float feedrate;
extern int feedmultiply;
extern int extrudemultiply; // Sets extrude multiply factor (in percent) for all extruders
extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in percent) for each extruder individually
extern float volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
extern float extruder_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
extern float current_position[NUM_AXIS] ;
extern float destination[NUM_AXIS] ;
extern float min_pos[3];
@ -334,7 +334,6 @@ extern unsigned long stoptime;
extern int bowden_length[4];
extern bool is_usb_printing;
extern bool homing_flag;
extern bool temp_cal_active;
extern bool loading_flag;
extern unsigned int usb_printing_counter;
@ -513,4 +512,6 @@ void load_filament_final_feed();
void marlin_wait_for_click();
void raise_z_above(float target, bool plan=true);
extern "C" void softReset();
#endif

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,8 @@
extern FILE _uartout;
#define uartout (&_uartout)
extern void softReset();
void bootapp_print_vars(void)
{
fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr);
@ -39,8 +41,7 @@ void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
boot_src_addr = (uint32_t)rptr;
boot_dst_addr = (uint32_t)fptr;
bootapp_print_vars();
wdt_enable(WDTO_15MS);
while(1);
softReset();
}
void bootapp_reboot_user0(uint8_t reserved)
@ -50,6 +51,5 @@ void bootapp_reboot_user0(uint8_t reserved)
boot_app_flags = BOOT_APP_FLG_USER0;
boot_reserved = reserved;
bootapp_print_vars();
wdt_enable(WDTO_15MS);
while(1);
softReset();
}

View file

@ -331,7 +331,7 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir)
{
SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
SERIAL_PROTOCOL(subdirname);
SERIAL_PROTOCOLLNPGM(".");
SERIAL_PROTOCOLLN('.');
return;
}
else
@ -431,7 +431,7 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru
{
SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
SERIAL_PROTOCOL(fname);
SERIAL_PROTOCOLLNPGM(".");
SERIAL_PROTOCOLLN('.');
}
}
else
@ -440,7 +440,7 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru
{
SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
SERIAL_PROTOCOL(fname);
SERIAL_PROTOCOLLNPGM(".");
SERIAL_PROTOCOLLN('.');
}
else
{
@ -497,17 +497,15 @@ void CardReader::getStatus()
SERIAL_PROTOCOLLNPGM("Print saved");
}
else {
SERIAL_PROTOCOL(longFilename);
SERIAL_PROTOCOLPGM("\n");
SERIAL_PROTOCOLLN(longFilename);
SERIAL_PROTOCOLRPGM(_N("SD printing byte "));////MSG_SD_PRINTING_BYTE
SERIAL_PROTOCOL(sdpos);
SERIAL_PROTOCOLPGM("/");
SERIAL_PROTOCOL('/');
SERIAL_PROTOCOLLN(filesize);
uint16_t time = _millis()/60000 - starttime/60000;
uint16_t time = ( _millis() - starttime ) / 60000U;
SERIAL_PROTOCOL(itostr2(time/60));
SERIAL_PROTOCOL(':');
SERIAL_PROTOCOL(itostr2(time%60));
SERIAL_PROTOCOLPGM("\n");
SERIAL_PROTOCOLLN(itostr2(time%60));
}
}
else {

View file

@ -341,8 +341,9 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
| 0x0D9F 3487 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - bed temp | ^ | D3 Ax0d9f C1
| 0x0DA0 3488 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - PINDA temp | ^ | D3 Ax0da0 C1
| 0x0DA1 3489 | uint8 | ??? | 00h 0 | ffh 255 | ??? | ??? | D3 Ax0da1 C1
| 0x0D48 3400 | uint8 | EEPROM_FSENSOR_PCB | ??? | ffh 255 | Filament Sensor type old vs new | ??? | D3 Ax0d48 C1
| ^ | ^ | ^ | ??? | ^ | Filament Sensor type ??? | ^ | ^
| 0x0D48 3400 | uint8 | EEPROM_FSENSOR_PCB | ffh 255 | ffh 255 | Filament Sensor type IR unknown | LCD Support | D3 Ax0d48 C1
| ^ | ^ | ^ | 00h 0 | ^ | Filament Sensor type IR 0.3 or older | ^ | ^
| ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor type IR 0.4 or newer | ^ | ^
| 0x0D47 3399 | uint8 | EEPROM_FSENSOR_ACTION_NA | 00h 0 | ffh 255 | Filament Sensor action: __Continue__ | LCD menu | D3 Ax0d47 C1
| ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor action: __Pause__ | ^ | ^
| 0x0D37 3383 | float | EEPROM_UVLO_SAVED_TARGET | ??? | ff ff ff ffh | Power panic saved target all-axis | ??? | D3 Ax0d37 C16
@ -358,6 +359,12 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
| ^ | ^ | ^ | 00h 0 | ^ | LCD backlight mode: __Dim__ | ^ | ^
| 0x0D30 3376 | uint16 | EEPROM_BACKLIGHT_TIMEOUT | 01 00 - ff ff | 0a 00h 65535 | LCD backlight timeout: __10__ seconds | LCD menu | D3 Ax0d30 C2
| 0x0D2C 3372 | float | EEPROM_UVLO_LA_K | ??? | ff ff ff ffh | Power panic saved Linear Advanced K value | ??? | D3 Ax0d2c C4
| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | ffh 255 | ffh 255 | ALTFAN override unknown state | LCD menu | D3 Ax0d2b C1
| ^ | ^ | ^ | 00h 0 | ^ | ALTFAN override deactivated | ^ | ^
| ^ | ^ | ^ | 01h 1 | ^ | ALTFAN override activated | ^ | ^
| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | ffh 255 | ffh 255 | Experimental menu visibility unknown state | LCD menu | D3 Ax0d2a C1
| ^ | ^ | ^ | 00h 0 | ^ | Experimental menu visibility hidden | ^ | ^
| ^ | ^ | ^ | 01h 1 | ^ | Experimental menu visibility visible | ^ | ^
| Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code
@ -560,8 +567,11 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
#define EEPROM_UVLO_LA_K (EEPROM_BACKLIGHT_TIMEOUT-4) // float
#define EEPROM_ALTFAN_OVERRIDE (EEPROM_UVLO_LA_K-1) //uint8
#define EEPROM_EXPERIMENTAL_VISIBILITY (EEPROM_ALTFAN_OVERRIDE-1) //uint8
//This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
#define EEPROM_LAST_ITEM EEPROM_UVLO_LA_K
#define EEPROM_LAST_ITEM EEPROM_EXPERIMENTAL_VISIBILITY
// !!!!!
// !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
// !!!!!

View file

@ -58,7 +58,7 @@
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
/// check if pin is an timer
#define _GET_TIMER(IO) ((DIO ## IO ## _PWM)
#define _GET_TIMER(IO) (DIO ## IO ## _PWM)
// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html

View file

@ -170,6 +170,21 @@ void fsensor_checkpoint_print(void)
restore_print_from_ram_and_continue(0);
}
#ifdef IR_SENSOR_ANALOG
const char* FsensorIRVersionText()
{
switch(oFsensorPCB)
{
case ClFsensorPCB::_Old:
return _T(MSG_IR_03_OR_OLDER);
case ClFsensorPCB::_Rev04:
return _T(MSG_IR_04_OR_NEWER);
default:
return _T(MSG_IR_UNKNOWN);
}
}
#endif //IR_SENSOR_ANALOG
void fsensor_init(void)
{
#ifdef PAT9125
@ -207,9 +222,9 @@ void fsensor_init(void)
}
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) ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER));
printf_P(PSTR(" (sensor board revision:%S)\n"), FsensorIRVersionText());
#else //IR_SENSOR_ANALOG
printf_P(PSTR("\n"));
MYSERIAL.println();
#endif //IR_SENSOR_ANALOG
if (check_for_ir_sensor()){
ir_sensor_detected = true;
@ -463,22 +478,8 @@ bool fsensor_oq_result(void)
}
#endif //FSENSOR_QUALITY
ISR(FSENSOR_INT_PIN_VECT)
FORCE_INLINE static void fsensor_isr(int st_cnt)
{
if (mmu_enabled || ir_sensor_detected) return;
if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
// prevent isr re-entry
static bool _lock = false;
if (_lock) return;
_lock = true;
// fetch fsensor_st_cnt atomically
int st_cnt = fsensor_st_cnt;
fsensor_st_cnt = 0;
sei();
uint8_t old_err_cnt = fsensor_err_cnt;
uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y();
if (!pat9125_res)
@ -563,8 +564,28 @@ ISR(FSENSOR_INT_PIN_VECT)
#endif //DEBUG_FSENSOR_LOG
pat9125_y = 0;
_lock = false;
return;
}
ISR(FSENSOR_INT_PIN_VECT)
{
if (mmu_enabled || ir_sensor_detected) return;
if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
// prevent isr re-entry
static bool _lock = false;
if (!_lock)
{
// fetch fsensor_st_cnt atomically
int st_cnt = fsensor_st_cnt;
fsensor_st_cnt = 0;
_lock = true;
sei();
fsensor_isr(st_cnt);
cli();
_lock = false;
}
}
void fsensor_setup_interrupt(void)
@ -611,42 +632,41 @@ void fsensor_enque_M600(){
void fsensor_update(void)
{
#ifdef PAT9125
if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
{
fsensor_stop_and_save_print();
if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
{
fsensor_stop_and_save_print();
KEEPALIVE_STATE(IN_HANDLER);
bool autoload_enabled_tmp = fsensor_autoload_enabled;
fsensor_autoload_enabled = false;
bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled;
fsensor_oq_meassure_enabled = true;
bool autoload_enabled_tmp = fsensor_autoload_enabled;
fsensor_autoload_enabled = false;
bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled;
fsensor_oq_meassure_enabled = true;
// move the nozzle away while checking the filament
current_position[Z_AXIS] += 0.8;
if(current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS], active_extruder);
plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS]);
st_synchronize();
// check the filament in isolation
fsensor_reset_err_cnt();
fsensor_oq_meassure_start(0);
fsensor_oq_meassure_start(0);
float e_tmp = current_position[E_AXIS];
current_position[E_AXIS] -= 3;
plan_buffer_line_curposXYZE(250/60, active_extruder);
plan_buffer_line_curposXYZE(250/60);
current_position[E_AXIS] = e_tmp;
plan_buffer_line_curposXYZE(200/60, active_extruder);
plan_buffer_line_curposXYZE(200/60);
st_synchronize();
fsensor_oq_meassure_stop();
fsensor_oq_meassure_stop();
bool err = false;
err |= (fsensor_err_cnt > 0); // final error count is non-zero
err |= (fsensor_oq_er_sum > FSENSOR_OQ_MAX_ES); // total error count is above limit
err |= (fsensor_oq_yd_sum < FSENSOR_OQ_MIN_YD); // total measured distance is below limit
bool err = false;
err |= (fsensor_err_cnt > 0); // final error count is non-zero
err |= (fsensor_oq_er_sum > FSENSOR_OQ_MAX_ES); // total error count is above limit
err |= (fsensor_oq_yd_sum < FSENSOR_OQ_MIN_YD); // total measured distance is below limit
fsensor_restore_print_and_continue();
fsensor_autoload_enabled = autoload_enabled_tmp;
fsensor_oq_meassure_enabled = oq_meassure_enabled_tmp;
unsigned long now = _millis();
if (!err && (now - fsensor_softfail_last) > FSENSOR_SOFTERR_DELTA)
fsensor_softfail_ccnt = 0;
@ -663,70 +683,70 @@ void fsensor_update(void)
fsensor_softfail_last = 0;
fsensor_enque_M600();
}
}
}
#else //PAT9125
if (CHECK_FSENSOR && ir_sensor_detected)
if (CHECK_FSENSOR && ir_sensor_detected)
{
if(digitalRead(IR_SENSOR_PIN))
{ // IR_SENSOR_PIN ~ H
if(digitalRead(IR_SENSOR_PIN))
{ // IR_SENSOR_PIN ~ H
#ifdef IR_SENSOR_ANALOG
if(!bIRsensorStateFlag)
if(!bIRsensorStateFlag)
{
bIRsensorStateFlag=true;
nIRsensorLastTime=_millis();
}
else
{
if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY)
{
bIRsensorStateFlag=true;
nIRsensorLastTime=_millis();
}
else
{
if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY)
{
uint8_t nMUX1,nMUX2;
uint16_t nADC;
bIRsensorStateFlag=false;
// sequence for direct data reading from AD converter
DISABLE_TEMPERATURE_INTERRUPT();
nMUX1=ADMUX; // ADMUX saving
nMUX2=ADCSRB;
adc_setmux(VOLT_IR_PIN);
ADCSRA|=(1<<ADSC); // first conversion after ADMUX change discarded (preventively)
while(ADCSRA&(1<<ADSC))
;
ADCSRA|=(1<<ADSC); // second conversion used
while(ADCSRA&(1<<ADSC))
;
nADC=ADC;
ADMUX=nMUX1; // ADMUX restoring
ADCSRB=nMUX2;
ENABLE_TEMPERATURE_INTERRUPT();
// end of sequence for ...
// 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)
uint8_t nMUX1,nMUX2;
uint16_t nADC;
bIRsensorStateFlag=false;
// sequence for direct data reading from AD converter
DISABLE_TEMPERATURE_INTERRUPT();
nMUX1=ADMUX; // ADMUX saving
nMUX2=ADCSRB;
adc_setmux(VOLT_IR_PIN);
ADCSRA|=(1<<ADSC); // first conversion after ADMUX change discarded (preventively)
while(ADCSRA&(1<<ADSC))
;
ADCSRA|=(1<<ADSC); // second conversion used
while(ADCSRA&(1<<ADSC))
;
nADC=ADC;
ADMUX=nMUX1; // ADMUX restoring
ADCSRB=nMUX2;
ENABLE_TEMPERATURE_INTERRUPT();
// end of sequence for ...
// 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 we are printing and FS action is set to "Pause", force pause the print
if(oFsensorActionNA==ClFsensorActionNA::_Pause)
lcd_pause_print();
}
else
{
// if we are printing and FS action is set to "Pause", force pause the print
if(oFsensorActionNA==ClFsensorActionNA::_Pause)
lcd_pause_print();
}
else
{
#endif //IR_SENSOR_ANALOG
fsensor_checkpoint_print();
fsensor_enque_M600();
fsensor_checkpoint_print();
fsensor_enque_M600();
#ifdef IR_SENSOR_ANALOG
}
}
}
}
}
else
{ // IR_SENSOR_PIN ~ L
bIRsensorStateFlag=false;
}
}
else
{ // IR_SENSOR_PIN ~ L
bIRsensorStateFlag=false;
#endif //IR_SENSOR_ANALOG
}
}
}
}
#endif //PAT9125
}
@ -734,24 +754,36 @@ void fsensor_update(void)
/// 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;
}
}
// otherwise the IR fsensor is considered working correctly
return true;
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 - check sensor\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;
}
/// newer IR sensor cannot normally produce 0-0.3V, this is considered a failure
#if 0 //Disabled as it has to be decided if we gonna use this or not.
if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){
printf_P(PSTR("fsensor v0.4 in fault range 0.0-0.3V - wrong IR sensor\n"));
return false;
}
#endif
}
/// If IR sensor is "uknown state" and filament is not loaded > 1.5V return false
#if 0
if( (oFsensorPCB == ClFsensorPCB::_Undef) && ( current_voltage_raw_IR > IRsensor_Lmax_TRESHOLD ) ){
printf_P(PSTR("Unknown IR sensor version and no filament loaded detected.\n"));
return false;
}
#endif
// otherwise the IR fsensor is considered working correctly
return true;
}
#endif //IR_SENSOR_ANALOG

View file

@ -83,6 +83,7 @@ extern uint8_t fsensor_log;
//! @}
#endif //PAT9125
#define VOLT_DIV_REF 5
#ifdef IR_SENSOR_ANALOG
#define IR_SENSOR_STEADY 10 // [ms]
@ -103,8 +104,21 @@ enum class ClFsensorActionNA:uint_least8_t
extern ClFsensorPCB oFsensorPCB;
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) );
}
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
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_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368
#endif //IR_SENSOR_ANALOG
#endif //FSENSOR_H

View file

@ -59,7 +59,6 @@ enum class States : uint8_t {
RISE, ///< 16 fast PWM cycles with increasing duty up to steady ON
RISE_TO_ONE, ///< metastate allowing the timer change its state atomically without artefacts on the output pin
ONE, ///< steady 1 (ON), no change for the whole period
ONE_TO_FALL, ///< metastate allowing the timer change its state atomically without artefacts on the output pin
FALL, ///< 16 fast PWM cycles with decreasing duty down to steady OFF
FALL_TO_ZERO ///< metastate allowing the timer change its state atomically without artefacts on the output pin
};
@ -155,12 +154,7 @@ ISR(TIMER0_OVF_vect) // timer compare interrupt service routine
return; // want full duty for the next ONE cycle again - so keep on heating and just wait for the next timer ovf
}
// otherwise moving towards FALL
// @@TODO it looks like ONE_TO_FALL isn't necessary, there are no artefacts at all
state = States::ONE;//_TO_FALL;
// TCCR0B = (1 << CS00); // change prescaler to 1, i.e. 62.5kHz
// break;
// case States::ONE_TO_FALL:
// OCR0B = 255; // zero duty
state=States::FALL;
fastCounter = fastMax - 1;// we'll do 16-1 cycles of RISE
TCNT0 = 255; // force overflow on the next clock cycle

View file

@ -78,10 +78,10 @@ float la10c_jerk(float j)
return j;
// bring low E-jerk values into equivalent LA 1.5 values by
// flattening the response in the (1-4.5) range using a piecewise
// flattening the response in the (0.3-4.5) range using a piecewise
// function. Is it truly worth to preserve the difference between
// 1.5/2.5 E-jerk for LA1.0? Probably not, but we try nonetheless.
j = j < 1.0? j * 3.625:
j = j < 0.3? j * 11.5:
j < 4.5? j * 0.25 + 3.375:
j;

View file

@ -53,6 +53,7 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo
{
menu_menu = menu;
lcd_encoder = encoder;
menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
CRITICAL_SECTION_END;
if (reset_menu_state)
menu_data_reset();

View file

@ -920,7 +920,7 @@ static inline void go_xy(float x, float y, float fr)
static inline void go_to_current(float fr)
{
plan_buffer_line_curposXYZE(fr, active_extruder);
plan_buffer_line_curposXYZE(fr);
st_synchronize();
}
@ -929,7 +929,7 @@ static inline void update_current_position_xyz()
current_position[X_AXIS] = st_get_position_mm(X_AXIS);
current_position[Y_AXIS] = st_get_position_mm(Y_AXIS);
current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
plan_set_position_curposXYZE();
}
static inline void update_current_position_z()

View file

@ -140,8 +140,9 @@ const char MSG_DIM[] PROGMEM_I1 = ISTR("Dim"); ////c=6
const char MSG_AUTO[] PROGMEM_I1 = ISTR("Auto"); ////c=6
#ifdef IR_SENSOR_ANALOG
// Beware - the space at the beginning is necessary since it is reused in LCD menu items which are to be with a space
const char MSG_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////c=18
const char MSG_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////c=18
const char MSG_IR_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////c=18
const char MSG_IR_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////c=18
const char MSG_IR_UNKNOWN[] PROGMEM_I1 = ISTR("unknown state");////c=18
#endif
//not internationalized messages

View file

@ -139,8 +139,9 @@ extern const char MSG_BRIGHT[];
extern const char MSG_DIM[];
extern const char MSG_AUTO[];
#ifdef IR_SENSOR_ANALOG
extern const char MSG_04_OR_NEWER[];
extern const char MSG_03_OR_OLDER[];
extern const char MSG_IR_04_OR_NEWER[];
extern const char MSG_IR_03_OR_OLDER[];
extern const char MSG_IR_UNKNOWN[];
#endif
//not internationalized messages

View file

@ -540,7 +540,7 @@ void mmu_command(MmuCmd cmd)
void mmu_load_step(bool synchronize)
{
current_position[E_AXIS] = current_position[E_AXIS] + MMU_LOAD_FEEDRATE * 0.1;
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder);
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE);
if (synchronize) st_synchronize();
}
@ -605,7 +605,7 @@ bool mmu_get_response(uint8_t move)
{
printf_P(PSTR("Unload 1\n"));
current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder);
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE);
st_synchronize();
}
}
@ -623,7 +623,7 @@ bool mmu_get_response(uint8_t move)
{
printf_P(PSTR("Unload 2\n"));
current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder);
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE);
st_synchronize();
}
}
@ -701,13 +701,13 @@ void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move)
//lift z
current_position[Z_AXIS] += Z_PAUSE_LIFT;
if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
plan_buffer_line_curposXYZE(15, active_extruder);
plan_buffer_line_curposXYZE(15);
st_synchronize();
//Move XY to side
current_position[X_AXIS] = X_PAUSE_POS;
current_position[Y_AXIS] = Y_PAUSE_POS;
plan_buffer_line_curposXYZE(50, active_extruder);
plan_buffer_line_curposXYZE(50);
st_synchronize();
}
if (turn_off_nozzle) {
@ -758,17 +758,17 @@ void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move)
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature..."));
delay_keep_alive(3000);
}
mmu_wait_for_heater_blocking();
mmu_wait_for_heater_blocking();
}
if (move_axes) {
lcd_clear();
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming position..."));
current_position[X_AXIS] = x_position_bckp;
current_position[Y_AXIS] = y_position_bckp;
plan_buffer_line_curposXYZE(50, active_extruder);
plan_buffer_line_curposXYZE(50);
st_synchronize();
current_position[Z_AXIS] = z_position_bckp;
plan_buffer_line_curposXYZE(15, active_extruder);
plan_buffer_line_curposXYZE(15);
st_synchronize();
}
else {
@ -807,19 +807,19 @@ void mmu_load_to_nozzle()
current_position[E_AXIS] += 7.2f;
}
float feedrate = 562;
plan_buffer_line_curposXYZE(feedrate / 60, active_extruder);
plan_buffer_line_curposXYZE(feedrate / 60);
st_synchronize();
current_position[E_AXIS] += 14.4f;
feedrate = 871;
plan_buffer_line_curposXYZE(feedrate / 60, active_extruder);
plan_buffer_line_curposXYZE(feedrate / 60);
st_synchronize();
current_position[E_AXIS] += 36.0f;
feedrate = 1393;
plan_buffer_line_curposXYZE(feedrate / 60, active_extruder);
plan_buffer_line_curposXYZE(feedrate / 60);
st_synchronize();
current_position[E_AXIS] += 14.4f;
feedrate = 871;
plan_buffer_line_curposXYZE(feedrate / 60, active_extruder);
plan_buffer_line_curposXYZE(feedrate / 60);
st_synchronize();
if (!saved_e_relative_mode) axis_relative_modes &= ~E_AXIS_MASK;
}
@ -1072,7 +1072,7 @@ void mmu_filament_ramming()
for(uint8_t i = 0; i < (sizeof(ramming_sequence)/sizeof(E_step));++i)
{
current_position[E_AXIS] += pgm_read_float(&(ramming_sequence[i].extrude));
plan_buffer_line_curposXYZE(pgm_read_float(&(ramming_sequence[i].feed_rate)), active_extruder);
plan_buffer_line_curposXYZE(pgm_read_float(&(ramming_sequence[i].feed_rate)));
st_synchronize();
}
}
@ -1446,9 +1446,9 @@ bFilamentAction=false; // NOT in "mmu_fil_eject_menu(
static bool can_load()
{
current_position[E_AXIS] += 60;
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder);
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE);
current_position[E_AXIS] -= 52;
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder);
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE);
st_synchronize();
uint_least8_t filament_detected_count = 0;
@ -1458,7 +1458,7 @@ static bool can_load()
for(uint_least8_t i = 0; i < steps; ++i)
{
current_position[E_AXIS] -= e_increment;
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE, active_extruder);
plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE);
st_synchronize();
if(0 == PIN_GET(IR_SENSOR_PIN))
{

View file

@ -99,9 +99,11 @@ struct block_t;
extern struct block_t *block_buffer;
//! @brief Enter an STK500 compatible Optiboot boot loader waiting for flashing the languages to an external flash memory.
void optiboot_w25x20cl_enter()
//! @return 1 if "start\n" was not sent. Optiboot was skipped
//! @return 0 if "start\n" was sent. Optiboot ran normally. No need to send "start\n" in setup()
uint8_t optiboot_w25x20cl_enter()
{
if (boot_app_flags & BOOT_APP_FLG_USER0) return;
if (boot_app_flags & BOOT_APP_FLG_USER0) return 1;
uint8_t ch;
uint8_t rampz = 0;
register uint16_t address = 0;
@ -120,38 +122,46 @@ void optiboot_w25x20cl_enter()
unsigned long boot_timer = 0;
const char *ptr = entry_magic_send;
const char *end = strlen_P(entry_magic_send) + ptr;
// Initialize the serial line.
UCSR0A |= (1 << U2X0);
UBRR0L = (((float)(F_CPU))/(((float)(115200))*8.0)-1.0+0.5);
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
const uint8_t selectedSerialPort_bak = selectedSerialPort;
// Flush the serial line.
while (RECV_READY) {
watchdogReset();
// Dummy register read (discard)
(void)(*(char *)UDR0);
}
selectedSerialPort = 0; //switch to Serial0
MYSERIAL.flush(); //clear RX buffer
int SerialHead = rx_buffer.head;
// Send the initial magic string.
while (ptr != end)
putch(pgm_read_byte(ptr ++));
watchdogReset();
// Wait for one second until a magic string (constant entry_magic) is received
// Wait for two seconds until a magic string (constant entry_magic) is received
// from the serial line.
ptr = entry_magic_receive;
end = strlen_P(entry_magic_receive) + ptr;
while (ptr != end) {
while (! RECV_READY) {
while (rx_buffer.head == SerialHead) {
watchdogReset();
delayMicroseconds(1);
if (++ boot_timer > boot_timeout)
{
// Timeout expired, continue with the application.
return;
selectedSerialPort = selectedSerialPort_bak; //revert Serial setting
return 0;
}
}
ch = UDR0;
ch = rx_buffer.buffer[SerialHead];
SerialHead = (unsigned int)(SerialHead + 1) % RX_BUFFER_SIZE;
if (pgm_read_byte(ptr ++) != ch)
{
// Magic was not received correctly, continue with the application
return;
selectedSerialPort = selectedSerialPort_bak; //revert Serial setting
return 0;
}
watchdogReset();
}
cbi(UCSR0B, RXCIE0); //disable the MarlinSerial0 interrupt
// Send the cfm magic string.
ptr = entry_magic_cfm;
while (ptr != end)

View file

@ -1,6 +1,6 @@
#ifndef OPTIBOOT_W25X20CL_H
#define OPTIBOOT_W25X20CL_H
extern void optiboot_w25x20cl_enter();
extern uint8_t optiboot_w25x20cl_enter();
#endif /* OPTIBOOT_W25X20CL_H */

View file

@ -226,11 +226,23 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
// Size of Plateau of Nominal Rate.
uint32_t plateau_steps = 0;
#ifdef LIN_ADVANCE
uint16_t final_adv_steps = 0;
uint16_t max_adv_steps = 0;
if (block->use_advance_lead) {
final_adv_steps = final_rate * block->adv_comp;
}
#endif
// Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will
// have to use intersection_distance() to calculate when to abort acceleration and start braking
// in order to reach the final_rate exactly at the end of this block.
if (accel_decel_steps < block->step_event_count.wide) {
plateau_steps = block->step_event_count.wide - accel_decel_steps;
#ifdef LIN_ADVANCE
if (block->use_advance_lead)
max_adv_steps = block->nominal_rate * block->adv_comp;
#endif
} else {
uint32_t acceleration_x4 = acceleration << 2;
// Avoid negative numbers
@ -263,14 +275,20 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
decelerate_steps = block->step_event_count.wide;
accelerate_steps = block->step_event_count.wide - decelerate_steps;
}
}
#ifdef LIN_ADVANCE
uint16_t final_adv_steps = 0;
if (block->use_advance_lead) {
final_adv_steps = exit_speed * block->adv_comp;
}
if (block->use_advance_lead) {
if(!accelerate_steps || !decelerate_steps) {
// accelerate_steps=0: deceleration-only ramp, max_rate is effectively unused
// decelerate_steps=0: acceleration-only ramp, max_rate _is_ final_rate
max_adv_steps = final_adv_steps;
} else {
float max_rate = sqrt(acceleration_x2 * accelerate_steps + initial_rate_sqr);
max_adv_steps = max_rate * block->adv_comp;
}
}
#endif
}
CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section
// This block locks the interrupts globally for 4.38 us,
@ -284,6 +302,7 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
block->final_rate = final_rate;
#ifdef LIN_ADVANCE
block->final_adv_steps = final_adv_steps;
block->max_adv_steps = max_adv_steps;
#endif
}
CRITICAL_SECTION_END;
@ -671,8 +690,16 @@ void planner_abort_hard()
waiting_inside_plan_buffer_line_print_aborted = true;
}
void plan_buffer_line_curposXYZE(float feed_rate, uint8_t extruder) {
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feed_rate, extruder );
void plan_buffer_line_curposXYZE(float feed_rate) {
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feed_rate, active_extruder );
}
void plan_buffer_line_destinationXYZE(float feed_rate) {
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feed_rate, active_extruder);
}
void plan_set_position_curposXYZE(){
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
float junction_deviation = 0.1;
@ -1069,12 +1096,20 @@ Having the real displacement of the head, we can calculate the total movement le
&& delta_mm[E_AXIS] >= 0
&& abs(delta_mm[Z_AXIS]) < 0.5;
if (block->use_advance_lead) {
#ifdef LA_FLOWADJ
// M221/FLOW should change uniformly the extrusion thickness
float delta_e = (e - position_float[E_AXIS]) / extruder_multiplier[extruder];
#else
// M221/FLOW only adjusts for an incorrect source diameter
float delta_e = (e - position_float[E_AXIS]);
#endif
float delta_D = sqrt(sq(x - position_float[X_AXIS])
+ sq(y - position_float[Y_AXIS])
+ sq(z - position_float[Z_AXIS]));
// all extrusion moves with LA require a compression which is proportional to the
// extrusion_length to distance ratio (e/D)
e_D_ratio = (e - position_float[E_AXIS]) /
sqrt(sq(x - position_float[X_AXIS])
+ sq(y - position_float[Y_AXIS])
+ sq(z - position_float[Z_AXIS]));
e_D_ratio = delta_e / delta_D;
// Check for unusual high e_D ratio to detect if a retract move was combined with the last
// print move due to min. steps per segment. Never execute this with advance! This assumes
@ -1124,53 +1159,7 @@ Having the real displacement of the head, we can calculate the total movement le
block->acceleration_st = (block->acceleration_st + (bresenham_oversample >> 1)) / bresenham_oversample;
#endif
block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
#ifdef LIN_ADVANCE
if (block->use_advance_lead) {
// the nominal speed doesn't change past this point: calculate the compression ratio for the
// segment and the required advance steps
block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS];
block->max_adv_steps = block->nominal_speed * block->adv_comp;
float advance_speed;
if (e_D_ratio > 0)
advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
else
advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS];
// to save more space we avoid another copy of calc_timer and go through slow division, but we
// still need to replicate the *exact* same step grouping policy (see below)
if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY;
float advance_rate = (F_CPU / 8.0) / advance_speed;
if (advance_speed > 20000) {
block->advance_rate = advance_rate * 4;
block->advance_step_loops = 4;
}
else if (advance_speed > 10000) {
block->advance_rate = advance_rate * 2;
block->advance_step_loops = 2;
}
else
{
// never overflow the internal accumulator with very low rates
if (advance_rate < UINT16_MAX)
block->advance_rate = advance_rate;
else
block->advance_rate = UINT16_MAX;
block->advance_step_loops = 1;
}
#ifdef LA_DEBUG
if (block->advance_step_loops > 2)
// @wavexx: we should really check for the difference between step_loops and
// advance_step_loops instead. A difference of more than 1 will lead
// to uneven speed and *should* be adjusted here by furthermore
// reducing the speed.
SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed.");
#endif
}
#endif
block->acceleration_rate = ((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
// Start with a safe speed.
// Safe speed is the speed, from which the machine may halt to stop immediately.
@ -1297,6 +1286,53 @@ Having the real displacement of the head, we can calculate the total movement le
// Precalculate the division, so when all the trapezoids in the planner queue get recalculated, the division is not repeated.
block->speed_factor = block->nominal_rate / block->nominal_speed;
#ifdef LIN_ADVANCE
if (block->use_advance_lead) {
// calculate the compression ratio for the segment (the required advance steps are computed
// during trapezoid planning)
float adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS]; // (step/(mm/s))
block->adv_comp = adv_comp / block->speed_factor; // step/(step/min)
float advance_speed;
if (e_D_ratio > 0)
advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
else
advance_speed = cs.max_jerk[E_AXIS] * cs.axis_steps_per_unit[E_AXIS];
// to save more space we avoid another copy of calc_timer and go through slow division, but we
// still need to replicate the *exact* same step grouping policy (see below)
if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY;
float advance_rate = (F_CPU / 8.0) / advance_speed;
if (advance_speed > 20000) {
block->advance_rate = advance_rate * 4;
block->advance_step_loops = 4;
}
else if (advance_speed > 10000) {
block->advance_rate = advance_rate * 2;
block->advance_step_loops = 2;
}
else
{
// never overflow the internal accumulator with very low rates
if (advance_rate < UINT16_MAX)
block->advance_rate = advance_rate;
else
block->advance_rate = UINT16_MAX;
block->advance_step_loops = 1;
}
#ifdef LA_DEBUG
if (block->advance_step_loops > 2)
// @wavexx: we should really check for the difference between step_loops and
// advance_step_loops instead. A difference of more than 1 will lead
// to uneven speed and *should* be adjusted here by furthermore
// reducing the speed.
SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed.");
#endif
}
#endif
calculate_trapezoid_for_block(block, block->entry_speed, safe_speed);
if (block->step_event_count.wide <= 32767)

View file

@ -73,12 +73,12 @@ typedef struct {
// steps_x.y,z, step_event_count, acceleration_rate, direction_bits and active_extruder are set by plan_buffer_line().
dda_isteps_t steps_x, steps_y, steps_z, steps_e; // Step count along each axis
dda_usteps_t step_event_count; // The number of step events required to complete this block
long acceleration_rate; // The acceleration rate used for acceleration calculation
uint32_t acceleration_rate; // The acceleration rate used for acceleration calculation
unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
unsigned char active_extruder; // Selects the active extruder
// accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller.
long accelerate_until; // The index of the step event on which to stop acceleration
long decelerate_after; // The index of the step event on which to start decelerating
uint32_t accelerate_until; // The index of the step event on which to stop acceleration
uint32_t decelerate_after; // The index of the step event on which to start decelerating
// Fields used by the motion planner to manage acceleration
// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis
@ -100,13 +100,12 @@ typedef struct {
// Settings for the trapezoid generator (runs inside an interrupt handler).
// Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts.
//FIXME nominal_rate, initial_rate and final_rate are limited to uint16_t by MultiU24X24toH16 in the stepper interrupt anyway!
unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec
unsigned long initial_rate; // The jerk-adjusted step rate at start of block
unsigned long final_rate; // The minimal rate at exit
unsigned long acceleration_st; // acceleration steps/sec^2
//FIXME does it have to be unsigned long? Probably uint8_t would be just fine.
unsigned long fan_speed;
//FIXME does it have to be int? Probably uint8_t would be just fine. Need to change in other places as well
int fan_speed;
volatile char busy;
@ -154,7 +153,11 @@ vector_3 plan_get_position();
/// plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], ...
/// saves almost 5KB.
/// The performance penalty is negligible, since these planned lines are usually maintenance moves with the extruder.
void plan_buffer_line_curposXYZE(float feed_rate, uint8_t extruder);
void plan_buffer_line_curposXYZE(float feed_rate);
void plan_buffer_line_destinationXYZE(float feed_rate);
void plan_set_position_curposXYZE();
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, uint8_t extruder, const float* gcode_target = NULL);
//void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder);

View file

@ -80,15 +80,21 @@ asm volatile ( \
#else //_NO_ASM
// NOTE: currently not implemented
void MultiU16X8toH16(unsigned short& intRes, unsigned char& charIn1, unsigned short& intIn2);
void MultiU24X24toH16(uint16_t& intRes, int32_t& longIn1, long& longIn2);
static inline void MultiU16X8toH16(uint16_t& intRes, uint8_t& charIn1, uint16_t& intIn2)
{
intRes = ((uint32_t)charIn1 * (uint32_t)intIn2) >> 16;
}
static inline void MultiU24X24toH16(uint16_t& intRes, uint32_t& longIn1, uint32_t& longIn2)
{
intRes = ((uint64_t)longIn1 * (uint64_t)longIn2) >> 24;
}
#endif //_NO_ASM
FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) {
unsigned short timer;
uint16_t timer;
if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY;
if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times
@ -108,7 +114,7 @@ FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops)
if(step_rate >= (8*256)){ // higher step rate
unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
unsigned char tmp_step_rate = (step_rate & 0x00ff);
unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2);
uint16_t gain = (uint16_t)pgm_read_word_near(table_address+2);
MultiU16X8toH16(timer, tmp_step_rate, gain);
timer = (unsigned short)pgm_read_word_near(table_address) - timer;
}

View file

@ -71,8 +71,7 @@ static dda_isteps_t
counter_z,
counter_e;
volatile dda_usteps_t step_events_completed; // The number of step events executed in the current block
static int32_t acceleration_time, deceleration_time;
//static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate;
static uint32_t acceleration_time, deceleration_time;
static uint16_t acc_step_rate; // needed for deccelaration start point
static uint8_t step_loops;
static uint16_t OCR1A_nominal;
@ -125,7 +124,7 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
static uint16_t main_Rate;
static uint16_t eISR_Rate;
static uint16_t eISR_Err;
static uint32_t eISR_Err;
static uint16_t current_adv_steps;
static uint16_t target_adv_steps;
@ -234,7 +233,7 @@ void invert_z_endstop(bool endstop_invert)
// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates
// first block->accelerate_until step_events_completed, then keeps going at constant speed until
// step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset.
// The slope of acceleration is calculated with the leib ramp alghorithm.
// The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far.
// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
@ -348,10 +347,7 @@ FORCE_INLINE void stepper_next_block()
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
e_step_loops = current_block->advance_step_loops;
target_adv_steps = current_block->max_adv_steps;
} else {
e_step_loops = 1;
}
e_steps = 0;
nextAdvanceISR = ADV_NEVER;
@ -736,38 +732,30 @@ FORCE_INLINE uint16_t fastdiv(uint16_t q, uint8_t d)
FORCE_INLINE void advance_spread(uint16_t timer)
{
if(eISR_Err > timer)
eISR_Err += timer;
uint8_t ticks = 0;
while(eISR_Err >= current_block->advance_rate)
{
++ticks;
eISR_Err -= current_block->advance_rate;
}
if(!ticks)
{
// advance-step skipped
eISR_Err -= timer;
eISR_Rate = timer;
nextAdvanceISR = timer;
return;
}
// at least one step
uint8_t ticks = 1;
uint32_t block = current_block->advance_rate;
uint16_t max_t = timer - eISR_Err;
while (block < max_t)
{
++ticks;
block += current_block->advance_rate;
}
if (block > timer)
eISR_Err += block - timer;
else
eISR_Err -= timer - block;
if (ticks <= 4)
eISR_Rate = fastdiv(timer, ticks);
if (ticks <= 3)
eISR_Rate = fastdiv(timer, ticks + 1);
else
{
// >4 ticks are still possible on slow moves
eISR_Rate = timer / ticks;
eISR_Rate = timer / (ticks + 1);
}
nextAdvanceISR = eISR_Rate / 2;
nextAdvanceISR = eISR_Rate;
}
#endif
@ -799,7 +787,7 @@ FORCE_INLINE void isr() {
// 25.12us for acceleration / deceleration.
{
//WRITE_NC(LOGIC_ANALYZER_CH1, true);
if (step_events_completed.wide <= (unsigned long int)current_block->accelerate_until) {
if (step_events_completed.wide <= current_block->accelerate_until) {
// v = t * a -> acc_step_rate = acceleration_time * current_block->acceleration_rate
MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
acc_step_rate += uint16_t(current_block->initial_rate);
@ -812,19 +800,29 @@ FORCE_INLINE void isr() {
acceleration_time += timer;
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
if (step_events_completed.wide <= (unsigned long int)step_loops)
if (step_events_completed.wide <= (unsigned long int)step_loops) {
la_state = ADV_INIT | ADV_ACC_VARY;
if (e_extruding && current_adv_steps > target_adv_steps)
target_adv_steps = current_adv_steps;
}
}
#endif
}
else if (step_events_completed.wide > (unsigned long int)current_block->decelerate_after) {
else if (step_events_completed.wide > current_block->decelerate_after) {
uint16_t step_rate;
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
step_rate = acc_step_rate - step_rate; // Decelerate from aceleration end point.
if ((step_rate & 0x8000) || step_rate < uint16_t(current_block->final_rate)) {
// Result is negative or too small.
step_rate = uint16_t(current_block->final_rate);
if (step_rate > acc_step_rate) { // Check step_rate stays positive
step_rate = uint16_t(current_block->final_rate);
}
else {
step_rate = acc_step_rate - step_rate; // Decelerate from acceleration end point.
// lower limit
if (step_rate < current_block->final_rate)
step_rate = uint16_t(current_block->final_rate);
}
// Step_rate to timer interval.
uint16_t timer = calc_timer(step_rate, step_loops);
_NEXT_ISR(timer);
@ -832,9 +830,11 @@ FORCE_INLINE void isr() {
#ifdef LIN_ADVANCE
if (current_block->use_advance_lead) {
if (step_events_completed.wide <= (unsigned long int)current_block->decelerate_after + step_loops) {
if (step_events_completed.wide <= current_block->decelerate_after + step_loops) {
target_adv_steps = current_block->final_adv_steps;
la_state = ADV_INIT | ADV_ACC_VARY;
if (e_extruding && current_adv_steps < target_adv_steps)
target_adv_steps = current_adv_steps;
}
}
#endif
@ -848,12 +848,12 @@ FORCE_INLINE void isr() {
#ifdef LIN_ADVANCE
if(current_block->use_advance_lead) {
if (!nextAdvanceISR) {
// Due to E-jerk, there can be discontinuities in pressure state where an
// acceleration or deceleration can be skipped or joined with the previous block.
// If LA was not previously active, re-check the pressure level
la_state = ADV_INIT;
}
// Due to E-jerk, there can be discontinuities in pressure state where an
// acceleration or deceleration can be skipped or joined with the previous block.
// If LA was not previously active, re-check the pressure level
la_state = ADV_INIT;
if (e_extruding)
target_adv_steps = current_adv_steps;
}
#endif
}
@ -865,14 +865,21 @@ FORCE_INLINE void isr() {
#ifdef LIN_ADVANCE
// avoid multiple instances or function calls to advance_spread
if (la_state & ADV_INIT) {
LA_phase = -1;
if (current_adv_steps == target_adv_steps) {
// nothing to be done in this phase
// nothing to be done in this phase, cancel any pending eisr
la_state = 0;
nextAdvanceISR = ADV_NEVER;
}
else {
eISR_Err = current_block->advance_rate / 4;
// reset error and iterations per loop for this phase
eISR_Err = current_block->advance_rate;
e_step_loops = current_block->advance_step_loops;
if ((la_state & ADV_ACC_VARY) && e_extruding && (current_adv_steps > target_adv_steps)) {
// LA could reverse the direction of extrusion in this phase
eISR_Err += current_block->advance_rate;
LA_phase = 0;
}
}
@ -882,11 +889,13 @@ FORCE_INLINE void isr() {
advance_spread(main_Rate);
if (LA_phase >= 0) {
if (step_loops == e_step_loops)
LA_phase = (eISR_Rate > main_Rate);
LA_phase = (current_block->advance_rate < main_Rate);
else {
// avoid overflow through division. warning: we need to _guarantee_ step_loops
// and e_step_loops are <= 4 due to fastdiv's limit
LA_phase = (fastdiv(eISR_Rate, step_loops) > fastdiv(main_Rate, e_step_loops));
auto adv_rate_n = fastdiv(current_block->advance_rate, step_loops);
auto main_rate_n = fastdiv(main_Rate, e_step_loops);
LA_phase = (adv_rate_n < main_rate_n);
}
}
}
@ -928,26 +937,34 @@ FORCE_INLINE void isr() {
FORCE_INLINE void advance_isr() {
if (current_adv_steps > target_adv_steps) {
// decompression
if (e_step_loops != 1) {
uint16_t d_steps = current_adv_steps - target_adv_steps;
if (d_steps < e_step_loops)
e_step_loops = d_steps;
}
e_steps -= e_step_loops;
if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR);
if(current_adv_steps > e_step_loops)
current_adv_steps -= e_step_loops;
else
current_adv_steps = 0;
nextAdvanceISR = eISR_Rate;
current_adv_steps -= e_step_loops;
}
else if (current_adv_steps < target_adv_steps) {
// compression
if (e_step_loops != 1) {
uint16_t d_steps = target_adv_steps - current_adv_steps;
if (d_steps < e_step_loops)
e_step_loops = d_steps;
}
e_steps += e_step_loops;
if (e_steps) WRITE_NC(E0_DIR_PIN, e_steps < 0? INVERT_E0_DIR: !INVERT_E0_DIR);
current_adv_steps += e_step_loops;
nextAdvanceISR = eISR_Rate;
}
else {
if (current_adv_steps == target_adv_steps) {
// advance steps completed
nextAdvanceISR = ADV_NEVER;
LA_phase = -1;
e_step_loops = 1;
}
else {
// schedule another tick
nextAdvanceISR = eISR_Rate;
}
}
@ -1017,7 +1034,7 @@ FORCE_INLINE void advance_isr_scheduler() {
// Schedule the next closest tick, ignoring advance if scheduled too
// soon in order to avoid skewing the regular stepper acceleration
if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + TCNT1 + 40) < nextMainISR)
if (nextAdvanceISR != ADV_NEVER && (nextAdvanceISR + 40) < nextMainISR)
OCR1A = nextAdvanceISR;
else
OCR1A = nextMainISR;

View file

@ -8,11 +8,12 @@
#ifdef SYSTEM_TIMER_2
#include "timer02.h"
#include "tone04.h"
#define _millis millis2
#define _micros micros2
#define _delay delay2
#define _tone tone
#define _noTone noTone
#define _tone tone4
#define _noTone noTone4
#define timer02_set_pwm0(pwm0)

View file

@ -143,14 +143,22 @@ static volatile bool temp_meas_ready = false;
#ifdef FAN_SOFT_PWM
static unsigned char soft_pwm_fan;
#endif
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
unsigned long extruder_autofan_last_check = _millis();
uint8_t fanSpeedBckp = 255;
bool fan_measuring = false;
#endif
uint8_t fanSpeedBckp = 255;
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
unsigned long extruder_autofan_last_check = _millis();
bool fan_measuring = false;
uint8_t fanState = 0;
#ifdef EXTRUDER_ALTFAN_DETECT
struct
{
uint8_t isAltfan : 1;
uint8_t altfanOverride : 1;
} altfanStatus;
#endif //EXTRUDER_ALTFAN_DETECT
#endif
#if EXTRUDERS > 3
@ -176,6 +184,12 @@ static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP;
#ifdef BED_MAXTEMP
static int bed_maxttemp_raw = HEATER_BED_RAW_HI_TEMP;
#endif
#ifdef AMBIENT_MINTEMP
static int ambient_minttemp_raw = AMBIENT_RAW_LO_TEMP;
#endif
#ifdef AMBIENT_MAXTEMP
static int ambient_maxttemp_raw = AMBIENT_RAW_HI_TEMP;
#endif
static void *heater_ttbl_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( (void *)HEATER_0_TEMPTABLE, (void *)HEATER_1_TEMPTABLE, (void *)HEATER_2_TEMPTABLE );
static uint8_t heater_ttbllen_map[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN );
@ -210,6 +224,56 @@ static void temp_runaway_check(int _heater_id, float _target_temperature, float
static void temp_runaway_stop(bool isPreheat, bool isBed);
#endif
#ifdef EXTRUDER_ALTFAN_DETECT
ISR(INT6_vect) {
fan_edge_counter[0]++;
}
bool extruder_altfan_detect()
{
setExtruderAutoFanState(3);
SET_INPUT(TACH_0);
uint8_t overrideVal = eeprom_read_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE);
if (overrideVal == EEPROM_EMPTY_VALUE)
{
overrideVal = (calibration_status() == CALIBRATION_STATUS_CALIBRATED) ? 1 : 0;
eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, overrideVal);
}
altfanStatus.altfanOverride = overrideVal;
CRITICAL_SECTION_START;
EICRB &= ~(1 << ISC61);
EICRB |= (1 << ISC60);
EIMSK |= (1 << INT6);
fan_edge_counter[0] = 0;
CRITICAL_SECTION_END;
extruder_autofan_last_check = _millis();
_delay(1000);
EIMSK &= ~(1 << INT6);
countFanSpeed();
altfanStatus.isAltfan = fan_speed[0] > 100;
setExtruderAutoFanState(1);
return altfanStatus.isAltfan;
}
void altfanOverride_toggle()
{
altfanStatus.altfanOverride = !altfanStatus.altfanOverride;
eeprom_update_byte((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanStatus.altfanOverride);
}
bool altfanOverride_get()
{
return altfanStatus.altfanOverride;
}
#endif //EXTRUDER_ALTFAN_DETECT
// return "false", if all extruder-heaters are 'off' (ie. "true", if any heater is 'on')
bool checkAllHotends(void)
{
@ -239,9 +303,7 @@ bool checkAllHotends(void)
const uint8_t safety_check_cycles_count = (extruder < 0) ? 45 : 10; //10 cycles / 20s delay for extruder and 45 cycles / 90s for heatbed
float temp_ambient;
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
unsigned long extruder_autofan_last_check = _millis();
#endif
@ -289,9 +351,7 @@ bool checkAllHotends(void)
max=max(max,input);
min=min(min,input);
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
if(_millis() - extruder_autofan_last_check > 2500) {
checkExtruderAutoFans();
extruder_autofan_last_check = _millis();
@ -447,29 +507,31 @@ int getHeaterPower(int heater) {
return soft_pwm[heater];
}
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
#if defined(FAN_PIN) && FAN_PIN > -1
#if EXTRUDER_0_AUTO_FAN_PIN == FAN_PIN
#error "You cannot set EXTRUDER_0_AUTO_FAN_PIN equal to FAN_PIN"
#endif
#if EXTRUDER_1_AUTO_FAN_PIN == FAN_PIN
#error "You cannot set EXTRUDER_1_AUTO_FAN_PIN equal to FAN_PIN"
#endif
#if EXTRUDER_2_AUTO_FAN_PIN == FAN_PIN
#error "You cannot set EXTRUDER_2_AUTO_FAN_PIN equal to FAN_PIN"
#endif
#endif
#endif
void setExtruderAutoFanState(int pin, bool state)
void setExtruderAutoFanState(uint8_t state)
{
unsigned char newFanSpeed = (state != 0) ? EXTRUDER_AUTO_FAN_SPEED : 0;
// this idiom allows both digital and PWM fan outputs (see M42 handling).
pinMode(pin, OUTPUT);
digitalWrite(pin, newFanSpeed);
//analogWrite(pin, newFanSpeed);
//If bit 1 is set (0x02), then the extruder fan speed won't be adjusted according to temperature. Useful for forcing
//the fan to either On or Off during certain tests/errors.
fanState = state;
uint8_t newFanSpeed = 0;
if (fanState & 0x01)
{
#ifdef EXTRUDER_ALTFAN_DETECT
if (altfanStatus.isAltfan && !altfanStatus.altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT;
else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
#else //EXTRUDER_ALTFAN_DETECT
newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
#endif //EXTRUDER_ALTFAN_DETECT
}
timer4_set_fan0(newFanSpeed);
}
#if (defined(FANCHECK) && (((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1)))))
@ -503,7 +565,7 @@ void checkFanSpeed()
fans_check_enabled = (eeprom_read_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED) > 0);
static unsigned char fan_speed_errors[2] = { 0,0 };
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 >-1))
if ((fan_speed[0] == 0) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;}
if ((fan_speed[0] < 20) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;}
else{
fan_speed_errors[0] = 0;
host_keepalive();
@ -577,47 +639,14 @@ void fanSpeedError(unsigned char _fan) {
void checkExtruderAutoFans()
{
uint8_t fanState = 0;
// which fan pins need to be turned on?
#if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
if (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)
fanState |= 1;
#endif
#if defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1
if (current_temperature[1] > EXTRUDER_AUTO_FAN_TEMPERATURE)
{
if (EXTRUDER_1_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else
fanState |= 2;
}
#endif
#if defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1
if (current_temperature[2] > EXTRUDER_AUTO_FAN_TEMPERATURE)
{
if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN)
fanState |= 2;
else
fanState |= 4;
}
#endif
// update extruder auto fan states
#if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, (fanState & 1) != 0);
#endif
#if defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1
if (EXTRUDER_1_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_1_AUTO_FAN_PIN, (fanState & 2) != 0);
#endif
#if defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1
if (EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN
&& EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_1_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_2_AUTO_FAN_PIN, (fanState & 4) != 0);
#endif
#if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
if (!(fanState & 0x02))
{
fanState &= ~1;
fanState |= current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE;
}
setExtruderAutoFanState(fanState);
#endif
}
#endif // any extruder auto fan pins set
@ -641,6 +670,7 @@ void manage_heater()
return;
// more precisely - this condition partially stabilizes time interval for regulation values evaluation (@ ~ 230ms)
// ADC values need to be converted before checking: converted values are later used in MINTEMP
updateTemperaturesFromRawValues();
check_max_temp();
@ -737,9 +767,7 @@ void manage_heater()
#define FAN_CHECK_DURATION 100 //100ms
#ifndef DEBUG_DISABLE_FANCHECK
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN > -1) || \
(defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN > -1)
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
#ifdef FAN_SOFT_PWM
#ifdef FANCHECK
@ -1098,7 +1126,9 @@ void tp_init()
timer0_init();
OCR2B = 128;
TIMSK2 |= (1<<OCIE2B);
TIMSK2 |= (1<<OCIE2B);
timer4_init(); //for tone and Extruder fan PWM
// Wait for temperature measurement to settle
_delay(250);
@ -1167,7 +1197,6 @@ void tp_init()
#endif //MAXTEMP 2
#ifdef BED_MINTEMP
/* No bed MINTEMP error implemented?!? */
while(analog2tempBed(bed_minttemp_raw) < BED_MINTEMP) {
#if HEATER_BED_RAW_LO_TEMP < HEATER_BED_RAW_HI_TEMP
bed_minttemp_raw += OVERSAMPLENR;
@ -1175,7 +1204,6 @@ void tp_init()
bed_minttemp_raw -= OVERSAMPLENR;
#endif
}
#endif //BED_MINTEMP
#ifdef BED_MAXTEMP
while(analog2tempBed(bed_maxttemp_raw) > BED_MAXTEMP) {
@ -1186,6 +1214,25 @@ void tp_init()
#endif
}
#endif //BED_MAXTEMP
#ifdef AMBIENT_MINTEMP
while(analog2tempAmbient(ambient_minttemp_raw) < AMBIENT_MINTEMP) {
#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP
ambient_minttemp_raw += OVERSAMPLENR;
#else
ambient_minttemp_raw -= OVERSAMPLENR;
#endif
}
#endif //AMBIENT_MINTEMP
#ifdef AMBIENT_MAXTEMP
while(analog2tempAmbient(ambient_maxttemp_raw) > AMBIENT_MAXTEMP) {
#if HEATER_AMBIENT_RAW_LO_TEMP < HEATER_AMBIENT_RAW_HI_TEMP
ambient_maxttemp_raw -= OVERSAMPLENR;
#else
ambient_maxttemp_raw += OVERSAMPLENR;
#endif
}
#endif //AMBIENT_MAXTEMP
}
#if (defined (TEMP_RUNAWAY_BED_HYSTERESIS) && TEMP_RUNAWAY_BED_TIMEOUT > 0) || (defined (TEMP_RUNAWAY_EXTRUDER_HYSTERESIS) && TEMP_RUNAWAY_EXTRUDER_TIMEOUT > 0)
@ -1357,9 +1404,11 @@ void temp_runaway_stop(bool isPreheat, bool isBed)
isBed ? LCD_ALERTMESSAGEPGM("BED PREHEAT ERROR") : LCD_ALERTMESSAGEPGM("PREHEAT ERROR");
SERIAL_ERROR_START;
isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)");
SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
#ifdef EXTRUDER_ALTFAN_DETECT
altfanStatus.altfanOverride = 1; //full speed
#endif //EXTRUDER_ALTFAN_DETECT
setExtruderAutoFanState(3);
SET_OUTPUT(FAN_PIN);
WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
#ifdef FAN_SOFT_PWM
fanSpeedSoftPwm = 255;
#else //FAN_SOFT_PWM
@ -1427,26 +1476,55 @@ enum { LCDALERT_NONE = 0, LCDALERT_HEATERMINTEMP, LCDALERT_BEDMINTEMP, LCDALERT_
//! to prevent flicker and improve speed
uint8_t last_alert_sent_to_lcd = LCDALERT_NONE;
//! update the current temperature error message
//! @param type short error abbreviation (PROGMEM)
//! @param func optional lcd update function (lcd_setalertstatus when first setting the error)
void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*) = lcd_updatestatus)
{
char msg[LCD_WIDTH];
strcpy_P(msg, PSTR("Err: "));
strcat_P(msg, type);
(*func)(msg);
}
//! signal a temperature error on both the lcd and serial
//! @param type short error abbreviation (PROGMEM)
//! @param e optional extruder index for hotend errors
void temp_error_messagepgm(const char* PROGMEM type, uint8_t e = EXTRUDERS)
{
temp_update_messagepgm(type, lcd_setalertstatus);
SERIAL_ERROR_START;
if(e != EXTRUDERS) {
SERIAL_ERROR((int)e);
SERIAL_ERRORPGM(": ");
}
SERIAL_ERRORPGM("Heaters switched off. ");
SERIAL_ERRORRPGM(type);
SERIAL_ERRORLNPGM(" triggered!");
}
void max_temp_error(uint8_t e) {
disable_heater();
if(IsStopped() == false) {
SERIAL_ERROR_START;
SERIAL_ERRORLN((int)e);
SERIAL_ERRORLNPGM(": Extruder switched off. MAXTEMP triggered !");
LCD_ALERTMESSAGEPGM("Err: MAXTEMP");
temp_error_messagepgm(PSTR("MAXTEMP"), e);
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop();
#endif
SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
SET_OUTPUT(FAN_PIN);
SET_OUTPUT(BEEPER);
WRITE(FAN_PIN, 1);
WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
WRITE(BEEPER, 1);
#ifdef EXTRUDER_ALTFAN_DETECT
altfanStatus.altfanOverride = 1; //full speed
#endif //EXTRUDER_ALTFAN_DETECT
setExtruderAutoFanState(3);
// fanSpeed will consumed by the check_axes_activity() routine.
fanSpeed=255;
if (farm_mode) { prusa_statistics(93); }
@ -1456,18 +1534,15 @@ void min_temp_error(uint8_t e) {
#ifdef DEBUG_DISABLE_MINTEMP
return;
#endif
//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
disable_heater();
static const char err[] PROGMEM = "Err: MINTEMP";
//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
static const char err[] PROGMEM = "MINTEMP";
if(IsStopped() == false) {
SERIAL_ERROR_START;
SERIAL_ERRORLN((int)e);
SERIAL_ERRORLNPGM(": Extruder switched off. MINTEMP triggered !");
lcd_setalertstatuspgm(err);
temp_error_messagepgm(err, e);
last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP;
} else if( last_alert_sent_to_lcd != LCDALERT_HEATERMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time)
// we are already stopped due to some error, only update the status message without flickering
lcd_updatestatuspgm(err);
temp_update_messagepgm(err);
last_alert_sent_to_lcd = LCDALERT_HEATERMINTEMP;
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
@ -1482,37 +1557,27 @@ void min_temp_error(uint8_t e) {
}
void bed_max_temp_error(void) {
#if HEATER_BED_PIN > -1
//WRITE(HEATER_BED_PIN, 0);
#endif
disable_heater();
if(IsStopped() == false) {
SERIAL_ERROR_START;
SERIAL_ERRORLNPGM("Temperature heated bed switched off. MAXTEMP triggered !");
LCD_ALERTMESSAGEPGM("Err: MAXTEMP BED");
temp_error_messagepgm(PSTR("MAXTEMP BED"));
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop();
#endif
}
void bed_min_temp_error(void) {
#ifdef DEBUG_DISABLE_MINTEMP
return;
#endif
//if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
#if HEATER_BED_PIN > -1
//WRITE(HEATER_BED_PIN, 0);
#endif
static const char err[] PROGMEM = "Err: MINTEMP BED";
disable_heater();
static const char err[] PROGMEM = "MINTEMP BED";
if(IsStopped() == false) {
SERIAL_ERROR_START;
SERIAL_ERRORLNPGM("Temperature heated bed switched off. MINTEMP triggered !");
lcd_setalertstatuspgm(err);
temp_error_messagepgm(err);
last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP;
} else if( last_alert_sent_to_lcd != LCDALERT_BEDMINTEMP ){ // only update, if the lcd message is to be changed (i.e. not the same as last time)
// we are already stopped due to some error, only update the status message without flickering
lcd_updatestatuspgm(err);
temp_update_messagepgm(err);
last_alert_sent_to_lcd = LCDALERT_BEDMINTEMP;
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
@ -1520,6 +1585,33 @@ void bed_min_temp_error(void) {
#endif
}
#ifdef AMBIENT_THERMISTOR
void ambient_max_temp_error(void) {
disable_heater();
if(IsStopped() == false) {
temp_error_messagepgm(PSTR("MAXTEMP AMB"));
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop();
#endif
}
void ambient_min_temp_error(void) {
#ifdef DEBUG_DISABLE_MINTEMP
return;
#endif
disable_heater();
if(IsStopped() == false) {
temp_error_messagepgm(PSTR("MINTEMP AMB"));
}
#ifndef BOGUS_TEMPERATURE_FAILSAFE_OVERRIDE
Stop();
#endif
}
#endif
#ifdef HEATER_0_USES_MAX6675
#define MAX6675_HEAT_INTERVAL 250
long max6675_previous_millis = MAX6675_HEAT_INTERVAL;
@ -1604,18 +1696,8 @@ void adc_ready(void) //callback from adc when sampling finished
} // extern "C"
// Timer2 (originaly timer0) is shared with millies
#ifdef SYSTEM_TIMER_2
ISR(TIMER2_COMPB_vect)
#else //SYSTEM_TIMER_2
ISR(TIMER0_COMPB_vect)
#endif //SYSTEM_TIMER_2
FORCE_INLINE static void temperature_isr()
{
static bool _lock = false;
if (_lock) return;
_lock = true;
asm("sei");
if (!temp_meas_ready) adc_cycle();
lcd_buttons_update();
@ -1981,8 +2063,24 @@ ISR(TIMER0_COMPB_vect)
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
check_fans();
#endif //(defined(TACH_0))
}
_lock = false;
// Timer2 (originaly timer0) is shared with millies
#ifdef SYSTEM_TIMER_2
ISR(TIMER2_COMPB_vect)
#else //SYSTEM_TIMER_2
ISR(TIMER0_COMPB_vect)
#endif //SYSTEM_TIMER_2
{
static bool _lock = false;
if (!_lock)
{
_lock = true;
sei();
temperature_isr();
cli();
_lock = false;
}
}
void check_max_temp()
@ -2002,11 +2100,19 @@ void check_max_temp()
#else
if (current_temperature_bed_raw >= bed_maxttemp_raw) {
#endif
target_temperature_bed = 0;
bed_max_temp_error();
}
#endif
//ambient
#if defined(AMBIENT_MAXTEMP) && (TEMP_SENSOR_AMBIENT != 0)
#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP
if (current_temperature_raw_ambient <= ambient_maxttemp_raw) {
#else
if (current_temperature_raw_ambient >= ambient_maxttemp_raw) {
#endif
ambient_max_temp_error();
}
#endif
}
//! number of repeating the same state with consecutive step() calls
//! used to slow down text switching
@ -2101,12 +2207,32 @@ void check_min_temp_bed()
}
}
#ifdef AMBIENT_MINTEMP
void check_min_temp_ambient()
{
#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP
if (current_temperature_raw_ambient >= ambient_minttemp_raw) {
#else
if (current_temperature_raw_ambient <= ambient_minttemp_raw) {
#endif
ambient_min_temp_error();
}
}
#endif
void check_min_temp()
{
static bool bCheckingOnHeater=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over heaterMintemp)
static bool bCheckingOnBed=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over bedMintemp)
#ifdef AMBIENT_THERMISTOR
if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type, so operator is ">" ;-)
#ifdef AMBIENT_MINTEMP
check_min_temp_ambient();
#endif
#if AMBIENT_RAW_LO_TEMP > AMBIENT_RAW_HI_TEMP
if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type
#else
if(current_temperature_raw_ambient=<(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW))
#endif
{ // ambient temperature is low
#endif //AMBIENT_THERMISTOR
// *** 'common' part of code for MK2.5 & MK3
@ -2194,4 +2320,20 @@ float unscalePID_d(float d)
#endif //PIDTEMP
#ifdef PINDA_THERMISTOR
//! @brief PINDA thermistor detected
//!
//! @retval true firmware should do temperature compensation and allow calibration
//! @retval false PINDA thermistor is not detected, disable temperature compensation and calibration
//!
bool has_temperature_compensation()
{
#ifdef DETECT_SUPERPINDA
return (current_temperature_pinda >= PINDA_MINTEMP) ? true : false;
#else
return true;
#endif
}
#endif //PINDA_THERMISTOR

View file

@ -63,6 +63,7 @@ extern float current_temperature_bed;
#ifdef PINDA_THERMISTOR
extern uint16_t current_temperature_raw_pinda;
extern float current_temperature_pinda;
bool has_temperature_compensation();
#endif
#ifdef AMBIENT_THERMISTOR
@ -245,7 +246,7 @@ FORCE_INLINE void autotempShutdown(){
void PID_autotune(float temp, int extruder, int ncycles);
void setExtruderAutoFanState(int pin, bool state);
void setExtruderAutoFanState(uint8_t state);
void checkExtruderAutoFans();
@ -270,10 +271,14 @@ void check_fans();
void check_min_temp();
void check_max_temp();
#endif
#ifdef EXTRUDER_ALTFAN_DETECT
extern bool extruder_altfan_detect();
extern void altfanOverride_toggle();
extern bool altfanOverride_get();
#endif //EXTRUDER_ALTFAN_DETECT
extern unsigned long extruder_autofan_last_check;
extern uint8_t fanSpeedBckp;
extern bool fan_measuring;
#endif

View file

@ -1213,6 +1213,8 @@ const short temptable_1047[][2] PROGMEM = {
#endif
#if (THERMISTORAMBIENT == 2000) //100k thermistor NTCG104LH104JT1
# define AMBIENT_RAW_HI_TEMP 0
# define AMBIENT_RAW_LO_TEMP 16383
const short temptable_2000[][2] PROGMEM = {
// Source: https://product.tdk.com/info/en/catalog/datasheets/503021/tpd_ntc-thermistor_ntcg_en.pdf
// Calculated using 4.7kohm pullup, voltage divider math, and manufacturer provided temp/resistance

126
Firmware/tone04.c Normal file
View file

@ -0,0 +1,126 @@
//tone04.c
// use atmega timer4 as main tone timer instead of timer2
// timer2 is used for System timer.
#include "system_timer.h"
#include "Configuration_prusa.h"
#ifdef SYSTEM_TIMER_2
#include <avr/io.h>
#include <avr/interrupt.h>
#include "pins.h"
#ifndef CRITICAL_SECTION_START
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
#define CRITICAL_SECTION_END SREG = _sreg;
#endif //CRITICAL_SECTION_START
#include "fastio.h"
void timer4_init(void)
{
CRITICAL_SECTION_START;
SET_OUTPUT(BEEPER);
WRITE(BEEPER, LOW);
SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
// Set timer mode 9 (PWM,Phase and Frequency Correct)
// Prescaler is CLK/1024
// Output compare is disabled on all timer pins
// Input capture is disabled
// All interrupts are disabled
TCCR4A = (1 << WGM40);
TCCR4B = (1 << WGM43) | (1 << CS42) | (1 << CS40);
OCR4A = 255;
OCR4B = 255;
OCR4C = 255;
TIMSK4 = 0;
CRITICAL_SECTION_END;
}
#ifdef EXTRUDER_0_AUTO_FAN_PIN
void timer4_set_fan0(uint8_t duty)
{
if (duty == 0 || duty == 255)
{
// We use digital logic if the duty cycle is 0% or 100%
TCCR4A &= ~(1 << COM4C1);
OCR4C = 0;
WRITE(EXTRUDER_0_AUTO_FAN_PIN, duty);
}
else
{
// Use the timer for fan speed. Enable the timer compare output and set the duty cycle.
// This function also handles the impossible scenario of a fan speed change during a Tone.
// Better be safe than sorry.
CRITICAL_SECTION_START;
// Enable the PWM output on the fan pin.
TCCR4A |= (1 << COM4C1);
OCR4C = (((uint32_t)duty) * ((uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255))) / ((uint32_t)255);
CRITICAL_SECTION_END;
}
}
#endif //EXTRUDER_0_AUTO_FAN_PIN
// Because of the timer mode change, we need two interrupts. We could also try to assume that the frequency is x2
// and use a TOGGLE(), but this seems to work well enough so I left it as it is now.
ISR(TIMER4_COMPA_vect)
{
WRITE(BEEPER, 1);
}
ISR(TIMER4_OVF_vect)
{
WRITE(BEEPER, 0);
}
void tone4(__attribute__((unused)) uint8_t _pin, uint16_t frequency)
{
//this ocr and prescalarbits calculation is taken from the Arduino core and simplified for one type of timer only
uint8_t prescalarbits = 0b001;
uint32_t ocr = F_CPU / frequency / 2 - 1;
if (ocr > 0xffff)
{
ocr = F_CPU / frequency / 2 / 64 - 1;
prescalarbits = 0b011;
}
CRITICAL_SECTION_START;
// Set calcualted prescaler
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
#ifdef EXTRUDER_0_AUTO_FAN_PIN
// Scale the fan PWM duty cycle so that it remains constant, but at the tone frequency
OCR4C = (((uint32_t)OCR4C) * ocr) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255);
#endif //EXTRUDER_0_AUTO_FAN_PIN
// Set calcualted ocr
OCR4A = ocr;
// Enable Output compare A interrupt and timer overflow interrupt
TIMSK4 |= (1 << OCIE4A) | (1 << TOIE4);
CRITICAL_SECTION_END;
}
void noTone4(__attribute__((unused)) uint8_t _pin)
{
CRITICAL_SECTION_START;
// Revert prescaler to CLK/1024
TCCR4B = (TCCR4B & 0b11111000) | (1 << CS42) | (1 << CS40);
#ifdef EXTRUDER_0_AUTO_FAN_PIN
// Scale the fan OCR back to the original value.
OCR4C = (((uint32_t)OCR4C) * (uint32_t)255) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255);
#endif //EXTRUDER_0_AUTO_FAN_PIN
OCR4A = 255;
// Disable Output compare A interrupt and timer overflow interrupt
TIMSK4 &= ~((1 << OCIE4A) | (1 << TOIE4));
CRITICAL_SECTION_END;
// Turn beeper off if it was on when noTone was called
WRITE(BEEPER, 0);
}
#endif //SYSTEM_TIMER_2

25
Firmware/tone04.h Normal file
View file

@ -0,0 +1,25 @@
//tone04.h
// use atmega timer4 as main tone timer instead of timer2
// timer2 is used for System timer.
#ifndef TIMER04_H
#define TIMER04_H
#include <inttypes.h>
#if defined(__cplusplus)
extern "C" {
#endif //defined(__cplusplus)
extern void timer4_init(void);
extern void timer4_set_fan0(uint8_t duty);
extern void tone4(uint8_t _pin, uint16_t frequency);
extern void noTone4(uint8_t _pin);
#if defined(__cplusplus)
}
#endif //defined(__cplusplus)
#endif //TIMER02_H

View file

@ -818,6 +818,36 @@ void lcd_status_screen() // NOT static due to using ins
}
}
#ifdef ULTIPANEL_FEEDMULTIPLY
// Dead zone at 100% feedrate
if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
(feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
{
lcd_encoder = 0;
feedmultiply = 100;
}
if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply != 100)
{
feedmultiply += int(lcd_encoder);
lcd_encoder = 0;
}
#endif //ULTIPANEL_FEEDMULTIPLY
if (feedmultiply < 10)
feedmultiply = 10;
else if (feedmultiply > 999)
feedmultiply = 999;
if (lcd_status_update_delay)
lcd_status_update_delay--;
else
@ -894,36 +924,6 @@ void lcd_status_screen() // NOT static due to using ins
menu_submenu(lcd_main_menu);
lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
}
#ifdef ULTIPANEL_FEEDMULTIPLY
// Dead zone at 100% feedrate
if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
(feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
{
lcd_encoder = 0;
feedmultiply = 100;
}
if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
{
feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
lcd_encoder = 0;
}
else if (feedmultiply != 100)
{
feedmultiply += int(lcd_encoder);
lcd_encoder = 0;
}
#endif //ULTIPANEL_FEEDMULTIPLY
if (feedmultiply < 10)
feedmultiply = 10;
else if (feedmultiply > 999)
feedmultiply = 999;
}
void lcd_commands()
@ -1943,6 +1943,7 @@ static void lcd_support_menu()
sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"),
_md->ip[0], _md->ip[1],
_md->ip[2], _md->ip[3]);
} else if (_md->is_flash_air &&
_md->ip[0] == 0 && _md->ip[1] == 0 &&
_md->ip[2] == 0 && _md->ip[3] == 0 &&
@ -1983,18 +1984,7 @@ static void lcd_support_menu()
#ifdef IR_SENSOR_ANALOG
MENU_ITEM_BACK_P(STR_SEPARATOR);
MENU_ITEM_BACK_P(PSTR("Fil. sensor v.:"));
switch(oFsensorPCB)
{
case ClFsensorPCB::_Old:
MENU_ITEM_BACK_P(_T(MSG_03_OR_OLDER));
break;
case ClFsensorPCB::_Rev04:
MENU_ITEM_BACK_P(_T(MSG_04_OR_NEWER));
break;
case ClFsensorPCB::_Undef:
default:
MENU_ITEM_BACK_P(PSTR(" unknown state"));
}
MENU_ITEM_BACK_P(FsensorIRVersionText());
#endif // IR_SENSOR_ANALOG
MENU_ITEM_BACK_P(STR_SEPARATOR);
@ -2038,6 +2028,7 @@ static void lcd_support_menu()
MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 r=1
#endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN
#ifdef DEBUG_BUILD
MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);////c=18 r=1
#endif /* DEBUG_BUILD */
@ -2324,6 +2315,12 @@ static void mFilamentItem_ASA()
mFilamentItem(ASA_PREHEAT_HOTEND_TEMP, ASA_PREHEAT_HPB_TEMP);
}
static void mFilamentItem_PC()
{
bFilamentPreheatState = false;
mFilamentItem(PC_PREHEAT_HOTEND_TEMP, PC_PREHEAT_HPB_TEMP);
}
static void mFilamentItem_ABS()
{
bFilamentPreheatState = false;
@ -2383,6 +2380,7 @@ void lcd_generic_preheat_menu()
MENU_ITEM_SUBMENU_P(PSTR("PLA - " STRINGIFY(PLA_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PLA_PREHEAT_HPB_TEMP)),mFilamentItem_PLA);
MENU_ITEM_SUBMENU_P(PSTR("PET - " STRINGIFY(PET_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PET_PREHEAT_HPB_TEMP)),mFilamentItem_PET);
MENU_ITEM_SUBMENU_P(PSTR("ASA - " STRINGIFY(ASA_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ASA_PREHEAT_HPB_TEMP)),mFilamentItem_ASA);
MENU_ITEM_SUBMENU_P(PSTR("PC - " STRINGIFY(PC_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PC_PREHEAT_HPB_TEMP)),mFilamentItem_PC);
MENU_ITEM_SUBMENU_P(PSTR("ABS - " STRINGIFY(ABS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ABS_PREHEAT_HPB_TEMP)),mFilamentItem_ABS);
MENU_ITEM_SUBMENU_P(PSTR("HIPS - " STRINGIFY(HIPS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(HIPS_PREHEAT_HPB_TEMP)),mFilamentItem_HIPS);
MENU_ITEM_SUBMENU_P(PSTR("PP - " STRINGIFY(PP_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PP_PREHEAT_HPB_TEMP)),mFilamentItem_PP);
@ -2736,7 +2734,7 @@ static void _lcd_move(const char *name, int axis, int min, int max)
if (max_software_endstops && current_position[axis] > max) current_position[axis] = max;
lcd_encoder = 0;
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
plan_buffer_line_curposXYZE(manual_feedrate[axis] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[axis] / 60);
lcd_draw_update = 1;
}
}
@ -2761,7 +2759,7 @@ static void lcd_move_e()
{
current_position[E_AXIS] += float((int)lcd_encoder) * move_menu_scale;
lcd_encoder = 0;
plan_buffer_line_curposXYZE(manual_feedrate[E_AXIS] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[E_AXIS] / 60);
lcd_draw_update = 1;
}
}
@ -3279,7 +3277,7 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z)
{
// Don't know where we are. Let's claim we are Z=0, so the soft end stops will not be triggered when moving up.
current_position[Z_AXIS] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
plan_set_position_curposXYZE();
// Until confirmed by the confirmation dialog.
for (;;) {
@ -3301,7 +3299,7 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z)
// Only move up, whatever direction the user rotates the encoder.
current_position[Z_AXIS] += fabs(lcd_encoder);
lcd_encoder = 0;
plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60);
}
}
if (lcd_clicked()) {
@ -3337,7 +3335,7 @@ calibrated:
else {
current_position[Z_AXIS] = Z_MAX_POS+4.f;
}
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
plan_set_position_curposXYZE();
return true;
canceled:
@ -3741,14 +3739,12 @@ void lcd_temp_cal_show_result(bool result) {
eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 1);
SERIAL_ECHOLNPGM("Temperature calibration done. Continue with pressing the knob.");
lcd_show_fullscreen_message_and_wait_P(_T(MSG_TEMP_CALIBRATION_DONE));
temp_cal_active = true;
eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, 1);
}
else {
eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 0);
SERIAL_ECHOLNPGM("Temperature calibration failed. Continue with pressing the knob.");
lcd_show_fullscreen_message_and_wait_P(_i("Temperature calibration failed"));////MSG_TEMP_CAL_FAILED c=20 r=8
temp_cal_active = false;
eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, 0);
}
lcd_update_enable(true);
@ -3855,7 +3851,7 @@ void prusa_statistics_err(char c){
}
static void prusa_statistics_case0(uint8_t statnr){
SERIAL_ECHO("{");
SERIAL_ECHO('{');
prusa_stat_printerstatus(statnr);
prusa_stat_farm_number();
prusa_stat_printinfo();
@ -3883,7 +3879,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
}
else
{
SERIAL_ECHO("{");
SERIAL_ECHO('{');
prusa_stat_printerstatus(1);
prusa_stat_farm_number();
prusa_stat_diameter();
@ -4449,9 +4445,9 @@ void lcd_pinda_calibration_menu()
}
void lcd_temp_calibration_set() {
bool temp_cal_active = eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE);
temp_cal_active = !temp_cal_active;
eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, temp_cal_active);
st_current_init();
}
#ifdef HAS_SECOND_SERIAL_PORT
@ -4709,7 +4705,7 @@ void lcd_language()
static void wait_preheat()
{
current_position[Z_AXIS] = 100; //move in z axis to make space for loading filament
plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60, active_extruder);
plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60);
delay_keep_alive(2000);
lcd_display_message_fullscreen_P(_T(MSG_WIZARD_HEATING));
lcd_set_custom_characters();
@ -5416,6 +5412,7 @@ do\
}\
while (0)
#if 0 // temporarily unused
static void lcd_check_gcode_set(void)
{
switch(oCheckGcode)
@ -5434,6 +5431,7 @@ switch(oCheckGcode)
}
eeprom_update_byte((uint8_t*)EEPROM_CHECK_GCODE,(uint8_t)oCheckGcode);
}
#endif
#define SETTINGS_GCODE \
do\
@ -5526,6 +5524,25 @@ static void sheets_menu()
void lcd_hw_setup_menu(void) // can not be "static"
{
typedef struct
{// 2bytes total
int8_t status;
uint8_t experimental_menu_visibility;
} _menu_data_t;
static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data");
_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
if (_md->status == 0 || lcd_draw_update)
{
_md->experimental_menu_visibility = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY);
if (_md->experimental_menu_visibility == EEPROM_EMPTY_VALUE)
{
_md->experimental_menu_visibility = 0;
eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, _md->experimental_menu_visibility);
}
}
MENU_BEGIN();
MENU_ITEM_BACK_P(_T(bSettings?MSG_SETTINGS:MSG_BACK)); // i.e. default menu-item / menu-item after checking mismatch
@ -5535,8 +5552,16 @@ void lcd_hw_setup_menu(void) // can not be "static"
#ifdef IR_SENSOR_ANALOG
FSENSOR_ACTION_NA;
MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor);
//! Fsensor Detection isn't ready for mmu yet it is temporarily disabled.
//! @todo Don't forget to remove this as soon Fsensor Detection works with mmu
if(!mmu_enabled) MENU_ITEM_FUNCTION_P(PSTR("Fsensor Detection"), lcd_detect_IRsensor);
#endif //IR_SENSOR_ANALOG
if (_md->experimental_menu_visibility)
{
MENU_ITEM_SUBMENU_P(PSTR("Experimental"), lcd_experimental_menu);////MSG_MENU_EXPERIMENTAL c=18
}
MENU_END();
}
@ -5575,8 +5600,10 @@ static void lcd_settings_menu()
#if defined (TMC2130) && defined (LINEARITY_CORRECTION)
MENU_ITEM_SUBMENU_P(_i("Lin. correction"), lcd_settings_linearity_correction_menu);
#endif //LINEARITY_CORRECTION && TMC2130
MENU_ITEM_TOGGLE_P(_T(MSG_TEMP_CALIBRATION), temp_cal_active ? _T(MSG_ON) : _T(MSG_OFF), lcd_temp_calibration_set);
if(has_temperature_compensation())
{
MENU_ITEM_TOGGLE_P(_T(MSG_TEMP_CALIBRATION), eeprom_read_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE) ? _T(MSG_ON) : _T(MSG_OFF), lcd_temp_calibration_set);
}
#ifdef HAS_SECOND_SERIAL_PORT
MENU_ITEM_TOGGLE_P(_T(MSG_RPI_PORT), (selectedSerialPort == 0) ? _T(MSG_OFF) : _T(MSG_ON), lcd_second_serial_set);
@ -5680,7 +5707,10 @@ static void lcd_calibration_menu()
//MENU_ITEM_FUNCTION_P(MSG_RESET_CALIBRATE_E, lcd_extr_cal_reset);
#endif
#ifndef MK1BP
MENU_ITEM_SUBMENU_P(_i("Temp. calibration"), lcd_pinda_calibration_menu);////MSG_CALIBRATION_PINDA_MENU c=17 r=1
if(has_temperature_compensation())
{
MENU_ITEM_SUBMENU_P(_i("Temp. calibration"), lcd_pinda_calibration_menu);////MSG_CALIBRATION_PINDA_MENU c=17 r=1
}
#endif //MK1BP
}
@ -6197,13 +6227,13 @@ void unload_filament()
// extr_unload2();
current_position[E_AXIS] -= 45;
plan_buffer_line_curposXYZE(5200 / 60, active_extruder);
plan_buffer_line_curposXYZE(5200 / 60);
st_synchronize();
current_position[E_AXIS] -= 15;
plan_buffer_line_curposXYZE(1000 / 60, active_extruder);
plan_buffer_line_curposXYZE(1000 / 60);
st_synchronize();
current_position[E_AXIS] -= 20;
plan_buffer_line_curposXYZE(1000 / 60, active_extruder);
plan_buffer_line_curposXYZE(1000 / 60);
st_synchronize();
lcd_display_message_fullscreen_P(_T(MSG_PULL_OUT_FILAMENT));
@ -6483,7 +6513,7 @@ static bool fan_error_selftest()
fanSpeedSoftPwm = 255;
#endif //FAN_SOFT_PWM
manage_heater(); //enables print fan
setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, 1); //force enables the extruder fan untill the first manage_heater() call.
setExtruderAutoFanState(3); //force enables the extruder fan
#ifdef FAN_SOFT_PWM
extruder_autofan_last_check = _millis();
fan_measuring = true;
@ -6491,6 +6521,7 @@ static bool fan_error_selftest()
_delay(1000); //delay_keep_alive would turn off extruder fan, because temerature is too low (maybe)
manage_heater();
fanSpeed = 0;
setExtruderAutoFanState(1); //releases lock on the extruder fan
#ifdef FAN_SOFT_PWM
fanSpeedSoftPwm = 0;
#endif //FAN_SOFT_PWM
@ -7171,13 +7202,13 @@ void lcd_print_stop()
cancel_heatup = true; //unroll temperature wait loop stack.
current_position[Z_AXIS] += 10; //lift Z.
plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60);
if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]) //if axis are homed, move to parked position.
{
current_position[X_AXIS] = X_CANCEL_POS;
current_position[Y_AXIS] = Y_CANCEL_POS;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
}
st_synchronize();
@ -7399,8 +7430,8 @@ 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 ? _T(MSG_04_OR_NEWER) : _T(MSG_03_OR_OLDER));
void printf_IRSensorAnalogBoardChange(){
printf_P(PSTR("Filament sensor board change detected: revision%S\n"), FsensorIRVersionText());
}
static bool lcd_selftest_IRsensor(bool bStandalone)
@ -7425,8 +7456,8 @@ static bool lcd_selftest_IRsensor(bool bStandalone)
return(false);
}
if((bPCBrev04 ? 1 : 0) != (uint8_t)oFsensorPCB){ // safer then "(uint8_t)bPCBrev04"
printf_IRSensorAnalogBoardChange(bPCBrev04);
oFsensorPCB=bPCBrev04 ? ClFsensorPCB::_Rev04 : ClFsensorPCB::_Old;
printf_IRSensorAnalogBoardChange();
eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,(uint8_t)oFsensorPCB);
}
return(true);
@ -7434,22 +7465,26 @@ static bool lcd_selftest_IRsensor(bool bStandalone)
static void lcd_detect_IRsensor(){
bool bAction;
bool loaded;
bMenuFSDetect = true; // inhibits some code inside "manage_inactivity()"
bAction = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is filament loaded?"), false, false);
if(bAction){
lcd_show_fullscreen_message_and_wait_P(_i("Please unload the filament first, then repeat this action."));////c=20 r=4
/// Check if filament is loaded. If it is loaded stop detection.
/// @todo Add autodetection with MMU2s
loaded = ! READ(IR_SENSOR_PIN);
if(loaded ){
lcd_show_fullscreen_message_and_wait_P(_i("Please unload the filament first, then repeat this action."));
return;
} else {
lcd_show_fullscreen_message_and_wait_P(_i("Please check the IR sensor connections and filament is unloaded."));
bAction = lcd_selftest_IRsensor(true);
}
bAction = lcd_selftest_IRsensor(true);
if(bAction){
if(bAction){
lcd_show_fullscreen_message_and_wait_P(_i("Sensor verified, remove the filament now."));////c=20 r=3
// the fsensor board has been successfully identified, any previous "not responding" may be cleared now
fsensor_not_responding = false;
// 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."));////c=20 r=5
// here it is unclear what to to with the fsensor_not_responding flag
}
// 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
@ -7465,9 +7500,17 @@ bool lcd_selftest()
bool _result = true;
bool _swapped_fan = false;
#ifdef IR_SENSOR_ANALOG
//! Check if IR sensor is in unknown state, set it temporarily to 0.3 or older
//! @todo This has to be improved
if( oFsensorPCB == ClFsensorPCB::_Undef) eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,0);
//! Check if IR sensor is in unknown state, if so run Fsensor Detection
//! As the Fsensor Detection isn't yet ready for the mmu2s we set temporarily the IR sensor 0.3 or older for mmu2s
//! @todo Don't forget to remove this as soon Fsensor Detection works with mmu
if( oFsensorPCB == ClFsensorPCB::_Undef) {
if (!mmu_enabled) {
lcd_detect_IRsensor();
}
else {
eeprom_update_byte((uint8_t*)EEPROM_FSENSOR_PCB,0);
}
}
#endif //IR_SENSOR_ANALOG
lcd_wait_for_cool_down();
lcd_clear();
@ -7605,7 +7648,7 @@ bool lcd_selftest()
current_position[Y_AXIS] += 4;
#endif //TMC2130
current_position[Z_AXIS] = current_position[Z_AXIS] + 10;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
set_destination_to_current();
_progress = lcd_selftest_screen(TestScreen::AxisZ, _progress, 3, true, 1500);
@ -7617,7 +7660,7 @@ bool lcd_selftest()
//raise Z to not damage the bed during and hotend testing
current_position[Z_AXIS] += 20;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
}
@ -7625,7 +7668,7 @@ bool lcd_selftest()
if (_result)
{
current_position[Z_AXIS] = current_position[Z_AXIS] + 10;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
_progress = lcd_selftest_screen(TestScreen::Home, 0, 2, true, 0);
bool bres = tmc2130_home_calibrate(X_AXIS);
@ -7675,10 +7718,12 @@ bool lcd_selftest()
_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //fil sensor OK
}
#endif //PAT9125
//#ifdef IR_SENSOR_ANALOG
#if (0)
#if 0
// Intentionally disabled - that's why we moved the detection to runtime by just checking the two voltages.
// The idea is not to force the user to remove and insert the filament on an assembled printer.
//def IR_SENSOR_ANALOG
_progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filament sensor
_result = lcd_selftest_IRsensor();
_result = lcd_selftest_IRsensor();
if (_result)
{
_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //filament sensor OK
@ -7721,7 +7766,7 @@ bool lcd_selftest()
static void reset_crash_det(unsigned char axis) {
current_position[axis] += 10;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_DET)) tmc2130_sg_stop_on_crash = true;
}
@ -7750,7 +7795,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
// first axis length measurement begin
current_position[axis] -= (axis_length + margin);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
@ -7760,11 +7805,11 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
current_position_init = st_get_position_mm(axis);
current_position[axis] += 2 * margin;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
current_position[axis] += axis_length;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
@ -7780,11 +7825,11 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
current_position[axis] -= margin;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
current_position[axis] -= (axis_length + margin);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
@ -7809,7 +7854,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
lcd_selftest_error(TestError::Axis, _error_1, "");
current_position[axis] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
plan_set_position_curposXYZE();
reset_crash_det(axis);
enable_endstops(true);
endstops_hit_on_purpose();
@ -7829,13 +7874,13 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
lcd_selftest_error(TestError::Pulley, _error_1, "");
current_position[axis] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
plan_set_position_curposXYZE();
reset_crash_det(axis);
endstops_hit_on_purpose();
return false;
}
current_position[axis] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
plan_set_position_curposXYZE();
reset_crash_det(axis);
endstops_hit_on_purpose();
return true;
@ -7857,13 +7902,13 @@ static bool lcd_selfcheck_axis(int _axis, int _travel)
if (_axis == X_AXIS) {
current_position[Z_AXIS] += 17;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
}
do {
current_position[_axis] = current_position[_axis] - 1;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
#ifdef TMC2130
if ((READ(Z_MIN_PIN) ^ (bool)Z_MIN_ENDSTOP_INVERTING))
@ -7943,7 +7988,7 @@ static bool lcd_selfcheck_axis(int _axis, int _travel)
}
}
current_position[_axis] = 0; //simulate axis home to avoid negative numbers for axis position, especially Z.
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
plan_set_position_curposXYZE();
return _stepresult;
}
@ -7966,17 +8011,17 @@ static bool lcd_selfcheck_pulleys(int axis)
current_position_init = current_position[axis];
current_position[axis] += 2;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
for (i = 0; i < 5; i++) {
refresh_cmd_timeout();
current_position[axis] = current_position[axis] + move;
st_current_set(0, 850); //set motor current higher
plan_buffer_line_curposXYZE(200, active_extruder);
plan_buffer_line_curposXYZE(200);
st_synchronize();
if (SilentModeMenu != SILENT_MODE_OFF) st_current_set(0, tmp_motor[0]); //set back to normal operation currents
else st_current_set(0, tmp_motor_loud[0]); //set motor current back
current_position[axis] = current_position[axis] - move;
plan_buffer_line_curposXYZE(50, active_extruder);
plan_buffer_line_curposXYZE(50);
st_synchronize();
if (((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING) == 1) ||
((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING) == 1)) {
@ -7993,7 +8038,7 @@ static bool lcd_selfcheck_pulleys(int axis)
endstop_triggered = true;
if (current_position_init - 1 <= current_position[axis] && current_position_init + 1 >= current_position[axis]) {
current_position[axis] += 10;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
return(true);
}
@ -8004,7 +8049,7 @@ static bool lcd_selfcheck_pulleys(int axis)
}
else {
current_position[axis] -= 1;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
if (_millis() > timeout_counter) {
lcd_selftest_error(TestError::Pulley, (axis == 0) ? "X" : "Y", "");
@ -8034,7 +8079,7 @@ static bool lcd_selfcheck_endstops()
#endif //!TMC2130
if ((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING) == 1) current_position[2] += 10;
}
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60, active_extruder);
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
if (
@ -8360,8 +8405,7 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
lcd_set_cursor(0, 1);
if(check_opposite == true) lcd_puts_P(_T(MSG_SELFTEST_COOLING_FAN));
else lcd_puts_P(_T(MSG_SELFTEST_EXTRUDER_FAN));
SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
setExtruderAutoFanState(3);
break;
case 1:
// object cooling fan
@ -8390,23 +8434,6 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
lcd_button_pressed = false;
do
{
switch (_fan)
{
case 0:
// extruder cooling fan
SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
break;
case 1:
// object cooling fan
SET_OUTPUT(FAN_PIN);
#ifdef FAN_SOFT_PWM
fanSpeedSoftPwm = 255;
#else //FAN_SOFT_PWM
analogWrite(FAN_PIN, 255);
#endif //FAN_SOFT_PWM
break;
}
if (abs((enc_dif - lcd_encoder_diff)) > 2) {
if (enc_dif > lcd_encoder_diff) {
_result = !check_opposite;
@ -8433,8 +8460,7 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
} while (!lcd_clicked());
KEEPALIVE_STATE(IN_HANDLER);
SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
WRITE(EXTRUDER_0_AUTO_FAN_PIN, 0);
setExtruderAutoFanState(0);
SET_OUTPUT(FAN_PIN);
#ifdef FAN_SOFT_PWM
fanSpeedSoftPwm = 0;
@ -8454,20 +8480,20 @@ static FanCheck lcd_selftest_fan_auto(int _fan)
case 0:
fanSpeed = 0;
manage_heater(); //turn off fan
setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, 1); //extruder fan
setExtruderAutoFanState(3); //extruder fan
#ifdef FAN_SOFT_PWM
extruder_autofan_last_check = _millis();
fan_measuring = true;
#endif //FAN_SOFT_PWM
_delay(2000); //delay_keep_alive would turn off extruder fan, because temerature is too low
_delay(2000);
setExtruderAutoFanState(0); //extruder fan
manage_heater(); //count average fan speed from 2s delay and turn off fans
printf_P(PSTR("Test 1:\n"));
printf_P(PSTR("Print fan speed: %d \n"), fan_speed[1]);
printf_P(PSTR("Extr fan speed: %d \n"), fan_speed[0]);
if (!fan_speed[0]) {
if (fan_speed[0] < 20) { // < 1200 RPM would mean either a faulty Noctua or Altfan
return FanCheck::ExtruderFan;
}
#ifdef FAN_SOFT_PWM
@ -8545,7 +8571,7 @@ static FanCheck lcd_selftest_fan_auto(int _fan)
static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_scale, bool _clear, int _delay)
{
lcd_update_enable(false);
lcd_update_enable(false);
const char *_indicator = (_progress >= _progress_scale) ? "-" : "|";
@ -8593,7 +8619,7 @@ static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_s
{
//SERIAL_ECHOLNPGM("Other tests");
TestScreen _step_block = TestScreen::AxisX;
TestScreen _step_block = TestScreen::AxisX;
lcd_selftest_screen_step(2, 2, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "X", _indicator);
_step_block = TestScreen::AxisY;
@ -8605,8 +8631,8 @@ static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_s
_step_block = TestScreen::Bed;
lcd_selftest_screen_step(3, 0, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Bed", _indicator);
_step_block = TestScreen::Hotend;
lcd_selftest_screen_step(3, 9, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Hotend", _indicator);
_step_block = TestScreen::Hotend;
lcd_selftest_screen_step(3, 9, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Hotend", _indicator);
}
if (_delay > 0) delay_keep_alive(_delay);
@ -8843,13 +8869,14 @@ void lcd_finishstatus() {
lcd_draw_update = 2;
}
void lcd_setstatus(const char* message)
{
if (lcd_status_message_level > 0)
return;
strncpy(lcd_status_message, message, LCD_WIDTH);
lcd_finishstatus();
lcd_updatestatus(message);
}
void lcd_updatestatuspgm(const char *message){
strncpy_P(lcd_status_message, message, LCD_WIDTH);
lcd_status_message[LCD_WIDTH] = 0;
@ -8864,12 +8891,29 @@ void lcd_setstatuspgm(const char* message)
return;
lcd_updatestatuspgm(message);
}
void lcd_updatestatus(const char *message){
strncpy(lcd_status_message, message, LCD_WIDTH);
lcd_status_message[LCD_WIDTH] = 0;
lcd_finishstatus();
// hack lcd_draw_update to 1, i.e. without clear
lcd_draw_update = 1;
}
void lcd_setalertstatuspgm(const char* message)
{
lcd_setstatuspgm(message);
lcd_status_message_level = 1;
lcd_return_to_status();
}
void lcd_setalertstatus(const char* message)
{
lcd_setstatus(message);
lcd_status_message_level = 1;
lcd_return_to_status();
}
void lcd_reset_alert_level()
{
lcd_status_message_level = 0;
@ -8889,6 +8933,13 @@ void menu_lcd_longpress_func(void)
lcd_quick_feedback();
return;
}
if (menu_menu == lcd_hw_setup_menu)
{
// only toggle the experimental menu visibility flag
lcd_quick_feedback();
lcd_experimental_toggle();
return;
}
// explicitely listed menus which are allowed to rise the move-z or live-adj-z functions
// The lists are not the same for both functions, so first decide which function is to be performed
@ -9052,3 +9103,25 @@ void lcd_crash_detect_disable()
eeprom_update_byte((uint8_t*)EEPROM_CRASH_DET, 0x00);
}
#endif
void lcd_experimental_toggle()
{
uint8_t oldVal = eeprom_read_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY);
if (oldVal == EEPROM_EMPTY_VALUE)
oldVal = 0;
else
oldVal = !oldVal;
eeprom_update_byte((uint8_t *)EEPROM_EXPERIMENTAL_VISIBILITY, oldVal);
}
void lcd_experimental_menu()
{
MENU_BEGIN();
MENU_ITEM_BACK_P(_T(MSG_BACK));
#ifdef EXTRUDER_ALTFAN_DETECT
MENU_ITEM_TOGGLE_P(_N("ALTFAN det."), altfanOverride_get()?_T(MSG_OFF):_T(MSG_ON), altfanOverride_toggle);////MSG_MENU_ALTFAN c=18
#endif //EXTRUDER_ALTFAN_DETECT
MENU_END();
}

View file

@ -23,9 +23,11 @@ void lcd_setstatuspgm(const char* message);
//! - always returns the display to the main status screen
//! - always makes lcd_reset (which is slow and causes flicker)
//! - does not update the message if there is already one (i.e. lcd_status_message_level > 0)
void lcd_setalertstatus(const char* message);
void lcd_setalertstatuspgm(const char* message);
//! only update the alert message on the main status screen
//! has no sideeffects, may be called multiple times
void lcd_updatestatus(const char *message);
void lcd_updatestatuspgm(const char *message);
void lcd_reset_alert_level();
@ -142,7 +144,7 @@ extern uint8_t farm_status;
#ifdef IR_SENSOR_ANALOG
extern bool bMenuFSDetect;
void printf_IRSensorAnalogBoardChange(bool bPCBrev04);
void printf_IRSensorAnalogBoardChange();
#endif //IR_SENSOR_ANALOG
extern int8_t SilentModeMenu;
@ -256,21 +258,7 @@ enum class WizState : uint8_t
void lcd_wizard(WizState state);
#define VOLT_DIV_REF 5
#ifdef IR_SENSOR_ANALOG
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
extern void lcd_experimental_toggle();
extern void lcd_experimental_menu();
#endif //ULTRALCD_H

View file

@ -330,6 +330,10 @@ PREHEAT SETTINGS
#define ASA_PREHEAT_HPB_TEMP 105
#define ASA_PREHEAT_FAN_SPEED 0
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_FAN_SPEED 0
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100
#define ABS_PREHEAT_FAN_SPEED 0

View file

@ -326,6 +326,9 @@ PREHEAT SETTINGS
#define ASA_PREHEAT_HOTEND_TEMP 260
#define ASA_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 105
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100

View file

@ -384,6 +384,9 @@
#define ASA_PREHEAT_HOTEND_TEMP 260
#define ASA_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 105
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100

View file

@ -385,6 +385,9 @@
#define ASA_PREHEAT_HOTEND_TEMP 260
#define ASA_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 105
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100

View file

@ -384,6 +384,9 @@
#define ASA_PREHEAT_HOTEND_TEMP 260
#define ASA_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 105
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100

View file

@ -385,6 +385,9 @@
#define ASA_PREHEAT_HOTEND_TEMP 260
#define ASA_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 105
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100

View file

@ -294,6 +294,9 @@
#if BED_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"
#endif
#define DETECT_SUPERPINDA
#define PINDA_MINTEMP BED_MINTEMP
#define AMBIENT_MINTEMP -30
// Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
@ -304,6 +307,7 @@
#define HEATER_1_MAXTEMP 305
#define HEATER_2_MAXTEMP 305
#define BED_MAXTEMP 125
#define AMBIENT_MAXTEMP 100
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
// Define PID constants for extruder with PT100
@ -496,6 +500,9 @@
#define ASA_PREHEAT_HOTEND_TEMP 260
#define ASA_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 110
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100

View file

@ -296,6 +296,9 @@
#if BED_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"
#endif
#define DETECT_SUPERPINDA
#define PINDA_MINTEMP BED_MINTEMP
#define AMBIENT_MINTEMP -30
// Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
@ -306,6 +309,7 @@
#define HEATER_1_MAXTEMP 305
#define HEATER_2_MAXTEMP 305
#define BED_MAXTEMP 125
#define AMBIENT_MAXTEMP 100
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
// Define PID constants for extruder with PT100
@ -331,6 +335,8 @@
#define EXTRUDER_2_AUTO_FAN_PIN -1
#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
#define EXTRUDER_AUTO_FAN_SPEED 255 // == full speed
#define EXTRUDER_ALTFAN_DETECT
#define EXTRUDER_ALTFAN_SPEED_SILENT 128
@ -498,6 +504,9 @@
#define ASA_PREHEAT_HOTEND_TEMP 260
#define ASA_PREHEAT_HPB_TEMP 105
#define PC_PREHEAT_HOTEND_TEMP 275
#define PC_PREHEAT_HPB_TEMP 110
#define ABS_PREHEAT_HOTEND_TEMP 255
#define ABS_PREHEAT_HPB_TEMP 100

View file

@ -26,14 +26,28 @@ The firmware for the Original Prusa i3 printers is proudly based on [Marlin 1.0.
1. Clone this repository and checkout the correct branch for your desired release version.
2. Set your printer model.
1. Set your printer model.
- For MK3 --> skip to step 3.
- If you have a different printer model, follow step [2.b](#2b) from Windows build
1. Install GNU AWK `sudo apt-get install gawk`
If you use mawk instead of gawk you get strange errors when multi language support is generated like:
`awk: line 2: function strtonum never defined
sed: couldn't write 4 items to stdout: Broken pipe
./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined
sed: couldn't write 4 items to stdout: Broken pipe
tr: write error: Broken pipe
./lang-build.sh: 121: ./lang-build.sh: arithmetic expression: expecting EOF: "0x"awk: line 2: function strtonum never defined
sed: couldn't write 4 items to stdout: Broken pipe
tr: write error: Broken pipe
tr: write error
cut: write error: Broken pipeNG! - some texts not found in lang_en.txt! updating binary:
primary language ids...awk: line 2: function strtonum never defined
sed: couldn't flush stdout: Broken pipe`
3. Run `./build.sh`
1. Run `./build.sh`
- Output hex file is at `"PrusaFirmware/lang/firmware.hex"` . In the same folder you can hex files for other languages as well.
4. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE.
1. Connect your printer and flash with PrusaSlicer ( Configuration --> Flash printer firmware ) or Slic3r PE.
- If you wish to flash from Arduino, follow step [2.c](#2c) from Windows build first.
@ -182,7 +196,7 @@ Example:
`ninja`
## Runing
## Running
`./tests`
# 4. Documentation