break;
case 500: // M500 saves some volatile settings to config override file
- case 503: // M503 just prints the settings
+ case 503: { // M503 just prints the settings
gcode->stream->printf(";Steps per unit:\nM92 X%1.5f Y%1.5f Z%1.5f\n", actuators[0]->steps_per_mm, actuators[1]->steps_per_mm, actuators[2]->steps_per_mm);
gcode->stream->printf(";Acceleration mm/sec^2:\nM204 S%1.5f\n", THEKERNEL->planner->acceleration);
gcode->stream->printf(";X- Junction Deviation, S - Minimum Planner speed:\nM205 X%1.5f S%1.5f\n", THEKERNEL->planner->junction_deviation, THEKERNEL->planner->minimum_planner_speed);
gcode->stream->printf(";Max feedrates in mm/sec, XYZ cartesian, ABC actuator:\nM203 X%1.5f Y%1.5f Z%1.5f A%1.5f B%1.5f C%1.5f\n",
this->max_speeds[X_AXIS], this->max_speeds[Y_AXIS], this->max_speeds[Z_AXIS],
alpha_stepper_motor->max_rate, beta_stepper_motor->max_rate, gamma_stepper_motor->max_rate);
+
+ // get or save any arm solution specific optional values
+ BaseSolution::arm_options_t options;
+ if(arm_solution->get_optional(options) && !options.empty()) {
+ gcode->stream->printf(";Optional arm solution specific settings:\nM665");
+ for(auto& i : options) {
+ gcode->stream->printf(" %c%1.4f", i.first, i.second);
+ }
+ gcode->stream->printf("\n");
+ }
gcode->mark_as_taken();
break;
+ }
- case 665: // M665 set optional arm solution variables based on arm solution. NOTE these are not saved with M500
+ case 665: { // M665 set optional arm solution variables based on arm solution.
gcode->mark_as_taken();
- // the parameter args could be any letter except S so try each one
- for(char c='A';c<='Z';c++) {
- if(c == 'S') continue; // used for segments per second
- float v;
- bool supported= arm_solution->get_optional(c, &v); // retrieve current value if supported
-
- if(supported && gcode->has_letter(c)) { // set new value if supported
- v= gcode->get_value(c);
- arm_solution->set_optional(c, v);
- }
- if(supported) { // print all current values of supported options
- gcode->stream->printf("%c %8.3f ", c, v);
+ // the parameter args could be any letter except S so ask solution what options it supports
+ BaseSolution::arm_options_t options;
+ if(arm_solution->get_optional(options)) {
+ for(auto& i : options) {
+ // foreach optional value
+ char c= i.first;
+ if(gcode->has_letter(c)) { // set new value
+ i.second= gcode->get_value(c);
+ }
+ // print all current values of supported options
+ gcode->stream->printf("%c: %8.4f ", i.first, i.second);
gcode->add_nl = true;
}
+ // set the new options
+ arm_solution->set_optional(options);
}
- // set delta segments per second
+
+ // set delta segments per second, not saved by M500
if(gcode->has_letter('S')) {
this->delta_segments_per_second= gcode->get_value('S');
}
break;
+ }
}
}
#ifndef BASESOLUTION_H
#define BASESOLUTION_H
+#include <map>
class Config;
class BaseSolution {
virtual ~BaseSolution() {};
virtual void cartesian_to_actuator( float[], float[] ) = 0;
virtual void actuator_to_cartesian( float[], float[] ) = 0;
-
- virtual bool set_optional(char parameter, float value) { return false; };
- virtual bool get_optional(char parameter, float *value) { return false; };
+ typedef std::map<char, float> arm_options_t;
+ virtual bool set_optional(const arm_options_t& options) { return false; };
+ virtual bool get_optional(arm_options_t& options) { return false; };
};
#endif
cartesian_mm[2] = ROUND(cartesian[2], 4);
}
-bool JohannKosselSolution::set_optional(char parameter, float value) {
-
- switch(parameter) {
- case 'L': // sets arm_length
- arm_length= value;
- break;
- case 'R': // sets arm_radius
- arm_radius= value;
- break;
- default:
- return false;
+bool JohannKosselSolution::set_optional(const arm_options_t& options) {
+
+ arm_options_t::const_iterator i;
+
+ i= options.find('L');
+ if(i != options.end()) {
+ arm_length= i->second;
+
+ }
+ i= options.find('R');
+ if(i != options.end()) {
+ arm_radius= i->second;
}
init();
return true;
}
-bool JohannKosselSolution::get_optional(char parameter, float *value) {
- if(value == NULL) return false;
-
- switch(parameter) {
- case 'L': // get arm_length
- *value= this->arm_length;
- break;
- case 'R': // get arm_radius
- *value= this->arm_radius;
- break;
- default:
- return false;
- }
-
+bool JohannKosselSolution::get_optional(arm_options_t& options) {
+ options['L']= this->arm_length;
+ options['R']= this->arm_radius;
return true;
};
void cartesian_to_actuator( float[], float[] );
void actuator_to_cartesian( float[], float[] );
- bool set_optional(char parameter, float value);
- bool get_optional(char parameter, float *value);
+ bool set_optional(const arm_options_t& options);
+ bool get_optional(arm_options_t& options);
private:
void init();
#define debounce_count_checksum CHECKSUM("debounce_count")
#define feedrate_checksum CHECKSUM("feedrate")
+#define delta_homing_checksum CHECKSUM("delta_homing")
+
#define alpha_steps_per_mm_checksum CHECKSUM("alpha_steps_per_mm")
#define beta_steps_per_mm_checksum CHECKSUM("beta_steps_per_mm")
#define gamma_steps_per_mm_checksum CHECKSUM("gamma_steps_per_mm")
this->steps_per_mm[2] = THEKERNEL->config->value(gamma_steps_per_mm_checksum)->as_number();
this->feedrate = THEKERNEL->config->value(zprobe_checksum, feedrate_checksum)->by_default(5)->as_number()*this->steps_per_mm[Z_AXIS]; // feedrate in steps/sec
+
+ // see what type of arm solution we need to use
+ this->is_delta = THEKERNEL->config->value(delta_homing_checksum)->by_default(false)->as_bool();
+
}
bool ZProbe::wait_for_probe(int steps[])
THEKERNEL->stepper->turn_enable_pins_on();
// move Z down
- // TODO for delta need to move all three actuators
this->running= true;
this->steppers[Z_AXIS]->set_speed(0); // will be increased by acceleration tick
this->steppers[Z_AXIS]->move(true, 100*this->steps_per_mm[Z_AXIS]); // always probes down, no more than 100mm
+ if(this->is_delta) {
+ // for delta need to move all three actuators
+ this->steppers[X_AXIS]->set_speed(0);
+ this->steppers[X_AXIS]->move(true, 100*this->steps_per_mm[X_AXIS]);
+ this->steppers[Y_AXIS]->set_speed(0);
+ this->steppers[Y_AXIS]->move(true, 100*this->steps_per_mm[Y_AXIS]);
+ }
+
bool r= wait_for_probe(steps);
this->running= false;
return r;
THEKERNEL->robot->reset_axis_position(gcode->get_value('Z'), Z_AXIS);
}else{
// move probe back to where it was
+ this->running= true;
this->steppers[Z_AXIS]->set_speed(0); // will be increased by acceleration tick
this->steppers[Z_AXIS]->move(false, steps[Z_AXIS]);
- this->running= true;
- while(this->steppers[Z_AXIS]->moving) { // wait for it to complete
+ if(this->is_delta) {
+ this->steppers[X_AXIS]->set_speed(0);
+ this->steppers[X_AXIS]->move(false, steps[X_AXIS]);
+ this->steppers[Y_AXIS]->set_speed(0);
+ this->steppers[Y_AXIS]->move(false, steps[Y_AXIS]);
+ }
+ while(this->steppers[X_AXIS]->moving || this->steppers[Y_AXIS]->moving || this->steppers[Z_AXIS]->moving) {
+ // wait for it to complete
THEKERNEL->call_event(ON_IDLE);
}
- this->running= true;
+
+ this->running= false;
}
}else{
gcode->stream->printf("ZProbe not triggered\n");
if(!this->running) return(0); // nothing to do
// foreach stepper that is moving
- for ( int c = 0; c <= 2; c++ ) {
+ for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
if( !this->steppers[c]->moving ) continue;
uint32_t current_rate = this->steppers[c]->steps_per_second;
Pin pin;
unsigned int debounce_count;
bool running;
+ bool is_delta;
};
#endif /* ZPROBE_H_ */