diff --git a/Grbl_Esp32/Custom/CoreXY.cpp b/Grbl_Esp32/Custom/CoreXY.cpp index b1c6fb87..0acad5b4 100644 --- a/Grbl_Esp32/Custom/CoreXY.cpp +++ b/Grbl_Esp32/Custom/CoreXY.cpp @@ -314,7 +314,7 @@ void forward_kinematics(float* position) { // apply the forward kinemetics to the machine coordinates // https://corexy.com/theory.html //calc_fwd[X_AXIS] = 0.5 / geometry_factor * (position[X_AXIS] + position[Y_AXIS]); - calc_fwd[X_AXIS] = ((0.5 * (print_position[X_AXIS] + print_position[Y_AXIS]) * geometry_factor) - wco[X_AXIS]); + calc_fwd[X_AXIS] = ((0.5 * (print_position[X_AXIS] + print_position[Y_AXIS]) / geometry_factor) - wco[X_AXIS]); calc_fwd[Y_AXIS] = ((0.5 * (print_position[X_AXIS] - print_position[Y_AXIS])) - wco[Y_AXIS]); for (int axis = 0; axis < n_axis; axis++) { diff --git a/Grbl_Esp32/Custom/oled_basic.cpp b/Grbl_Esp32/Custom/oled_basic.cpp index 49984ab8..fedc543e 100644 --- a/Grbl_Esp32/Custom/oled_basic.cpp +++ b/Grbl_Esp32/Custom/oled_basic.cpp @@ -38,12 +38,11 @@ Add this to your machine definition file #define DISPLAY_CODE_FILENAME "Custom/oled_basic.cpp" - */ // Include the correct display library -#include "SSD1306Wire.h" // legacy: #include "SSD1306.h" +#include "SSD1306Wire.h" #include "../src/WebUI/WebSettings.h" #ifndef OLED_ADDRESS @@ -66,142 +65,129 @@ SSD1306Wire display(OLED_ADDRESS, OLED_SDA, OLED_SCL, OLED_GEOMETRY); static TaskHandle_t displayUpdateTaskHandle = 0; -// returns the position of a machine axis -// wpos =true for corrected work postion -float getPosition(uint8_t axis, bool wpos = true) { - float wco; // work coordinate system offset - - float current_position = sys_position[axis] / axis_settings[axis]->steps_per_mm->get(); - - if (wpos) { - // Apply work coordinate offsets and tool length offset to current position. - wco = gc_state.coord_system[axis] + gc_state.coord_offset[axis]; - if (axis == TOOL_LENGTH_OFFSET_AXIS) { - wco += gc_state.tool_length_offset; - } - - current_position -= wco; - } - return current_position; -} - -String getStateText() { - String str = ""; - - switch (sys.state) { - case State::Idle: - str = "Idle"; - break; - case State::Cycle: - str = "Run"; - break; - case State::Hold: - if (!(sys.suspend.bit.jogCancel)) { - str = "Hold:"; - sys.suspend.bit.holdComplete ? str += "0" : str += "1"; // Ready to resume - break; - } // Continues to print jog state during jog cancel. - case State::Jog: - str = "Jog"; - break; - case State::Homing: - str = "Homing"; - break; - case State::Alarm: - str = "Alarm"; - break; - case State::CheckMode: - str = "Check"; - break; - case State::SafetyDoor: - str = "Door:"; - if (sys.suspend.bit.initiateRestore) { - str += "3"; // Restoring - } else { - if (sys.suspend.bit.retractComplete) { - sys.suspend.bit.safetyDoorAjar ? str += "1" : str += "0"; // Door ajar - // Door closed and ready to resume - } else { - str += "2"; // Retracting - } - } - break; - case State::Sleep: - str = "Sleep"; - break; - } - - return str; -} - // This displays the status of the ESP32 Radios...BT, WiFi, etc void displayRadioInfo() { - String radio_info = ""; - - const uint8_t row1 = 18; - const uint8_t row2 = 30; - const uint8_t row3 = 42; - - display.setTextAlignment(TEXT_ALIGN_LEFT); - display.setFont(ArialMT_Plain_10); + String radio_addr = ""; + String radio_name = ""; + String radio_status = ""; #ifdef ENABLE_BLUETOOTH if (WebUI::wifi_radio_mode->get() == ESP_BT) { - radio_info = String("Bluetooth: ") + WebUI::bt_name->get(); - display.drawString(0, row1, radio_info); - radio_info = String("Status: ") + String(WebUI::SerialBT.hasClient() ? "Connected" : "Not connected"); - display.drawString(0, row2, radio_info); + radio_name = String("BT: ") + WebUI::bt_name->get(); } #endif #ifdef ENABLE_WIFI if ((WiFi.getMode() == WIFI_MODE_STA) || (WiFi.getMode() == WIFI_MODE_APSTA)) { - radio_info = "STA SSID: " + WiFi.SSID(); - display.drawString(0, row1, radio_info); - - radio_info = "IP: " + WiFi.localIP().toString(); - display.drawString(0, row2, radio_info); - - radio_info = "Status: "; - (WiFi.status() == WL_CONNECTED) ? radio_info += "Connected" : radio_info += "Not connected"; - display.drawString(0, row3, radio_info); - //} + radio_name = "STA: " + WiFi.SSID(); + radio_addr = WiFi.localIP().toString(); } else if ((WiFi.getMode() == WIFI_MODE_AP) || (WiFi.getMode() == WIFI_MODE_APSTA)) { - radio_info = String("AP SSID: ") + WebUI::wifi_ap_ssid->get(); - - display.drawString(0, row1, radio_info); - - radio_info = "IP: " + WiFi.softAPIP().toString(); - display.drawString(0, row2, radio_info); + radio_name = String("AP:") + WebUI::wifi_ap_ssid->get(); + radio_addr = WiFi.softAPIP().toString(); } #endif #ifdef WIFI_OR_BLUETOOTH if (WebUI::wifi_radio_mode->get() == ESP_RADIO_OFF) { - display.drawString(0, row1, "Radio Mode: None"); + radio_name = "Radio Mode: None"; } #else - display.drawString(0, row1, "Wifi and Bluetooth Disabled"); + radio_name = "Radio Mode:Disabled"; #endif + + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.setFont(ArialMT_Plain_10); + + if (sys.state == State::Alarm) { // print below Alarm: + display.drawString(0, 18, radio_name); + display.drawString(0, 30, radio_addr); + + } else { // print next to status + if (WebUI::wifi_radio_mode->get() == ESP_BT) { + display.drawString(55, 2, radio_name); + } else { + display.drawString(55, 2, radio_addr); + } + } +} +// Here changes begin Here changes begin Here changes begin Here changes begin Here changes begin + +void draw_checkbox(int16_t x, int16_t y, int16_t width, int16_t height, bool checked) { + if (checked) + display.fillRect(x, y, width, height); // If log.0 + else + display.drawRect(x, y, width, height); // If log.1 } void displayDRO() { + uint8_t oled_y_pos; + float print_position[MAX_N_AXIS]; + //float wco[MAX_N_AXIS]; + + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.setFont(ArialMT_Plain_10); + char axisVal[20]; - display.setFont(ArialMT_Plain_16); - display.setTextAlignment(TEXT_ALIGN_LEFT); - display.drawString(0, 13, String('X') + ":"); - display.drawString(0, 30, "Y:"); - display.drawString(0, 47, "Z:"); + display.drawString(80, 14, "L"); // Limit switch - display.setTextAlignment(TEXT_ALIGN_RIGHT); - snprintf(axisVal, 20 - 1, "%.3f", getPosition(X_AXIS, true)); - display.drawString(100, 13, axisVal); + auto n_axis = number_axis->get(); + AxisMask lim_pin_state = limits_get_state(); + ControlPins ctrl_pin_state = system_control_get_state(); + bool prb_pin_state = probe_get_state(); - snprintf(axisVal, 20 - 1, "%.3f", getPosition(Y_AXIS, true)); - display.drawString(100, 30, axisVal); + if (bit_istrue(status_mask->get(), RtStatus::Position)) { + calc_mpos(print_position); + } else { + calc_wpos(print_position); + } - snprintf(axisVal, 20 - 1, "%.3f", getPosition(Z_AXIS, true)); - display.drawString(100, 47, axisVal); + for (uint8_t axis = X_AXIS; axis < n_axis; axis++) { + oled_y_pos = 24 + (axis * 10); + + String axis_letter = String(report_get_axis_letter(axis)); + axis_letter += ":"; + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawString(0, oled_y_pos, axis_letter); // String('X') + ":"); + + display.setTextAlignment(TEXT_ALIGN_RIGHT); + snprintf(axisVal, 20 - 1, "%.3f", print_position[axis]); + display.drawString(60, oled_y_pos, axisVal); + + if (limitsSwitchDefined(axis, 0)) { // olny draw the box if a switch has been defined + draw_checkbox(80, 27 + (axis * 10), 7, 7, bit_istrue(lim_pin_state, bit(axis))); + } + } + + oled_y_pos = 14; + + if (PROBE_PIN != UNDEFINED_PIN) { + display.drawString(110, oled_y_pos, "P"); + draw_checkbox(120, oled_y_pos + 3, 7, 7, prb_pin_state); + oled_y_pos += 10; + } + +#ifdef CONTROL_FEED_HOLD_PIN + display.drawString(110, oled_y_pos, "H"); + draw_checkbox(120, oled_y_pos + 3, 7, 7, ctrl_pin_state.bit.feedHold); + oled_y_pos += 10; +#endif + +#ifdef CONTROL_CYCLE_START_PIN + display.drawString(110, oled_y_pos, "S"); + draw_checkbox(120, oled_y_pos + 3, 7, 7, ctrl_pin_state.bit.cycleStart); + oled_y_pos += 10; +#endif + +#ifdef CONTROL_RESET_PIN + display.drawString(110, oled_y_pos, "R"); + draw_checkbox(120, oled_y_pos + 3, 7, 7, ctrl_pin_state.bit.reset); + oled_y_pos += 10; +#endif + +#ifdef CONTROL_SAFETY_DOOR_PIN + display.drawString(110, oled_y_pos, "D"); + draw_checkbox(120, oled_y_pos + 3, 7, 7, ctrl_pin_state.bit.safetyDoor); +#endif } void displayUpdate(void* pvParameters) { @@ -218,31 +204,33 @@ void displayUpdate(void* pvParameters) { while (true) { display.clear(); - String state_string = getStateText(); - - state_string.toUpperCase(); + String state_string = ""; display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_16); - display.drawString(0, 0, state_string); + display.drawString(0, 0, report_state_text()); if (get_sd_state(false) == SDState::BusyPrinting) { display.clear(); - display.setTextAlignment(TEXT_ALIGN_LEFT); - display.setFont(ArialMT_Plain_16); + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.setFont(ArialMT_Plain_10); state_string = "SD File"; for (int i = 0; i < sd_file_ticker % 10; i++) { state_string += "."; } sd_file_ticker++; - display.drawString(25, 0, state_string); + display.drawString(63, 0, state_string); + + char path[50]; + sd_get_current_filename(path); + display.drawString(63, 12, path); int progress = sd_report_perc_complete(); // draw the progress bar display.drawProgressBar(0, 45, 120, 10, progress); // draw the percentage as String - display.setFont(ArialMT_Plain_16); + display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(64, 25, String(progress) + "%"); @@ -250,7 +238,9 @@ void displayUpdate(void* pvParameters) { displayRadioInfo(); } else { displayDRO(); + displayRadioInfo(); } + display.display(); vTaskDelayUntil(&xLastWakeTime, xDisplayFrequency); @@ -260,20 +250,22 @@ void displayUpdate(void* pvParameters) { void display_init() { // Initialising the UI will init the display too. grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Init Basic OLED SDA:%s SCL:%s", pinName(OLED_SDA), pinName(OLED_SCL)); - display.init(); + display.flipScreenVertically(); + display.clear(); + display.setTextAlignment(TEXT_ALIGN_CENTER); - display.setFont(ArialMT_Plain_16); + display.setFont(ArialMT_Plain_10); String mach_name = MACHINE_NAME; // remove characters from the end until the string fits while (display.getStringWidth(mach_name) > 128) { mach_name = mach_name.substring(0, mach_name.length() - 1); } - display.drawString(63, 0, mach_name); + display.display(); xTaskCreatePinnedToCore(displayUpdate, // task diff --git a/Grbl_Esp32/src/data/favicon.ico b/Grbl_Esp32/data/favicon.ico similarity index 100% rename from Grbl_Esp32/src/data/favicon.ico rename to Grbl_Esp32/data/favicon.ico diff --git a/Grbl_Esp32/src/data/index.html.gz b/Grbl_Esp32/data/index.html.gz similarity index 100% rename from Grbl_Esp32/src/data/index.html.gz rename to Grbl_Esp32/data/index.html.gz diff --git a/Grbl_Esp32/src/Grbl.h b/Grbl_Esp32/src/Grbl.h index bfa875e3..1aa867c5 100644 --- a/Grbl_Esp32/src/Grbl.h +++ b/Grbl_Esp32/src/Grbl.h @@ -22,7 +22,7 @@ // Grbl versioning system const char* const GRBL_VERSION = "1.3a"; -const char* const GRBL_VERSION_BUILD = "20210320"; +const char* const GRBL_VERSION_BUILD = "20210329"; //#include #include diff --git a/Grbl_Esp32/src/Limits.cpp b/Grbl_Esp32/src/Limits.cpp index b87840c1..2c31661e 100644 --- a/Grbl_Esp32/src/Limits.cpp +++ b/Grbl_Esp32/src/Limits.cpp @@ -406,6 +406,10 @@ bool limitsCheckTravel(float* target) { return false; } +bool limitsSwitchDefined(uint8_t axis, uint8_t gang_index) { + return (limit_pins[axis][gang_index] != UNDEFINED_PIN); +} + bool __attribute__((weak)) user_defined_homing(uint8_t cycle_mask) { return false; } diff --git a/Grbl_Esp32/src/Limits.h b/Grbl_Esp32/src/Limits.h index 3cc2fccd..3697f8e0 100644 --- a/Grbl_Esp32/src/Limits.h +++ b/Grbl_Esp32/src/Limits.h @@ -54,3 +54,6 @@ float limitsMinPosition(uint8_t axis); // Internal factor used by limits_soft_check bool limitsCheckTravel(float* target); + +// check if a switch has been defined +bool limitsSwitchDefined(uint8_t axis, uint8_t gang_index); diff --git a/Grbl_Esp32/src/Report.cpp b/Grbl_Esp32/src/Report.cpp index b4728154..678c1d0e 100644 --- a/Grbl_Esp32/src/Report.cpp +++ b/Grbl_Esp32/src/Report.cpp @@ -291,13 +291,13 @@ std::map MessageText = { // NOTE: For interfaces, messages are always placed within brackets. And if silent mode // is installed, the message number codes are less than zero. void report_feedback_message(Message message) { // ok to send to all clients -#if defined (ENABLE_SD_CARD) +#if defined(ENABLE_SD_CARD) if (message == Message::SdFileQuit) { grbl_notifyf("SD print canceled", "Reset during SD file at line: %d", sd_get_current_line_number()); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Reset during SD file at line: %d", sd_get_current_line_number()); - } else -#endif //ENABLE_SD_CARD + } else +#endif //ENABLE_SD_CARD { auto it = MessageText.find(message); if (it != MessageText.end()) { @@ -592,82 +592,52 @@ void report_echo_line_received(char* line, uint8_t client) { grbl_sendf(client, "[echo: %s]\r\n", line); } +// Calculate the position for status reports. +// float print_position = returned position +// float wco = returns the work coordinate offset +// bool wpos = true for work position compensation +void report_calc_status_position(float* print_position, float* wco, bool wpos) { + int32_t current_position[MAX_N_AXIS]; // Copy current state of the system position variable + memcpy(current_position, sys_position, sizeof(sys_position)); + system_convert_array_steps_to_mpos(print_position, current_position); + + //float wco[MAX_N_AXIS]; + if (wpos || (sys.report_wco_counter == 0)) { + auto n_axis = number_axis->get(); + for (uint8_t idx = 0; idx < n_axis; idx++) { + // Apply work coordinate offsets and tool length offset to current position. + wco[idx] = gc_state.coord_system[idx] + gc_state.coord_offset[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) { + wco[idx] += gc_state.tool_length_offset; + } + if (wpos) { + print_position[idx] -= wco[idx]; + } + } + } + + forward_kinematics(print_position); // a weak definition does nothing. Users can provide strong version +} + // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram // and the actual location of the CNC machine. Users may change the following function to their // specific needs, but the desired real-time data report must be as short as possible. This is // requires as it minimizes the computational overhead and allows grbl to keep running smoothly, // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz). void report_realtime_status(uint8_t client) { - uint8_t idx; - int32_t current_position[MAX_N_AXIS]; // Copy current state of the system position variable - memcpy(current_position, sys_position, sizeof(sys_position)); float print_position[MAX_N_AXIS]; char status[200]; char temp[MAX_N_AXIS * 20]; - system_convert_array_steps_to_mpos(print_position, current_position); - // Report current machine state and sub-states + strcpy(status, "<"); - switch (sys.state) { - case State::Idle: - strcat(status, "Idle"); - break; - case State::Cycle: - strcat(status, "Run"); - break; - case State::Hold: - if (!(sys.suspend.bit.jogCancel)) { - strcat(status, "Hold:"); - strcat(status, sys.suspend.bit.holdComplete ? "0" : "1"); // Ready to resume - break; - } // Continues to print jog state during jog cancel. - case State::Jog: - strcat(status, "Jog"); - break; - case State::Homing: - strcat(status, "Home"); - break; - case State::Alarm: - strcat(status, "Alarm"); - break; - case State::CheckMode: - strcat(status, "Check"); - break; - case State::SafetyDoor: - strcat(status, "Door:"); - if (sys.suspend.bit.initiateRestore) { - strcat(status, "3"); // Restoring - } else { - if (sys.suspend.bit.retractComplete) { - strcat(status, sys.suspend.bit.safetyDoorAjar ? "1" : "0"); // Door ajar - // Door closed and ready to resume - } else { - strcat(status, "2"); // Retracting - } - } - break; - case State::Sleep: - strcat(status, "Sleep"); - break; - } - float wco[MAX_N_AXIS]; - if (bit_isfalse(status_mask->get(), RtStatus::Position) || (sys.report_wco_counter == 0)) { - auto n_axis = number_axis->get(); - for (idx = 0; idx < n_axis; idx++) { - // Apply work coordinate offsets and tool length offset to current position. - wco[idx] = gc_state.coord_system[idx] + gc_state.coord_offset[idx]; - if (idx == TOOL_LENGTH_OFFSET_AXIS) { - wco[idx] += gc_state.tool_length_offset; - } - if (bit_isfalse(status_mask->get(), RtStatus::Position)) { - print_position[idx] -= wco[idx]; - } - } - } - forward_kinematics(print_position); // a weak definition does nothing. Users can provide strong version - // Report machine position + strcat(status, report_state_text()); + + // Report position if (bit_istrue(status_mask->get(), RtStatus::Position)) { + calc_mpos(print_position); strcat(status, "|MPos:"); } else { + calc_wpos(print_position); strcat(status, "|WPos:"); } report_util_axis_values(print_position, temp); @@ -793,7 +763,7 @@ void report_realtime_status(uint8_t client) { sys.report_ovr_counter = 1; // Set override on next report. } strcat(status, "|WCO:"); - report_util_axis_values(wco, temp); + report_util_axis_values(get_wco(), temp); strcat(status, temp); } #endif @@ -913,6 +883,54 @@ void report_hex_msg(uint8_t* buf, const char* prefix, int len) { grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "%s", report); } +char* report_state_text() { + static char state[10]; + + switch (sys.state) { + case State::Idle: + strcpy(state, "Idle"); + break; + case State::Cycle: + strcpy(state, "Run"); + break; + case State::Hold: + if (!(sys.suspend.bit.jogCancel)) { + sys.suspend.bit.holdComplete ? strcpy(state, "Hold:0") : strcpy(state, "Hold:1"); + break; + } // Continues to print jog state during jog cancel. + case State::Jog: + strcpy(state, "Jog"); + break; + case State::Homing: + strcpy(state, "Home"); + break; + case State::Alarm: + strcpy(state, "Alarm"); + break; + case State::CheckMode: + strcpy(state, "Check"); + break; + case State::SafetyDoor: + strcpy(state, "Door:"); + if (sys.suspend.bit.initiateRestore) { + strcat(state, "3"); // Restoring + } else { + if (sys.suspend.bit.retractComplete) { + sys.suspend.bit.safetyDoorAjar ? strcat(state, "1") : strcat(state, "0"); + ; // Door ajar + // Door closed and ready to resume + } else { + strcat(state, "2"); // Retracting + } + } + break; + case State::Sleep: + strcpy(state, "Sleep"); + break; + } + return state; +} + char report_get_axis_letter(uint8_t axis) { switch (axis) { case X_AXIS: @@ -960,4 +978,37 @@ void reportTaskStackSize(UBaseType_t& saved) { #endif } +void calc_mpos(float* print_position) { + int32_t current_position[MAX_N_AXIS]; // Copy current state of the system position variable + memcpy(current_position, sys_position, sizeof(sys_position)); + system_convert_array_steps_to_mpos(print_position, current_position); + forward_kinematics(print_position); // a weak definition does nothing. Users can provide strong version +} + +void calc_wpos(float* print_position) { + int32_t current_position[MAX_N_AXIS]; // Copy current state of the system position variable + memcpy(current_position, sys_position, sizeof(sys_position)); + system_convert_array_steps_to_mpos(print_position, current_position); + + float* wco = get_wco(); + auto n_axis = number_axis->get(); + for (int idx = 0; idx < n_axis; idx++) { + print_position[idx] -= wco[idx]; + } + + forward_kinematics(print_position); // a weak definition does nothing. Users can provide strong version +} +float* get_wco() { + static float wco[MAX_N_AXIS]; + auto n_axis = number_axis->get(); + for (int idx = 0; idx < n_axis; idx++) { + // Apply work coordinate offsets and tool length offset to current position. + wco[idx] = gc_state.coord_system[idx] + gc_state.coord_offset[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) { + wco[idx] += gc_state.tool_length_offset; + } + } + return wco; +} + void __attribute__((weak)) forward_kinematics(float* position) {} // This version does nothing. Make your own to do something with it diff --git a/Grbl_Esp32/src/Report.h b/Grbl_Esp32/src/Report.h index 2ffcecee..366e8d9d 100644 --- a/Grbl_Esp32/src/Report.h +++ b/Grbl_Esp32/src/Report.h @@ -92,6 +92,9 @@ void report_grbl_settings(uint8_t client, uint8_t show_extended); // Prints an echo of the pre-parsed line received right before execution. void report_echo_line_received(char* line, uint8_t client); +// calculate the postion for status reports +void report_calc_status_position(float* print_position, float* wco, bool wpos); + // Prints realtime status report void report_realtime_status(uint8_t client); @@ -122,10 +125,14 @@ void report_machine_type(uint8_t client); void report_hex_msg(char* buf, const char* prefix, int len); void report_hex_msg(uint8_t* buf, const char* prefix, int len); -char report_get_axis_letter(uint8_t axis); - +char report_get_axis_letter(uint8_t axis); char* reportAxisLimitsMsg(uint8_t axis); char* reportAxisNameMsg(uint8_t axis); char* reportAxisNameMsg(uint8_t axis, uint8_t dual_axis); void reportTaskStackSize(UBaseType_t& saved); + +char* report_state_text(); +float* get_wco(); +void calc_mpos(float* print_position); +void calc_wpos(float* print_position);