2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie 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.
4 Smoothie 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.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
9 TemperatureSwitch is an optional module that will automatically turn on or off a switch
10 based on a setpoint temperature. It is commonly used to turn on/off a cooling fan or water pump
11 to cool the hot end's cold zone. Specifically, it turns one of the small MOSFETs on or off.
13 Author: Michael Hackney, mhackney@eclecticangler.com
16 #include "TemperatureSwitch.h"
17 #include "libs/Module.h"
18 #include "libs/Kernel.h"
19 #include "modules/tools/temperaturecontrol/TemperatureControlPublicAccess.h"
20 #include "SwitchPublicAccess.h"
25 #include "ConfigValue.h"
26 #include "checksumm.h"
27 #include "PublicData.h"
28 #include "StreamOutputPool.h"
30 #define temperatureswitch_checksum CHECKSUM("temperatureswitch")
31 #define enable_checksum CHECKSUM("enable")
32 #define temperatureswitch_hotend_checksum CHECKSUM("hotend")
33 #define temperatureswitch_threshold_temp_checksum CHECKSUM("threshold_temp")
34 #define temperatureswitch_type_checksum CHECKSUM("type")
35 #define temperatureswitch_switch_checksum CHECKSUM("switch")
36 #define temperatureswitch_heatup_poll_checksum CHECKSUM("heatup_poll")
37 #define temperatureswitch_cooldown_poll_checksum CHECKSUM("cooldown_poll")
38 #define designator_checksum CHECKSUM("designator")
40 TemperatureSwitch::TemperatureSwitch()
42 this->temperatureswitch_state
= false;
43 this->second_counter
= 0;
47 void TemperatureSwitch::on_module_loaded()
49 vector
<uint16_t> modulist
;
50 // allow for multiple temperature switches
51 THEKERNEL
->config
->get_module_list(&modulist
, temperatureswitch_checksum
);
52 for (auto m
: modulist
) {
56 // no longer need this instance as it is just used to load the other instances
61 bool TemperatureSwitch::load_config(uint16_t modcs
)
64 if (!THEKERNEL
->config
->value(temperatureswitch_checksum
, modcs
, enable_checksum
)->by_default(false)->as_bool()) {
68 // create a temperature control and load settings
71 string s
= THEKERNEL
->config
->value(temperatureswitch_checksum
, modcs
, designator_checksum
)->by_default("")->as_string();
73 // for backward compatibility temperatureswitch.hotend will need designator 'T' by default @DEPRECATED
74 if(modcs
== temperatureswitch_hotend_checksum
) designator
= 'T';
80 if(designator
== 0) return false; // no designator then not valid
82 // create a new temperature switch module
83 TemperatureSwitch
*ts
= new TemperatureSwitch();
85 // get the list of temperature controllers and remove any that don't have designator == specified designator
86 vector
<uint16_t> tempcontrollers
;
87 THEKERNEL
->config
->get_module_list(&tempcontrollers
, temperature_control_checksum
);
89 // see what its designator is and add to list of it the one we specified
91 for (auto controller
: tempcontrollers
) {
92 bool temp_ok
= PublicData::get_value(temperature_control_checksum
, controller
, current_temperature_checksum
, &returned_temp
);
94 struct pad_temperature temp
= *static_cast<struct pad_temperature
*>(returned_temp
);
95 if (temp
.designator
[0] == designator
) {
96 ts
->temp_controllers
.push_back(controller
);
101 // if we don't have any matching controllers, then not valid
102 if (ts
->temp_controllers
.empty()) {
107 // load settings from config file
108 s
= THEKERNEL
->config
->value(temperatureswitch_checksum
, modcs
, temperatureswitch_switch_checksum
)->by_default("")->as_string();
110 // handle old configs where this was called type @DEPRECATED
111 s
= THEKERNEL
->config
->value(temperatureswitch_checksum
, modcs
, temperatureswitch_type_checksum
)->by_default("")->as_string();
113 // no switch specified so invalid entry
118 ts
->temperatureswitch_switch_cs
= get_checksum(s
); // checksum of the switch to use
120 ts
->temperatureswitch_threshold_temp
= THEKERNEL
->config
->value(temperatureswitch_checksum
, modcs
, temperatureswitch_threshold_temp_checksum
)->by_default(50.0f
)->as_number();
122 // these are to tune the heatup and cooldown polling frequencies
123 ts
->temperatureswitch_heatup_poll
= THEKERNEL
->config
->value(temperatureswitch_checksum
, modcs
, temperatureswitch_heatup_poll_checksum
)->by_default(15)->as_number();
124 ts
->temperatureswitch_cooldown_poll
= THEKERNEL
->config
->value(temperatureswitch_checksum
, modcs
, temperatureswitch_cooldown_poll_checksum
)->by_default(60)->as_number();
125 ts
->current_delay
= ts
->temperatureswitch_heatup_poll
;
127 // Register for events
128 ts
->register_for_event(ON_SECOND_TICK
);
133 // Called once a second but we only need to service on the cooldown and heatup poll intervals
134 void TemperatureSwitch::on_second_tick(void *argument
)
137 if (second_counter
< current_delay
) {
141 float current_temp
= this->get_highest_temperature();
143 if (current_temp
>= this->temperatureswitch_threshold_temp
) {
144 // temp >= threshold temp, turn the cooler switch on if it isn't already
145 if (!temperatureswitch_state
) {
147 current_delay
= temperatureswitch_cooldown_poll
;
150 // temp < threshold temp, turn the cooler switch off if it isn't already
151 if (temperatureswitch_state
) {
153 current_delay
= temperatureswitch_heatup_poll
;
159 // Get the highest temperature from the set of temperature controllers
160 float TemperatureSwitch::get_highest_temperature()
163 float high_temp
= 0.0;
165 for (auto controller
: temp_controllers
) {
166 bool temp_ok
= PublicData::get_value(temperature_control_checksum
, controller
, current_temperature_checksum
, &returned_temp
);
168 struct pad_temperature temp
= *static_cast<struct pad_temperature
*>(returned_temp
);
169 // check if this controller's temp is the highest and save it if so
170 if (temp
.current_temperature
> high_temp
) {
171 high_temp
= temp
.current_temperature
;
178 // Turn the switch on (true) or off (false)
179 void TemperatureSwitch::set_switch(bool switch_state
)
181 this->temperatureswitch_state
= switch_state
;
182 bool ok
= PublicData::set_value(switch_checksum
, this->temperatureswitch_switch_cs
, state_checksum
, &this->temperatureswitch_state
);
184 THEKERNEL
->streams
->printf("Failed changing switch state.\r\n");