Filament_sensor.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #pragma once
  2. #include <inttypes.h>
  3. #include "cmdqueue.h"
  4. #include "pins.h"
  5. #include "fastio.h"
  6. #include "adc.h"
  7. #include "pat9125.h"
  8. #define FSENSOR_IR 1
  9. #define FSENSOR_IR_ANALOG 2
  10. #define FSENSOR_PAT9125 3
  11. /// Can be used to block printer's filament sensor handling - to avoid errorneous injecting of M600
  12. /// while doing a toolchange with the MMU
  13. /// In case of "no filament sensor" these methods default to an empty implementation
  14. class FSensorBlockRunout {
  15. public:
  16. FSensorBlockRunout();
  17. ~FSensorBlockRunout();
  18. };
  19. #ifdef FILAMENT_SENSOR
  20. class Filament_sensor {
  21. public:
  22. virtual void init() = 0;
  23. virtual void deinit() = 0;
  24. virtual bool update() = 0;
  25. virtual bool getFilamentPresent() = 0;
  26. #ifdef FSENSOR_PROBING
  27. virtual bool probeOtherType() = 0; //checks if the wrong fsensor type is detected.
  28. #endif
  29. enum class State : uint8_t {
  30. disabled = 0,
  31. initializing,
  32. ready,
  33. error,
  34. };
  35. enum class SensorActionOnError : uint8_t {
  36. _Continue = 0,
  37. _Pause = 1,
  38. _Undef = EEPROM_EMPTY_VALUE
  39. };
  40. void setEnabled(bool enabled);
  41. void setAutoLoadEnabled(bool state, bool updateEEPROM = false);
  42. bool getAutoLoadEnabled() {
  43. return autoLoadEnabled;
  44. }
  45. void setRunoutEnabled(bool state, bool updateEEPROM = false);
  46. bool getRunoutEnabled() {
  47. return runoutEnabled;
  48. }
  49. void setActionOnError(SensorActionOnError state, bool updateEEPROM = false);
  50. SensorActionOnError getActionOnError() {
  51. return sensorActionOnError;
  52. }
  53. bool getFilamentLoadEvent() {
  54. return postponedLoadEvent;
  55. }
  56. bool isError() {
  57. return state == State::error;
  58. }
  59. bool isReady() {
  60. return state == State::ready;
  61. }
  62. bool isEnabled() {
  63. return state != State::disabled;
  64. }
  65. protected:
  66. void settings_init_common();
  67. bool checkFilamentEvents();
  68. void triggerFilamentInserted();
  69. void triggerFilamentRemoved();
  70. void filAutoLoad();
  71. void filRunout();
  72. void triggerError();
  73. State state;
  74. bool autoLoadEnabled;
  75. bool runoutEnabled;
  76. bool oldFilamentPresent; //for creating filament presence switching events.
  77. bool postponedLoadEvent; //this event lasts exactly one update cycle. It is long enough to be able to do polling for load event.
  78. ShortTimer eventBlankingTimer;
  79. SensorActionOnError sensorActionOnError;
  80. };
  81. #if (FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
  82. class IR_sensor: public Filament_sensor {
  83. public:
  84. void init() override;
  85. void deinit() override;
  86. bool update()override ;
  87. bool getFilamentPresent()override;
  88. #ifdef FSENSOR_PROBING
  89. bool probeOtherType()override;
  90. #endif
  91. void settings_init();
  92. };
  93. #if (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
  94. constexpr static uint16_t Voltage2Raw(float V) {
  95. return (V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F;
  96. }
  97. constexpr static float Raw2Voltage(uint16_t raw) {
  98. return VOLT_DIV_REF * (raw / (1023.F * OVERSAMPLENR));
  99. }
  100. class IR_sensor_analog: public IR_sensor {
  101. public:
  102. void init()override;
  103. void deinit()override;
  104. bool update()override;
  105. void voltUpdate(uint16_t raw);
  106. uint16_t getVoltRaw();
  107. void settings_init();
  108. enum class SensorRevision : uint8_t {
  109. _Old = 0,
  110. _Rev04 = 1,
  111. _Undef = EEPROM_EMPTY_VALUE
  112. };
  113. SensorRevision getSensorRevision() {
  114. return sensorRevision;
  115. }
  116. const char* getIRVersionText();
  117. void setSensorRevision(SensorRevision rev, bool updateEEPROM = false);
  118. bool checkVoltage(uint16_t raw);
  119. // Voltage2Raw is not constexpr :/
  120. constexpr static uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982
  121. constexpr static uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910
  122. constexpr static uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821
  123. constexpr static uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059
  124. constexpr static uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368
  125. private:
  126. SensorRevision sensorRevision;
  127. volatile bool voltReady; //this gets set by the adc ISR
  128. volatile uint16_t voltRaw;
  129. uint16_t minVolt = Voltage2Raw(6.F);
  130. uint16_t maxVolt = 0;
  131. uint16_t nFSCheckCount;
  132. uint8_t voltageErrorCnt;
  133. static constexpr uint16_t FS_CHECK_COUNT = 4;
  134. /// Switching mechanism of the fsensor type.
  135. /// Called from 2 spots which have a very similar behavior
  136. /// 1: SensorRevision::_Old -> SensorRevision::_Rev04 and print _i("FS v0.4 or newer")
  137. /// 2: SensorRevision::_Rev04 -> sensorRevision=SensorRevision::_Old and print _i("FS v0.3 or older")
  138. void IR_ANALOG_Check(SensorRevision isVersion, SensorRevision switchTo);
  139. };
  140. #endif //(FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
  141. #endif //(FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
  142. #if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
  143. class PAT9125_sensor: public Filament_sensor {
  144. public:
  145. void init()override;
  146. void deinit()override;
  147. bool update()override;
  148. bool getFilamentPresent() override{
  149. return filterFilPresent;
  150. }
  151. #ifdef FSENSOR_PROBING
  152. bool probeOtherType() override;
  153. #endif
  154. void setJamDetectionEnabled(bool state, bool updateEEPROM = false);
  155. bool getJamDetectionEnabled() {
  156. return jamDetection;
  157. }
  158. void stStep(bool rev) { //from stepper isr
  159. stepCount += rev ? -1 : 1;
  160. }
  161. void settings_init();
  162. private:
  163. static constexpr uint16_t pollingPeriod = 10; //[ms]
  164. static constexpr uint8_t filterCnt = 5; //how many checks need to be done in order to determine the filament presence precisely.
  165. ShortTimer pollingTimer;
  166. uint8_t filter;
  167. uint8_t filterFilPresent;
  168. bool jamDetection;
  169. int16_t oldPos;
  170. volatile int16_t stepCount;
  171. int16_t chunkSteps;
  172. uint8_t jamErrCnt;
  173. constexpr void calcChunkSteps(float u) {
  174. chunkSteps = (int16_t)(1.25 * u); //[mm]
  175. }
  176. int16_t getStepCount();
  177. void resetStepCount();
  178. void filJam();
  179. bool updatePAT9125();
  180. };
  181. #endif //(FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
  182. #if FILAMENT_SENSOR_TYPE == FSENSOR_IR
  183. extern IR_sensor fsensor;
  184. #elif FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG
  185. extern IR_sensor_analog fsensor;
  186. #elif FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125
  187. extern PAT9125_sensor fsensor;
  188. #endif
  189. #endif //FILAMENT_SENSOR