Power monitor and display (#17437)
This commit is contained in:
parent
c8e99d572c
commit
424569b4c4
32 changed files with 652 additions and 28 deletions
|
@ -2984,6 +2984,23 @@
|
||||||
//#define FILAMENT_LCD_DISPLAY
|
//#define FILAMENT_LCD_DISPLAY
|
||||||
#endif
|
#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
|
* CNC Coordinate Systems
|
||||||
*
|
*
|
||||||
|
|
|
@ -162,6 +162,7 @@ inline void HAL_adc_init() {
|
||||||
#define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
|
#define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define HAL_ADC_VREF 5.0
|
||||||
#define HAL_ADC_RESOLUTION 10
|
#define HAL_ADC_RESOLUTION 10
|
||||||
#define HAL_READ_ADC() ADC
|
#define HAL_READ_ADC() ADC
|
||||||
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
|
#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
|
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_ADC_RESOLUTION 10
|
||||||
|
#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch)
|
||||||
#define HAL_READ_ADC() HAL_adc_result
|
#define HAL_READ_ADC() HAL_adc_result
|
||||||
#define HAL_ADC_READY() true
|
#define HAL_ADC_READY() true
|
||||||
|
|
||||||
|
|
|
@ -112,8 +112,9 @@ void analogWrite(pin_t pin, int value);
|
||||||
|
|
||||||
void HAL_adc_init();
|
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_ADC_RESOLUTION 10
|
||||||
|
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
||||||
#define HAL_READ_ADC() HAL_adc_result
|
#define HAL_READ_ADC() HAL_adc_result
|
||||||
#define HAL_ADC_READY() true
|
#define HAL_ADC_READY() true
|
||||||
|
|
||||||
|
|
|
@ -86,9 +86,10 @@ int freeMemory();
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
// ADC
|
// ADC
|
||||||
|
#define HAL_ADC_VREF 5.0
|
||||||
|
#define HAL_ADC_RESOLUTION 10
|
||||||
#define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch)
|
#define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch)
|
||||||
#define HAL_START_ADC(ch) HAL_adc_start_conversion(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_READ_ADC() HAL_adc_get_result()
|
||||||
#define HAL_ADC_READY() true
|
#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
|
// 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)
|
// 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_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
|
#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();
|
void HAL_adc_init();
|
||||||
|
|
||||||
//#define HAL_ADC_FILTERED // Disable Marlin's oversampling. The HAL filters ADC values.
|
//#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_ADC_RESOLUTION 10 // ... 12
|
||||||
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
||||||
#define HAL_READ_ADC() HAL_adc_result
|
#define HAL_READ_ADC() HAL_adc_result
|
||||||
|
|
|
@ -199,8 +199,9 @@ static inline int freeMemory() {
|
||||||
|
|
||||||
inline void HAL_adc_init() {}
|
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_ADC_RESOLUTION 10
|
||||||
|
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
||||||
#define HAL_READ_ADC() HAL_adc_result
|
#define HAL_READ_ADC() HAL_adc_result
|
||||||
#define HAL_ADC_READY() true
|
#define HAL_ADC_READY() true
|
||||||
|
|
||||||
|
|
|
@ -139,9 +139,15 @@ const uint8_t adc_pins[] = {
|
||||||
#if HAS_JOY_ADC_Z
|
#if HAS_JOY_ADC_Z
|
||||||
JOY_Z_PIN,
|
JOY_Z_PIN,
|
||||||
#endif
|
#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
|
#if HAS_TEMP_ADC_0
|
||||||
TEMP_0,
|
TEMP_0,
|
||||||
#endif
|
#endif
|
||||||
|
@ -187,6 +193,12 @@ enum TEMP_PINS : char {
|
||||||
#if HAS_JOY_ADC_Z
|
#if HAS_JOY_ADC_Z
|
||||||
JOY_Z,
|
JOY_Z,
|
||||||
#endif
|
#endif
|
||||||
|
#if ENABLED(POWER_MONITOR_CURRENT)
|
||||||
|
POWERMON_CURRENT,
|
||||||
|
#endif
|
||||||
|
#if ENABLED(POWER_MONITOR_VOLTAGE)
|
||||||
|
POWERMON_VOLTS,
|
||||||
|
#endif
|
||||||
ADC_PIN_COUNT
|
ADC_PIN_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -323,7 +335,8 @@ void HAL_adc_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HAL_adc_start_conversion(const uint8_t adc_pin) {
|
void HAL_adc_start_conversion(const uint8_t adc_pin) {
|
||||||
TEMP_PINS pin_index;
|
//TEMP_PINS pin_index;
|
||||||
|
TempPinIndex pin_index;
|
||||||
switch (adc_pin) {
|
switch (adc_pin) {
|
||||||
default: return;
|
default: return;
|
||||||
#if HAS_TEMP_ADC_0
|
#if HAS_TEMP_ADC_0
|
||||||
|
@ -371,6 +384,12 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
|
||||||
#if ENABLED(ADC_KEYPAD)
|
#if ENABLED(ADC_KEYPAD)
|
||||||
case ADC_KEYPAD_PIN: pin_index = ADC_KEY; break;
|
case ADC_KEYPAD_PIN: pin_index = ADC_KEY; break;
|
||||||
#endif
|
#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.
|
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();
|
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_ADC_RESOLUTION 10
|
||||||
|
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
||||||
#define HAL_READ_ADC() HAL_adc_result
|
#define HAL_READ_ADC() HAL_adc_result
|
||||||
#define HAL_ADC_READY() true
|
#define HAL_ADC_READY() true
|
||||||
|
|
||||||
|
|
|
@ -219,8 +219,9 @@ static inline int freeMemory() {
|
||||||
|
|
||||||
inline void HAL_adc_init() {}
|
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_ADC_RESOLUTION 10
|
||||||
|
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
||||||
#define HAL_READ_ADC() HAL_adc_result
|
#define HAL_READ_ADC() HAL_adc_result
|
||||||
#define HAL_ADC_READY() true
|
#define HAL_ADC_READY() true
|
||||||
|
|
||||||
|
|
|
@ -107,8 +107,9 @@ extern "C" {
|
||||||
|
|
||||||
void HAL_adc_init();
|
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_ADC_RESOLUTION 10
|
||||||
|
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
||||||
#define HAL_READ_ADC() HAL_adc_get_result()
|
#define HAL_READ_ADC() HAL_adc_get_result()
|
||||||
#define HAL_ADC_READY() true
|
#define HAL_ADC_READY() true
|
||||||
|
|
||||||
|
|
|
@ -112,8 +112,9 @@ extern "C" {
|
||||||
|
|
||||||
void HAL_adc_init();
|
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_ADC_RESOLUTION 10
|
||||||
|
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
|
||||||
#define HAL_READ_ADC() HAL_adc_get_result()
|
#define HAL_READ_ADC() HAL_adc_get_result()
|
||||||
#define HAL_ADC_READY() true
|
#define HAL_ADC_READY() true
|
||||||
|
|
||||||
|
|
|
@ -97,10 +97,13 @@
|
||||||
#define CBI(A,B) (A &= ~(1 << (B)))
|
#define CBI(A,B) (A &= ~(1 << (B)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TBI(N,B) (N ^= _BV(B))
|
||||||
|
|
||||||
#define _BV32(b) (1UL << (b))
|
#define _BV32(b) (1UL << (b))
|
||||||
#define TEST32(n,b) !!((n)&_BV32(b))
|
#define TEST32(n,b) !!((n)&_BV32(b))
|
||||||
#define SBI32(n,b) (n |= _BV32(b))
|
#define SBI32(n,b) (n |= _BV32(b))
|
||||||
#define CBI32(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 cu(x) ({__typeof__(x) _x = (x); (_x)*(_x)*(_x);})
|
||||||
#define RADIANS(d) ((d)*float(M_PI)/180.0f)
|
#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
|
case 428: M428(); break; // M428: Apply current_position to home_offset
|
||||||
#endif
|
#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)
|
#if ENABLED(CANCEL_OBJECTS)
|
||||||
case 486: M486(); break; // M486: Identify and cancel objects
|
case 486: M486(); break; // M486: Identify and cancel objects
|
||||||
#endif
|
#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)
|
* 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)
|
* 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)
|
* 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)
|
* M486 - Identify and cancel objects. (Requires CANCEL_OBJECTS)
|
||||||
* M500 - Store parameters in EEPROM. (Requires EEPROM_SETTINGS)
|
* M500 - Store parameters in EEPROM. (Requires EEPROM_SETTINGS)
|
||||||
* M501 - Restore parameters from 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_M206_COMMAND, static void M428());
|
||||||
|
|
||||||
|
TERN_(HAS_POWER_MONITOR, static void M430());
|
||||||
|
|
||||||
TERN_(CANCEL_OBJECTS, static void M486());
|
TERN_(CANCEL_OBJECTS, static void M486());
|
||||||
|
|
||||||
static void M500();
|
static void M500();
|
||||||
|
|
|
@ -352,6 +352,17 @@
|
||||||
#define SD_CONNECTION_IS(...) 0
|
#define SD_CONNECTION_IS(...) 0
|
||||||
#endif
|
#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
|
// 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)
|
#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
|
#define NO_EEPROM_SELECTED 1
|
||||||
|
|
|
@ -30,6 +30,13 @@
|
||||||
// Extras for CI testing
|
// Extras for CI testing
|
||||||
#endif
|
#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
|
// Linear advance uses Jerk since E is an isolated axis
|
||||||
#if BOTH(HAS_JUNCTION_DEVIATION, LIN_ADVANCE)
|
#if BOTH(HAS_JUNCTION_DEVIATION, LIN_ADVANCE)
|
||||||
#define HAS_LINEAR_E_JERK 1
|
#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
|
||||||
#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
|
* Volumetric Extruder Limit
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -48,6 +48,10 @@
|
||||||
#include "../../feature/spindle_laser.h"
|
#include "../../feature/spindle_laser.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAS_POWER_MONITOR
|
||||||
|
#include "../../feature/power_monitor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
#include "../../sd/cardreader.h"
|
#include "../../sd/cardreader.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -103,6 +107,59 @@
|
||||||
#define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1)
|
#define STATUS_HEATERS_BOT (STATUS_HEATERS_Y + STATUS_HEATERS_HEIGHT - 1)
|
||||||
#endif
|
#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_X 54
|
||||||
#define PROGRESS_BAR_Y (EXTRAS_BASELINE + 1)
|
#define PROGRESS_BAR_Y (EXTRAS_BASELINE + 1)
|
||||||
#define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X)
|
#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) {
|
void MarlinUI::draw_status_message(const bool blink) {
|
||||||
|
|
||||||
// Get the UTF8 character count of the string
|
// 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)
|
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||||
|
|
||||||
static bool last_blink = false;
|
static bool last_blink = false;
|
||||||
|
|
||||||
if (slen <= LCD_WIDTH) {
|
if (slen <= lcd_width) {
|
||||||
// The string fits within the line. Print with no scrolling
|
// The string fits within the line. Print with no scrolling
|
||||||
lcd_put_u8str(status_message);
|
lcd_put_u8str(status_message);
|
||||||
while (slen < LCD_WIDTH) { lcd_put_wchar(' '); ++slen; }
|
while (slen < lcd_width) { lcd_put_wchar(' '); ++slen; }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// String is longer than the available space
|
// String is longer than the available space
|
||||||
|
@ -805,20 +871,21 @@ void MarlinUI::draw_status_message(const bool blink) {
|
||||||
// and the string remaining length
|
// and the string remaining length
|
||||||
uint8_t rlen;
|
uint8_t rlen;
|
||||||
const char *stat = status_and_len(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 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
|
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
|
if (--chars) { // Draw a second dot if there's space
|
||||||
lcd_put_wchar('.');
|
lcd_put_wchar('.');
|
||||||
if (--chars) { // Print a second copy of the message
|
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(' ');
|
lcd_put_wchar(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_blink != blink) {
|
if (last_blink != blink) {
|
||||||
last_blink = blink;
|
last_blink = blink;
|
||||||
advance_status_scroll();
|
advance_status_scroll();
|
||||||
|
@ -830,12 +897,16 @@ void MarlinUI::draw_status_message(const bool blink) {
|
||||||
UNUSED(blink);
|
UNUSED(blink);
|
||||||
|
|
||||||
// Just print the string to the LCD
|
// 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
|
// 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
|
#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
|
#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_INFO_SCREEN = _UxGT("Info Screen");
|
||||||
PROGMEM Language_Str MSG_PREPARE = _UxGT("Prepare");
|
PROGMEM Language_Str MSG_PREPARE = _UxGT("Prepare");
|
||||||
PROGMEM Language_Str MSG_TUNE = _UxGT("Tune");
|
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_START_PRINT = _UxGT("Start Print");
|
||||||
PROGMEM Language_Str MSG_BUTTON_NEXT = _UxGT("Next");
|
PROGMEM Language_Str MSG_BUTTON_NEXT = _UxGT("Next");
|
||||||
PROGMEM Language_Str MSG_BUTTON_INIT = _UxGT("Init");
|
PROGMEM Language_Str MSG_BUTTON_INIT = _UxGT("Init");
|
||||||
|
|
|
@ -59,6 +59,14 @@ void menu_configuration();
|
||||||
void menu_user();
|
void menu_user();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAS_POWER_MONITOR
|
||||||
|
void menu_power_monitor();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
void menu_mixer();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(ADVANCED_PAUSE_FEATURE)
|
#if ENABLED(ADVANCED_PAUSE_FEATURE)
|
||||||
void _menu_temp_filament_op(const PauseMode, const int8_t);
|
void _menu_temp_filament_op(const PauseMode, const int8_t);
|
||||||
void menu_change_filament();
|
void menu_change_filament();
|
||||||
|
@ -76,10 +84,6 @@ void menu_configuration();
|
||||||
void menu_spindle_laser();
|
void menu_spindle_laser();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(MIXING_EXTRUDER)
|
|
||||||
void menu_mixer();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const char M21_STR[];
|
extern const char M21_STR[];
|
||||||
|
|
||||||
void menu_main() {
|
void menu_main() {
|
||||||
|
@ -155,6 +159,10 @@ void menu_main() {
|
||||||
|
|
||||||
SUBMENU(MSG_TEMPERATURE, menu_temperature);
|
SUBMENU(MSG_TEMPERATURE, menu_temperature);
|
||||||
|
|
||||||
|
#if HAS_POWER_MONITOR
|
||||||
|
MENU_ITEM(submenu, MSG_POWER_MONITOR, menu_power_monitor);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(MIXING_EXTRUDER)
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
SUBMENU(MSG_MIXER, menu_mixer);
|
SUBMENU(MSG_MIXER, menu_mixer);
|
||||||
#endif
|
#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"
|
#include "../module/thermistor/thermistors.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAS_POWER_MONITOR
|
||||||
|
#include "../feature/power_monitor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HAS_ENCODER_ACTION
|
#if HAS_ENCODER_ACTION
|
||||||
volatile uint8_t MarlinUI::buttons;
|
volatile uint8_t MarlinUI::buttons;
|
||||||
#if HAS_SLOW_BUTTONS
|
#if HAS_SLOW_BUTTONS
|
||||||
|
@ -533,7 +537,6 @@ void MarlinUI::status_screen() {
|
||||||
#endif // LCD_PROGRESS_BAR
|
#endif // LCD_PROGRESS_BAR
|
||||||
|
|
||||||
#if HAS_LCD_MENU
|
#if HAS_LCD_MENU
|
||||||
|
|
||||||
if (use_click()) {
|
if (use_click()) {
|
||||||
#if BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT)
|
#if BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT)
|
||||||
next_filament_display = millis() + 5000UL; // Show status message for 5s
|
next_filament_display = millis() + 5000UL; // Show status message for 5s
|
||||||
|
|
|
@ -174,6 +174,27 @@ const char* ftostr12ns(const float &f) {
|
||||||
return &conv[3];
|
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
|
// 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) {
|
const char* ftostr42_52(const float &f) {
|
||||||
if (f <= -10 || f >= 100) return ftostr52(f); // -23.45 / 123.45
|
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
|
// Convert unsigned float to string with 1.23 format
|
||||||
const char* ftostr12ns(const float &x);
|
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
|
// 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);
|
const char* ftostr42_52(const float &x);
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,10 @@
|
||||||
#include "../feature/powerloss.h"
|
#include "../feature/powerloss.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(POWER_MONITOR)
|
||||||
|
#include "../feature/power_monitor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../feature/pause.h"
|
#include "../feature/pause.h"
|
||||||
|
|
||||||
#if ENABLED(BACKLASH_COMPENSATION)
|
#if ENABLED(BACKLASH_COMPENSATION)
|
||||||
|
@ -301,6 +305,11 @@ typedef struct SettingsDataStruct {
|
||||||
user_thermistor_t user_thermistor[USER_THERMISTORS]; // M305 P0 R4700 T100000 B3950
|
user_thermistor_t user_thermistor[USER_THERMISTORS]; // M305 P0 R4700 T100000 B3950
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Power monitor
|
||||||
|
//
|
||||||
|
uint8_t power_monitor_flags; // M430 I V W
|
||||||
|
|
||||||
//
|
//
|
||||||
// HAS_LCD_CONTRAST
|
// HAS_LCD_CONTRAST
|
||||||
//
|
//
|
||||||
|
@ -881,6 +890,19 @@ void MarlinSettings::postprocess() {
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
// LCD Contrast
|
||||||
//
|
//
|
||||||
|
@ -1745,6 +1767,19 @@ void MarlinSettings::postprocess() {
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
// LCD Contrast
|
||||||
//
|
//
|
||||||
|
@ -2604,6 +2639,11 @@ void MarlinSettings::reset() {
|
||||||
//
|
//
|
||||||
TERN_(HAS_USER_THERMISTORS, thermalManager.reset_user_thermistors());
|
TERN_(HAS_USER_THERMISTORS, thermalManager.reset_user_thermistors());
|
||||||
|
|
||||||
|
//
|
||||||
|
// Power Monitor
|
||||||
|
//
|
||||||
|
TERN_(POWER_MONITOR, power_monitor.reset());
|
||||||
|
|
||||||
//
|
//
|
||||||
// LCD Contrast
|
// LCD Contrast
|
||||||
//
|
//
|
||||||
|
|
|
@ -84,6 +84,10 @@
|
||||||
#include "../feature/filwidth.h"
|
#include "../feature/filwidth.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAS_POWER_MONITOR
|
||||||
|
#include "../feature/power_monitor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(EMERGENCY_PARSER)
|
#if ENABLED(EMERGENCY_PARSER)
|
||||||
#include "../feature/e_parser.h"
|
#include "../feature/e_parser.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1529,11 +1533,13 @@ void Temperature::updateTemperaturesFromRawValues() {
|
||||||
#if HAS_HOTEND
|
#if HAS_HOTEND
|
||||||
HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e);
|
HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TERN_(HAS_HEATED_BED, temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw));
|
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_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_(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_(TEMP_SENSOR_1_AS_REDUNDANT, redundant_temperature = analog_to_celsius_hotend(redundant_temperature_raw, 1));
|
||||||
TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_measured_mm());
|
TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_measured_mm());
|
||||||
|
TERN_(HAS_POWER_MONITOR, power_monitor.capture_values());
|
||||||
|
|
||||||
// Reset the watchdog on good temperature measurement
|
// Reset the watchdog on good temperature measurement
|
||||||
watchdog_refresh();
|
watchdog_refresh();
|
||||||
|
@ -1740,6 +1746,12 @@ void Temperature::init() {
|
||||||
#if HAS_ADC_BUTTONS
|
#if HAS_ADC_BUTTONS
|
||||||
HAL_ANALOG_SELECT(ADC_KEYPAD_PIN);
|
HAL_ANALOG_SELECT(ADC_KEYPAD_PIN);
|
||||||
#endif
|
#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);
|
HAL_timer_start(TEMP_TIMER_NUM, TEMP_TIMER_FREQUENCY);
|
||||||
ENABLE_TEMPERATURE_INTERRUPT();
|
ENABLE_TEMPERATURE_INTERRUPT();
|
||||||
|
@ -2760,10 +2772,28 @@ void Temperature::tick() {
|
||||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||||
case Prepare_FILWIDTH: HAL_START_ADC(FILWIDTH_PIN); break;
|
case Prepare_FILWIDTH: HAL_START_ADC(FILWIDTH_PIN); break;
|
||||||
case Measure_FILWIDTH:
|
case Measure_FILWIDTH:
|
||||||
if (!HAL_ADC_READY())
|
if (!HAL_ADC_READY()) next_sensor_state = adc_sensor_state; // Redo this state
|
||||||
next_sensor_state = adc_sensor_state; // redo this state
|
else filwidth.accumulate(HAL_READ_ADC());
|
||||||
else
|
break;
|
||||||
filwidth.accumulate(HAL_READ_ADC());
|
#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;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,14 @@ enum ADCSensorState : char {
|
||||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||||
Prepare_FILWIDTH, Measure_FILWIDTH,
|
Prepare_FILWIDTH, Measure_FILWIDTH,
|
||||||
#endif
|
#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
|
#if HAS_ADC_BUTTONS
|
||||||
Prepare_ADC_KEY, Measure_ADC_KEY,
|
Prepare_ADC_KEY, Measure_ADC_KEY,
|
||||||
#endif
|
#endif
|
||||||
|
|
Reference in a new issue