Merge pull request #6272 from thinkyhead/rc_adc_variable_rate
Make ADC sensor reading frequency adjustable
This commit is contained in:
commit
02fca543bb
|
@ -91,28 +91,6 @@ enum EndstopEnum {
|
|||
Z2_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* Temperature
|
||||
* Stages in the ISR loop
|
||||
*/
|
||||
enum TempState {
|
||||
PrepareTemp_0,
|
||||
MeasureTemp_0,
|
||||
PrepareTemp_BED,
|
||||
MeasureTemp_BED,
|
||||
PrepareTemp_1,
|
||||
MeasureTemp_1,
|
||||
PrepareTemp_2,
|
||||
MeasureTemp_2,
|
||||
PrepareTemp_3,
|
||||
MeasureTemp_3,
|
||||
PrepareTemp_4,
|
||||
MeasureTemp_4,
|
||||
Prepare_FILWIDTH,
|
||||
Measure_FILWIDTH,
|
||||
StartupDelay // Startup, delay initial temp reading a tiny bit so the hardware can settle
|
||||
};
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
enum e_parser_state {
|
||||
state_RESET,
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* temperature.cpp - temperature control
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "ultralcd.h"
|
||||
#include "temperature.h"
|
||||
|
@ -1538,8 +1536,8 @@ void Temperature::isr() {
|
|||
CBI(TIMSK0, OCIE0B); //Disable Temperature ISR
|
||||
sei();
|
||||
|
||||
static uint8_t temp_count = 0;
|
||||
static TempState temp_state = StartupDelay;
|
||||
static int8_t temp_count = -1;
|
||||
static ADCSensorState adc_sensor_state = StartupDelay;
|
||||
static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
|
||||
// avoid multiple loads of pwm_count
|
||||
uint8_t pwm_count_tmp = pwm_count;
|
||||
|
@ -1812,6 +1810,22 @@ void Temperature::isr() {
|
|||
|
||||
#endif // SLOW_PWM_HEATERS
|
||||
|
||||
//
|
||||
// Update lcd buttons 488 times per second
|
||||
//
|
||||
static bool do_buttons;
|
||||
if ((do_buttons ^= true)) lcd_buttons_update();
|
||||
|
||||
/**
|
||||
* One sensor is sampled on every other call of the ISR.
|
||||
* Each sensor is read 16 (OVERSAMPLENR) times, taking the average.
|
||||
*
|
||||
* On each Prepare pass, ADC is started for a sensor pin.
|
||||
* On the next pass, the ADC value is read and accumulated.
|
||||
*
|
||||
* This gives each ADC 0.9765ms to charge up.
|
||||
*/
|
||||
|
||||
#define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
|
||||
#ifdef MUX5
|
||||
#define START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
|
||||
|
@ -1819,122 +1833,94 @@ void Temperature::isr() {
|
|||
#define START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
|
||||
#endif
|
||||
|
||||
// Prepare or measure a sensor, each one every 14th frame
|
||||
switch (temp_state) {
|
||||
case PrepareTemp_0:
|
||||
switch (adc_sensor_state) {
|
||||
|
||||
case SensorsReady: {
|
||||
// All sensors have been read. Stay in this state for a few
|
||||
// ISRs to save on calls to temp update/checking code below.
|
||||
constexpr int extra_loops = MIN_ADC_ISR_LOOPS - (int)SensorsReady;
|
||||
static uint8_t delay_count = 0;
|
||||
if (extra_loops > 0) {
|
||||
if (delay_count == 0) delay_count = extra_loops; // Init this delay
|
||||
if (--delay_count) // While delaying...
|
||||
adc_sensor_state = (ADCSensorState)(int(SensorsReady) - 1); // retain this state (else, next state will be 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
adc_sensor_state = (ADCSensorState)0; // Fall-through to start first sensor now
|
||||
}
|
||||
|
||||
#if HAS_TEMP_0
|
||||
case PrepareTemp_0:
|
||||
START_ADC(TEMP_0_PIN);
|
||||
#endif
|
||||
lcd_buttons_update();
|
||||
temp_state = MeasureTemp_0;
|
||||
break;
|
||||
case MeasureTemp_0:
|
||||
#if HAS_TEMP_0
|
||||
raw_temp_value[0] += ADC;
|
||||
#endif
|
||||
temp_state = PrepareTemp_BED;
|
||||
break;
|
||||
|
||||
case PrepareTemp_BED:
|
||||
#if HAS_TEMP_BED
|
||||
START_ADC(TEMP_BED_PIN);
|
||||
#endif
|
||||
lcd_buttons_update();
|
||||
temp_state = MeasureTemp_BED;
|
||||
|
||||
#if HAS_TEMP_BED
|
||||
case PrepareTemp_BED:
|
||||
START_ADC(TEMP_BED_PIN);
|
||||
break;
|
||||
case MeasureTemp_BED:
|
||||
#if HAS_TEMP_BED
|
||||
raw_temp_bed_value += ADC;
|
||||
#endif
|
||||
temp_state = PrepareTemp_1;
|
||||
break;
|
||||
|
||||
case PrepareTemp_1:
|
||||
#if HAS_TEMP_1
|
||||
START_ADC(TEMP_1_PIN);
|
||||
#endif
|
||||
lcd_buttons_update();
|
||||
temp_state = MeasureTemp_1;
|
||||
|
||||
#if HAS_TEMP_1
|
||||
case PrepareTemp_1:
|
||||
START_ADC(TEMP_1_PIN);
|
||||
break;
|
||||
case MeasureTemp_1:
|
||||
#if HAS_TEMP_1
|
||||
raw_temp_value[1] += ADC;
|
||||
#endif
|
||||
temp_state = PrepareTemp_2;
|
||||
break;
|
||||
|
||||
case PrepareTemp_2:
|
||||
#if HAS_TEMP_2
|
||||
START_ADC(TEMP_2_PIN);
|
||||
#endif
|
||||
lcd_buttons_update();
|
||||
temp_state = MeasureTemp_2;
|
||||
|
||||
#if HAS_TEMP_2
|
||||
case PrepareTemp_2:
|
||||
START_ADC(TEMP_2_PIN);
|
||||
break;
|
||||
case MeasureTemp_2:
|
||||
#if HAS_TEMP_2
|
||||
raw_temp_value[2] += ADC;
|
||||
#endif
|
||||
temp_state = PrepareTemp_3;
|
||||
break;
|
||||
|
||||
case PrepareTemp_3:
|
||||
#if HAS_TEMP_3
|
||||
START_ADC(TEMP_3_PIN);
|
||||
#endif
|
||||
lcd_buttons_update();
|
||||
temp_state = MeasureTemp_3;
|
||||
|
||||
#if HAS_TEMP_3
|
||||
case PrepareTemp_3:
|
||||
START_ADC(TEMP_3_PIN);
|
||||
break;
|
||||
case MeasureTemp_3:
|
||||
#if HAS_TEMP_3
|
||||
raw_temp_value[3] += ADC;
|
||||
#endif
|
||||
temp_state = PrepareTemp_4;
|
||||
break;
|
||||
|
||||
case PrepareTemp_4:
|
||||
#if HAS_TEMP_4
|
||||
START_ADC(TEMP_4_PIN);
|
||||
#endif
|
||||
lcd_buttons_update();
|
||||
temp_state = MeasureTemp_4;
|
||||
|
||||
#if HAS_TEMP_4
|
||||
case PrepareTemp_4:
|
||||
START_ADC(TEMP_4_PIN);
|
||||
break;
|
||||
case MeasureTemp_4:
|
||||
#if HAS_TEMP_4
|
||||
raw_temp_value[4] += ADC;
|
||||
#endif
|
||||
temp_state = Prepare_FILWIDTH;
|
||||
break;
|
||||
|
||||
case Prepare_FILWIDTH:
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
START_ADC(FILWIDTH_PIN);
|
||||
#endif
|
||||
lcd_buttons_update();
|
||||
temp_state = Measure_FILWIDTH;
|
||||
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
case Prepare_FILWIDTH:
|
||||
START_ADC(FILWIDTH_PIN);
|
||||
break;
|
||||
case Measure_FILWIDTH:
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
// raw_filwidth_value += ADC; //remove to use an IIR filter approach
|
||||
if (ADC > 102) { //check that ADC is reading a voltage > 0.5 volts, otherwise don't take in the data.
|
||||
raw_filwidth_value -= (raw_filwidth_value >> 7); //multiply raw_filwidth_value by 127/128
|
||||
raw_filwidth_value += ((unsigned long)ADC << 7); //add new ADC reading
|
||||
if (ADC > 102) { // Make sure ADC is reading > 0.5 volts, otherwise don't read.
|
||||
raw_filwidth_value -= (raw_filwidth_value >> 7); // Subtract 1/128th of the raw_filwidth_value
|
||||
raw_filwidth_value += ((unsigned long)ADC << 7); // Add new ADC reading, scaled by 128
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
temp_state = PrepareTemp_0;
|
||||
temp_count++;
|
||||
break;
|
||||
|
||||
case StartupDelay:
|
||||
temp_state = PrepareTemp_0;
|
||||
break;
|
||||
case StartupDelay: break;
|
||||
|
||||
// default:
|
||||
// SERIAL_ERROR_START;
|
||||
// SERIAL_ERRORLNPGM("Temp measurement error!");
|
||||
// break;
|
||||
} // switch(temp_state)
|
||||
} // switch(adc_sensor_state)
|
||||
|
||||
if (temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256) = 164ms.
|
||||
if (!adc_sensor_state && ++temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256) = 164ms.
|
||||
|
||||
temp_count = 0;
|
||||
|
||||
|
@ -1998,6 +1984,9 @@ void Temperature::isr() {
|
|||
|
||||
} // temp_count >= OVERSAMPLENR
|
||||
|
||||
// Go to the next state, up to SensorsReady
|
||||
adc_sensor_state = (ADCSensorState)((int(adc_sensor_state) + 1) % int(StartupDelay));
|
||||
|
||||
#if ENABLED(BABYSTEPPING)
|
||||
LOOP_XYZ(axis) {
|
||||
int curTodo = babystepsTodo[axis]; //get rid of volatile for performance
|
||||
|
|
|
@ -50,6 +50,49 @@
|
|||
#define EXTRUDER_IDX active_extruder
|
||||
#endif
|
||||
|
||||
/**
|
||||
* States for ADC reading in the ISR
|
||||
*/
|
||||
enum ADCSensorState {
|
||||
#if HAS_TEMP_0
|
||||
PrepareTemp_0,
|
||||
MeasureTemp_0,
|
||||
#endif
|
||||
#if HAS_TEMP_1
|
||||
PrepareTemp_1,
|
||||
MeasureTemp_1,
|
||||
#endif
|
||||
#if HAS_TEMP_2
|
||||
PrepareTemp_2,
|
||||
MeasureTemp_2,
|
||||
#endif
|
||||
#if HAS_TEMP_3
|
||||
PrepareTemp_3,
|
||||
MeasureTemp_3,
|
||||
#endif
|
||||
#if HAS_TEMP_4
|
||||
PrepareTemp_4,
|
||||
MeasureTemp_4,
|
||||
#endif
|
||||
#if HAS_TEMP_BED
|
||||
PrepareTemp_BED,
|
||||
MeasureTemp_BED,
|
||||
#endif
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
Prepare_FILWIDTH,
|
||||
Measure_FILWIDTH,
|
||||
#endif
|
||||
SensorsReady, // Temperatures ready. Delay the next round of readings to let ADC pins settle.
|
||||
StartupDelay // Startup, delay initial temp reading a tiny bit so the hardware can settle
|
||||
};
|
||||
|
||||
// Minimum number of Temperature::ISR loops between sensor readings.
|
||||
// Multiplied by 16 (OVERSAMPLENR) to obtain the total time to
|
||||
// get all oversampled sensor readings
|
||||
#define MIN_ADC_ISR_LOOPS 10
|
||||
|
||||
#define ACTUAL_ADC_SAMPLES max(int(MIN_ADC_ISR_LOOPS), int(SensorsReady))
|
||||
|
||||
class Temperature {
|
||||
|
||||
public:
|
||||
|
@ -74,7 +117,7 @@ class Temperature {
|
|||
#endif
|
||||
|
||||
#if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
|
||||
#define PID_dT ((OVERSAMPLENR * 12.0)/(F_CPU / 64.0 / 256.0))
|
||||
#define PID_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / (F_CPU / 64.0 / 256.0))
|
||||
#endif
|
||||
|
||||
#if ENABLED(PIDTEMP)
|
||||
|
|
Loading…
Reference in a new issue