Browse Source

Power monitor and display (#17437)

Scott Lahteine 5 years ago
parent
commit
424569b4c4
No account linked to committer's email address

+ 17
- 0
Marlin/Configuration_adv.h View File

2985
 #endif
2985
 #endif
2986
 
2986
 
2987
 /**
2987
 /**
2988
+ * Power Monitor
2989
+ * Monitor voltage (V) and/or current (A), and -when possible- power (W)
2990
+ *
2991
+ * Read and configure with M430
2992
+ *
2993
+ * The current sensor feeds DC voltage (relative to the measured current) to an analog pin
2994
+ * The voltage sensor feeds DC voltage (relative to the measured voltage) to an analog pin
2995
+ */
2996
+//#define POWER_MONITOR_CURRENT   // Monitor the system current
2997
+//#define POWER_MONITOR_VOLTAGE   // Monitor the system voltage
2998
+#if EITHER(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE)
2999
+  #define POWER_MONITOR_VOLTS_PER_AMP   0.05000   // Input voltage to the MCU analog pin per amp  - DO NOT apply more than ADC_VREF!
3000
+  #define POWER_MONITOR_VOLTS_PER_VOLT  0.11786   // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF!
3001
+  #define POWER_MONITOR_FIXED_VOLTAGE   13.6      // Voltage for a current sensor with no voltage sensor (for power display)
3002
+#endif
3003
+
3004
+/**
2988
  * CNC Coordinate Systems
3005
  * CNC Coordinate Systems
2989
  *
3006
  *
2990
  * Enables G53 and G54-G59.3 commands to select coordinate systems
3007
  * Enables G53 and G54-G59.3 commands to select coordinate systems

+ 1
- 0
Marlin/src/HAL/AVR/HAL.h View File

162
   #define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
162
   #define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
163
 #endif
163
 #endif
164
 
164
 
165
+#define HAL_ADC_VREF        5.0
165
 #define HAL_ADC_RESOLUTION 10
166
 #define HAL_ADC_RESOLUTION 10
166
 #define HAL_READ_ADC()  ADC
167
 #define HAL_READ_ADC()  ADC
167
 #define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
168
 #define HAL_ADC_READY() !TEST(ADCSRA, ADSC)

+ 2
- 1
Marlin/src/HAL/DUE/HAL.h View File

143
 
143
 
144
 inline void HAL_adc_init() {}//todo
144
 inline void HAL_adc_init() {}//todo
145
 
145
 
146
-#define HAL_START_ADC(ch)   HAL_adc_start_conversion(ch)
146
+#define HAL_ADC_VREF         3.3
147
 #define HAL_ADC_RESOLUTION  10
147
 #define HAL_ADC_RESOLUTION  10
148
+#define HAL_START_ADC(ch)   HAL_adc_start_conversion(ch)
148
 #define HAL_READ_ADC()      HAL_adc_result
149
 #define HAL_READ_ADC()      HAL_adc_result
149
 #define HAL_ADC_READY()     true
150
 #define HAL_ADC_READY()     true
150
 
151
 

+ 2
- 1
Marlin/src/HAL/ESP32/HAL.h View File

112
 
112
 
113
 void HAL_adc_init();
113
 void HAL_adc_init();
114
 
114
 
115
-#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
115
+#define HAL_ADC_VREF         3.3
116
 #define HAL_ADC_RESOLUTION  10
116
 #define HAL_ADC_RESOLUTION  10
117
+#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
117
 #define HAL_READ_ADC()      HAL_adc_result
118
 #define HAL_READ_ADC()      HAL_adc_result
118
 #define HAL_ADC_READY()     true
119
 #define HAL_ADC_READY()     true
119
 
120
 

+ 2
- 1
Marlin/src/HAL/LINUX/HAL.h View File

86
 #pragma GCC diagnostic pop
86
 #pragma GCC diagnostic pop
87
 
87
 
88
 // ADC
88
 // ADC
89
+#define HAL_ADC_VREF           5.0
90
+#define HAL_ADC_RESOLUTION    10
89
 #define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch)
91
 #define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch)
90
 #define HAL_START_ADC(ch)     HAL_adc_start_conversion(ch)
92
 #define HAL_START_ADC(ch)     HAL_adc_start_conversion(ch)
91
-#define HAL_ADC_RESOLUTION    10
92
 #define HAL_READ_ADC()        HAL_adc_get_result()
93
 #define HAL_READ_ADC()        HAL_adc_get_result()
93
 #define HAL_ADC_READY()       true
94
 #define HAL_ADC_READY()       true
94
 
95
 

+ 2
- 0
Marlin/src/HAL/LPC1768/HAL.h View File

150
                                     // K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
150
                                     // K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
151
                                     // Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
151
                                     // Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
152
 
152
 
153
+#define HAL_ADC_VREF            3.3 // ADC voltage reference
154
+
153
 #define HAL_ADC_RESOLUTION     12   // 15 bit maximum, raw temperature is stored as int16_t
155
 #define HAL_ADC_RESOLUTION     12   // 15 bit maximum, raw temperature is stored as int16_t
154
 #define HAL_ADC_FILTERED            // Disable oversampling done in Marlin as ADC values already filtered in HAL
156
 #define HAL_ADC_FILTERED            // Disable oversampling done in Marlin as ADC values already filtered in HAL
155
 
157
 

+ 1
- 0
Marlin/src/HAL/SAMD51/HAL.h View File

122
 void HAL_adc_init();
122
 void HAL_adc_init();
123
 
123
 
124
 //#define HAL_ADC_FILTERED          // Disable Marlin's oversampling. The HAL filters ADC values.
124
 //#define HAL_ADC_FILTERED          // Disable Marlin's oversampling. The HAL filters ADC values.
125
+#define HAL_ADC_VREF         3.3
125
 #define HAL_ADC_RESOLUTION  10      // ... 12
126
 #define HAL_ADC_RESOLUTION  10      // ... 12
126
 #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
127
 #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
127
 #define HAL_READ_ADC()      HAL_adc_result
128
 #define HAL_READ_ADC()      HAL_adc_result

+ 2
- 1
Marlin/src/HAL/STM32/HAL.h View File

199
 
199
 
200
 inline void HAL_adc_init() {}
200
 inline void HAL_adc_init() {}
201
 
201
 
202
-#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
202
+#define HAL_ADC_VREF         3.3
203
 #define HAL_ADC_RESOLUTION  10
203
 #define HAL_ADC_RESOLUTION  10
204
+#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
204
 #define HAL_READ_ADC()      HAL_adc_result
205
 #define HAL_READ_ADC()      HAL_adc_result
205
 #define HAL_ADC_READY()     true
206
 #define HAL_ADC_READY()     true
206
 
207
 

+ 21
- 2
Marlin/src/HAL/STM32F1/HAL.cpp View File

139
   #if HAS_JOY_ADC_Z
139
   #if HAS_JOY_ADC_Z
140
     JOY_Z_PIN,
140
     JOY_Z_PIN,
141
   #endif
141
   #endif
142
+  #if ENABLED(POWER_MONITOR_CURRENT)
143
+    POWER_MONITOR_CURRENT_PIN,
144
+  #endif
145
+  #if ENABLED(POWER_MONITOR_VOLTAGE)
146
+    POWER_MONITOR_VOLTAGE_PIN,
147
+  #endif
142
 };
148
 };
143
 
149
 
144
-enum TEMP_PINS : char {
150
+enum TempPinIndex : char {
145
   #if HAS_TEMP_ADC_0
151
   #if HAS_TEMP_ADC_0
146
     TEMP_0,
152
     TEMP_0,
147
   #endif
153
   #endif
187
   #if HAS_JOY_ADC_Z
193
   #if HAS_JOY_ADC_Z
188
     JOY_Z,
194
     JOY_Z,
189
   #endif
195
   #endif
196
+  #if ENABLED(POWER_MONITOR_CURRENT)
197
+    POWERMON_CURRENT,
198
+  #endif
199
+  #if ENABLED(POWER_MONITOR_VOLTAGE)
200
+    POWERMON_VOLTS,
201
+  #endif
190
   ADC_PIN_COUNT
202
   ADC_PIN_COUNT
191
 };
203
 };
192
 
204
 
323
 }
335
 }
324
 
336
 
325
 void HAL_adc_start_conversion(const uint8_t adc_pin) {
337
 void HAL_adc_start_conversion(const uint8_t adc_pin) {
326
-  TEMP_PINS pin_index;
338
+  //TEMP_PINS pin_index;
339
+  TempPinIndex pin_index;
327
   switch (adc_pin) {
340
   switch (adc_pin) {
328
     default: return;
341
     default: return;
329
     #if HAS_TEMP_ADC_0
342
     #if HAS_TEMP_ADC_0
371
     #if ENABLED(ADC_KEYPAD)
384
     #if ENABLED(ADC_KEYPAD)
372
       case ADC_KEYPAD_PIN: pin_index = ADC_KEY; break;
385
       case ADC_KEYPAD_PIN: pin_index = ADC_KEY; break;
373
     #endif
386
     #endif
387
+    #if ENABLED(POWER_MONITOR_CURRENT)
388
+      case POWER_MONITOR_CURRENT_PIN: pin_index = POWERMON_CURRENT; break;
389
+    #endif
390
+    #if ENABLED(POWER_MONITOR_VOLTAGE)
391
+      case POWER_MONITOR_VOLTAGE_PIN: pin_index = POWERMON_VOLTS; break;
392
+    #endif
374
   }
393
   }
375
   HAL_adc_result = (HAL_adc_results[(int)pin_index] >> 2) & 0x3FF; // shift to get 10 bits only.
394
   HAL_adc_result = (HAL_adc_results[(int)pin_index] >> 2) & 0x3FF; // shift to get 10 bits only.
376
 }
395
 }

+ 2
- 1
Marlin/src/HAL/STM32F1/HAL.h View File

255
 
255
 
256
 void HAL_adc_init();
256
 void HAL_adc_init();
257
 
257
 
258
-#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
258
+#define HAL_ADC_VREF         3.3
259
 #define HAL_ADC_RESOLUTION  10
259
 #define HAL_ADC_RESOLUTION  10
260
+#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
260
 #define HAL_READ_ADC()      HAL_adc_result
261
 #define HAL_READ_ADC()      HAL_adc_result
261
 #define HAL_ADC_READY()     true
262
 #define HAL_ADC_READY()     true
262
 
263
 

+ 2
- 1
Marlin/src/HAL/STM32_F4_F7/HAL.h View File

219
 
219
 
220
 inline void HAL_adc_init() {}
220
 inline void HAL_adc_init() {}
221
 
221
 
222
-#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
222
+#define HAL_ADC_VREF         3.3
223
 #define HAL_ADC_RESOLUTION  10
223
 #define HAL_ADC_RESOLUTION  10
224
+#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
224
 #define HAL_READ_ADC()      HAL_adc_result
225
 #define HAL_READ_ADC()      HAL_adc_result
225
 #define HAL_ADC_READY()     true
226
 #define HAL_ADC_READY()     true
226
 
227
 

+ 2
- 1
Marlin/src/HAL/TEENSY31_32/HAL.h View File

107
 
107
 
108
 void HAL_adc_init();
108
 void HAL_adc_init();
109
 
109
 
110
-#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
110
+#define HAL_ADC_VREF         3.3
111
 #define HAL_ADC_RESOLUTION  10
111
 #define HAL_ADC_RESOLUTION  10
112
+#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
112
 #define HAL_READ_ADC()      HAL_adc_get_result()
113
 #define HAL_READ_ADC()      HAL_adc_get_result()
113
 #define HAL_ADC_READY()     true
114
 #define HAL_ADC_READY()     true
114
 
115
 

+ 2
- 1
Marlin/src/HAL/TEENSY35_36/HAL.h View File

112
 
112
 
113
 void HAL_adc_init();
113
 void HAL_adc_init();
114
 
114
 
115
-#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
115
+#define HAL_ADC_VREF         3.3
116
 #define HAL_ADC_RESOLUTION  10
116
 #define HAL_ADC_RESOLUTION  10
117
+#define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin)
117
 #define HAL_READ_ADC()      HAL_adc_get_result()
118
 #define HAL_READ_ADC()      HAL_adc_get_result()
118
 #define HAL_ADC_READY()     true
119
 #define HAL_ADC_READY()     true
119
 
120
 

+ 3
- 0
Marlin/src/core/macros.h View File

97
   #define CBI(A,B) (A &= ~(1 << (B)))
97
   #define CBI(A,B) (A &= ~(1 << (B)))
98
 #endif
98
 #endif
99
 
99
 
100
+#define TBI(N,B) (N ^= _BV(B))
101
+
100
 #define _BV32(b) (1UL << (b))
102
 #define _BV32(b) (1UL << (b))
101
 #define TEST32(n,b) !!((n)&_BV32(b))
103
 #define TEST32(n,b) !!((n)&_BV32(b))
102
 #define SBI32(n,b) (n |= _BV32(b))
104
 #define SBI32(n,b) (n |= _BV32(b))
103
 #define CBI32(n,b) (n &= ~_BV32(b))
105
 #define CBI32(n,b) (n &= ~_BV32(b))
106
+#define TBI32(N,B) (N ^= _BV32(B))
104
 
107
 
105
 #define cu(x)      ({__typeof__(x) _x = (x); (_x)*(_x)*(_x);})
108
 #define cu(x)      ({__typeof__(x) _x = (x); (_x)*(_x)*(_x);})
106
 #define RADIANS(d) ((d)*float(M_PI)/180.0f)
109
 #define RADIANS(d) ((d)*float(M_PI)/180.0f)

+ 74
- 0
Marlin/src/feature/power_monitor.cpp View File

1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../inc/MarlinConfigPre.h"
24
+
25
+#if HAS_POWER_MONITOR
26
+
27
+#include "power_monitor.h"
28
+
29
+#include "../lcd/ultralcd.h"
30
+#include "../lcd/lcdprint.h"
31
+
32
+uint8_t PowerMonitor::flags; // = 0
33
+
34
+#if ENABLED(POWER_MONITOR_CURRENT)
35
+  pm_lpf_t<PowerMonitor::amps_adc_scale, PM_K_VALUE, PM_K_SCALE> PowerMonitor::amps;
36
+#endif
37
+#if ENABLED(POWER_MONITOR_VOLTAGE)
38
+  pm_lpf_t<PowerMonitor::volts_adc_scale, PM_K_VALUE, PM_K_SCALE> PowerMonitor::volts;
39
+#endif
40
+
41
+millis_t PowerMonitor::display_item_ms;
42
+uint8_t PowerMonitor::display_item;
43
+
44
+PowerMonitor power_monitor; // Single instance - this calls the constructor
45
+
46
+#if HAS_GRAPHICAL_LCD
47
+
48
+  #if ENABLED(POWER_MONITOR_CURRENT)
49
+    void PowerMonitor::draw_current() {
50
+      const float amps = getAmps();
51
+      lcd_put_u8str(amps < 100 ? ftostr21ns(amps) : ui16tostr4((uint16_t)amps));
52
+      lcd_put_wchar('A');
53
+    }
54
+  #endif
55
+
56
+  #if HAS_POWER_MONITOR_VREF
57
+    void PowerMonitor::draw_voltage() {
58
+      const float volts = getVolts();
59
+      lcd_put_u8str(volts < 100 ? ftostr21ns(volts) : ui16tostr4((uint16_t)volts));
60
+      lcd_put_wchar('V');
61
+    }
62
+  #endif
63
+
64
+  #if HAS_POWER_MONITOR_WATTS
65
+    void PowerMonitor::draw_power() {
66
+      const float power = getPower();
67
+      lcd_put_u8str(power < 100 ? ftostr21ns(power) : ui16tostr4((uint16_t)power));
68
+      lcd_put_wchar('W');
69
+    }
70
+  #endif
71
+
72
+#endif // HAS_GRAPHICAL_LCD
73
+
74
+#endif // HAS_POWER_MONITOR

+ 140
- 0
Marlin/src/feature/power_monitor.h View File

1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+#include "../inc/MarlinConfig.h"
25
+
26
+#define PM_SAMPLE_RANGE 1024
27
+#define PM_K_VALUE      6
28
+#define PM_K_SCALE      6
29
+
30
+template <const float & SCALE, int K_VALUE, int K_SCALE>
31
+struct pm_lpf_t {
32
+  uint32_t filter_buf;
33
+  float value;
34
+  void add_sample(const uint16_t sample) {
35
+    filter_buf = filter_buf - (filter_buf >> K_VALUE) + (uint32_t(sample) << K_SCALE);
36
+  }
37
+  void capture() {
38
+    value = filter_buf * (SCALE * (1.0f / (1UL << (PM_K_VALUE + PM_K_SCALE))));
39
+  }
40
+  void reset(uint16_t reset_value = 0) {
41
+    filter_buf = uint32_t(reset_value) << (K_VALUE + K_SCALE);
42
+    capture();
43
+  }
44
+};
45
+
46
+class PowerMonitor {
47
+private:
48
+  #if ENABLED(POWER_MONITOR_CURRENT)
49
+    static constexpr float amps_adc_scale = float(ADC_VREF) / (POWER_MONITOR_VOLTS_PER_AMP * PM_SAMPLE_RANGE);
50
+    static pm_lpf_t<amps_adc_scale, PM_K_VALUE, PM_K_SCALE> amps;
51
+  #endif
52
+  #if ENABLED(POWER_MONITOR_VOLTAGE)
53
+    static constexpr float volts_adc_scale = float(ADC_VREF) / (POWER_MONITOR_VOLTS_PER_VOLT * PM_SAMPLE_RANGE);
54
+    static pm_lpf_t<volts_adc_scale, PM_K_VALUE, PM_K_SCALE> volts;
55
+  #endif
56
+
57
+public:
58
+  static uint8_t flags;  // M430 flags to display current
59
+
60
+  static millis_t display_item_ms;
61
+  static uint8_t display_item;
62
+
63
+  PowerMonitor() { reset(); }
64
+
65
+  enum PM_Display_Bit : uint8_t {
66
+    PM_DISP_BIT_I, // Current display enable bit
67
+    PM_DISP_BIT_V, // Voltage display enable bit
68
+    PM_DISP_BIT_P  // Power display enable bit
69
+  };
70
+
71
+  #if ENABLED(POWER_MONITOR_CURRENT)
72
+    FORCE_INLINE static float getAmps() { return amps.value; }
73
+    void add_current_sample(const uint16_t value) { amps.add_sample(value); }
74
+  #endif
75
+
76
+  #if HAS_POWER_MONITOR_VREF
77
+    #if ENABLED(POWER_MONITOR_VOLTAGE)
78
+      FORCE_INLINE static float getVolts() { return volts.value; }
79
+    #else
80
+      FORCE_INLINE static float getVolts() { return POWER_MONITOR_FIXED_VOLTAGE; }  // using a specified fixed valtage as the voltage measurement
81
+    #endif
82
+    #if ENABLED(POWER_MONITOR_VOLTAGE)
83
+      void add_voltage_sample(const uint16_t value) { volts.add_sample(value); }
84
+    #endif
85
+  #endif
86
+
87
+  #if HAS_POWER_MONITOR_WATTS
88
+    FORCE_INLINE static float getPower() { return getAmps() * getVolts(); }
89
+  #endif
90
+
91
+  #if HAS_SPI_LCD
92
+    FORCE_INLINE static bool display_enabled() { return flags != 0x00; }
93
+    #if ENABLED(POWER_MONITOR_CURRENT)
94
+      static void draw_current();
95
+      FORCE_INLINE static bool current_display_enabled() { return TEST(flags, PM_DISP_BIT_I); }
96
+      FORCE_INLINE static void set_current_display(const bool b) { SET_BIT_TO(flags, PM_DISP_BIT_I, b); }
97
+      FORCE_INLINE static void toggle_current_display() { TBI(flags, PM_DISP_BIT_I); }
98
+    #endif
99
+    #if HAS_POWER_MONITOR_VREF
100
+      static void draw_voltage();
101
+      FORCE_INLINE static bool voltage_display_enabled() { return TEST(flags, PM_DISP_BIT_V); }
102
+      FORCE_INLINE static void set_voltage_display(const bool b) { SET_BIT_TO(flags, PM_DISP_BIT_V, b); }
103
+      FORCE_INLINE static void toggle_voltage_display() { TBI(flags, PM_DISP_BIT_I); }
104
+    #endif
105
+    #if HAS_POWER_MONITOR_WATTS
106
+      static void draw_power();
107
+      FORCE_INLINE static bool power_display_enabled() { return TEST(flags, PM_DISP_BIT_P); }
108
+      FORCE_INLINE static void set_power_display(const bool b) { SET_BIT_TO(flags, PM_DISP_BIT_P, b); }
109
+      FORCE_INLINE static void toggle_power_display() { TBI(flags, PM_DISP_BIT_I); }
110
+    #endif
111
+  #endif
112
+
113
+  static void reset() {
114
+    flags = 0x00;
115
+
116
+    #if ENABLED(POWER_MONITOR_CURRENT)
117
+      amps.reset();
118
+    #endif
119
+
120
+    #if ENABLED(POWER_MONITOR_VOLTAGE)
121
+      volts.reset();
122
+    #endif
123
+
124
+    #if ENABLED(SDSUPPORT)
125
+      display_item_ms = 0;
126
+      display_item = 0;
127
+    #endif
128
+  }
129
+
130
+  static void capture_values() {
131
+    #if ENABLED(POWER_MONITOR_CURRENT)
132
+     amps.capture();
133
+    #endif
134
+    #if ENABLED(POWER_MONITOR_VOLTAGE)
135
+      volts.capture();
136
+    #endif
137
+  }
138
+};
139
+
140
+extern PowerMonitor power_monitor;

+ 70
- 0
Marlin/src/gcode/feature/power_monitor/M430.cpp View File

1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../../inc/MarlinConfig.h"
24
+
25
+#if HAS_POWER_MONITOR
26
+
27
+#include "../../../feature/power_monitor.h"
28
+#include "../../../Marlin.h"
29
+#include "../../gcode.h"
30
+
31
+/**
32
+ * M430: Enable/disable current LCD display
33
+ *       With no parameters report the system current draw (in Amps)
34
+ *
35
+ *  I[bool] - Set Display of current on the LCD
36
+ *  V[bool] - Set Display of voltage on the LCD
37
+ *  W[bool] - Set Display of power on the LCD
38
+ */
39
+void GcodeSuite::M430() {
40
+  bool do_report = true;
41
+  #if HAS_SPI_LCD
42
+    #if ENABLED(POWER_MONITOR_CURRENT)
43
+      if (parser.seen('I')) { power_monitor.set_current_display(parser.value_bool()); do_report = false; }
44
+    #endif
45
+    #if HAS_POWER_MONITOR_VREF
46
+      if (parser.seen('V')) { power_monitor.set_voltage_display(parser.value_bool()); do_report = false; }
47
+    #endif
48
+    #if HAS_POWER_MONITOR_WATTS
49
+      if (parser.seen('W')) { power_monitor.set_power_display(parser.value_bool()); do_report = false; }
50
+    #endif
51
+  #endif
52
+  if (do_report) {
53
+    SERIAL_ECHOLNPAIR(
54
+      #if ENABLED(POWER_MONITOR_CURRENT)
55
+        "Current: ", power_monitor.getAmps(), "A"
56
+        #if HAS_POWER_MONITOR_VREF
57
+          "  "
58
+        #endif
59
+      #endif
60
+      #if HAS_POWER_MONITOR_VREF
61
+        "Voltage: ", power_monitor.getVolts(), "V"
62
+      #endif
63
+      #if HAS_POWER_MONITOR_WATTS
64
+        "  Power: ", power_monitor.getPower(), "W"
65
+      #endif
66
+    );
67
+  }
68
+}
69
+
70
+#endif // HAS_POWER_MONITOR

+ 4
- 0
Marlin/src/gcode/gcode.cpp View File

720
         case 428: M428(); break;                                  // M428: Apply current_position to home_offset
720
         case 428: M428(); break;                                  // M428: Apply current_position to home_offset
721
       #endif
721
       #endif
722
 
722
 
723
+      #if HAS_POWER_MONITOR
724
+        case 430: M430(); break;                                  // M430: Read the system current (A), voltage (V), and power (W)
725
+      #endif
726
+
723
       #if ENABLED(CANCEL_OBJECTS)
727
       #if ENABLED(CANCEL_OBJECTS)
724
         case 486: M486(); break;                                  // M486: Identify and cancel objects
728
         case 486: M486(); break;                                  // M486: Identify and cancel objects
725
       #endif
729
       #endif

+ 3
- 0
Marlin/src/gcode/gcode.h View File

217
  * M422 - Set Z Stepper automatic alignment position using probe. X<units> Y<units> A<axis> (Requires Z_STEPPER_AUTO_ALIGN)
217
  * M422 - Set Z Stepper automatic alignment position using probe. X<units> Y<units> A<axis> (Requires Z_STEPPER_AUTO_ALIGN)
218
  * M425 - Enable/Disable and tune backlash correction. (Requires BACKLASH_COMPENSATION and BACKLASH_GCODE)
218
  * M425 - Enable/Disable and tune backlash correction. (Requires BACKLASH_COMPENSATION and BACKLASH_GCODE)
219
  * M428 - Set the home_offset based on the current_position. Nearest edge applies. (Disabled by NO_WORKSPACE_OFFSETS or DELTA)
219
  * M428 - Set the home_offset based on the current_position. Nearest edge applies. (Disabled by NO_WORKSPACE_OFFSETS or DELTA)
220
+ * M430 - Read the system current, voltage, and power (Requires POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE, or POWER_MONITOR_FIXED_VOLTAGE)
220
  * M486 - Identify and cancel objects. (Requires CANCEL_OBJECTS)
221
  * M486 - Identify and cancel objects. (Requires CANCEL_OBJECTS)
221
  * M500 - Store parameters in EEPROM. (Requires EEPROM_SETTINGS)
222
  * M500 - Store parameters in EEPROM. (Requires EEPROM_SETTINGS)
222
  * M501 - Restore parameters from EEPROM. (Requires EEPROM_SETTINGS)
223
  * M501 - Restore parameters from EEPROM. (Requires EEPROM_SETTINGS)
735
 
736
 
736
   TERN_(HAS_M206_COMMAND, static void M428());
737
   TERN_(HAS_M206_COMMAND, static void M428());
737
 
738
 
739
+  TERN_(HAS_POWER_MONITOR, static void M430());
740
+
738
   TERN_(CANCEL_OBJECTS, static void M486());
741
   TERN_(CANCEL_OBJECTS, static void M486());
739
 
742
 
740
   static void M500();
743
   static void M500();

+ 11
- 0
Marlin/src/inc/Conditionals_adv.h View File

352
   #define SD_CONNECTION_IS(...) 0
352
   #define SD_CONNECTION_IS(...) 0
353
 #endif
353
 #endif
354
 
354
 
355
+// Power Monitor sensors
356
+#if EITHER(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE)
357
+  #define HAS_POWER_MONITOR 1
358
+#endif
359
+#if ENABLED(POWER_MONITOR_VOLTAGE) || defined(POWER_MONITOR_FIXED_VOLTAGE)
360
+  #define HAS_POWER_MONITOR_VREF 1
361
+#endif
362
+#if BOTH(HAS_POWER_MONITOR_VREF, POWER_MONITOR_CURRENT)
363
+  #define HAS_POWER_MONITOR_WATTS 1
364
+#endif
365
+
355
 // Flag if an EEPROM type is pre-selected
366
 // Flag if an EEPROM type is pre-selected
356
 #if ENABLED(EEPROM_SETTINGS) && NONE(I2C_EEPROM, SPI_EEPROM, QSPI_EEPROM, FLASH_EEPROM_EMULATION, SRAM_EEPROM_EMULATION, SDCARD_EEPROM_EMULATION)
367
 #if ENABLED(EEPROM_SETTINGS) && NONE(I2C_EEPROM, SPI_EEPROM, QSPI_EEPROM, FLASH_EEPROM_EMULATION, SRAM_EEPROM_EMULATION, SDCARD_EEPROM_EMULATION)
357
   #define NO_EEPROM_SELECTED 1
368
   #define NO_EEPROM_SELECTED 1

+ 7
- 0
Marlin/src/inc/Conditionals_post.h View File

30
   // Extras for CI testing
30
   // Extras for CI testing
31
 #endif
31
 #endif
32
 
32
 
33
+// ADC
34
+#ifdef BOARD_ADC_VREF
35
+  #define ADC_VREF BOARD_ADC_VREF
36
+#else
37
+  #define ADC_VREF HAL_ADC_VREF
38
+#endif
39
+
33
 // Linear advance uses Jerk since E is an isolated axis
40
 // Linear advance uses Jerk since E is an isolated axis
34
 #if BOTH(HAS_JUNCTION_DEVIATION, LIN_ADVANCE)
41
 #if BOTH(HAS_JUNCTION_DEVIATION, LIN_ADVANCE)
35
   #define HAS_LINEAR_E_JERK 1
42
   #define HAS_LINEAR_E_JERK 1

+ 11
- 0
Marlin/src/inc/SanityCheck.h View File

1481
 #endif
1481
 #endif
1482
 
1482
 
1483
 /**
1483
 /**
1484
+ * System Power Sensor
1485
+ */
1486
+#if ENABLED(POWER_MONITOR_CURRENT) && !PIN_EXISTS(POWER_MONITOR_CURRENT)
1487
+  #error "POWER_MONITOR_CURRENT requires a valid POWER_MONITOR_CURRENT_PIN."
1488
+#elif ENABLED(POWER_MONITOR_VOLTAGE) && !PIN_EXISTS(POWER_MONITOR_VOLTAGE)
1489
+  #error "POWER_MONITOR_VOLTAGE requires POWER_MONITOR_VOLTAGE_PIN to be defined."
1490
+#elif BOTH(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE) && POWER_MONITOR_CURRENT_PIN == POWER_MONITOR_VOLTAGE_PIN
1491
+  #error "POWER_MONITOR_CURRENT_PIN and POWER_MONITOR_VOLTAGE_PIN must be different."
1492
+#endif
1493
+
1494
+/**
1484
  * Volumetric Extruder Limit
1495
  * Volumetric Extruder Limit
1485
  */
1496
  */
1486
 #if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT)
1497
 #if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT)

+ 80
- 9
Marlin/src/lcd/dogm/status_screen_DOGM.cpp View File

48
   #include "../../feature/spindle_laser.h"
48
   #include "../../feature/spindle_laser.h"
49
 #endif
49
 #endif
50
 
50
 
51
+#if HAS_POWER_MONITOR
52
+  #include "../../feature/power_monitor.h"
53
+#endif
54
+
51
 #if ENABLED(SDSUPPORT)
55
 #if ENABLED(SDSUPPORT)
52
   #include "../../sd/cardreader.h"
56
   #include "../../sd/cardreader.h"
53
 #endif
57
 #endif
103
   #define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1)
107
   #define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1)
104
 #endif
108
 #endif
105
 
109
 
110
+#if HAS_POWER_MONITOR
111
+
112
+  void display_power_monitor(const uint8_t x, const uint8_t y) {
113
+
114
+    lcd_moveto(x, y);
115
+
116
+    #if ENABLED(POWER_MONITOR_CURRENT)
117
+      const bool iflag = power_monitor.current_display_enabled();
118
+    #endif
119
+    #if HAS_POWER_MONITOR_VREF
120
+      const bool vflag = power_monitor.voltage_display_enabled();
121
+    #endif
122
+    #if HAS_POWER_MONITOR_WATTS
123
+      const bool wflag = power_monitor.power_display_enabled();
124
+    #endif
125
+
126
+    #if ENABLED(POWER_MONITOR_CURRENT) || HAS_POWER_MONITOR_VREF
127
+      // cycle between current, voltage, and power
128
+      if (ELAPSED(millis(), power_monitor.display_item_ms)) {
129
+        power_monitor.display_item_ms = millis() + 1000UL;
130
+        ++power_monitor.display_item;
131
+      }
132
+    #endif
133
+
134
+    // ensure we have the right one selected for display
135
+    for (uint8_t i = 0; i < 3; i++) {
136
+      #if ENABLED(POWER_MONITOR_CURRENT)
137
+        if (power_monitor.display_item == 0 && !iflag) ++power_monitor.display_item;
138
+      #endif
139
+      #if HAS_POWER_MONITOR_VREF
140
+        if (power_monitor.display_item == 1 && !vflag) ++power_monitor.display_item;
141
+      #endif
142
+      #if ENABLED(POWER_MONITOR_CURRENT)
143
+        if (power_monitor.display_item == 2 && !wflag) ++power_monitor.display_item;
144
+      #endif
145
+      if (power_monitor.display_item >= 3) power_monitor.display_item = 0;
146
+    }
147
+
148
+    switch (power_monitor.display_item) {
149
+      #if ENABLED(POWER_MONITOR_CURRENT)                // Current
150
+        case 0: if (iflag) power_monitor.draw_current(); break;
151
+      #endif
152
+      #if HAS_POWER_MONITOR_VREF                        // Voltage
153
+        case 1: if (vflag) power_monitor.draw_voltage(); break;
154
+      #endif
155
+      #if HAS_POWER_MONITOR_WATTS                       // Power
156
+        case 2: if (wflag) power_monitor.draw_power(); break;
157
+      #endif
158
+      default: break;
159
+    }
160
+  }
161
+#endif
162
+
106
 #define PROGRESS_BAR_X 54
163
 #define PROGRESS_BAR_X 54
107
 #define PROGRESS_BAR_Y (EXTRAS_BASELINE + 1)
164
 #define PROGRESS_BAR_Y (EXTRAS_BASELINE + 1)
108
 #define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X)
165
 #define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X)
787
 void MarlinUI::draw_status_message(const bool blink) {
844
 void MarlinUI::draw_status_message(const bool blink) {
788
 
845
 
789
   // Get the UTF8 character count of the string
846
   // Get the UTF8 character count of the string
790
-  uint8_t slen = utf8_strlen(status_message);
847
+  uint8_t lcd_width = LCD_WIDTH, pixel_width = LCD_PIXEL_WIDTH,
848
+          slen = utf8_strlen(status_message);
849
+
850
+  #if HAS_POWER_MONITOR
851
+    if (power_monitor.display_enabled()) {
852
+      // make room at the end of the status line for the power monitor reading
853
+      lcd_width -= 6;
854
+      pixel_width -= (MENU_FONT_WIDTH) * 6;
855
+    }
856
+  #endif
791
 
857
 
792
   #if ENABLED(STATUS_MESSAGE_SCROLLING)
858
   #if ENABLED(STATUS_MESSAGE_SCROLLING)
793
 
859
 
794
     static bool last_blink = false;
860
     static bool last_blink = false;
795
 
861
 
796
-    if (slen <= LCD_WIDTH) {
862
+    if (slen <= lcd_width) {
797
       // The string fits within the line. Print with no scrolling
863
       // The string fits within the line. Print with no scrolling
798
       lcd_put_u8str(status_message);
864
       lcd_put_u8str(status_message);
799
-      while (slen < LCD_WIDTH) { lcd_put_wchar(' '); ++slen; }
865
+      while (slen < lcd_width) { lcd_put_wchar(' '); ++slen; }
800
     }
866
     }
801
     else {
867
     else {
802
       // String is longer than the available space
868
       // String is longer than the available space
805
       // and the string remaining length
871
       // and the string remaining length
806
       uint8_t rlen;
872
       uint8_t rlen;
807
       const char *stat = status_and_len(rlen);
873
       const char *stat = status_and_len(rlen);
808
-      lcd_put_u8str_max(stat, LCD_PIXEL_WIDTH);
874
+      lcd_put_u8str_max(stat, pixel_width);
809
 
875
 
810
       // If the remaining string doesn't completely fill the screen
876
       // If the remaining string doesn't completely fill the screen
811
-      if (rlen < LCD_WIDTH) {
877
+      if (rlen < lcd_width) {
812
         lcd_put_wchar('.');                     // Always at 1+ spaces left, draw a dot
878
         lcd_put_wchar('.');                     // Always at 1+ spaces left, draw a dot
813
-        uint8_t chars = LCD_WIDTH - rlen;       // Amount of space left in characters
879
+        uint8_t chars = lcd_width - rlen;       // Amount of space left in characters
814
         if (--chars) {                          // Draw a second dot if there's space
880
         if (--chars) {                          // Draw a second dot if there's space
815
           lcd_put_wchar('.');
881
           lcd_put_wchar('.');
816
           if (--chars) {                        // Print a second copy of the message
882
           if (--chars) {                        // Print a second copy of the message
817
-            lcd_put_u8str_max(status_message, LCD_PIXEL_WIDTH - (rlen + 2) * (MENU_FONT_WIDTH));
883
+            lcd_put_u8str_max(status_message, pixel_width - (rlen + 2) * (MENU_FONT_WIDTH));
818
             lcd_put_wchar(' ');
884
             lcd_put_wchar(' ');
819
           }
885
           }
820
         }
886
         }
821
       }
887
       }
888
+
822
       if (last_blink != blink) {
889
       if (last_blink != blink) {
823
         last_blink = blink;
890
         last_blink = blink;
824
         advance_status_scroll();
891
         advance_status_scroll();
830
     UNUSED(blink);
897
     UNUSED(blink);
831
 
898
 
832
     // Just print the string to the LCD
899
     // Just print the string to the LCD
833
-    lcd_put_u8str_max(status_message, LCD_PIXEL_WIDTH);
900
+    lcd_put_u8str_max(status_message, pixel_width);
834
 
901
 
835
     // Fill the rest with spaces
902
     // Fill the rest with spaces
836
-    for (; slen < LCD_WIDTH; ++slen) lcd_put_wchar(' ');
903
+    for (; slen < lcd_width; ++slen) lcd_put_wchar(' ');
837
 
904
 
838
   #endif // !STATUS_MESSAGE_SCROLLING
905
   #endif // !STATUS_MESSAGE_SCROLLING
906
+
907
+  #if HAS_POWER_MONITOR
908
+    display_power_monitor(pixel_width + MENU_FONT_WIDTH, STATUS_BASELINE);
909
+  #endif
839
 }
910
 }
840
 
911
 
841
 #endif // HAS_GRAPHICAL_LCD && !LIGHTWEIGHT_UI
912
 #endif // HAS_GRAPHICAL_LCD && !LIGHTWEIGHT_UI

+ 4
- 0
Marlin/src/lcd/language/language_en.h View File

340
   PROGMEM Language_Str MSG_INFO_SCREEN                     = _UxGT("Info Screen");
340
   PROGMEM Language_Str MSG_INFO_SCREEN                     = _UxGT("Info Screen");
341
   PROGMEM Language_Str MSG_PREPARE                         = _UxGT("Prepare");
341
   PROGMEM Language_Str MSG_PREPARE                         = _UxGT("Prepare");
342
   PROGMEM Language_Str MSG_TUNE                            = _UxGT("Tune");
342
   PROGMEM Language_Str MSG_TUNE                            = _UxGT("Tune");
343
+  PROGMEM Language_Str MSG_POWER_MONITOR                   = _UxGT("Power monitor");
344
+  PROGMEM Language_Str MSG_CURRENT                         = _UxGT("Current");
345
+  PROGMEM Language_Str MSG_VOLTAGE                         = _UxGT("Voltage");
346
+  PROGMEM Language_Str MSG_POWER                           = _UxGT("Power");
343
   PROGMEM Language_Str MSG_START_PRINT                     = _UxGT("Start Print");
347
   PROGMEM Language_Str MSG_START_PRINT                     = _UxGT("Start Print");
344
   PROGMEM Language_Str MSG_BUTTON_NEXT                     = _UxGT("Next");
348
   PROGMEM Language_Str MSG_BUTTON_NEXT                     = _UxGT("Next");
345
   PROGMEM Language_Str MSG_BUTTON_INIT                     = _UxGT("Init");
349
   PROGMEM Language_Str MSG_BUTTON_INIT                     = _UxGT("Init");

+ 12
- 4
Marlin/src/lcd/menu/menu_main.cpp View File

59
   void menu_user();
59
   void menu_user();
60
 #endif
60
 #endif
61
 
61
 
62
+#if HAS_POWER_MONITOR
63
+  void menu_power_monitor();
64
+#endif
65
+
66
+#if ENABLED(MIXING_EXTRUDER)
67
+  void menu_mixer();
68
+#endif
69
+
62
 #if ENABLED(ADVANCED_PAUSE_FEATURE)
70
 #if ENABLED(ADVANCED_PAUSE_FEATURE)
63
   void _menu_temp_filament_op(const PauseMode, const int8_t);
71
   void _menu_temp_filament_op(const PauseMode, const int8_t);
64
   void menu_change_filament();
72
   void menu_change_filament();
76
   void menu_spindle_laser();
84
   void menu_spindle_laser();
77
 #endif
85
 #endif
78
 
86
 
79
-#if ENABLED(MIXING_EXTRUDER)
80
-  void menu_mixer();
81
-#endif
82
-
83
 extern const char M21_STR[];
87
 extern const char M21_STR[];
84
 
88
 
85
 void menu_main() {
89
 void menu_main() {
155
 
159
 
156
   SUBMENU(MSG_TEMPERATURE, menu_temperature);
160
   SUBMENU(MSG_TEMPERATURE, menu_temperature);
157
 
161
 
162
+  #if HAS_POWER_MONITOR
163
+    MENU_ITEM(submenu, MSG_POWER_MONITOR, menu_power_monitor);
164
+  #endif
165
+
158
   #if ENABLED(MIXING_EXTRUDER)
166
   #if ENABLED(MIXING_EXTRUDER)
159
     SUBMENU(MSG_MIXER, menu_mixer);
167
     SUBMENU(MSG_MIXER, menu_mixer);
160
   #endif
168
   #endif

+ 62
- 0
Marlin/src/lcd/menu/menu_power_monitor.cpp View File

1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+//
24
+// Power Monitor Menu
25
+//
26
+
27
+#include "../../inc/MarlinConfigPre.h"
28
+
29
+#if HAS_LCD_MENU && HAS_POWER_MONITOR
30
+
31
+#include "menu.h"
32
+#include "../../feature/power_monitor.h"
33
+
34
+void menu_power_monitor() {
35
+  START_MENU();
36
+  MENU_BACK(MSG_MAIN);
37
+
38
+  #if ENABLED(POWER_MONITOR_CURRENT)
39
+  {
40
+    bool ena = power_monitor.current_display_enabled();
41
+    MENU_ITEM_EDIT_CALLBACK(bool, MSG_CURRENT, &ena, power_monitor.toggle_current_display);
42
+  }
43
+  #endif
44
+
45
+  #if HAS_POWER_MONITOR_VREF
46
+  {
47
+    bool ena = power_monitor.voltage_display_enabled();
48
+    MENU_ITEM_EDIT_CALLBACK(bool, MSG_VOLTAGE, &ena, power_monitor.toggle_voltage_display);
49
+  }
50
+  #endif
51
+
52
+  #if HAS_POWER_MONITOR_WATTS
53
+  {
54
+    bool ena = power_monitor.power_display_enabled();
55
+    MENU_ITEM_EDIT_CALLBACK(bool, MSG_POWER, &ena, power_monitor.toggle_power_display);
56
+  }
57
+  #endif
58
+
59
+  END_MENU();
60
+}
61
+
62
+#endif // HAS_LCD_MENU && HAS_POWER_MONITOR

+ 4
- 1
Marlin/src/lcd/ultralcd.cpp View File

112
   #include "../module/thermistor/thermistors.h"
112
   #include "../module/thermistor/thermistors.h"
113
 #endif
113
 #endif
114
 
114
 
115
+#if HAS_POWER_MONITOR
116
+  #include "../feature/power_monitor.h"
117
+#endif
118
+
115
 #if HAS_ENCODER_ACTION
119
 #if HAS_ENCODER_ACTION
116
   volatile uint8_t MarlinUI::buttons;
120
   volatile uint8_t MarlinUI::buttons;
117
   #if HAS_SLOW_BUTTONS
121
   #if HAS_SLOW_BUTTONS
533
   #endif // LCD_PROGRESS_BAR
537
   #endif // LCD_PROGRESS_BAR
534
 
538
 
535
   #if HAS_LCD_MENU
539
   #if HAS_LCD_MENU
536
-
537
     if (use_click()) {
540
     if (use_click()) {
538
       #if BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT)
541
       #if BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT)
539
         next_filament_display = millis() + 5000UL;  // Show status message for 5s
542
         next_filament_display = millis() + 5000UL;  // Show status message for 5s

+ 21
- 0
Marlin/src/libs/numtostr.cpp View File

174
   return &conv[3];
174
   return &conv[3];
175
 }
175
 }
176
 
176
 
177
+// Convert unsigned float to string with 12.3 format
178
+const char* ftostr31ns(const float &f) {
179
+  const long i = ((f < 0 ? -f : f) * 100 + 5) / 10;
180
+  conv[3] = DIGIMOD(i, 100);
181
+  conv[4] = DIGIMOD(i, 10);
182
+  conv[5] = '.';
183
+  conv[6] = DIGIMOD(i, 1);
184
+  return &conv[3];
185
+}
186
+
187
+// Convert unsigned float to string with 123.4 format
188
+const char* ftostr41ns(const float &f) {
189
+  const long i = ((f < 0 ? -f : f) * 100 + 5) / 10;
190
+  conv[2] = DIGIMOD(i, 1000);
191
+  conv[3] = DIGIMOD(i, 100);
192
+  conv[4] = DIGIMOD(i, 10);
193
+  conv[5] = '.';
194
+  conv[6] = DIGIMOD(i, 1);
195
+  return &conv[2];
196
+}
197
+
177
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
198
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
178
 const char* ftostr42_52(const float &f) {
199
 const char* ftostr42_52(const float &f) {
179
   if (f <= -10 || f >= 100) return ftostr52(f); // -23.45 / 123.45
200
   if (f <= -10 || f >= 100) return ftostr52(f); // -23.45 / 123.45

+ 6
- 0
Marlin/src/libs/numtostr.h View File

58
 // Convert unsigned float to string with 1.23 format
58
 // Convert unsigned float to string with 1.23 format
59
 const char* ftostr12ns(const float &x);
59
 const char* ftostr12ns(const float &x);
60
 
60
 
61
+// Convert unsigned float to string with 12.3 format
62
+const char* ftostr31ns(const float &x);
63
+
64
+// Convert unsigned float to string with 123.4 format
65
+const char* ftostr41ns(const float &x);
66
+
61
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
67
 // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
62
 const char* ftostr42_52(const float &x);
68
 const char* ftostr42_52(const float &x);
63
 
69
 

+ 40
- 0
Marlin/src/module/configuration_store.cpp View File

94
   #include "../feature/powerloss.h"
94
   #include "../feature/powerloss.h"
95
 #endif
95
 #endif
96
 
96
 
97
+#if ENABLED(POWER_MONITOR)
98
+  #include "../feature/power_monitor.h"
99
+#endif
100
+
97
 #include "../feature/pause.h"
101
 #include "../feature/pause.h"
98
 
102
 
99
 #if ENABLED(BACKLASH_COMPENSATION)
103
 #if ENABLED(BACKLASH_COMPENSATION)
302
   #endif
306
   #endif
303
 
307
 
304
   //
308
   //
309
+  // Power monitor
310
+  //
311
+  uint8_t power_monitor_flags;                          // M430 I V W
312
+
313
+  //
305
   // HAS_LCD_CONTRAST
314
   // HAS_LCD_CONTRAST
306
   //
315
   //
307
   int16_t lcd_contrast;                                 // M250 C
316
   int16_t lcd_contrast;                                 // M250 C
882
     #endif
891
     #endif
883
 
892
 
884
     //
893
     //
894
+    // Power monitor
895
+    //
896
+    {
897
+      #if HAS_POWER_MONITOR
898
+        const uint8_t &power_monitor_flags = power_monitor.flags;
899
+      #else
900
+        constexpr uint8_t power_monitor_flags = 0x00;
901
+      #endif
902
+      _FIELD_TEST(power_monitor_flags);
903
+      EEPROM_WRITE(power_monitor_flags);
904
+    }
905
+
906
+    //
885
     // LCD Contrast
907
     // LCD Contrast
886
     //
908
     //
887
     {
909
     {
1746
       #endif
1768
       #endif
1747
 
1769
 
1748
       //
1770
       //
1771
+      // Power monitor
1772
+      //
1773
+      {
1774
+        #if HAS_POWER_MONITOR
1775
+          uint8_t &power_monitor_flags = power_monitor.flags;
1776
+        #else
1777
+          uint8_t power_monitor_flags;
1778
+        #endif
1779
+        _FIELD_TEST(power_monitor_flags);
1780
+        EEPROM_READ(power_monitor_flags);
1781
+      }
1782
+
1783
+      //
1749
       // LCD Contrast
1784
       // LCD Contrast
1750
       //
1785
       //
1751
       {
1786
       {
2605
   TERN_(HAS_USER_THERMISTORS, thermalManager.reset_user_thermistors());
2640
   TERN_(HAS_USER_THERMISTORS, thermalManager.reset_user_thermistors());
2606
 
2641
 
2607
   //
2642
   //
2643
+  // Power Monitor
2644
+  //
2645
+  TERN_(POWER_MONITOR, power_monitor.reset());
2646
+
2647
+  //
2608
   // LCD Contrast
2648
   // LCD Contrast
2609
   //
2649
   //
2610
   TERN_(HAS_LCD_CONTRAST, ui.set_contrast(DEFAULT_LCD_CONTRAST));
2650
   TERN_(HAS_LCD_CONTRAST, ui.set_contrast(DEFAULT_LCD_CONTRAST));

+ 34
- 4
Marlin/src/module/temperature.cpp View File

84
   #include "../feature/filwidth.h"
84
   #include "../feature/filwidth.h"
85
 #endif
85
 #endif
86
 
86
 
87
+#if HAS_POWER_MONITOR
88
+  #include "../feature/power_monitor.h"
89
+#endif
90
+
87
 #if ENABLED(EMERGENCY_PARSER)
91
 #if ENABLED(EMERGENCY_PARSER)
88
   #include "../feature/e_parser.h"
92
   #include "../feature/e_parser.h"
89
 #endif
93
 #endif
1529
   #if HAS_HOTEND
1533
   #if HAS_HOTEND
1530
     HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e);
1534
     HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e);
1531
   #endif
1535
   #endif
1536
+
1532
   TERN_(HAS_HEATED_BED, temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw));
1537
   TERN_(HAS_HEATED_BED, temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw));
1533
   TERN_(HAS_TEMP_CHAMBER, temp_chamber.celsius = analog_to_celsius_chamber(temp_chamber.raw));
1538
   TERN_(HAS_TEMP_CHAMBER, temp_chamber.celsius = analog_to_celsius_chamber(temp_chamber.raw));
1534
   TERN_(HAS_TEMP_PROBE, temp_probe.celsius = analog_to_celsius_probe(temp_probe.raw));
1539
   TERN_(HAS_TEMP_PROBE, temp_probe.celsius = analog_to_celsius_probe(temp_probe.raw));
1535
   TERN_(TEMP_SENSOR_1_AS_REDUNDANT, redundant_temperature = analog_to_celsius_hotend(redundant_temperature_raw, 1));
1540
   TERN_(TEMP_SENSOR_1_AS_REDUNDANT, redundant_temperature = analog_to_celsius_hotend(redundant_temperature_raw, 1));
1536
   TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_measured_mm());
1541
   TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_measured_mm());
1542
+  TERN_(HAS_POWER_MONITOR, power_monitor.capture_values());
1537
 
1543
 
1538
   // Reset the watchdog on good temperature measurement
1544
   // Reset the watchdog on good temperature measurement
1539
   watchdog_refresh();
1545
   watchdog_refresh();
1740
   #if HAS_ADC_BUTTONS
1746
   #if HAS_ADC_BUTTONS
1741
     HAL_ANALOG_SELECT(ADC_KEYPAD_PIN);
1747
     HAL_ANALOG_SELECT(ADC_KEYPAD_PIN);
1742
   #endif
1748
   #endif
1749
+  #if ENABLED(POWER_MONITOR_CURRENT)
1750
+    HAL_ANALOG_SELECT(POWER_MONITOR_CURRENT_PIN);
1751
+  #endif
1752
+  #if ENABLED(POWER_MONITOR_VOLTAGE)
1753
+    HAL_ANALOG_SELECT(POWER_MONITOR_VOLTAGE_PIN);
1754
+  #endif
1743
 
1755
 
1744
   HAL_timer_start(TEMP_TIMER_NUM, TEMP_TIMER_FREQUENCY);
1756
   HAL_timer_start(TEMP_TIMER_NUM, TEMP_TIMER_FREQUENCY);
1745
   ENABLE_TEMPERATURE_INTERRUPT();
1757
   ENABLE_TEMPERATURE_INTERRUPT();
2760
     #if ENABLED(FILAMENT_WIDTH_SENSOR)
2772
     #if ENABLED(FILAMENT_WIDTH_SENSOR)
2761
       case Prepare_FILWIDTH: HAL_START_ADC(FILWIDTH_PIN); break;
2773
       case Prepare_FILWIDTH: HAL_START_ADC(FILWIDTH_PIN); break;
2762
       case Measure_FILWIDTH:
2774
       case Measure_FILWIDTH:
2763
-        if (!HAL_ADC_READY())
2764
-          next_sensor_state = adc_sensor_state; // redo this state
2765
-        else
2766
-          filwidth.accumulate(HAL_READ_ADC());
2775
+        if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; // Redo this state
2776
+        else filwidth.accumulate(HAL_READ_ADC());
2767
       break;
2777
       break;
2768
     #endif
2778
     #endif
2769
 
2779
 
2780
+    #if ENABLED(POWER_MONITOR_CURRENT)
2781
+      case Prepare_POWER_MONITOR_CURRENT:
2782
+        HAL_START_ADC(POWER_MONITOR_CURRENT_PIN);
2783
+        break;
2784
+      case Measure_POWER_MONITOR_CURRENT:
2785
+        if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; // Redo this state
2786
+        else power_monitor.add_current_sample(HAL_READ_ADC());
2787
+        break;
2788
+    #endif
2789
+
2790
+    #if ENABLED(POWER_MONITOR_VOLTAGE)
2791
+      case Prepare_POWER_MONITOR_VOLTAGE:
2792
+        HAL_START_ADC(POWER_MONITOR_VOLTAGE_PIN);
2793
+        break;
2794
+      case Measure_POWER_MONITOR_VOLTAGE:
2795
+        if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; // Redo this state
2796
+        else power_monitor.add_voltage_sample(HAL_READ_ADC());
2797
+        break;
2798
+    #endif
2799
+
2770
     #if HAS_JOY_ADC_X
2800
     #if HAS_JOY_ADC_X
2771
       case PrepareJoy_X: HAL_START_ADC(JOY_X_PIN); break;
2801
       case PrepareJoy_X: HAL_START_ADC(JOY_X_PIN); break;
2772
       case MeasureJoy_X: ACCUMULATE_ADC(joystick.x); break;
2802
       case MeasureJoy_X: ACCUMULATE_ADC(joystick.x); break;

+ 8
- 0
Marlin/src/module/temperature.h View File

148
   #if ENABLED(FILAMENT_WIDTH_SENSOR)
148
   #if ENABLED(FILAMENT_WIDTH_SENSOR)
149
     Prepare_FILWIDTH, Measure_FILWIDTH,
149
     Prepare_FILWIDTH, Measure_FILWIDTH,
150
   #endif
150
   #endif
151
+  #if ENABLED(POWER_MONITOR_CURRENT)
152
+    Prepare_POWER_MONITOR_CURRENT,
153
+    Measure_POWER_MONITOR_CURRENT,
154
+  #endif
155
+  #if ENABLED(POWER_MONITOR_VOLTAGE)
156
+    Prepare_POWER_MONITOR_VOLTAGE,
157
+    Measure_POWER_MONITOR_VOLTAGE,
158
+  #endif
151
   #if HAS_ADC_BUTTONS
159
   #if HAS_ADC_BUTTONS
152
     Prepare_ADC_KEY, Measure_ADC_KEY,
160
     Prepare_ADC_KEY, Measure_ADC_KEY,
153
   #endif
161
   #endif

Loading…
Cancel
Save