Merge pull request #1442 from mkbel/auto_deplete_2

Auto deplete 2
This commit is contained in:
PavelSindler 2019-01-15 20:36:37 +01:00 committed by GitHub
commit 2f4e859da9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 275 additions and 8 deletions

View File

@ -14,7 +14,9 @@ set(TEST_SOURCES
Tests/tests.cpp Tests/tests.cpp
Tests/Example_test.cpp Tests/Example_test.cpp
Tests/Timer_test.cpp Tests/Timer_test.cpp
Tests/AutoDeplete_test.cpp
Firmware/Timer.cpp Firmware/Timer.cpp
Firmware/AutoDeplete.cpp
) )
add_executable(tests ${TEST_SOURCES}) add_executable(tests ${TEST_SOURCES})
target_include_directories(tests PRIVATE Tests) target_include_directories(tests PRIVATE Tests)

79
Firmware/AutoDeplete.cpp Normal file
View File

@ -0,0 +1,79 @@
//! @file
//! @author: Marek Bel
//! @date Jan 3, 2019
#include "AutoDeplete.h"
#include "assert.h"
//! @brief bit field marking depleted filaments
//!
//! binary 1 marks filament as depleted
//! Zero initialized value means, that no filament is depleted.
static uint8_t depleted;
static const uint8_t filamentCount = 5;
//! @return binary 1 for all filaments
//! @par fCount number of filaments
static constexpr uint8_t allDepleted(uint8_t fCount)
{
return fCount == 1 ? 1 : ((1 << (fCount - 1)) | allDepleted(fCount - 1));
}
//! @brief Is filament available for printing?
//! @par filament Filament number to be checked
//! @retval true Filament is available for printing.
//! @retval false Filament is not available for printing.
static bool loaded(uint8_t filament)
{
if (depleted & (1 << filament)) return false;
return true;
}
//! @brief Mark filament as not available for printing.
//! @par filament filament to be marked
void ad_markDepleted(uint8_t filament)
{
assert(filament < filamentCount);
if (filament < filamentCount)
{
depleted |= 1 << filament;
}
}
//! @brief Mark filament as available for printing.
//! @par filament filament to be marked
void ad_markLoaded(uint8_t filament)
{
assert(filament < filamentCount);
if (filament < filamentCount)
{
depleted &= ~(1 << filament);
}
}
//! @brief Get alternative filament, which is not depleted
//! @par filament filament
//! @return Filament, if it is depleted, returns next available,
//! if all filaments are depleted, returns filament function parameter.
uint8_t ad_getAlternative(uint8_t filament)
{
assert(filament < filamentCount);
for (uint8_t i = 0; i<filamentCount; ++i)
{
uint8_t nextFilament = (filament + i) % filamentCount;
if (loaded(nextFilament)) return nextFilament;
}
return filament;
}
//! @brief Are all filaments depleted?
//! @retval true All filaments are depleted.
//! @retval false All filaments are not depleted.
bool ad_allDepleted()
{
if (allDepleted(filamentCount) == depleted)
{
return true;
}
return false;
}

17
Firmware/AutoDeplete.h Normal file
View File

@ -0,0 +1,17 @@
//! @file
//! @author: Marek Bel
//! @brief Filament auto deplete engine for multi-material prints with MMUv2 (Now marketed as SpoolJoin)
//!
//! Interface for marking MMUv2 filaments as depleted and getting alternative filament for printing.
#ifndef AUTODEPLETE_H
#define AUTODEPLETE_H
#include <stdint.h>
void ad_markDepleted(uint8_t filament);
void ad_markLoaded(uint8_t filament);
uint8_t ad_getAlternative(uint8_t filament);
bool ad_allDepleted();
#endif /* AUTODEPLETE_H */

View File

@ -78,6 +78,7 @@
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "Dcodes.h" #include "Dcodes.h"
#include "AutoDeplete.h"
#ifdef SWSPI #ifdef SWSPI
@ -6944,6 +6945,10 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
} }
else { else {
tmp_extruder = code_value(); tmp_extruder = code_value();
if (mmu_enabled && lcd_autoDepleteEnabled())
{
tmp_extruder = ad_getAlternative(tmp_extruder);
}
} }
st_synchronize(); st_synchronize();
snmm_filaments_used |= (1 << tmp_extruder); //for stop print snmm_filaments_used |= (1 << tmp_extruder); //for stop print

View File

