Просмотр исходного кода

Merge pull request #6272 from thinkyhead/rc_adc_variable_rate

Make ADC sensor reading frequency adjustable
Scott Lahteine 8 лет назад
Родитель
Сommit
02fca543bb
3 измененных файлов: 129 добавлений и 119 удалений
  1. 0
    22
      Marlin/enum.h
  2. 85
    96
      Marlin/temperature.cpp
  3. 44
    1
      Marlin/temperature.h

+ 0
- 22
Marlin/enum.h Просмотреть файл

91
   Z2_MAX
91
   Z2_MAX
92
 };
92
 };
93
 
93
 
94
-/**
95
- * Temperature
96
- * Stages in the ISR loop
97
- */
98
-enum TempState {
99
-  PrepareTemp_0,
100
-  MeasureTemp_0,
101
-  PrepareTemp_BED,
102
-  MeasureTemp_BED,
103
-  PrepareTemp_1,
104
-  MeasureTemp_1,
105
-  PrepareTemp_2,
106
-  MeasureTemp_2,
107
-  PrepareTemp_3,
108
-  MeasureTemp_3,
109
-  PrepareTemp_4,
110
-  MeasureTemp_4,
111
-  Prepare_FILWIDTH,
112
-  Measure_FILWIDTH,
113
-  StartupDelay // Startup, delay initial temp reading a tiny bit so the hardware can settle
114
-};
115
-
116
 #if ENABLED(EMERGENCY_PARSER)
94
 #if ENABLED(EMERGENCY_PARSER)
