Filament Width Sensor singleton (#15191)
This commit is contained in:
@ -26,11 +26,24 @@
|
||||
|
||||
#include "filwidth.h"
|
||||
|
||||
bool filament_sensor; // = false; // M405/M406 turns filament sensor control ON/OFF.
|
||||
float filament_width_nominal = DEFAULT_NOMINAL_FILAMENT_DIA, // Nominal filament width. Change with M404.
|
||||
filament_width_meas = DEFAULT_MEASURED_FILAMENT_DIA; // Measured filament diameter
|
||||
uint8_t meas_delay_cm = MEASUREMENT_DELAY_CM; // Distance delay setting
|
||||
int8_t measurement_delay[MAX_MEASUREMENT_DELAY + 1], // Ring buffer to delayed measurement. Store extruder factor after subtracting 100
|
||||
filwidth_delay_index[2] = { 0, -1 }; // Indexes into ring buffer
|
||||
FilamentWidthSensor filwidth;
|
||||
|
||||
bool FilamentWidthSensor::enabled; // = false; // (M405-M406) Filament Width Sensor ON/OFF.
|
||||
uint32_t FilamentWidthSensor::accum; // = 0 // ADC accumulator
|
||||
uint16_t FilamentWidthSensor::raw; // = 0 // Measured filament diameter - one extruder only
|
||||
float FilamentWidthSensor::nominal_mm = DEFAULT_NOMINAL_FILAMENT_DIA, // (M104) Nominal filament width
|
||||
FilamentWidthSensor::measured_mm = DEFAULT_MEASURED_FILAMENT_DIA, // Measured filament diameter
|
||||
FilamentWidthSensor::e_count = 0,
|
||||
FilamentWidthSensor::delay_dist = 0;
|
||||
uint8_t FilamentWidthSensor::meas_delay_cm = MEASUREMENT_DELAY_CM; // Distance delay setting
|
||||
int8_t FilamentWidthSensor::ratios[MAX_MEASUREMENT_DELAY + 1], // Ring buffer to delay measurement. (Extruder factor minus 100)
|
||||
FilamentWidthSensor::index_r, // Indexes into ring buffer
|
||||
FilamentWidthSensor::index_w;
|
||||
|
||||
void FilamentWidthSensor::init() {
|
||||
const int8_t ratio = sample_to_size_ratio();
|
||||
for (uint8_t i = 0; i < COUNT(ratios); ++i) ratios[i] = ratio;
|
||||
index_r = index_w = 0;
|
||||
}
|
||||
|
||||
#endif // FILAMENT_WIDTH_SENSOR
|
||||
|
@ -22,10 +22,98 @@
|
||||
#pragma once
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include "../module/planner.h"
|
||||
|
||||
extern bool filament_sensor; // M405/M406 turns filament sensor control ON/OFF.
|
||||
extern float filament_width_nominal, // Nominal filament width. Change with M404.
|
||||
filament_width_meas; // Measured filament diameter
|
||||
extern uint8_t meas_delay_cm; // Distance delay setting
|
||||
extern int8_t measurement_delay[MAX_MEASUREMENT_DELAY + 1], // Ring buffer to delayed measurement. Store extruder factor after subtracting 100
|
||||
filwidth_delay_index[2]; // Indexes into ring buffer
|
||||
class FilamentWidthSensor {
|
||||
public:
|
||||
static constexpr int MMD_CM = MAX_MEASUREMENT_DELAY + 1, MMD_MM = MMD_CM * 10;
|
||||
static bool enabled; // (M405-M406) Filament Width Sensor ON/OFF.
|
||||
static uint32_t accum; // ADC accumulator
|
||||
static uint16_t raw; // Measured filament diameter - one extruder only
|
||||
static float nominal_mm, // (M104) Nominal filament width
|
||||
measured_mm, // Measured filament diameter
|
||||
e_count, delay_dist;
|
||||
static uint8_t meas_delay_cm; // Distance delay setting
|
||||
static int8_t ratios[MMD_CM], // Ring buffer to delay measurement. (Extruder factor minus 100)
|
||||
index_r, index_w; // Indexes into ring buffer
|
||||
|
||||
FilamentWidthSensor() { init(); }
|
||||
static void init();
|
||||
|
||||
static inline void enable(const bool ena) { enabled = ena; }
|
||||
|
||||
static inline void set_delay_cm(const uint8_t cm) {
|
||||
meas_delay_cm = _MIN(cm, MAX_MEASUREMENT_DELAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Filament Width (mm) to an extrusion ratio
|
||||
* and reduce to an 8 bit value.
|
||||
*
|
||||
* A nominal width of 1.75 and measured width of 1.73
|
||||
* gives (100 * 1.75 / 1.73) for a ratio of 101 and
|
||||
* a return value of 1.
|
||||
*/
|
||||
static int8_t sample_to_size_ratio() {
|
||||
return ABS(nominal_mm - measured_mm) <= FILWIDTH_ERROR_MARGIN
|
||||
? int(100.0f * nominal_mm / measured_mm) - 100 : 0;
|
||||
}
|
||||
|
||||
// Apply a single ADC reading to the raw value
|
||||
static void accumulate(const uint16_t adc) {
|
||||
if (adc > 102) // Ignore ADC under 0.5 volts
|
||||
accum += (uint32_t(adc) << 7) - (accum >> 7);
|
||||
}
|
||||
|
||||
// Convert raw measurement to mm
|
||||
static inline float raw_to_mm(const uint16_t v) { return v * 5.0f * (1.0f / 16383.0f); }
|
||||
static inline float raw_to_mm() { return raw_to_mm(raw); }
|
||||
|
||||
// A scaled reading is ready
|
||||
// Divide to get to 0-16384 range since we used 1/128 IIR filter approach
|
||||
static inline void reading_ready() { raw = accum >> 10; }
|
||||
|
||||
// Update mm from the raw measurement
|
||||
static inline void update_measured_mm() { measured_mm = raw_to_mm(); }
|
||||
|
||||
// Update ring buffer used to delay filament measurements
|
||||
static inline void advance_e(const float &e_move) {
|
||||
|
||||
// Increment counters with the E distance
|
||||
e_count += e_move;
|
||||
delay_dist += e_move;
|
||||
|
||||
// Only get new measurements on forward E movement
|
||||
if (!UNEAR_ZERO(e_count)) {
|
||||
|
||||
// Loop the delay distance counter (modulus by the mm length)
|
||||
while (delay_dist >= MMD_MM) delay_dist -= MMD_MM;
|
||||
|
||||
// Convert into an index (cm) into the measurement array
|
||||
index_r = int8_t(delay_dist * 0.1f);
|
||||
|
||||
// If the ring buffer is not full...
|
||||
if (index_r != index_w) {
|
||||
e_count = 0; // Reset the E movement counter
|
||||
const int8_t meas_sample = sample_to_size_ratio();
|
||||
do {
|
||||
if (++index_w >= MMD_CM) index_w = 0; // The next unused slot
|
||||
ratios[index_w] = meas_sample; // Store the measurement
|
||||
} while (index_r != index_w); // More slots to fill?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamically set the volumetric multiplier based on the delayed width measurement.
|
||||
static inline void update_volumetric() {
|
||||
if (enabled) {
|
||||
int8_t read_index = index_r - meas_delay_cm;
|
||||
if (read_index < 0) read_index += MMD_CM; // Loop around buffer if needed
|
||||
LIMIT(read_index, 0, MAX_MEASUREMENT_DELAY);
|
||||
planner.apply_filament_width_sensor(ratios[read_index]);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern FilamentWidthSensor filwidth;
|
||||
|
Reference in New Issue
Block a user