Browse Source

Make ADC sensor reading frequency adjustable

Scott Lahteine 7 years ago
parent
commit
7f950a80c0
3 changed files with 129 additions and 119 deletions
  1. 0
    22
      Marlin/enum.h
  2. 85
    96
      Marlin/temperature.cpp
  3. 44
    1
      Marlin/temperature.h

+ 0
- 22
Marlin/enum.h View File

@@ -91,28 +91,6 @@ enum EndstopEnum {
91 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 94
 #if ENABLED(EMERGENCY_PARSER)
117 95
   enum e_parser_state {
118 96
     state_RESET,

+ 85
- 96
Marlin/temperature.cpp View File

@@ -24,8 +24,6 @@
24 24
  * temperature.cpp - temperature control
25 25
  */
26 26
 
27
-
28
-
29 27
 #include "Marlin.h"
30 28
 #include "ultralcd.h"
31 29
 #include "temperature.h"
@@ -1538,8 +1536,8 @@ void Temperature::isr() {
1538 1536
   CBI(TIMSK0, OCIE0B); //Disable Temperature ISR
1539 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 1541
   static uint8_t pwm_count = _BV(SOFT_PWM_SCALE);
1544 1542
   // avoid multiple loads of pwm_count
1545 1543
   uint8_t pwm_count_tmp = pwm_count;
@@ -1812,6 +1810,22 @@ void Temperature::isr() {
1812 1810
 
1813 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 1829
   #define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
1816 1830
   #ifdef MUX5
1817 1831
     #define START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
@@ -1819,122 +1833,94 @@ void Temperature::isr() {
1819 1833
     #define START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
1820 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 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 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 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 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 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 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 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 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 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 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 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 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 1909
         START_ADC(FILWIDTH_PIN);
1911
-      #endif
1912
-      lcd_buttons_update();
1913
-      temp_state = Measure_FILWIDTH;
1914 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 1925
     temp_count = 0;
1940 1926
 
@@ -1998,6 +1984,9 @@ void Temperature::isr() {
1998 1984
 
1999 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 1990
   #if ENABLED(BABYSTEPPING)
2002 1991
     LOOP_XYZ(axis) {
2003 1992
       int curTodo = babystepsTodo[axis]; //get rid of volatile for performance

+ 44
- 1
Marlin/temperature.h View File

@@ -50,6 +50,49 @@
50 50
   #define EXTRUDER_IDX  active_extruder
51 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 96
 class Temperature {
54 97
 
55 98
   public:
@@ -74,7 +117,7 @@ class Temperature {
74 117
     #endif
75 118
 
76 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 121
     #endif
79 122
 
80 123
     #if ENABLED(PIDTEMP)

Loading…
Cancel
Save