117
   enum e_parser_state {
95
   enum e_parser_state {
118
     state_RESET,
96
     state_RESET,

+ 85
- 96
Marlin/temperature.cpp Просмотреть файл

24
  * temperature.cpp - temperature control
24
  * temperature.cpp - temperature control
25
  */
25
  */
26
 
26
 
27
-
28
-
29
 #include "Marlin.h"
27
 #include "Marlin.h"
30
 #include "ultralcd.h"
28
 #include "ultralcd.h"
31
 #include "temperature.h"
29
 #include "temperature.h"
1538
   CBI(TIMSK0, OCIE0B); //Disable Temperature ISR
1536
   CBI(TIMSK0, OCIE0B); //Disable Temperature ISR
1539
   sei();
1537
   sei();
1540
 
1538
 
1541
-  static uint8_t temp_count = 0;
1542
-  static TempState temp_state = StartupDelay;
1539
+  static int8_t temp_count = -1;
1540
+  static ADCSensorState adc_sensor_state = StartupDelay;
1543
   static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
1541
   static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
1544
   // avoid multiple loads of pwm_count
1542
   // avoid multiple loads of pwm_count
1545
   uint8_t pwm_count_tmp = pwm_count;
1543
   uint8_t pwm_count_tmp = pwm_count;
1812
 
1810
 
1813
   #endif // SLOW_PWM_HEATERS
1811
   #endif // SLOW_PWM_HEATERS
1814
 
1812
 
1813
+  //
1814
+  // Update lcd buttons 488 times per second
1815
+  //
1816
+  static bool do_buttons;
1817
+  if ((do_buttons ^= true)) lcd_buttons_update();
1818
+
1819
+  /**
1820
+   * One sensor is sampled on every other call of the ISR.
1821
+   * Each sensor is read 16 (OVERSAMPLENR) times, taking the average.
1822
+   *
1823
+   * On each Prepare pass, ADC is started for a sensor pin.
1824
+   * On the next pass, the ADC value is read and accumulated.
1825
+   *
1826
+   * This gives each ADC 0.9765ms to charge up.
1827
+   */
1828
+
1815
   #define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
1829
   #define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
1816
   #ifdef MUX5
1830
   #ifdef MUX5
1817
     #define START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
1831
     #define START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
1819
     #define START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
1833
     #define START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
1820
   #endif
1834
   #endif
1821
 
1835
 
1822
-  // Prepare or measure a sensor, each one every 14th frame
1823
-  switch (temp_state) {
1824
-    case PrepareTemp_0:
1825
-      #if HAS_TEMP_0
1836
+  switch (adc_sensor_state) {
1837
+
1838
+    case SensorsReady: {
1839
+      // All sensors have been read. Stay in this state for a few
1840
+      // ISRs to save on calls to temp update/checking code below.
1841
+      constexpr int extra_loops = MIN_ADC_ISR_LOOPS - (int)SensorsReady;
1842
+      static uint8_t delay_count = 0;
1843
+      if (extra_loops > 0) {
1844
+        if (delay_count == 0) delay_count = extra_loops;   // Init this delay
1845
+        if (--delay_count)                                 // While delaying...
1846
+          adc_sensor_state = (ADCSensorState)(int(SensorsReady) - 1); // retain this state (else, next state will be 0)
1847
+        break;
1848
+      }
1849
+      else
1850
+        adc_sensor_state = (ADCSensorState)0; // Fall-through to start first sensor now
1851
+    }
1852
+
1853
+    #if HAS_TEMP_0
1854
+      case PrepareTemp_0:
1826
         START_ADC(TEMP_0_PIN);
1855
         START_ADC(TEMP_0_PIN);
1827
-      #endif
1828
-      lcd_buttons_update();
1829
-      temp_state = MeasureTemp_0;
1830
-      break;
1831
-    case MeasureTemp_0:
1832
-      #if HAS_TEMP_0
1856
+        break;
1857
+      case MeasureTemp_0:
1833
         raw_temp_value[0] += ADC;
1858
         raw_temp_value[0] += ADC;
1834
-      #endif
1835
-      temp_state = PrepareTemp_BED;
1836
-      break;
1859
+        break;
1860
+    #endif
1837
 
1861
 
1838
-    case PrepareTemp_BED:
1839
-      #if HAS_TEMP_BED
1862
+    #if HAS_TEMP_BED
1863
+      case PrepareTemp_BED:
1840
         START_ADC(TEMP_BED_PIN);
1864
         START_ADC(TEMP_BED_PIN);
1841
-      #endif
1842
-      lcd_buttons_update();
1843
-      temp_state = MeasureTemp_BED;
1844
-      break;
1845
-    case MeasureTemp_BED:
1846
-      #if HAS_TEMP_BED
1865
+        break;
1866
+      case MeasureTemp_BED:
1847
         raw_temp_bed_value += ADC;
1867
         raw_temp_bed_value += ADC;
1848
-      #endif
1849
-      temp_state = PrepareTemp_1;
1850
-      break;
1868
+        break;
1869
+    #endif
1851
 
1870
 
1852
-    case PrepareTemp_1:
1853
-      #if HAS_TEMP_1
1871
+    #if HAS_TEMP_1
1872
+      case PrepareTemp_1:
1854
         START_ADC(TEMP_1_PIN);
1873
         START_ADC(TEMP_1_PIN);
1855
-      #endif
1856
-      lcd_buttons_update();
1857
-      temp_state = MeasureTemp_1;
1858
-      break;
1859
-    case MeasureTemp_1:
1860
-      #if HAS_TEMP_1
1874
+        break;
1875
+      case MeasureTemp_1:
1861
         raw_temp_value[1] += ADC;
1876
         raw_temp_value[1] += ADC;
1862
-      #endif
1863
-      temp_state = PrepareTemp_2;
1864
-      break;
1877
+        break;
1878
+    #endif
1865
 
1879
 
1866
-    case PrepareTemp_2:
1867
-      #if HAS_TEMP_2
1880
+    #if HAS_TEMP_2
1881
+      case PrepareTemp_2:
1868
         START_ADC(TEMP_2_PIN);
1882
         START_ADC(TEMP_2_PIN);
1869
-      #endif
1870
-      lcd_buttons_update();
1871
-      temp_state = MeasureTemp_2;
1872
-      break;
1873
-    case MeasureTemp_2:
1874
-      #if HAS_TEMP_2
1883
+        break;
1884
+      case MeasureTemp_2:
1875
         raw_temp_value[2] += ADC;
1885
         raw_temp_value[2] += ADC;
1876
-      #endif
1877
-      temp_state = PrepareTemp_3;
1878
-      break;
1886
+        break;
1887
+    #endif
1879
 
1888
 
1880
-    case PrepareTemp_3:
1881
-      #if HAS_TEMP_3
1889
+    #if HAS_TEMP_3
1890
+      case PrepareTemp_3:
1882
         START_ADC(TEMP_3_PIN);
1891
         START_ADC(TEMP_3_PIN);
1883
-      #endif
1884
-      lcd_buttons_update();
1885
-      temp_state = MeasureTemp_3;
1886
-      break;
1887
-    case MeasureTemp_3:
1888
-      #if HAS_TEMP_3
1892
+        break;
1893
+      case MeasureTemp_3:
1889
         raw_temp_value[3] += ADC;
1894
         raw_temp_value[3] += ADC;
1890
-      #endif
1891
-      temp_state = PrepareTemp_4;
1892
-      break;
1895
+        break;
1896
+    #endif
1893
 
1897
 
1894
-    case PrepareTemp_4:
1895
-      #if HAS_TEMP_4
1898
+    #if HAS_TEMP_4
1899
+      case PrepareTemp_4:
1896
         START_ADC(TEMP_4_PIN);
1900
         START_ADC(TEMP_4_PIN);
1897
-      #endif
1898
-      lcd_buttons_update();
1899
-      temp_state = MeasureTemp_4;
1900
-      break;
1901
-    case MeasureTemp_4:
1902
-      #if HAS_TEMP_4
1901
+        break;
1902
+      case MeasureTemp_4:
1903
         raw_temp_value[4] += ADC;
1903
         raw_temp_value[4] += ADC;
1904
-      #endif
1905
-      temp_state = Prepare_FILWIDTH;
1906
-      break;
1904
+        break;
1905
+    #endif
1907
 
1906
 
1908
-    case Prepare_FILWIDTH:
1909
-      #if ENABLED(FILAMENT_WIDTH_SENSOR)
1907
+    #if ENABLED(FILAMENT_WIDTH_SENSOR)
1908
+      case Prepare_FILWIDTH:
1910
         START_ADC(FILWIDTH_PIN);
1909
         START_ADC(FILWIDTH_PIN);
1911
-      #endif
1912
-      lcd_buttons_update();
1913
-      temp_state = Measure_FILWIDTH;
1914
       break;
1910
       break;
1915
-    case Measure_FILWIDTH:
1916
-      #if ENABLED(FILAMENT_WIDTH_SENSOR)
1917
-        // raw_filwidth_value += ADC;  //remove to use an IIR filter approach
1918
-        if (ADC > 102) { //check that ADC is reading a voltage > 0.5 volts, otherwise don't take in the data.
1919
-          raw_filwidth_value -= (raw_filwidth_value >> 7); //multiply raw_filwidth_value by 127/128
1920
-          raw_filwidth_value += ((unsigned long)ADC << 7); //add new ADC reading
1911
+      case Measure_FILWIDTH:
1912
+        if (ADC > 102) { // Make sure ADC is reading > 0.5 volts, otherwise don't read.
1913
+          raw_filwidth_value -= (raw_filwidth_value >> 7); // Subtract 1/128th of the raw_filwidth_value
1914
+          raw_filwidth_value += ((unsigned long)ADC << 7); // Add new ADC reading, scaled by 128
1921
         }
1915
         }
1922
-      #endif
1923
-      temp_state = PrepareTemp_0;
1924
-      temp_count++;
1925
-      break;
1916
+        break;
1917
+    #endif
1926
 
1918
 
1927
-    case StartupDelay:
1928
-      temp_state = PrepareTemp_0;
1929
-      break;
1919
+    case StartupDelay: break;
1930
 
1920
 
1931
-    // default:
1932
-    //   SERIAL_ERROR_START;
1933
-    //   SERIAL_ERRORLNPGM("Temp measurement error!");
1934
-    //   break;
1935
-  } // switch(temp_state)
1921
+  } // switch(adc_sensor_state)
1936
 
1922
 
1937
-  if (temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256)  = 164ms.
1923
+  if (!adc_sensor_state && ++temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256)  = 164ms.
1938
 
1924
 
1939
     temp_count = 0;
1925
     temp_count = 0;
1940
 
1926
 
1998
 
1984
 
1999
   } // temp_count >= OVERSAMPLENR
1985
   } // temp_count >= OVERSAMPLENR
