1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://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)))) + (POWER_MONITOR_CURRENT_OFFSET);
}
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_WIRED_LCD
#if HAS_MARLINUI_U8GLIB && DISABLED(LIGHTWEIGHT_UI)
FORCE_INLINE static bool display_enabled() { return flags != 0x00; }
#endif
#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_V); }
#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_P); }
#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;
|