Pin* as_pin(){
Pin* pin = new Pin();
- pin->from_string(this->value);
+ pin->from_string(this->as_string());
return pin;
}
#include "libs/nuts_bolts.h"
#include "libs/SlowTicker.h"
#include "libs/Adc.h"
+#include "libs/Pauser.h"
#include "modules/communication/SerialConsole.h"
#include "modules/communication/GcodeDispatch.h"
NVIC_SetPriority(TIMER2_IRQn, 2);
// Core modules
- this->gcode_dispatch = new GcodeDispatch();
- this->robot = new Robot();
- this->stepper = new Stepper();
- this->planner = new Planner();
- this->player = new Player();
-
- this->add_module( this->gcode_dispatch );
- this->add_module( this->robot );
- this->add_module( this->stepper );
- this->add_module( this->planner );
- this->add_module( this->player );
-
+ this->add_module( this->gcode_dispatch = new GcodeDispatch() );
+ this->add_module( this->robot = new Robot() );
+ this->add_module( this->stepper = new Stepper() );
+ this->add_module( this->planner = new Planner() );
+ this->add_module( this->player = new Player() );
+ this->add_module( this->pauser = new Pauser() );
}
void Kernel::add_module(Module* module){
#include "libs/SlowTicker.h"
#include "libs/StepTicker.h"
#include "libs/Adc.h"
+#include "libs/Pauser.h"
#include "modules/communication/SerialConsole.h"
#include "modules/communication/GcodeDispatch.h"
#include "modules/robot/Planner.h"
Planner* planner;
Config* config;
Player* player;
+ Pauser* pauser;
int debug;
SlowTicker* slow_ticker;
return this;
}
+ inline Pin* as_input(){
+ this->port->FIODIR &= ~(1<<this->pin);
+ return this;
+ }
+
+ inline bool get(){
+ if( this->inverting ){
+ return ~(( this->port->FIOPIN >> this->pin ) & 1);
+ }else{
+ return (( this->port->FIOPIN >> this->pin ) & 1);
+ }
+ }
+
inline void set(bool value){
+ // TODO : This should be bitmath
if( this->inverting ){ value = !value; }
if( value ){
this->port->FIOSET = 1 << this->pin;
#include "modules/tools/temperaturecontrol/TemperatureControlPool.h"
#include "modules/robot/Player.h"
#include "modules/utils/simpleshell/SimpleShell.h"
-#include "modules/utils/pauser/Pauser.h"
+#include "modules/utils/pausebutton/PauseButton.h"
#include "libs/ChaNFSSD/SDFileSystem.h"
#include "libs/Config.h"
#include "libs/nuts_bolts.h"
kernel->add_module( new Extruder(p26,p27) );
kernel->add_module( new SimpleShell() );
kernel->add_module( new TemperatureControlPool() );
-
+ kernel->add_module( new PauseButton() );
+
kernel->add_module( &cdcmsc );
- wait(0.1);
- Pin* pin = new Pin();
- kernel->adc->enable_pin(pin->from_string("0.23"));
- wait(0.1);
- kernel->serial->printf("value: %u \r\n", kernel->adc->read(pin));
-
while(1){
kernel->call_event(ON_MAIN_LOOP);
}
// Gcodes are attached to their respective blocks so that on_gcode_execute can be called with it
void Block::append_gcode(Gcode* gcode){
- //this->commands.push_back(gcode->command);
- //this->travel_distances.push_back(gcode->millimeters_of_travel);
__disable_irq();
this->gcodes.push_back(*gcode);
__enable_irq();
// The attached gcodes are then poped and the on_gcode_execute event is called with them as a parameter
void Block::pop_and_execute_gcode(Kernel* &kernel){
Block* block = const_cast<Block*>(this);
- //for(unsigned short index=0; index<block->commands.size(); index++){
- // Gcode gcode = Gcode();
- // gcode.command = block->commands.at(index);
- // gcode.millimeters_of_travel = block->travel_distances.at(index);
- // kernel->call_event(ON_GCODE_EXECUTE, &gcode );
- //}
for(unsigned short index=0; index<block->gcodes.size(); index++){
- //this->player->kernel->serial->printf("exec: block:%p gcode:%p command:%p \r\n", block, &(block->gcodes[index]), &(block->gcodes[index].command) );
- //this->player->kernel->serial->printf(" str:%s \r\n", block->gcodes[index].command.c_str() );
- //wait(0.1);
kernel->call_event(ON_GCODE_EXECUTE, &(block->gcodes[index]));
}
}
this->pop_and_execute_gcode(this->player->kernel);
Player* player = this->player;
- //this->player->kernel->serial->printf("a %d\r\n", this->player->queue.size() );
if( player->queue.size() > 0 ){
player->queue.delete_first();
}
- //this->player->kernel->serial->printf("b %d %d\r\n", this->player->queue.size(), player->looking_for_new_block );
-
if( player->looking_for_new_block == false ){
- //player->pop_and_process_new_block(123);
if( player->queue.size() > 0 ){
Block* candidate = player->queue.get_ref(0);
if( candidate->is_ready ){
- //candidate->debug(player->kernel);
- //this->player->kernel->serial->printf("c %d %d\r\n", this->player->queue.size(), player->looking_for_new_block );
player->current_block = candidate;
player->kernel->call_event(ON_BLOCK_BEGIN, player->current_block);
if( player->current_block->times_taken < 1 ){
}
}else{
- //player->current_block->debug(player->kernel);
- //this->player->kernel->serial->printf("d %d %d\r\n", this->player->queue.size(), player->looking_for_new_block );
- //wait(0.1);
player->current_block = NULL;
}
}
this->current_block = NULL;
this->step_events_completed = 0;
this->divider = 0;
+ this->paused = false;
}
//Called when the module has just been loaded
// When the play/pause button is set to pause, or a module calls the ON_PAUSE event
void Stepper::on_pause(void* argument){
- //TODO: reImplement pause here
+ this->paused = true;
}
// When the play/pause button is set to play, or a module calls the ON_PLAY event
void Stepper::on_play(void* argument){
- //TODO: reImplement pause here
+ // TODO: Re-compute the whole queue for a cold-start
+ this->paused = false;
}
// A new block is popped from the queue
// Mark the new block as of interrest to us
block->take();
- if( block->final_rate < 0.1 ){
- //block->debug(this->kernel);
- }
-
// Setup
for( int stpr=ALPHA_STEPPER; stpr<=GAMMA_STEPPER; stpr++){ this->counters[stpr] = 0; this->stepped[stpr] = 0; }
this->step_events_completed = 0;
// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse of Smoothie. It is executed at the rate set with
// config_step_timer. It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
inline void Stepper::main_interrupt(){
-
+ if( this->paused ){ return; }
+
// Step dir pins first, then step pinse, stepper drivers like to know the direction before the step signal comes in
this->alpha_dir_pin->set( ( this->out_bits >> 0 ) & 1 );
this->beta_dir_pin->set( ( this->out_bits >> 1 ) & 1 );
// interrupt. It can be assumed that the trapezoid-generator-parameters and the
// current_block stays untouched by outside handlers for the duration of this function call.
void Stepper::trapezoid_generator_tick() {
- if(this->current_block && !this->trapezoid_generator_busy ) {
+ if(this->current_block && !this->trapezoid_generator_busy && !this->paused ) {
if(this->step_events_completed < this->current_block->accelerate_until<<16) {
this->trapezoid_adjusted_rate += this->current_block->rate_delta;
if (this->trapezoid_adjusted_rate > this->current_block->nominal_rate ) {
Pin* gamma_dir_pin;
unsigned short step_bits[3];
int counter_increment;
+ bool paused;
};
this->acceleration_lock = false;
this->step_counter = 0;
this->counter_increment = 0;
+ this->paused = false;
}
void Extruder::on_module_loaded() {
this->register_for_event(ON_BLOCK_BEGIN);
this->register_for_event(ON_BLOCK_END);
this->register_for_event(ON_GCODE_EXECUTE);
-
+ this->register_for_event(ON_PLAY);
+ this->register_for_event(ON_PAUSE);
+
// Start values
this->start_position = 0;
this->target_position = 0;
this->acceleration = this->kernel->config->value(acceleration_checksum )->by_default(1)->as_number();
}
+
+// When the play/pause button is set to pause, or a module calls the ON_PAUSE event
+void Extruder::on_pause(void* argument){
+ this->paused = true;
+}
+
+// When the play/pause button is set to play, or a module calls the ON_PLAY event
+void Extruder::on_play(void* argument){
+ this->paused = false;
+}
+
+
+
// Compute extrusion speed based on parameters and gcode distance of travel
void Extruder::on_gcode_execute(void* argument){
Gcode* gcode = static_cast<Gcode*>(argument);
void Extruder::acceleration_tick(){
// Avoid trying to work when we really shouldn't ( between blocks or re-entry )
- if( this->current_block == NULL || this->acceleration_lock ){ return; }
+ if( this->current_block == NULL || this->acceleration_lock || this->paused ){ return; }
this->acceleration_lock = true;
// In solo mode, we mode independently from the robot
}
inline void Extruder::stepping_tick(){
+ if( this->paused ){ return; }
this->step_counter += this->counter_increment;
if( this->step_counter > 1<<16 ){
void on_gcode_execute(void* argument);
void on_block_begin(void* argument);
void on_block_end(void* argument);
+ void on_play(void* argument);
+ void on_pause(void* argument);
void set_speed(int steps_per_second);
void acceleration_tick();
void stepping_tick();
char mode;
bool acceleration_lock;
+
+ bool paused;
};
#endif
void TemperatureControl::on_module_loaded(){
- // We start now desiring any temp
+ // We start not desiring any temp
this->desired_adc_value = UNDEFINED;
// Settings
void TemperatureControl::on_gcode_execute(void* argument){
Gcode* gcode = static_cast<Gcode*>(argument);
- // Set temperature
+ // Set temperature without waiting
if( gcode->has_letter('M') && gcode->get_value('M') == 104 && gcode->has_letter('S') ){
this->set_desired_temperature(gcode->get_value('S'));
}
+ // Set temperature and wait
+ if( gcode->has_letter('M') && gcode->get_value('M') == 109 && gcode->has_letter('S') ){
+ this->set_desired_temperature(gcode->get_value('S'));
+
+ // Pause
+ this->kernel->pauser->take();
+ this->waiting = true;
+
+ }
+
// Get temperature
if( gcode->has_letter('M') && gcode->get_value('M') == 105 ){
gcode->stream->printf("get temperature: %f current:%f target:%f \r\n", this->get_temperature(), this->new_thermistor_reading(), this->desired_adc_value );
this->heater_pin->set(1);
}else{
this->heater_pin->set(0);
+ if( this->waiting ){
+ this->kernel->pauser->release();
+ this->waiting = false;
+ }
}
}
}
Pin* thermistor_pin;
Pin* heater_pin;
+
+ bool waiting;
};
--- /dev/null
+#include "mbed.h"
+#include "libs/Kernel.h"
+#include "PauseButton.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include <string>
+using namespace std;
+
+PauseButton::PauseButton(){}
+
+void PauseButton::on_module_loaded(){
+ this->button_state = true;
+ this->play_state = true;
+ this->register_for_event(ON_PLAY);
+ this->register_for_event(ON_PAUSE);
+
+ this->button = this->kernel->config->value( pause_button_pin_checksum )->by_default("0.0")->as_pin()->as_input();
+ this->led = this->kernel->config->value( pause_led_pin_checksum )->by_default("0.1")->as_pin()->as_output();
+
+ this->kernel->slow_ticker->attach( 100, this, &PauseButton::button_tick );
+}
+
+//TODO: Make this use InterruptIn
+//Check the state of the button and act accordingly
+void PauseButton::button_tick(){
+ // If button changed
+ if(this->button_state != this->button->get()){
+ this->button_state = this->button->get();
+ // If button pressed
+ if( this->button_state ){
+ if( this->play_state ){
+ this->play_state = false;
+ this->kernel->pauser->take();
+ }else{
+ this->play_state = true;
+ this->kernel->pauser->release();
+ }
+ }
+ }
+}
+
+void PauseButton::on_play( void* argument ){
+ this->led->set(0);
+}
+
+void PauseButton::on_pause( void* argument ){
+ this->led->set(1);
+}
+
-#ifndef pauser_h
-#define pauser_h
+#ifndef PAUSEBUTTON_H
+#define PAUSEBUTTON_H
#include "mbed.h"
#include "libs/Kernel.h"
#include "libs/nuts_bolts.h"
#include "libs/utils.h"
+#include "libs/Pin.h"
+#define pause_button_pin_checksum 32709
+#define pause_led_pin_checksum 48477
-class Pauser : public Module {
+class PauseButton : public Module {
public:
- Pauser(PinName ButtonPin, PinName LedPin);
+ PauseButton();
void on_module_loaded();
void button_tick();
void on_play( void* argument );
void on_pause( void* argument );
- DigitalIn button;
- DigitalOut led;
- Ticker button_ticker;
+ Pin* button;
+ Pin* led;
bool button_state;
bool play_state;
};
+++ /dev/null
-#include "mbed.h"
-#include "libs/Kernel.h"
-#include "Pauser.h"
-#include "libs/nuts_bolts.h"
-#include "libs/utils.h"
-
-Pauser::Pauser(PinName ButtonPin, PinName LedPin) : button(ButtonPin), led(LedPin) {}
-
-void Pauser::on_module_loaded(){
- this->button_state = false;
- this->led = false;
- this->play_state = true;
- this->register_for_event(ON_PLAY);
- this->register_for_event(ON_PAUSE);
- this->button_ticker.attach_us(this, &Pauser::button_tick, 1000000/100);
-}
-
-//TODO: Make this use InterruptIn
-//Check the state of the button and ask accordingly
-void Pauser::button_tick(){
- if(this->button_state != this->button){
- this->button_state = this->button;
- if( this->button_state ){
- if( this->play_state ){
- this->play_state = false;
- this->kernel->call_event(ON_PAUSE, this);
- }else{
- this->play_state = true;
- this->kernel->call_event(ON_PLAY, this);
- }
- }
- }
-}
-
-void Pauser::on_play( void* argument ){
- this->play_state = true;
- this->led = false;
-}
-
-void Pauser::on_pause( void* argument ){
- this->play_state = false;
- this->led = true;
-}
-