2000
 
1986
 
1987
+  // Go to the next state, up to SensorsReady
1988
+  adc_sensor_state = (ADCSensorState)((int(adc_sensor_state) + 1) % int(StartupDelay));
1989
+
2001
   #if ENABLED(BABYSTEPPING)
1990
   #if ENABLED(BABYSTEPPING)
2002
     LOOP_XYZ(axis) {
1991
     LOOP_XYZ(axis) {
2003
       int curTodo = babystepsTodo[axis]; //get rid of volatile for performance
1992
       int curTodo = babystepsTodo[axis]; //get rid of volatile for performance

+ 44
- 1
Marlin/temperature.h Просмотреть файл

50
   #define EXTRUDER_IDX  active_extruder
50
   #define EXTRUDER_IDX  active_extruder
51
 #endif
51
 #endif
52
 
52
 
53
+/**
54
+ * States for ADC reading in the ISR
55
+ */
56
+enum ADCSensorState {
57
+  #if HAS_TEMP_0
58
+    PrepareTemp_0,
59
+    MeasureTemp_0,
60
+  #endif
61
+  #if HAS_TEMP_1
62
+    PrepareTemp_1,
63
+    MeasureTemp_1,
64
+  #endif
65
+  #if HAS_TEMP_2
66
+    PrepareTemp_2,
67
+    MeasureTemp_2,
68
+  #endif
69
+  #if HAS_TEMP_3
70
+    PrepareTemp_3,
71
+    MeasureTemp_3,
72
+  #endif
73
+  #if HAS_TEMP_4
74
+    PrepareTemp_4,
75
+    MeasureTemp_4,
76
+  #endif
77
+  #if HAS_TEMP_BED
78
+    PrepareTemp_BED,
79
+    MeasureTemp_BED,
80
+  #endif
81
+  #if ENABLED(FILAMENT_WIDTH_SENSOR)
82
+    Prepare_FILWIDTH,
83
+    Measure_FILWIDTH,
84
+  #endif
85
+  SensorsReady, // Temperatures ready. Delay the next round of readings to let ADC pins settle.
86
+  StartupDelay  // Startup, delay initial temp reading a tiny bit so the hardware can settle
87
+};
88
+
89
+// Minimum number of Temperature::ISR loops between sensor readings.
90
+// Multiplied by 16 (OVERSAMPLENR) to obtain the total time to
91
+// get all oversampled sensor readings
92
+#define MIN_ADC_ISR_LOOPS 10
93
+
94
+#define ACTUAL_ADC_SAMPLES max(int(MIN_ADC_ISR_LOOPS), int(SensorsReady))
95
+
53
 class Temperature {
96
 class Temperature {
54
 
97
 
55
   public:
98
   public:
74
     #endif
117
     #endif
75
 
118
 
76
     #if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
119
     #if ENABLED(PIDTEMP) || ENABLED(PIDTEMPBED)
77
-      #define PID_dT ((OVERSAMPLENR * 12.0)/(F_CPU / 64.0 / 256.0))
120
+      #define PID_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / (F_CPU / 64.0 / 256.0))
78
     #endif
121
     #endif
79
 
122
 
80
     #if ENABLED(PIDTEMP)
123
     #if ENABLED(PIDTEMP)

Загрузка…
Отмена
Сохранить