Filament_sensor.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #pragma once
  2. #include <inttypes.h>
  3. #include <stdio.h>
  4. #include <avr/pgmspace.h>
  5. #include "Marlin.h"
  6. #include "ultralcd.h"
  7. #include "menu.h"
  8. #include "cardreader.h"
  9. #include "temperature.h"
  10. #include "cmdqueue.h"
  11. #include "eeprom.h"
  12. #include "pins.h"
  13. #include "fastio.h"
  14. class Filament_sensor {
  15. public:
  16. virtual void init() = 0;
  17. virtual void update() = 0;
  18. virtual bool getFilamentPresent() = 0;
  19. enum class SensorActionOnError : uint8_t {
  20. _Continue = 0,
  21. _Pause = 1,
  22. _Undef = EEPROM_EMPTY_VALUE
  23. };
  24. void setAutoLoadEnabled(bool state, bool updateEEPROM = false) {
  25. autoLoadEnabled = state;
  26. if (updateEEPROM) {
  27. eeprom_update_byte((uint8_t *)EEPROM_FSENS_AUTOLOAD_ENABLED, state);
  28. }
  29. }
  30. void setRunoutEnabled(bool state, bool updateEEPROM = false) {
  31. runoutEnabled = state;
  32. if (updateEEPROM) {
  33. eeprom_update_byte((uint8_t *)EEPROM_FSENSOR, state);
  34. }
  35. }
  36. protected:
  37. void settings_init() {
  38. autoLoadEnabled = eeprom_read_byte((uint8_t*)EEPROM_FSENS_AUTOLOAD_ENABLED);
  39. runoutEnabled = eeprom_read_byte((uint8_t*)EEPROM_FSENSOR);
  40. sensorActionOnError = (SensorActionOnError)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA);
  41. if (sensorActionOnError == SensorActionOnError::_Undef) {
  42. sensorActionOnError = SensorActionOnError::_Pause;
  43. }
  44. }
  45. void checkFilamentEvents() {
  46. if (!ready)
  47. return;
  48. bool newFilamentPresent = getFilamentPresent();
  49. if (oldFilamentPresent != newFilamentPresent) {
  50. oldFilamentPresent = newFilamentPresent;
  51. if (newFilamentPresent) { //filament insertion
  52. puts_P(PSTR("filament inserted"));
  53. triggerFilamentInserted();
  54. }
  55. else { //filament removal
  56. puts_P(PSTR("filament removed"));
  57. triggerFilamentRemoved();
  58. }
  59. }
  60. };
  61. void triggerFilamentInserted() {
  62. if (autoLoadEnabled/* && (eFilamentAction == FilamentAction::None) */ && !(moves_planned() || IS_SD_PRINTING || usb_timer.running() || (lcd_commands_type == LcdCommands::Layer1Cal) || eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE))) {
  63. eFilamentAction = FilamentAction::AutoLoad;
  64. if(target_temperature[0] >= EXTRUDE_MINTEMP){
  65. bFilamentPreheatState = true;
  66. menu_submenu(mFilamentItemForce);
  67. } else {
  68. menu_submenu(lcd_generic_preheat_menu);
  69. lcd_timeoutToStatus.start();
  70. }
  71. }
  72. }
  73. void triggerFilamentRemoved() {
  74. if (runoutEnabled/* && (eFilamentAction == FilamentAction::None) */ && !saved_printing && (moves_planned() || IS_SD_PRINTING || usb_timer.running() || (lcd_commands_type == LcdCommands::Layer1Cal) || eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE))) {
  75. runoutEnabled = false;
  76. autoLoadEnabled = false;
  77. stop_and_save_print_to_ram(0, 0);
  78. restore_print_from_ram_and_continue(0);
  79. eeprom_update_byte((uint8_t*)EEPROM_FERROR_COUNT, eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) + 1);
  80. eeprom_update_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) + 1);
  81. enquecommand_front_P((PSTR("M600")));
  82. }
  83. }
  84. bool autoLoadEnabled;
  85. bool runoutEnabled;
  86. bool oldFilamentPresent; //for creating filament presence switching events.
  87. bool ready;
  88. SensorActionOnError sensorActionOnError;
  89. };
  90. class IR_sensor: public Filament_sensor {
  91. public:
  92. void init() {
  93. SET_INPUT(IR_SENSOR_PIN); //input mode
  94. WRITE(IR_SENSOR_PIN, 1); //pullup
  95. settings_init();
  96. }
  97. void update() {
  98. if (!ready) {
  99. ready = true; //the IR sensor gets ready instantly as it's just a gpio read operation.
  100. oldFilamentPresent = getFilamentPresent(); //initialize the current filament state so that we don't create a switching event right after the sensor is ready.
  101. }
  102. checkFilamentEvents();
  103. ;//
  104. }
  105. bool getFilamentPresent() {
  106. return !READ(IR_SENSOR_PIN);
  107. }
  108. void settings_init() {
  109. Filament_sensor::settings_init();
  110. }
  111. protected:
  112. };
  113. class IR_sensor_analog: public IR_sensor {
  114. public:
  115. void init() {
  116. IR_sensor::init();
  117. ;//
  118. }
  119. void update() {
  120. IR_sensor::update();
  121. ;//
  122. }
  123. void voltUpdate(uint16_t raw) { //to be called from the ADC ISR when a cycle is finished
  124. voltRaw = raw;
  125. voltReady = true;
  126. }
  127. void settings_init() {
  128. IR_sensor::settings_init();
  129. sensorRevision = (SensorRevision)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_PCB);
  130. }
  131. enum class SensorRevision : uint8_t {
  132. _Old = 0,
  133. _Rev04 = 1,
  134. _Undef = EEPROM_EMPTY_VALUE
  135. };
  136. private:
  137. SensorRevision sensorRevision;
  138. bool voltReady; //this gets set by the adc ISR
  139. uint16_t voltRaw;
  140. };
  141. extern IR_sensor_analog fsensor;