removed useless blocking while loop from _getc(), removed unused send_break method...
[clinton/Smoothieware.git] / src / modules / tools / spindle / AnalogSpindleControl.cpp
1 /*
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/>.
6 */
7
8 #include "libs/Module.h"
9 #include "libs/Kernel.h"
10 #include "libs/Pin.h"
11 #include "AnalogSpindleControl.h"
12 #include "Config.h"
13 #include "checksumm.h"
14 #include "ConfigValue.h"
15 #include "StreamOutputPool.h"
16 #include "PwmOut.h"
17
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")
24
25 void AnalogSpindleControl::on_module_loaded()
26 {
27
28 spindle_on = false;
29 target_rpm = 0;
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();
32
33 // Get the pin for hardware pwm
34 {
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();
39 delete smoothie_pin;
40 }
41 // If we got no hardware PWM pin, delete this module
42 if (pwm_pin == NULL)
43 {
44 THEKERNEL->streams->printf("Error: Spindle PWM pin must be P2.0-2.5 or other PWM pin\n");
45 delete this;
46 return;
47 }
48
49 // set pwm frequency
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);
54
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();
57 switch_on = NULL;
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);
61 }
62 // register for events
63 register_for_event(ON_GCODE_RECEIVED);
64 }
65
66 void AnalogSpindleControl::turn_on()
67 {
68 // set the output for switching the VFD on
69 if(switch_on != NULL)
70 switch_on->set(true);
71 spindle_on = true;
72
73 }
74
75
76 void AnalogSpindleControl::turn_off()
77 {
78 // clear the output for switching the VFD on
79 if(switch_on != NULL)
80 switch_on->set(false);
81 spindle_on = false;
82 // set the PWM value to 0 to make sure it stops
83 update_pwm(0);
84
85 }
86
87
88 void AnalogSpindleControl::set_speed(int rpm)
89 {
90 // limit the requested RPM value
91 if(rpm < 0) {
92 target_rpm = 0;
93 } else if (rpm > max_rpm) {
94 target_rpm = max_rpm;
95 } else if (rpm > 0 && rpm < min_rpm){
96 target_rpm = min_rpm;
97 } else {
98 target_rpm = rpm;
99 }
100 // calculate the duty cycle and update the PWM
101 update_pwm(1.0f / max_rpm * target_rpm);
102
103 }
104
105
106 void AnalogSpindleControl::report_speed()
107 {
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));
111
112 }
113
114
115 void AnalogSpindleControl::update_pwm(float value)
116 {
117 // set the requested PWM value, invert it if necessary
118 if(output_inverted)
119 pwm_pin->write(1.0f - value);
120 else
121 pwm_pin->write(value);
122
123 }
124