Power monitor and display (#17437)
This commit is contained in:
		| @@ -2984,6 +2984,23 @@ | ||||
|   //#define FILAMENT_LCD_DISPLAY | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * Power Monitor | ||||
|  * Monitor voltage (V) and/or current (A), and -when possible- power (W) | ||||
|  * | ||||
|  * Read and configure with M430 | ||||
|  * | ||||
|  * The current sensor feeds DC voltage (relative to the measured current) to an analog pin | ||||
|  * The voltage sensor feeds DC voltage (relative to the measured voltage) to an analog pin | ||||
|  */ | ||||
| //#define POWER_MONITOR_CURRENT   // Monitor the system current | ||||
| //#define POWER_MONITOR_VOLTAGE   // Monitor the system voltage | ||||
| #if EITHER(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE) | ||||
|   #define POWER_MONITOR_VOLTS_PER_AMP   0.05000   // Input voltage to the MCU analog pin per amp  - DO NOT apply more than ADC_VREF! | ||||
|   #define POWER_MONITOR_VOLTS_PER_VOLT  0.11786   // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF! | ||||
|   #define POWER_MONITOR_FIXED_VOLTAGE   13.6      // Voltage for a current sensor with no voltage sensor (for power display) | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * CNC Coordinate Systems | ||||
|  * | ||||
|   | ||||
| @@ -162,6 +162,7 @@ inline void HAL_adc_init() { | ||||
|   #define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch) | ||||
| #endif | ||||
|  | ||||
| #define HAL_ADC_VREF        5.0 | ||||
| #define HAL_ADC_RESOLUTION 10 | ||||
| #define HAL_READ_ADC()  ADC | ||||
| #define HAL_ADC_READY() !TEST(ADCSRA, ADSC) | ||||
|   | ||||
| @@ -143,8 +143,9 @@ extern uint16_t HAL_adc_result;     // result of last ADC conversion | ||||
|  | ||||
| inline void HAL_adc_init() {}//todo | ||||
|  | ||||
| #define HAL_START_ADC(ch)   HAL_adc_start_conversion(ch) | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10 | ||||
| #define HAL_START_ADC(ch)   HAL_adc_start_conversion(ch) | ||||
| #define HAL_READ_ADC()      HAL_adc_result | ||||
| #define HAL_ADC_READY()     true | ||||
|  | ||||
|   | ||||
| @@ -112,8 +112,9 @@ void analogWrite(pin_t pin, int value); | ||||
|  | ||||
| void HAL_adc_init(); | ||||
|  | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10 | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_READ_ADC()      HAL_adc_result | ||||
| #define HAL_ADC_READY()     true | ||||
|  | ||||
|   | ||||
| @@ -86,9 +86,10 @@ int freeMemory(); | ||||
| #pragma GCC diagnostic pop | ||||
|  | ||||
| // ADC | ||||
| #define HAL_ADC_VREF           5.0 | ||||
| #define HAL_ADC_RESOLUTION    10 | ||||
| #define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch) | ||||
| #define HAL_START_ADC(ch)     HAL_adc_start_conversion(ch) | ||||
| #define HAL_ADC_RESOLUTION    10 | ||||
| #define HAL_READ_ADC()        HAL_adc_get_result() | ||||
| #define HAL_ADC_READY()       true | ||||
|  | ||||
|   | ||||
| @@ -150,6 +150,8 @@ int freeMemory(); | ||||
|                                     // K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step | ||||
|                                     // Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels) | ||||
|  | ||||
| #define HAL_ADC_VREF            3.3 // ADC voltage reference | ||||
|  | ||||
| #define HAL_ADC_RESOLUTION     12   // 15 bit maximum, raw temperature is stored as int16_t | ||||
| #define HAL_ADC_FILTERED            // Disable oversampling done in Marlin as ADC values already filtered in HAL | ||||
|  | ||||
|   | ||||
| @@ -122,6 +122,7 @@ extern uint16_t HAL_adc_result;     // Most recent ADC conversion | ||||
| void HAL_adc_init(); | ||||
|  | ||||
| //#define HAL_ADC_FILTERED          // Disable Marlin's oversampling. The HAL filters ADC values. | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10      // ... 12 | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_READ_ADC()      HAL_adc_result | ||||
|   | ||||
| @@ -199,8 +199,9 @@ static inline int freeMemory() { | ||||
|  | ||||
| inline void HAL_adc_init() {} | ||||
|  | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10 | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_READ_ADC()      HAL_adc_result | ||||
| #define HAL_ADC_READY()     true | ||||
|  | ||||
|   | ||||
| @@ -139,9 +139,15 @@ const uint8_t adc_pins[] = { | ||||
|   #if HAS_JOY_ADC_Z | ||||
|     JOY_Z_PIN, | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|     POWER_MONITOR_CURRENT_PIN, | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|     POWER_MONITOR_VOLTAGE_PIN, | ||||
|   #endif | ||||
| }; | ||||
|  | ||||
| enum TEMP_PINS : char { | ||||
| enum TempPinIndex : char { | ||||
|   #if HAS_TEMP_ADC_0 | ||||
|     TEMP_0, | ||||
|   #endif | ||||
| @@ -187,6 +193,12 @@ enum TEMP_PINS : char { | ||||
|   #if HAS_JOY_ADC_Z | ||||
|     JOY_Z, | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|     POWERMON_CURRENT, | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|     POWERMON_VOLTS, | ||||
|   #endif | ||||
|   ADC_PIN_COUNT | ||||
| }; | ||||
|  | ||||
| @@ -323,7 +335,8 @@ void HAL_adc_init() { | ||||
| } | ||||
|  | ||||
| void HAL_adc_start_conversion(const uint8_t adc_pin) { | ||||
|   TEMP_PINS pin_index; | ||||
|   //TEMP_PINS pin_index; | ||||
|   TempPinIndex pin_index; | ||||
|   switch (adc_pin) { | ||||
|     default: return; | ||||
|     #if HAS_TEMP_ADC_0 | ||||
| @@ -371,6 +384,12 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) { | ||||
|     #if ENABLED(ADC_KEYPAD) | ||||
|       case ADC_KEYPAD_PIN: pin_index = ADC_KEY; break; | ||||
|     #endif | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|       case POWER_MONITOR_CURRENT_PIN: pin_index = POWERMON_CURRENT; break; | ||||
|     #endif | ||||
|     #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|       case POWER_MONITOR_VOLTAGE_PIN: pin_index = POWERMON_VOLTS; break; | ||||
|     #endif | ||||
|   } | ||||
|   HAL_adc_result = (HAL_adc_results[(int)pin_index] >> 2) & 0x3FF; // shift to get 10 bits only. | ||||
| } | ||||
|   | ||||
| @@ -255,8 +255,9 @@ static int freeMemory() { | ||||
|  | ||||
| void HAL_adc_init(); | ||||
|  | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10 | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_READ_ADC()      HAL_adc_result | ||||
| #define HAL_ADC_READY()     true | ||||
|  | ||||
|   | ||||
| @@ -219,8 +219,9 @@ static inline int freeMemory() { | ||||
|  | ||||
| inline void HAL_adc_init() {} | ||||
|  | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10 | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_READ_ADC()      HAL_adc_result | ||||
| #define HAL_ADC_READY()     true | ||||
|  | ||||
|   | ||||
| @@ -107,8 +107,9 @@ extern "C" { | ||||
|  | ||||
| void HAL_adc_init(); | ||||
|  | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10 | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_READ_ADC()      HAL_adc_get_result() | ||||
| #define HAL_ADC_READY()     true | ||||
|  | ||||
|   | ||||
| @@ -112,8 +112,9 @@ extern "C" { | ||||
|  | ||||
| void HAL_adc_init(); | ||||
|  | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_ADC_VREF         3.3 | ||||
| #define HAL_ADC_RESOLUTION  10 | ||||
| #define HAL_START_ADC(pin)  HAL_adc_start_conversion(pin) | ||||
| #define HAL_READ_ADC()      HAL_adc_get_result() | ||||
| #define HAL_ADC_READY()     true | ||||
|  | ||||
|   | ||||
| @@ -97,10 +97,13 @@ | ||||
|   #define CBI(A,B) (A &= ~(1 << (B))) | ||||
| #endif | ||||
|  | ||||
| #define TBI(N,B) (N ^= _BV(B)) | ||||
|  | ||||
| #define _BV32(b) (1UL << (b)) | ||||
| #define TEST32(n,b) !!((n)&_BV32(b)) | ||||
| #define SBI32(n,b) (n |= _BV32(b)) | ||||
| #define CBI32(n,b) (n &= ~_BV32(b)) | ||||
| #define TBI32(N,B) (N ^= _BV32(B)) | ||||
|  | ||||
| #define cu(x)      ({__typeof__(x) _x = (x); (_x)*(_x)*(_x);}) | ||||
| #define RADIANS(d) ((d)*float(M_PI)/180.0f) | ||||
|   | ||||
							
								
								
									
										74
									
								
								Marlin/src/feature/power_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								Marlin/src/feature/power_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if HAS_POWER_MONITOR | ||||
|  | ||||
| #include "power_monitor.h" | ||||
|  | ||||
| #include "../lcd/ultralcd.h" | ||||
| #include "../lcd/lcdprint.h" | ||||
|  | ||||
| uint8_t PowerMonitor::flags; // = 0 | ||||
|  | ||||
| #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|   pm_lpf_t<PowerMonitor::amps_adc_scale, PM_K_VALUE, PM_K_SCALE> PowerMonitor::amps; | ||||
| #endif | ||||
| #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|   pm_lpf_t<PowerMonitor::volts_adc_scale, PM_K_VALUE, PM_K_SCALE> PowerMonitor::volts; | ||||
| #endif | ||||
|  | ||||
| millis_t PowerMonitor::display_item_ms; | ||||
| uint8_t PowerMonitor::display_item; | ||||
|  | ||||
| PowerMonitor power_monitor; // Single instance - this calls the constructor | ||||
|  | ||||
| #if HAS_GRAPHICAL_LCD | ||||
|  | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|     void PowerMonitor::draw_current() { | ||||
|       const float amps = getAmps(); | ||||
|       lcd_put_u8str(amps < 100 ? ftostr21ns(amps) : ui16tostr4((uint16_t)amps)); | ||||
|       lcd_put_wchar('A'); | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_POWER_MONITOR_VREF | ||||
|     void PowerMonitor::draw_voltage() { | ||||
|       const float volts = getVolts(); | ||||
|       lcd_put_u8str(volts < 100 ? ftostr21ns(volts) : ui16tostr4((uint16_t)volts)); | ||||
|       lcd_put_wchar('V'); | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_POWER_MONITOR_WATTS | ||||
|     void PowerMonitor::draw_power() { | ||||
|       const float power = getPower(); | ||||
|       lcd_put_u8str(power < 100 ? ftostr21ns(power) : ui16tostr4((uint16_t)power)); | ||||
|       lcd_put_wchar('W'); | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
| #endif // HAS_GRAPHICAL_LCD | ||||
|  | ||||
| #endif // HAS_POWER_MONITOR | ||||
							
								
								
									
										140
									
								
								Marlin/src/feature/power_monitor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Marlin/src/feature/power_monitor.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../inc/MarlinConfig.h" | ||||
|  | ||||
| #define PM_SAMPLE_RANGE 1024 | ||||
| #define PM_K_VALUE      6 | ||||
| #define PM_K_SCALE      6 | ||||
|  | ||||
| template <const float & SCALE, int K_VALUE, int K_SCALE> | ||||
| struct pm_lpf_t { | ||||
|   uint32_t filter_buf; | ||||
|   float value; | ||||
|   void add_sample(const uint16_t sample) { | ||||
|     filter_buf = filter_buf - (filter_buf >> K_VALUE) + (uint32_t(sample) << K_SCALE); | ||||
|   } | ||||
|   void capture() { | ||||
|     value = filter_buf * (SCALE * (1.0f / (1UL << (PM_K_VALUE + PM_K_SCALE)))); | ||||
|   } | ||||
|   void reset(uint16_t reset_value = 0) { | ||||
|     filter_buf = uint32_t(reset_value) << (K_VALUE + K_SCALE); | ||||
|     capture(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| class PowerMonitor { | ||||
| private: | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|     static constexpr float amps_adc_scale = float(ADC_VREF) / (POWER_MONITOR_VOLTS_PER_AMP * PM_SAMPLE_RANGE); | ||||
|     static pm_lpf_t<amps_adc_scale, PM_K_VALUE, PM_K_SCALE> amps; | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|     static constexpr float volts_adc_scale = float(ADC_VREF) / (POWER_MONITOR_VOLTS_PER_VOLT * PM_SAMPLE_RANGE); | ||||
|     static pm_lpf_t<volts_adc_scale, PM_K_VALUE, PM_K_SCALE> volts; | ||||
|   #endif | ||||
|  | ||||
| public: | ||||
|   static uint8_t flags;  // M430 flags to display current | ||||
|  | ||||
|   static millis_t display_item_ms; | ||||
|   static uint8_t display_item; | ||||
|  | ||||
|   PowerMonitor() { reset(); } | ||||
|  | ||||
|   enum PM_Display_Bit : uint8_t { | ||||
|     PM_DISP_BIT_I, // Current display enable bit | ||||
|     PM_DISP_BIT_V, // Voltage display enable bit | ||||
|     PM_DISP_BIT_P  // Power display enable bit | ||||
|   }; | ||||
|  | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|     FORCE_INLINE static float getAmps() { return amps.value; } | ||||
|     void add_current_sample(const uint16_t value) { amps.add_sample(value); } | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_POWER_MONITOR_VREF | ||||
|     #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|       FORCE_INLINE static float getVolts() { return volts.value; } | ||||
|     #else | ||||
|       FORCE_INLINE static float getVolts() { return POWER_MONITOR_FIXED_VOLTAGE; }  // using a specified fixed valtage as the voltage measurement | ||||
|     #endif | ||||
|     #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|       void add_voltage_sample(const uint16_t value) { volts.add_sample(value); } | ||||
|     #endif | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_POWER_MONITOR_WATTS | ||||
|     FORCE_INLINE static float getPower() { return getAmps() * getVolts(); } | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_SPI_LCD | ||||
|     FORCE_INLINE static bool display_enabled() { return flags != 0x00; } | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|       static void draw_current(); | ||||
|       FORCE_INLINE static bool current_display_enabled() { return TEST(flags, PM_DISP_BIT_I); } | ||||
|       FORCE_INLINE static void set_current_display(const bool b) { SET_BIT_TO(flags, PM_DISP_BIT_I, b); } | ||||
|       FORCE_INLINE static void toggle_current_display() { TBI(flags, PM_DISP_BIT_I); } | ||||
|     #endif | ||||
|     #if HAS_POWER_MONITOR_VREF | ||||
|       static void draw_voltage(); | ||||
|       FORCE_INLINE static bool voltage_display_enabled() { return TEST(flags, PM_DISP_BIT_V); } | ||||
|       FORCE_INLINE static void set_voltage_display(const bool b) { SET_BIT_TO(flags, PM_DISP_BIT_V, b); } | ||||
|       FORCE_INLINE static void toggle_voltage_display() { TBI(flags, PM_DISP_BIT_I); } | ||||
|     #endif | ||||
|     #if HAS_POWER_MONITOR_WATTS | ||||
|       static void draw_power(); | ||||
|       FORCE_INLINE static bool power_display_enabled() { return TEST(flags, PM_DISP_BIT_P); } | ||||
|       FORCE_INLINE static void set_power_display(const bool b) { SET_BIT_TO(flags, PM_DISP_BIT_P, b); } | ||||
|       FORCE_INLINE static void toggle_power_display() { TBI(flags, PM_DISP_BIT_I); } | ||||
|     #endif | ||||
|   #endif | ||||
|  | ||||
|   static void reset() { | ||||
|     flags = 0x00; | ||||
|  | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|       amps.reset(); | ||||
|     #endif | ||||
|  | ||||
|     #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|       volts.reset(); | ||||
|     #endif | ||||
|  | ||||
|     #if ENABLED(SDSUPPORT) | ||||
|       display_item_ms = 0; | ||||
|       display_item = 0; | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   static void capture_values() { | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|      amps.capture(); | ||||
|     #endif | ||||
|     #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|       volts.capture(); | ||||
|     #endif | ||||
|   } | ||||
| }; | ||||
|  | ||||
| extern PowerMonitor power_monitor; | ||||
							
								
								
									
										70
									
								
								Marlin/src/gcode/feature/power_monitor/M430.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								Marlin/src/gcode/feature/power_monitor/M430.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "../../../inc/MarlinConfig.h" | ||||
|  | ||||
| #if HAS_POWER_MONITOR | ||||
|  | ||||
| #include "../../../feature/power_monitor.h" | ||||
| #include "../../../Marlin.h" | ||||
| #include "../../gcode.h" | ||||
|  | ||||
| /** | ||||
|  * M430: Enable/disable current LCD display | ||||
|  *       With no parameters report the system current draw (in Amps) | ||||
|  * | ||||
|  *  I[bool] - Set Display of current on the LCD | ||||
|  *  V[bool] - Set Display of voltage on the LCD | ||||
|  *  W[bool] - Set Display of power on the LCD | ||||
|  */ | ||||
| void GcodeSuite::M430() { | ||||
|   bool do_report = true; | ||||
|   #if HAS_SPI_LCD | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|       if (parser.seen('I')) { power_monitor.set_current_display(parser.value_bool()); do_report = false; } | ||||
|     #endif | ||||
|     #if HAS_POWER_MONITOR_VREF | ||||
|       if (parser.seen('V')) { power_monitor.set_voltage_display(parser.value_bool()); do_report = false; } | ||||
|     #endif | ||||
|     #if HAS_POWER_MONITOR_WATTS | ||||
|       if (parser.seen('W')) { power_monitor.set_power_display(parser.value_bool()); do_report = false; } | ||||
|     #endif | ||||
|   #endif | ||||
|   if (do_report) { | ||||
|     SERIAL_ECHOLNPAIR( | ||||
|       #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|         "Current: ", power_monitor.getAmps(), "A" | ||||
|         #if HAS_POWER_MONITOR_VREF | ||||
|           "  " | ||||
|         #endif | ||||
|       #endif | ||||
|       #if HAS_POWER_MONITOR_VREF | ||||
|         "Voltage: ", power_monitor.getVolts(), "V" | ||||
|       #endif | ||||
|       #if HAS_POWER_MONITOR_WATTS | ||||
|         "  Power: ", power_monitor.getPower(), "W" | ||||
|       #endif | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| #endif // HAS_POWER_MONITOR | ||||
| @@ -720,6 +720,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|         case 428: M428(); break;                                  // M428: Apply current_position to home_offset | ||||
|       #endif | ||||
|  | ||||
|       #if HAS_POWER_MONITOR | ||||
|         case 430: M430(); break;                                  // M430: Read the system current (A), voltage (V), and power (W) | ||||
|       #endif | ||||
|  | ||||
|       #if ENABLED(CANCEL_OBJECTS) | ||||
|         case 486: M486(); break;                                  // M486: Identify and cancel objects | ||||
|       #endif | ||||
|   | ||||
| @@ -217,6 +217,7 @@ | ||||
|  * M422 - Set Z Stepper automatic alignment position using probe. X<units> Y<units> A<axis> (Requires Z_STEPPER_AUTO_ALIGN) | ||||
|  * M425 - Enable/Disable and tune backlash correction. (Requires BACKLASH_COMPENSATION and BACKLASH_GCODE) | ||||
|  * M428 - Set the home_offset based on the current_position. Nearest edge applies. (Disabled by NO_WORKSPACE_OFFSETS or DELTA) | ||||
|  * M430 - Read the system current, voltage, and power (Requires POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE, or POWER_MONITOR_FIXED_VOLTAGE) | ||||
|  * M486 - Identify and cancel objects. (Requires CANCEL_OBJECTS) | ||||
|  * M500 - Store parameters in EEPROM. (Requires EEPROM_SETTINGS) | ||||
|  * M501 - Restore parameters from EEPROM. (Requires EEPROM_SETTINGS) | ||||
| @@ -735,6 +736,8 @@ private: | ||||
|  | ||||
|   TERN_(HAS_M206_COMMAND, static void M428()); | ||||
|  | ||||
|   TERN_(HAS_POWER_MONITOR, static void M430()); | ||||
|  | ||||
|   TERN_(CANCEL_OBJECTS, static void M486()); | ||||
|  | ||||
|   static void M500(); | ||||
|   | ||||
| @@ -352,6 +352,17 @@ | ||||
|   #define SD_CONNECTION_IS(...) 0 | ||||
| #endif | ||||
|  | ||||
| // Power Monitor sensors | ||||
| #if EITHER(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE) | ||||
|   #define HAS_POWER_MONITOR 1 | ||||
| #endif | ||||
| #if ENABLED(POWER_MONITOR_VOLTAGE) || defined(POWER_MONITOR_FIXED_VOLTAGE) | ||||
|   #define HAS_POWER_MONITOR_VREF 1 | ||||
| #endif | ||||
| #if BOTH(HAS_POWER_MONITOR_VREF, POWER_MONITOR_CURRENT) | ||||
|   #define HAS_POWER_MONITOR_WATTS 1 | ||||
| #endif | ||||
|  | ||||
| // Flag if an EEPROM type is pre-selected | ||||
| #if ENABLED(EEPROM_SETTINGS) && NONE(I2C_EEPROM, SPI_EEPROM, QSPI_EEPROM, FLASH_EEPROM_EMULATION, SRAM_EEPROM_EMULATION, SDCARD_EEPROM_EMULATION) | ||||
|   #define NO_EEPROM_SELECTED 1 | ||||
|   | ||||
| @@ -30,6 +30,13 @@ | ||||
|   // Extras for CI testing | ||||
| #endif | ||||
|  | ||||
| // ADC | ||||
| #ifdef BOARD_ADC_VREF | ||||
|   #define ADC_VREF BOARD_ADC_VREF | ||||
| #else | ||||
|   #define ADC_VREF HAL_ADC_VREF | ||||
| #endif | ||||
|  | ||||
| // Linear advance uses Jerk since E is an isolated axis | ||||
| #if BOTH(HAS_JUNCTION_DEVIATION, LIN_ADVANCE) | ||||
|   #define HAS_LINEAR_E_JERK 1 | ||||
|   | ||||
| @@ -1480,6 +1480,17 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal | ||||
|   #endif | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * System Power Sensor | ||||
|  */ | ||||
| #if ENABLED(POWER_MONITOR_CURRENT) && !PIN_EXISTS(POWER_MONITOR_CURRENT) | ||||
|   #error "POWER_MONITOR_CURRENT requires a valid POWER_MONITOR_CURRENT_PIN." | ||||
| #elif ENABLED(POWER_MONITOR_VOLTAGE) && !PIN_EXISTS(POWER_MONITOR_VOLTAGE) | ||||
|   #error "POWER_MONITOR_VOLTAGE requires POWER_MONITOR_VOLTAGE_PIN to be defined." | ||||
| #elif BOTH(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE) && POWER_MONITOR_CURRENT_PIN == POWER_MONITOR_VOLTAGE_PIN | ||||
|   #error "POWER_MONITOR_CURRENT_PIN and POWER_MONITOR_VOLTAGE_PIN must be different." | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * Volumetric Extruder Limit | ||||
|  */ | ||||
|   | ||||
| @@ -48,6 +48,10 @@ | ||||
|   #include "../../feature/spindle_laser.h" | ||||
| #endif | ||||
|  | ||||
| #if HAS_POWER_MONITOR | ||||
|   #include "../../feature/power_monitor.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(SDSUPPORT) | ||||
|   #include "../../sd/cardreader.h" | ||||
| #endif | ||||
| @@ -103,6 +107,59 @@ | ||||
|   #define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1) | ||||
| #endif | ||||
|  | ||||
| #if HAS_POWER_MONITOR | ||||
|  | ||||
|   void display_power_monitor(const uint8_t x, const uint8_t y) { | ||||
|  | ||||
|     lcd_moveto(x, y); | ||||
|  | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|       const bool iflag = power_monitor.current_display_enabled(); | ||||
|     #endif | ||||
|     #if HAS_POWER_MONITOR_VREF | ||||
|       const bool vflag = power_monitor.voltage_display_enabled(); | ||||
|     #endif | ||||
|     #if HAS_POWER_MONITOR_WATTS | ||||
|       const bool wflag = power_monitor.power_display_enabled(); | ||||
|     #endif | ||||
|  | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) || HAS_POWER_MONITOR_VREF | ||||
|       // cycle between current, voltage, and power | ||||
|       if (ELAPSED(millis(), power_monitor.display_item_ms)) { | ||||
|         power_monitor.display_item_ms = millis() + 1000UL; | ||||
|         ++power_monitor.display_item; | ||||
|       } | ||||
|     #endif | ||||
|  | ||||
|     // ensure we have the right one selected for display | ||||
|     for (uint8_t i = 0; i < 3; i++) { | ||||
|       #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|         if (power_monitor.display_item == 0 && !iflag) ++power_monitor.display_item; | ||||
|       #endif | ||||
|       #if HAS_POWER_MONITOR_VREF | ||||
|         if (power_monitor.display_item == 1 && !vflag) ++power_monitor.display_item; | ||||
|       #endif | ||||
|       #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|         if (power_monitor.display_item == 2 && !wflag) ++power_monitor.display_item; | ||||
|       #endif | ||||
|       if (power_monitor.display_item >= 3) power_monitor.display_item = 0; | ||||
|     } | ||||
|  | ||||
|     switch (power_monitor.display_item) { | ||||
|       #if ENABLED(POWER_MONITOR_CURRENT)                // Current | ||||
|         case 0: if (iflag) power_monitor.draw_current(); break; | ||||
|       #endif | ||||
|       #if HAS_POWER_MONITOR_VREF                        // Voltage | ||||
|         case 1: if (vflag) power_monitor.draw_voltage(); break; | ||||
|       #endif | ||||
|       #if HAS_POWER_MONITOR_WATTS                       // Power | ||||
|         case 2: if (wflag) power_monitor.draw_power(); break; | ||||
|       #endif | ||||
|       default: break; | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #define PROGRESS_BAR_X 54 | ||||
| #define PROGRESS_BAR_Y (EXTRAS_BASELINE + 1) | ||||
| #define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X) | ||||
| @@ -787,16 +844,25 @@ void MarlinUI::draw_status_screen() { | ||||
| void MarlinUI::draw_status_message(const bool blink) { | ||||
|  | ||||
|   // Get the UTF8 character count of the string | ||||
|   uint8_t slen = utf8_strlen(status_message); | ||||
|   uint8_t lcd_width = LCD_WIDTH, pixel_width = LCD_PIXEL_WIDTH, | ||||
|           slen = utf8_strlen(status_message); | ||||
|  | ||||
|   #if HAS_POWER_MONITOR | ||||
|     if (power_monitor.display_enabled()) { | ||||
|       // make room at the end of the status line for the power monitor reading | ||||
|       lcd_width -= 6; | ||||
|       pixel_width -= (MENU_FONT_WIDTH) * 6; | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(STATUS_MESSAGE_SCROLLING) | ||||
|  | ||||
|     static bool last_blink = false; | ||||
|  | ||||
|     if (slen <= LCD_WIDTH) { | ||||
|     if (slen <= lcd_width) { | ||||
|       // The string fits within the line. Print with no scrolling | ||||
|       lcd_put_u8str(status_message); | ||||
|       while (slen < LCD_WIDTH) { lcd_put_wchar(' '); ++slen; } | ||||
|       while (slen < lcd_width) { lcd_put_wchar(' '); ++slen; } | ||||
|     } | ||||
|     else { | ||||
|       // String is longer than the available space | ||||
| @@ -805,20 +871,21 @@ void MarlinUI::draw_status_message(const bool blink) { | ||||
|       // and the string remaining length | ||||
|       uint8_t rlen; | ||||
|       const char *stat = status_and_len(rlen); | ||||
|       lcd_put_u8str_max(stat, LCD_PIXEL_WIDTH); | ||||
|       lcd_put_u8str_max(stat, pixel_width); | ||||
|  | ||||
|       // If the remaining string doesn't completely fill the screen | ||||
|       if (rlen < LCD_WIDTH) { | ||||
|       if (rlen < lcd_width) { | ||||
|         lcd_put_wchar('.');                     // Always at 1+ spaces left, draw a dot | ||||
|         uint8_t chars = LCD_WIDTH - rlen;       // Amount of space left in characters | ||||
|         uint8_t chars = lcd_width - rlen;       // Amount of space left in characters | ||||
|         if (--chars) {                          // Draw a second dot if there's space | ||||
|           lcd_put_wchar('.'); | ||||
|           if (--chars) {                        // Print a second copy of the message | ||||
|             lcd_put_u8str_max(status_message, LCD_PIXEL_WIDTH - (rlen + 2) * (MENU_FONT_WIDTH)); | ||||
|             lcd_put_u8str_max(status_message, pixel_width - (rlen + 2) * (MENU_FONT_WIDTH)); | ||||
|             lcd_put_wchar(' '); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (last_blink != blink) { | ||||
|         last_blink = blink; | ||||
|         advance_status_scroll(); | ||||
| @@ -830,12 +897,16 @@ void MarlinUI::draw_status_message(const bool blink) { | ||||
|     UNUSED(blink); | ||||
|  | ||||
|     // Just print the string to the LCD | ||||
|     lcd_put_u8str_max(status_message, LCD_PIXEL_WIDTH); | ||||
|     lcd_put_u8str_max(status_message, pixel_width); | ||||
|  | ||||
|     // Fill the rest with spaces | ||||
|     for (; slen < LCD_WIDTH; ++slen) lcd_put_wchar(' '); | ||||
|     for (; slen < lcd_width; ++slen) lcd_put_wchar(' '); | ||||
|  | ||||
|   #endif // !STATUS_MESSAGE_SCROLLING | ||||
|  | ||||
|   #if HAS_POWER_MONITOR | ||||
|     display_power_monitor(pixel_width + MENU_FONT_WIDTH, STATUS_BASELINE); | ||||
|   #endif | ||||
| } | ||||
|  | ||||
| #endif // HAS_GRAPHICAL_LCD && !LIGHTWEIGHT_UI | ||||
|   | ||||
| @@ -340,6 +340,10 @@ namespace Language_en { | ||||
|   PROGMEM Language_Str MSG_INFO_SCREEN                     = _UxGT("Info Screen"); | ||||
|   PROGMEM Language_Str MSG_PREPARE                         = _UxGT("Prepare"); | ||||
|   PROGMEM Language_Str MSG_TUNE                            = _UxGT("Tune"); | ||||
|   PROGMEM Language_Str MSG_POWER_MONITOR                   = _UxGT("Power monitor"); | ||||
|   PROGMEM Language_Str MSG_CURRENT                         = _UxGT("Current"); | ||||
|   PROGMEM Language_Str MSG_VOLTAGE                         = _UxGT("Voltage"); | ||||
|   PROGMEM Language_Str MSG_POWER                           = _UxGT("Power"); | ||||
|   PROGMEM Language_Str MSG_START_PRINT                     = _UxGT("Start Print"); | ||||
|   PROGMEM Language_Str MSG_BUTTON_NEXT                     = _UxGT("Next"); | ||||
|   PROGMEM Language_Str MSG_BUTTON_INIT                     = _UxGT("Init"); | ||||
|   | ||||
| @@ -59,6 +59,14 @@ void menu_configuration(); | ||||
|   void menu_user(); | ||||
| #endif | ||||
|  | ||||
| #if HAS_POWER_MONITOR | ||||
|   void menu_power_monitor(); | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(MIXING_EXTRUDER) | ||||
|   void menu_mixer(); | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(ADVANCED_PAUSE_FEATURE) | ||||
|   void _menu_temp_filament_op(const PauseMode, const int8_t); | ||||
|   void menu_change_filament(); | ||||
| @@ -76,10 +84,6 @@ void menu_configuration(); | ||||
|   void menu_spindle_laser(); | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(MIXING_EXTRUDER) | ||||
|   void menu_mixer(); | ||||
| #endif | ||||
|  | ||||
| extern const char M21_STR[]; | ||||
|  | ||||
| void menu_main() { | ||||
| @@ -155,6 +159,10 @@ void menu_main() { | ||||
|  | ||||
|   SUBMENU(MSG_TEMPERATURE, menu_temperature); | ||||
|  | ||||
|   #if HAS_POWER_MONITOR | ||||
|     MENU_ITEM(submenu, MSG_POWER_MONITOR, menu_power_monitor); | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(MIXING_EXTRUDER) | ||||
|     SUBMENU(MSG_MIXER, menu_mixer); | ||||
|   #endif | ||||
|   | ||||
							
								
								
									
										62
									
								
								Marlin/src/lcd/menu/menu_power_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								Marlin/src/lcd/menu/menu_power_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (C) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| // | ||||
| // Power Monitor Menu | ||||
| // | ||||
|  | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if HAS_LCD_MENU && HAS_POWER_MONITOR | ||||
|  | ||||
| #include "menu.h" | ||||
| #include "../../feature/power_monitor.h" | ||||
|  | ||||
| void menu_power_monitor() { | ||||
|   START_MENU(); | ||||
|   MENU_BACK(MSG_MAIN); | ||||
|  | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|   { | ||||
|     bool ena = power_monitor.current_display_enabled(); | ||||
|     MENU_ITEM_EDIT_CALLBACK(bool, MSG_CURRENT, &ena, power_monitor.toggle_current_display); | ||||
|   } | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_POWER_MONITOR_VREF | ||||
|   { | ||||
|     bool ena = power_monitor.voltage_display_enabled(); | ||||
|     MENU_ITEM_EDIT_CALLBACK(bool, MSG_VOLTAGE, &ena, power_monitor.toggle_voltage_display); | ||||
|   } | ||||
|   #endif | ||||
|  | ||||
|   #if HAS_POWER_MONITOR_WATTS | ||||
|   { | ||||
|     bool ena = power_monitor.power_display_enabled(); | ||||
|     MENU_ITEM_EDIT_CALLBACK(bool, MSG_POWER, &ena, power_monitor.toggle_power_display); | ||||
|   } | ||||
|   #endif | ||||
|  | ||||
|   END_MENU(); | ||||
| } | ||||
|  | ||||
| #endif // HAS_LCD_MENU && HAS_POWER_MONITOR | ||||
| @@ -112,6 +112,10 @@ MarlinUI ui; | ||||
|   #include "../module/thermistor/thermistors.h" | ||||
| #endif | ||||
|  | ||||
| #if HAS_POWER_MONITOR | ||||
|   #include "../feature/power_monitor.h" | ||||
| #endif | ||||
|  | ||||
| #if HAS_ENCODER_ACTION | ||||
|   volatile uint8_t MarlinUI::buttons; | ||||
|   #if HAS_SLOW_BUTTONS | ||||
| @@ -533,7 +537,6 @@ void MarlinUI::status_screen() { | ||||
|   #endif // LCD_PROGRESS_BAR | ||||
|  | ||||
|   #if HAS_LCD_MENU | ||||
|  | ||||
|     if (use_click()) { | ||||
|       #if BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT) | ||||
|         next_filament_display = millis() + 5000UL;  // Show status message for 5s | ||||
|   | ||||
| @@ -174,6 +174,27 @@ const char* ftostr12ns(const float &f) { | ||||
|   return &conv[3]; | ||||
| } | ||||
|  | ||||
| // Convert unsigned float to string with 12.3 format | ||||
| const char* ftostr31ns(const float &f) { | ||||
|   const long i = ((f < 0 ? -f : f) * 100 + 5) / 10; | ||||
|   conv[3] = DIGIMOD(i, 100); | ||||
|   conv[4] = DIGIMOD(i, 10); | ||||
|   conv[5] = '.'; | ||||
|   conv[6] = DIGIMOD(i, 1); | ||||
|   return &conv[3]; | ||||
| } | ||||
|  | ||||
| // Convert unsigned float to string with 123.4 format | ||||
| const char* ftostr41ns(const float &f) { | ||||
|   const long i = ((f < 0 ? -f : f) * 100 + 5) / 10; | ||||
|   conv[2] = DIGIMOD(i, 1000); | ||||
|   conv[3] = DIGIMOD(i, 100); | ||||
|   conv[4] = DIGIMOD(i, 10); | ||||
|   conv[5] = '.'; | ||||
|   conv[6] = DIGIMOD(i, 1); | ||||
|   return &conv[2]; | ||||
| } | ||||
|  | ||||
| // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format | ||||
| const char* ftostr42_52(const float &f) { | ||||
|   if (f <= -10 || f >= 100) return ftostr52(f); // -23.45 / 123.45 | ||||
|   | ||||
| @@ -58,6 +58,12 @@ const char* i16tostr4signrj(const int16_t x); | ||||
| // Convert unsigned float to string with 1.23 format | ||||
| const char* ftostr12ns(const float &x); | ||||
|  | ||||
| // Convert unsigned float to string with 12.3 format | ||||
| const char* ftostr31ns(const float &x); | ||||
|  | ||||
| // Convert unsigned float to string with 123.4 format | ||||
| const char* ftostr41ns(const float &x); | ||||
|  | ||||
| // Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format | ||||
| const char* ftostr42_52(const float &x); | ||||
|  | ||||
|   | ||||
| @@ -94,6 +94,10 @@ | ||||
|   #include "../feature/powerloss.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(POWER_MONITOR) | ||||
|   #include "../feature/power_monitor.h" | ||||
| #endif | ||||
|  | ||||
| #include "../feature/pause.h" | ||||
|  | ||||
| #if ENABLED(BACKLASH_COMPENSATION) | ||||
| @@ -301,6 +305,11 @@ typedef struct SettingsDataStruct { | ||||
|     user_thermistor_t user_thermistor[USER_THERMISTORS]; // M305 P0 R4700 T100000 B3950 | ||||
|   #endif | ||||
|  | ||||
|   // | ||||
|   // Power monitor | ||||
|   // | ||||
|   uint8_t power_monitor_flags;                          // M430 I V W | ||||
|  | ||||
|   // | ||||
|   // HAS_LCD_CONTRAST | ||||
|   // | ||||
| @@ -881,6 +890,19 @@ void MarlinSettings::postprocess() { | ||||
|     } | ||||
|     #endif | ||||
|  | ||||
|     // | ||||
|     // Power monitor | ||||
|     // | ||||
|     { | ||||
|       #if HAS_POWER_MONITOR | ||||
|         const uint8_t &power_monitor_flags = power_monitor.flags; | ||||
|       #else | ||||
|         constexpr uint8_t power_monitor_flags = 0x00; | ||||
|       #endif | ||||
|       _FIELD_TEST(power_monitor_flags); | ||||
|       EEPROM_WRITE(power_monitor_flags); | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // LCD Contrast | ||||
|     // | ||||
| @@ -1745,6 +1767,19 @@ void MarlinSettings::postprocess() { | ||||
|       } | ||||
|       #endif | ||||
|  | ||||
|       // | ||||
|       // Power monitor | ||||
|       // | ||||
|       { | ||||
|         #if HAS_POWER_MONITOR | ||||
|           uint8_t &power_monitor_flags = power_monitor.flags; | ||||
|         #else | ||||
|           uint8_t power_monitor_flags; | ||||
|         #endif | ||||
|         _FIELD_TEST(power_monitor_flags); | ||||
|         EEPROM_READ(power_monitor_flags); | ||||
|       } | ||||
|  | ||||
|       // | ||||
|       // LCD Contrast | ||||
|       // | ||||
| @@ -2604,6 +2639,11 @@ void MarlinSettings::reset() { | ||||
|   // | ||||
|   TERN_(HAS_USER_THERMISTORS, thermalManager.reset_user_thermistors()); | ||||
|  | ||||
|   // | ||||
|   // Power Monitor | ||||
|   // | ||||
|   TERN_(POWER_MONITOR, power_monitor.reset()); | ||||
|  | ||||
|   // | ||||
|   // LCD Contrast | ||||
|   // | ||||
|   | ||||
| @@ -84,6 +84,10 @@ | ||||
|   #include "../feature/filwidth.h" | ||||
| #endif | ||||
|  | ||||
| #if HAS_POWER_MONITOR | ||||
|   #include "../feature/power_monitor.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(EMERGENCY_PARSER) | ||||
|   #include "../feature/e_parser.h" | ||||
| #endif | ||||
| @@ -1529,11 +1533,13 @@ void Temperature::updateTemperaturesFromRawValues() { | ||||
|   #if HAS_HOTEND | ||||
|     HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e); | ||||
|   #endif | ||||
|  | ||||
|   TERN_(HAS_HEATED_BED, temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw)); | ||||
|   TERN_(HAS_TEMP_CHAMBER, temp_chamber.celsius = analog_to_celsius_chamber(temp_chamber.raw)); | ||||
|   TERN_(HAS_TEMP_PROBE, temp_probe.celsius = analog_to_celsius_probe(temp_probe.raw)); | ||||
|   TERN_(TEMP_SENSOR_1_AS_REDUNDANT, redundant_temperature = analog_to_celsius_hotend(redundant_temperature_raw, 1)); | ||||
|   TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_measured_mm()); | ||||
|   TERN_(HAS_POWER_MONITOR, power_monitor.capture_values()); | ||||
|  | ||||
|   // Reset the watchdog on good temperature measurement | ||||
|   watchdog_refresh(); | ||||
| @@ -1740,6 +1746,12 @@ void Temperature::init() { | ||||
|   #if HAS_ADC_BUTTONS | ||||
|     HAL_ANALOG_SELECT(ADC_KEYPAD_PIN); | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|     HAL_ANALOG_SELECT(POWER_MONITOR_CURRENT_PIN); | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|     HAL_ANALOG_SELECT(POWER_MONITOR_VOLTAGE_PIN); | ||||
|   #endif | ||||
|  | ||||
|   HAL_timer_start(TEMP_TIMER_NUM, TEMP_TIMER_FREQUENCY); | ||||
|   ENABLE_TEMPERATURE_INTERRUPT(); | ||||
| @@ -2760,13 +2772,31 @@ void Temperature::tick() { | ||||
|     #if ENABLED(FILAMENT_WIDTH_SENSOR) | ||||
|       case Prepare_FILWIDTH: HAL_START_ADC(FILWIDTH_PIN); break; | ||||
|       case Measure_FILWIDTH: | ||||
|         if (!HAL_ADC_READY()) | ||||
|           next_sensor_state = adc_sensor_state; // redo this state | ||||
|         else | ||||
|           filwidth.accumulate(HAL_READ_ADC()); | ||||
|         if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; // Redo this state | ||||
|         else filwidth.accumulate(HAL_READ_ADC()); | ||||
|       break; | ||||
|     #endif | ||||
|  | ||||
|     #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|       case Prepare_POWER_MONITOR_CURRENT: | ||||
|         HAL_START_ADC(POWER_MONITOR_CURRENT_PIN); | ||||
|         break; | ||||
|       case Measure_POWER_MONITOR_CURRENT: | ||||
|         if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; // Redo this state | ||||
|         else power_monitor.add_current_sample(HAL_READ_ADC()); | ||||
|         break; | ||||
|     #endif | ||||
|  | ||||
|     #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|       case Prepare_POWER_MONITOR_VOLTAGE: | ||||
|         HAL_START_ADC(POWER_MONITOR_VOLTAGE_PIN); | ||||
|         break; | ||||
|       case Measure_POWER_MONITOR_VOLTAGE: | ||||
|         if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; // Redo this state | ||||
|         else power_monitor.add_voltage_sample(HAL_READ_ADC()); | ||||
|         break; | ||||
|     #endif | ||||
|  | ||||
|     #if HAS_JOY_ADC_X | ||||
|       case PrepareJoy_X: HAL_START_ADC(JOY_X_PIN); break; | ||||
|       case MeasureJoy_X: ACCUMULATE_ADC(joystick.x); break; | ||||
|   | ||||
| @@ -148,6 +148,14 @@ enum ADCSensorState : char { | ||||
|   #if ENABLED(FILAMENT_WIDTH_SENSOR) | ||||
|     Prepare_FILWIDTH, Measure_FILWIDTH, | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_CURRENT) | ||||
|     Prepare_POWER_MONITOR_CURRENT, | ||||
|     Measure_POWER_MONITOR_CURRENT, | ||||
|   #endif | ||||
|   #if ENABLED(POWER_MONITOR_VOLTAGE) | ||||
|     Prepare_POWER_MONITOR_VOLTAGE, | ||||
|     Measure_POWER_MONITOR_VOLTAGE, | ||||
|   #endif | ||||
|   #if HAS_ADC_BUTTONS | ||||
|     Prepare_ADC_KEY, Measure_ADC_KEY, | ||||
|   #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user