2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl) with additions from Sungeun K. Jeon (https://github.com/chamnit/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/>.
10 #include "libs/Module.h"
11 #include "libs/Kernel.h"
14 #include "StepperMotor.h"
16 #include "checksumm.h"
17 #include "SlowTicker.h"
19 #include "ConfigValue.h"
22 #include "StepTicker.h"
26 #include "libs/nuts_bolts.h"
27 #include "libs/Hook.h"
31 // The stepper reacts to blocks that have XYZ movement to transform them into actual stepper motor moves
34 this->current_block
= NULL
;
37 //Called when the module has just been loaded
38 void Stepper::on_module_loaded()
40 this->register_for_event(ON_BLOCK_BEGIN
);
41 this->register_for_event(ON_BLOCK_END
);
42 this->register_for_event(ON_GCODE_RECEIVED
);
43 this->register_for_event(ON_HALT
);
46 this->on_config_reload(this);
48 // Attach to the end_of_move stepper event
49 THEKERNEL
->step_ticker
->finished_fnc
= std::bind( &Stepper::stepper_motor_finished_move
, this);
52 // Get configuration from the config file
53 void Stepper::on_config_reload(void *argument
)
55 // Steppers start off by default
56 this->turn_enable_pins_off();
59 void Stepper::on_halt(void *argument
)
61 if(argument
== nullptr) {
62 this->turn_enable_pins_off();
66 void Stepper::on_gcode_received(void *argument
)
68 Gcode
*gcode
= static_cast<Gcode
*>(argument
);
71 if( gcode
->m
== 17 ) {
72 this->turn_enable_pins_on();
74 }else if( (gcode
->m
== 84 || gcode
->m
== 18) && !gcode
->has_letter('E') ) {
75 THEKERNEL
->conveyor
->wait_for_empty_queue();
76 this->turn_enable_pins_off();
82 void Stepper::turn_enable_pins_on()
84 for (auto a
: THEKERNEL
->robot
->actuators
)
86 this->enable_pins_status
= true;
87 THEKERNEL
->call_event(ON_ENABLE
, (void*)1);
91 void Stepper::turn_enable_pins_off()
93 for (auto a
: THEKERNEL
->robot
->actuators
)
95 this->enable_pins_status
= false;
96 THEKERNEL
->call_event(ON_ENABLE
, nullptr);
99 // A new block is popped from the queue
100 void Stepper::on_block_begin(void *argument
)
102 Block
*block
= static_cast<Block
*>(argument
);
104 // Mark the new block as of interrest to us, handle blocks that have no axis moves properly (like Extrude blocks etc)
106 if (block
->millimeters
> 0.0F
) {
107 for (size_t s
= 0; !take
&& s
< THEKERNEL
->robot
->actuators
.size(); s
++) {
108 take
= block
->steps
[s
] > 0;
115 // We can't move with the enable pins off
116 if( this->enable_pins_status
== false ) {
117 this->turn_enable_pins_on();
120 this->current_block
= block
;
122 // setup stepticker to execute this block
123 THEKERNEL
->step_ticker
->add_job(block
);
126 // Current block is discarded
127 void Stepper::on_block_end(void *argument
)
129 this->current_block
= NULL
; //stfu !
132 // When all moves in a block have finished this is called by step ticker (in the pendsv ISR)
133 void Stepper::stepper_motor_finished_move()
135 // This block is finished, release it
136 if( this->current_block
!= NULL
) {
137 this->current_block
->release();