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/>.
8 #include "libs/Module.h"
9 #include "libs/Kernel.h"
11 #include "AnalogSpindleControl.h"
13 #include "checksumm.h"
14 #include "ConfigValue.h"
15 #include "StreamOutputPool.h"
18 #define spindle_checksum CHECKSUM("spindle")
19 #define spindle_max_rpm_checksum CHECKSUM("max_rpm")
20 #define spindle_min_rpm_checksum CHECKSUM("min_rpm")
21 #define spindle_pwm_pin_checksum CHECKSUM("pwm_pin")
22 #define spindle_pwm_period_checksum CHECKSUM("pwm_period")
23 #define spindle_switch_on_pin_checksum CHECKSUM("switch_on_pin")
25 void AnalogSpindleControl::on_module_loaded()
30 min_rpm
= THEKERNEL
->config
->value(spindle_checksum
, spindle_min_rpm_checksum
)->by_default(100)->as_int();
31 max_rpm
= THEKERNEL
->config
->value(spindle_checksum
, spindle_max_rpm_checksum
)->by_default(5000)->as_int();
33 // Get the pin for hardware pwm
35 Pin
*smoothie_pin
= new Pin();
36 smoothie_pin
->from_string(THEKERNEL
->config
->value(spindle_checksum
, spindle_pwm_pin_checksum
)->by_default("nc")->as_string());
37 pwm_pin
= smoothie_pin
->as_output()->hardware_pwm();
38 output_inverted
= smoothie_pin
->is_inverting();
41 // If we got no hardware PWM pin, delete this module
44 THEKERNEL
->streams
->printf("Error: Spindle PWM pin must be P2.0-2.5 or other PWM pin\n");
50 int period
= THEKERNEL
->config
->value(spindle_checksum
, spindle_pwm_period_checksum
)->by_default(1000)->as_int();
51 pwm_pin
->period_us(period
);
52 // invert pwm signal if necessary
53 pwm_pin
->write(output_inverted
? 1 : 0);
55 // Get digital out pin for switching the VFD on and off (wired to a digital input on the VFD via an optocoupler)
56 std::string switch_on_pin
= THEKERNEL
->config
->value(spindle_checksum
, spindle_switch_on_pin_checksum
)->by_default("nc")->as_string();
58 if(switch_on_pin
.compare("nc") != 0) {
59 switch_on
= new Pin();
60 switch_on
->from_string(switch_on_pin
)->as_output()->set(false);
62 // register for events
63 register_for_event(ON_GCODE_RECEIVED
);
66 void AnalogSpindleControl::turn_on()
68 // set the output for switching the VFD on
76 void AnalogSpindleControl::turn_off()
78 // clear the output for switching the VFD on
80 switch_on
->set(false);
82 // set the PWM value to 0 to make sure it stops
88 void AnalogSpindleControl::set_speed(int rpm
)
90 // limit the requested RPM value
93 } else if (rpm
> max_rpm
) {
95 } else if (rpm
> 0 && rpm
< min_rpm
){
100 // calculate the duty cycle and update the PWM
101 update_pwm(1.0f
/ max_rpm
* target_rpm
);
106 void AnalogSpindleControl::report_speed()
108 // report the current RPM value, calculate the current PWM value and report it as well
109 THEKERNEL
->streams
->printf("Current RPM: %d Analog value: %5.3f\n",
110 target_rpm
, (1.0f
/ max_rpm
* target_rpm
));
115 void AnalogSpindleControl::update_pwm(float value
)
117 // set the requested PWM value, invert it if necessary
119 pwm_pin
->write(1.0f
- value
);
121 pwm_pin
->write(value
);