@ -1,4 +1,4 @@
//mmu.cpp //! @file
#include "mmu.h" #include "mmu.h"
#include "planner.h" #include "planner.h"
@ -14,6 +14,7 @@
#include "printers.h" #include "printers.h"
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "io_atmega2560.h" #include "io_atmega2560.h"
#include "AutoDeplete.h"
#ifdef TMC2130 #ifdef TMC2130
#include "tmc2130.h" #include "tmc2130.h"
@ -320,8 +321,15 @@ void mmu_loop(void)
if (!mmu_finda && CHECK_FINDA && fsensor_enabled) { if (!mmu_finda && CHECK_FINDA && fsensor_enabled) {
fsensor_stop_and_save_print(); fsensor_stop_and_save_print();
enquecommand_front_P(PSTR("FSENSOR_RECOVER")); //then recover enquecommand_front_P(PSTR("FSENSOR_RECOVER")); //then recover
if (lcd_autoDepleteEnabled()) enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command ad_markDepleted(mmu_extruder);
else enquecommand_front_P(PSTR("M600")); //save print and run M600 command if (lcd_autoDepleteEnabled() && !ad_allDepleted())
{
enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command
}
else
{
enquecommand_front_P(PSTR("M600")); //save print and run M600 command
}
} }
mmu_state = 1; mmu_state = 1;
if (mmu_cmd == 0) if (mmu_cmd == 0)
@ -417,16 +425,26 @@ int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament)
return timeout?1:0; return timeout?1:0;
} }
//! @brief Enqueue MMUv2 command
//!
//! Call manage_response() after enqueuing to process command.
//! If T command is enqueued, it disables current for extruder motor if TMC2130 driver present.
//! If T or L command is enqueued, it marks filament loaded in AutoDeplete module.
void mmu_command(uint8_t cmd) void mmu_command(uint8_t cmd)
{ {
#ifdef TMC2130
if ((cmd >= MMU_CMD_T0) && (cmd <= MMU_CMD_T4)) if ((cmd >= MMU_CMD_T0) && (cmd <= MMU_CMD_T4))
{ {
//disable extruder motor //disable extruder motor
#ifdef TMC2130
tmc2130_set_pwr(E_AXIS, 0); tmc2130_set_pwr(E_AXIS, 0);
//printf_P(PSTR("E-axis disabled\n"));
}
#endif //TMC2130 #endif //TMC2130
//printf_P(PSTR("E-axis disabled\n"));
ad_markLoaded(cmd - MMU_CMD_T0);
}
if ((cmd >= MMU_CMD_L0) && (cmd <= MMU_CMD_L4))
{
ad_markLoaded(cmd - MMU_CMD_L0);
}
mmu_cmd = cmd; mmu_cmd = cmd;
mmu_ready = false; mmu_ready = false;
@ -748,7 +766,7 @@ void mmu_M600_load_filament(bool automatic)
#endif //MMU_M600_SWITCH_EXTRUDER #endif //MMU_M600_SWITCH_EXTRUDER
} }
else { else {
tmp_extruder = (tmp_extruder+1)%5; tmp_extruder = ad_getAlternative(tmp_extruder);
} }
lcd_update_enable(false); lcd_update_enable(false);
lcd_clear(); lcd_clear();

View File

@ -1,4 +1,4 @@
//mmu.h //! @file
#include <inttypes.h> #include <inttypes.h>

146
Tests/AutoDeplete_test.cpp Normal file
View File

@ -0,0 +1,146 @@
/**
* @file
* @author Marek Bel
*/
#include "catch.hpp"
#include "../Firmware/AutoDeplete.h"
TEST_CASE( "AutoDeplete test.", "[AutoDeplete]" )
{
CHECK(ad_allDepleted() == false);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
ad_markDepleted(1);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markDepleted(3);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 4);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markDepleted(4);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 0);
CHECK(ad_getAlternative(4) == 0);
CHECK(ad_allDepleted() == false);
ad_markDepleted(4);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 0);
CHECK(ad_getAlternative(4) == 0);
CHECK(ad_allDepleted() == false);
ad_markDepleted(0);
CHECK(ad_getAlternative(0) == 2);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 2);
CHECK(ad_getAlternative(4) == 2);
CHECK(ad_allDepleted() == false);
ad_markDepleted(2);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == true);
ad_markDepleted(2);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == true);
ad_markLoaded(4);
CHECK(ad_getAlternative(0) == 4);
CHECK(ad_getAlternative(1) == 4);
CHECK(ad_getAlternative(2) == 4);
CHECK(ad_getAlternative(3) == 4);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(0);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 4);
CHECK(ad_getAlternative(2) == 4);
CHECK(ad_getAlternative(3) == 4);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(3);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 3);
CHECK(ad_getAlternative(2) == 3);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(3);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 3);
CHECK(ad_getAlternative(2) == 3);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(2);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(1);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(1);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
}