/** * 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 . * */ #pragma once #include "../inc/MarlinConfig.h" #define PM_SAMPLE_RANGE 1024 #define PM_K_VALUE 6 #define PM_K_SCALE 6 template 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; #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; #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 #if HAS_GRAPHICAL_LCD && 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;