X-Git-Url: https://git.hcoop.net/clinton/Smoothieware.git/blobdiff_plain/785da5811a0f7187c8bae5c53a2733c3190d7c10..e598a3f67acd7ec198596e6987f10964c2045381:/src/libs/Kernel.cpp diff --git a/src/libs/Kernel.cpp b/src/libs/Kernel.cpp index c351010b..58793d39 100644 --- a/src/libs/Kernel.cpp +++ b/src/libs/Kernel.cpp @@ -22,13 +22,17 @@ #include "modules/communication/GcodeDispatch.h" #include "modules/robot/Planner.h" #include "modules/robot/Robot.h" -#include "modules/robot/Stepper.h" #include "modules/robot/Conveyor.h" #include "StepperMotor.h" #include "BaseSolution.h" #include "EndstopsPublicAccess.h" #include "Configurator.h" #include "SimpleShell.h" +#include "TemperatureControlPublicAccess.h" + +#ifndef NO_TOOLS_LASER +#include "Laser.h" +#endif #include "platform_memory.h" @@ -36,27 +40,30 @@ #include #include +#define laser_checksum CHECKSUM("laser") #define baud_rate_setting_checksum CHECKSUM("baud_rate") #define uart0_checksum CHECKSUM("uart0") #define base_stepping_frequency_checksum CHECKSUM("base_stepping_frequency") #define microseconds_per_step_pulse_checksum CHECKSUM("microseconds_per_step_pulse") -#define acceleration_ticks_per_second_checksum CHECKSUM("acceleration_ticks_per_second") #define disable_leds_checksum CHECKSUM("leds_disable") #define grbl_mode_checksum CHECKSUM("grbl_mode") +#define feed_hold_enable_checksum CHECKSUM("enable_feed_hold") #define ok_per_line_checksum CHECKSUM("ok_per_line") Kernel* Kernel::instance; // The kernel is the central point in Smoothie : it stores modules, and handles event calls -Kernel::Kernel(){ - halted= false; - feed_hold= false; +Kernel::Kernel() +{ + halted = false; + feed_hold = false; + enable_feed_hold = false; - instance= this; // setup the Singleton instance of the kernel + instance = this; // setup the Singleton instance of the kernel // serial first at fixed baud rate (DEFAULT_SERIAL_BAUD_RATE) so config can report errors to serial - // Set to UART0, this will be changed to use the same UART as MRI if it's enabled + // Set to UART0, this will be changed to use the same UART as MRI if it's enabled this->serial = new SerialConsole(USBTX, USBRX, DEFAULT_SERIAL_BAUD_RATE); // Config next, but does not load cache yet @@ -67,7 +74,7 @@ Kernel::Kernel(){ // now config is loaded we can do normal setup for serial based on config delete this->serial; - this->serial= NULL; + this->serial = NULL; this->streams = new StreamOutputPool(); @@ -80,28 +87,37 @@ Kernel::Kernel(){ #if MRI_ENABLE != 0 switch( __mriPlatform_CommUartIndex() ) { case 0: - this->serial = new(AHB0) SerialConsole(USBTX, USBRX, this->config->value(uart0_checksum,baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); + this->serial = new(AHB0) SerialConsole(USBTX, USBRX, this->config->value(uart0_checksum, baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); break; case 1: - this->serial = new(AHB0) SerialConsole( p13, p14, this->config->value(uart0_checksum,baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); + this->serial = new(AHB0) SerialConsole( p13, p14, this->config->value(uart0_checksum, baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); break; case 2: - this->serial = new(AHB0) SerialConsole( p28, p27, this->config->value(uart0_checksum,baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); + this->serial = new(AHB0) SerialConsole( p28, p27, this->config->value(uart0_checksum, baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); break; case 3: - this->serial = new(AHB0) SerialConsole( p9, p10, this->config->value(uart0_checksum,baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); + this->serial = new(AHB0) SerialConsole( p9, p10, this->config->value(uart0_checksum, baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); break; } #endif // default if(this->serial == NULL) { - this->serial = new(AHB0) SerialConsole(USBTX, USBRX, this->config->value(uart0_checksum,baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); + this->serial = new(AHB0) SerialConsole(USBTX, USBRX, this->config->value(uart0_checksum, baud_rate_setting_checksum)->by_default(DEFAULT_SERIAL_BAUD_RATE)->as_number()); } //some boards don't have leds.. TOO BAD! - this->use_leds= !this->config->value( disable_leds_checksum )->by_default(false)->as_bool(); - this->grbl_mode= this->config->value( grbl_mode_checksum )->by_default(false)->as_bool(); - this->ok_per_line= this->config->value( ok_per_line_checksum )->by_default(true)->as_bool(); + this->use_leds = !this->config->value( disable_leds_checksum )->by_default(false)->as_bool(); + +#ifdef CNC + this->grbl_mode = this->config->value( grbl_mode_checksum )->by_default(true)->as_bool(); +#else + this->grbl_mode = this->config->value( grbl_mode_checksum )->by_default(false)->as_bool(); +#endif + + this->enable_feed_hold = this->config->value( feed_hold_enable_checksum )->by_default(this->grbl_mode)->as_bool(); + + // we expect ok per line now not per G code, setting this to false will return to the old (incorrect) way of ok per G code + this->ok_per_line = this->config->value( ok_per_line_checksum )->by_default(true)->as_bool(); this->add_module( this->serial ); @@ -109,7 +125,7 @@ Kernel::Kernel(){ add_module( this->slow_ticker = new SlowTicker()); this->step_ticker = new StepTicker(); - this->adc = new(AHB0) Adc(); + this->adc = new Adc(); // TODO : These should go into platform-specific files // LPC17xx-specific @@ -118,19 +134,18 @@ Kernel::Kernel(){ NVIC_SetPriority(TIMER1_IRQn, 1); NVIC_SetPriority(TIMER2_IRQn, 4); NVIC_SetPriority(PendSV_IRQn, 3); - NVIC_SetPriority(RIT_IRQn, 3); // we make acceleration tick the same prio as pendsv so it can't be pre-empted by end of block // Set other priorities lower than the timers NVIC_SetPriority(ADC_IRQn, 5); NVIC_SetPriority(USB_IRQn, 5); // If MRI is enabled - if( MRI_ENABLE ){ - if( NVIC_GetPriority(UART0_IRQn) > 0 ){ NVIC_SetPriority(UART0_IRQn, 5); } - if( NVIC_GetPriority(UART1_IRQn) > 0 ){ NVIC_SetPriority(UART1_IRQn, 5); } - if( NVIC_GetPriority(UART2_IRQn) > 0 ){ NVIC_SetPriority(UART2_IRQn, 5); } - if( NVIC_GetPriority(UART3_IRQn) > 0 ){ NVIC_SetPriority(UART3_IRQn, 5); } - }else{ + if( MRI_ENABLE ) { + if( NVIC_GetPriority(UART0_IRQn) > 0 ) { NVIC_SetPriority(UART0_IRQn, 5); } + if( NVIC_GetPriority(UART1_IRQn) > 0 ) { NVIC_SetPriority(UART1_IRQn, 5); } + if( NVIC_GetPriority(UART2_IRQn) > 0 ) { NVIC_SetPriority(UART2_IRQn, 5); } + if( NVIC_GetPriority(UART3_IRQn) > 0 ) { NVIC_SetPriority(UART3_IRQn, 5); } + } else { NVIC_SetPriority(UART0_IRQn, 5); NVIC_SetPriority(UART1_IRQn, 5); NVIC_SetPriority(UART2_IRQn, 5); @@ -139,23 +154,20 @@ Kernel::Kernel(){ // Configure the step ticker this->base_stepping_frequency = this->config->value(base_stepping_frequency_checksum)->by_default(100000)->as_number(); - float microseconds_per_step_pulse = this->config->value(microseconds_per_step_pulse_checksum)->by_default(5)->as_number(); - this->acceleration_ticks_per_second = THEKERNEL->config->value(acceleration_ticks_per_second_checksum)->by_default(1000)->as_number(); + float microseconds_per_step_pulse = this->config->value(microseconds_per_step_pulse_checksum)->by_default(1)->as_number(); - // Configure the step ticker ( TODO : shouldnt this go into stepticker's code ? ) - this->step_ticker->set_reset_delay( microseconds_per_step_pulse ); + // Configure the step ticker this->step_ticker->set_frequency( this->base_stepping_frequency ); - this->step_ticker->set_acceleration_ticks_per_second(acceleration_ticks_per_second); // must be set after set_frequency + this->step_ticker->set_unstep_time( microseconds_per_step_pulse ); // Core modules + this->add_module( this->conveyor = new Conveyor() ); 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->conveyor = new Conveyor() ); this->add_module( this->simpleshell = new SimpleShell() ); - this->planner = new(AHB0) Planner(); - this->configurator = new Configurator(); + this->planner = new Planner(); + this->configurator = new Configurator(); } // return a GRBL-like query string for serial ? @@ -164,80 +176,146 @@ std::string Kernel::get_query_string() std::string str; bool homing; bool ok = PublicData::get_value(endstops_checksum, get_homing_status_checksum, 0, &homing); - if(!ok) homing= false; - bool running= false; + if(!ok) homing = false; + bool running = false; str.append("<"); if(halted) { - str.append("Alarm,"); - }else if(homing) { - str.append("Home,"); - }else if(feed_hold) { - str.append("Hold,"); - }else if(this->conveyor->is_queue_empty()) { - str.append("Idle,"); - }else{ - running= true; - str.append("Run,"); + str.append("Alarm"); + } else if(homing) { + running = true; + str.append("Home"); + } else if(feed_hold) { + str.append("Hold"); + } else if(this->conveyor->is_idle()) { + str.append("Idle"); + } else { + running = true; + str.append("Run"); } if(running) { - // get real time current actuator position in mm - ActuatorCoordinates current_position{ - robot->actuators[X_AXIS]->get_current_position(), - robot->actuators[Y_AXIS]->get_current_position(), - robot->actuators[Z_AXIS]->get_current_position() - }; - - // get machine position from the actuator position using FK float mpos[3]; - robot->arm_solution->actuator_to_cartesian(current_position, mpos); + robot->get_current_machine_position(mpos); + // current_position/mpos includes the compensation transform so we need to get the inverse to get actual position + if(robot->compensationTransform) robot->compensationTransform(mpos, true); // get inverse compensation transform char buf[128]; // machine position - size_t n= snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f,", robot->from_millimeters(mpos[0]), robot->from_millimeters(mpos[1]), robot->from_millimeters(mpos[2])); - str.append("MPos:").append(buf, n); + size_t n = snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f", robot->from_millimeters(mpos[0]), robot->from_millimeters(mpos[1]), robot->from_millimeters(mpos[2])); + if(n > sizeof(buf)) n= sizeof(buf); + + str.append("|MPos:").append(buf, n); + +#if MAX_ROBOT_ACTUATORS > 3 + // deal with the ABC axis (E will be A) + for (int i = A_AXIS; i < robot->get_number_registered_motors(); ++i) { + // current actuator position + n = snprintf(buf, sizeof(buf), ",%1.4f", robot->from_millimeters(robot->actuators[i]->get_current_position())); + if(n > sizeof(buf)) n= sizeof(buf); + str.append(buf, n); + } +#endif // work space position - Robot::wcs_t pos= robot->mcs2wcs(mpos); - n= snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f", robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos))); - str.append("WPos:").append(buf, n); - str.append(">\r\n"); - - }else{ + Robot::wcs_t pos = robot->mcs2wcs(mpos); + n = snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f", robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos))); + if(n > sizeof(buf)) n= sizeof(buf); + + str.append("|WPos:").append(buf, n); + // current feedrate + float fr= robot->from_millimeters(conveyor->get_current_feedrate()*60.0F); + n = snprintf(buf, sizeof(buf), "|F:%1.4f", fr); + if(n > sizeof(buf)) n= sizeof(buf); + str.append(buf, n); + float sr= robot->get_s_value(); + n = snprintf(buf, sizeof(buf), "|S:%1.4f", sr); + if(n > sizeof(buf)) n= sizeof(buf); + str.append(buf, n); + + // current Laser power + #ifndef NO_TOOLS_LASER + Laser *plaser= nullptr; + if(PublicData::get_value(laser_checksum, (void *)&plaser) && plaser != nullptr) { + float lp= plaser->get_current_power(); + n = snprintf(buf, sizeof(buf), "|L:%1.4f", lp); + if(n > sizeof(buf)) n= sizeof(buf); + str.append(buf, n); + } + #endif + + } else { // return the last milestone if idle char buf[128]; // machine position - Robot::wcs_t mpos= robot->get_axis_position(); - size_t n= snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f,", robot->from_millimeters(std::get(mpos)), robot->from_millimeters(std::get(mpos)), robot->from_millimeters(std::get(mpos))); - str.append("MPos:").append(buf, n); + Robot::wcs_t mpos = robot->get_axis_position(); + size_t n = snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f", robot->from_millimeters(std::get(mpos)), robot->from_millimeters(std::get(mpos)), robot->from_millimeters(std::get(mpos))); + if(n > sizeof(buf)) n= sizeof(buf); + + str.append("|MPos:").append(buf, n); + +#if MAX_ROBOT_ACTUATORS > 3 + // deal with the ABC axis (E will be A) + for (int i = A_AXIS; i < robot->get_number_registered_motors(); ++i) { + // current actuator position + n = snprintf(buf, sizeof(buf), ",%1.4f", robot->from_millimeters(robot->actuators[i]->get_current_position())); + if(n > sizeof(buf)) n= sizeof(buf); + str.append(buf, n); + } +#endif // work space position - Robot::wcs_t pos= robot->mcs2wcs(mpos); - n= snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f", robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos))); - str.append("WPos:").append(buf, n); - str.append(">\r\n"); + Robot::wcs_t pos = robot->mcs2wcs(mpos); + n = snprintf(buf, sizeof(buf), "%1.4f,%1.4f,%1.4f", robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos)), robot->from_millimeters(std::get(pos))); + if(n > sizeof(buf)) n= sizeof(buf); + str.append("|WPos:").append(buf, n); + + float fr= robot->from_millimeters(robot->get_feed_rate()); + n = snprintf(buf, sizeof(buf), "|F:%1.4f", fr); + if(n > sizeof(buf)) n= sizeof(buf); + str.append(buf, n); + } + // if not grbl mode get temperatures + if(!is_grbl_mode()) { + struct pad_temperature temp; + // scan all temperature controls + std::vector controllers; + bool ok = PublicData::get_value(temperature_control_checksum, poll_controls_checksum, &controllers); + if (ok) { + char buf[32]; + for (auto &c : controllers) { + size_t n= snprintf(buf, sizeof(buf), "|%s:%1.1f,%1.1f", c.designator.c_str(), c.current_temperature, c.target_temperature); + if(n > sizeof(buf)) n= sizeof(buf); + str.append(buf, n); + } + } } + + str.append(">\n"); return str; } // Add a module to Kernel. We don't actually hold a list of modules we just call its on_module_loaded -void Kernel::add_module(Module* module){ +void Kernel::add_module(Module* module) +{ module->on_module_loaded(); } // Adds a hook for a given module and event -void Kernel::register_for_event(_EVENT_ENUM id_event, Module *mod){ +void Kernel::register_for_event(_EVENT_ENUM id_event, Module *mod) +{ this->hooks[id_event].push_back(mod); } // Call a specific event with an argument -void Kernel::call_event(_EVENT_ENUM id_event, void * argument){ - bool was_idle= true; +void Kernel::call_event(_EVENT_ENUM id_event, void * argument) +{ + bool was_idle = true; if(id_event == ON_HALT) { - this->halted= (argument == nullptr); - was_idle= conveyor->is_queue_empty(); // see if we were doing anything like printing + this->halted = (argument == nullptr); + if(!this->halted && this->feed_hold) this->feed_hold= false; // also clear feed hold + was_idle = conveyor->is_idle(); // see if we were doing anything like printing } // send to all registered modules @@ -245,9 +323,13 @@ void Kernel::call_event(_EVENT_ENUM id_event, void * argument){ (m->*kernel_callback_functions[id_event])(argument); } - if(id_event == ON_HALT && !was_idle) { - // we need to try to correct current positions if we were running - this->robot->reset_position_from_current_actuator_position(); + if(id_event == ON_HALT) { + if(!this->halted || !was_idle) { + // if we were running and this is a HALT + // or if we are clearing the halt with $X or M999 + // fix up the current positions in case they got out of sync due to backed up commands + this->robot->reset_position_from_current_actuator_position(); + } } }