Filament_sensor.h 5.3 KB

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