Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Changed workings of VFD code, added H2A VFD (#544)
* Renamed Huanyang to VFD for H2A work * Fixed Huanyang spindle implementation again. Fixed includes in vcxproj generator * Changed the VFD implementation. Implemented H2A along the way. UNTESTED! * Fixed retry loop in VFD. Added SettingsDefinition. Fixed name conflict within GRBL (`init()`). * Added VFD_DEBUG_MODE. * Fixed usability of VFD_DEBUG_MODE. Added a TODO in the H2ASpindle code. Removed it from the test machine config * Fixed bug in VFD spindle: the uart should be set up first, before running the rs485 task. * Fixed bug in VFD_DEBUG_MODE output. Fixed bug in RX length of set_speed command for Huanyang VFD. * Fixed a bug in the spindle code with states. Also, VFD didn't update state correctly. Updated TODO/FIXME * Added some more functionality to the Null spindle, to aid testing purposes. Fixed report compatibility with vanilla grbl. Some values were reported in a slightly different format. * Fixed commands.h * Fixed review by Mitch Co-authored-by: Stefan de Bruijn <stefan@nubilosoft.com>
- Loading branch information
Showing
16 changed files
with
1,073 additions
and
413 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#pragma once | ||
// clang-format off | ||
|
||
/* | ||
3axis_xyx.h | ||
Part of Grbl_ESP32 | ||
This is a general XYZ-axis RS-485 CNC machine. The schematic is quite | ||
easy, you basically need a MAX485 wired through a logic level converter | ||
for the VFD, and a few pins wired through an ULN2803A to the external | ||
stepper drivers. It's common to have a dual gantry for the Y axis. | ||
Optional limit pins are slightly more difficult, as these require a | ||
Schmitt trigger and optocouplers. | ||
2020 - Stefan de Bruijn | ||
Grbl_ESP32 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. | ||
Grbl 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. | ||
You should have received a copy of the GNU General Public License | ||
along with Grbl_ESP32. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#define MACHINE_NAME "ESP32_XYZ_RS485" | ||
#define X_STEP_PIN GPIO_NUM_4 // labeled X | ||
#define X_DIRECTION_PIN GPIO_NUM_16 // labeled X | ||
#define Y_STEP_PIN GPIO_NUM_17 // labeled Y | ||
#define Y_DIRECTION_PIN GPIO_NUM_18 // labeled Y | ||
#define Y2_STEP_PIN GPIO_NUM_19 // labeled Y2 | ||
#define Y2_DIRECTION_PIN GPIO_NUM_21 // labeled Y2 | ||
#define Z_STEP_PIN GPIO_NUM_22 // labeled Z | ||
#define Z_DIRECTION_PIN GPIO_NUM_23 // labeled Z | ||
|
||
#define SPINDLE_TYPE SPINDLE_TYPE_H2A | ||
#define VFD_RS485_TXD_PIN GPIO_NUM_13 // RS485 TX | ||
#define VFD_RS485_RTS_PIN GPIO_NUM_15 // RS485 RTS | ||
#define VFD_RS485_RXD_PIN GPIO_NUM_2 // RS485 RX | ||
|
||
#define X_LIMIT_PIN GPIO_NUM_33 | ||
#define Y_LIMIT_PIN GPIO_NUM_32 | ||
#define Y2_LIMIT_PIN GPIO_NUM_35 | ||
#define Z_LIMIT_PIN GPIO_NUM_34 | ||
|
||
#ifdef HOMING_CYCLE_0 | ||
#undef HOMING_CYCLE_0 | ||
#endif | ||
#define HOMING_CYCLE_0 bit(Z_AXIS) // Z first | ||
|
||
#ifdef HOMING_CYCLE_1 | ||
#undef HOMING_CYCLE_1 | ||
#endif | ||
#define HOMING_CYCLE_1 (bit(X_AXIS)|bit(Y_AXIS)) | ||
|
||
#ifdef HOMING_CYCLE_2 | ||
#undef HOMING_CYCLE_2 | ||
#endif | ||
|
||
#define PROBE_PIN GPIO_NUM_14 // labeled Probe | ||
#define CONTROL_RESET_PIN GPIO_NUM_27 // labeled Reset | ||
#define CONTROL_FEED_HOLD_PIN GPIO_NUM_26 // labeled Hold | ||
#define CONTROL_CYCLE_START_PIN GPIO_NUM_25 // labeled Start | ||
|
||
// #define VFD_DEBUG_MODE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
#include "H2ASpindle.h" | ||
|
||
/* | ||
H2ASpindle.cpp | ||
This is for the new H2A H2A VFD based spindle via RS485 Modbus. | ||
Part of Grbl_ESP32 | ||
2020 - Stefan de Bruijn | ||
Grbl 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. | ||
Grbl 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. | ||
You should have received a copy of the GNU General Public License | ||
along with Grbl. If not, see <http://www.gnu.org/licenses/>. | ||
WARNING!!!! | ||
VFDs are very dangerous. They have high voltages and are very powerful | ||
Remove power before changing bits. | ||
The documentation is okay once you get how it works, but unfortunately | ||
incomplete... See H2ASpindle.md for the remainder of the docs that I | ||
managed to piece together. | ||
*/ | ||
|
||
#include <driver/uart.h> | ||
|
||
namespace Spindles { | ||
void H2A::default_modbus_settings(uart_config_t& uart) { | ||
// sets the uart to 19200 8E1 | ||
VFD::default_modbus_settings(uart); | ||
|
||
uart.baud_rate = 19200; | ||
uart.data_bits = UART_DATA_8_BITS; | ||
uart.parity = UART_PARITY_EVEN; | ||
uart.stop_bits = UART_STOP_BITS_1; | ||
} | ||
|
||
void H2A::direction_command(uint8_t mode, ModbusCommand& data) { | ||
// NOTE: data length is excluding the CRC16 checksum. | ||
data.tx_length = 6; | ||
data.rx_length = 6; | ||
|
||
data.msg[1] = 0x06; // WRITE | ||
data.msg[2] = 0x20; // Command ID 0x2000 | ||
data.msg[3] = 0x00; | ||
data.msg[4] = 0x00; | ||
data.msg[5] = (mode == SPINDLE_ENABLE_CCW) ? 0x02 : (mode == SPINDLE_ENABLE_CW ? 0x01 : 0x06); | ||
} | ||
|
||
void H2A::set_speed_command(uint32_t rpm, ModbusCommand& data) { | ||
// NOTE: data length is excluding the CRC16 checksum. | ||
data.tx_length = 6; | ||
data.rx_length = 6; | ||
|
||
// We have to know the max RPM before we can set the current RPM: | ||
auto max_rpm = this->_max_rpm; | ||
|
||
// Speed is in [0..10'000] where 10'000 = 100%. | ||
// We have to use a 32-bit integer here; typical values are 10k/24k rpm. | ||
// I've never seen a 400K RPM spindle in my life, and they aren't supported | ||
// by this modbus protocol anyways... So I guess this is OK. | ||
uint16_t speed = (uint32_t(rpm) * 10000L) / uint32_t(max_rpm); | ||
if (speed < 0) { | ||
speed = 0; | ||
} | ||
if (speed > 10000) { | ||
speed = 10000; | ||
} | ||
|
||
data.msg[1] = 0x06; // WRITE | ||
data.msg[2] = 0x10; // Command ID 0x1000 | ||
data.msg[3] = 0x00; | ||
data.msg[4] = uint8_t(speed >> 8); // RPM | ||
data.msg[5] = uint8_t(speed & 0xFF); | ||
} | ||
|
||
H2A::response_parser H2A::get_max_rpm(ModbusCommand& data) { | ||
// NOTE: data length is excluding the CRC16 checksum. | ||
data.tx_length = 6; | ||
data.rx_length = 8; | ||
|
||
// Send: 01 03 B005 0002 | ||
data.msg[1] = 0x03; // READ | ||
data.msg[2] = 0xB0; // B0.05 = Get RPM | ||
data.msg[3] = 0x05; | ||
data.msg[4] = 0x00; // Read 2 values | ||
data.msg[5] = 0x02; | ||
|
||
// Recv: 01 03 00 04 5D C0 03 F6 | ||
// -- -- = 24000 (val #1) | ||
return [](const uint8_t* response, Spindles::VFD* vfd) -> bool { | ||
uint16_t rpm = (uint16_t(response[4]) << 8) | uint16_t(response[5]); | ||
vfd->_max_rpm = rpm; | ||
|
||
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "H2A spindle is initialized at %d RPM", int(rpm)); | ||
|
||
return true; | ||
}; | ||
} | ||
|
||
H2A::response_parser H2A::get_current_rpm(ModbusCommand& data) { | ||
// NOTE: data length is excluding the CRC16 checksum. | ||
data.tx_length = 6; | ||
data.rx_length = 8; | ||
|
||
// Send: 01 03 700C 0002 | ||
data.msg[1] = 0x03; // READ | ||
data.msg[2] = 0x70; // B0.05 = Get RPM | ||
data.msg[3] = 0x0C; | ||
data.msg[4] = 0x00; // Read 2 values | ||
data.msg[5] = 0x02; | ||
|
||
// Recv: 01 03 0004 095D 0000 | ||
// ---- = 2397 (val #1) | ||
|
||
// TODO: What are we going to do with this? Update sys.spindle_speed? Update vfd state? | ||
return [](const uint8_t* response, Spindles::VFD* vfd) -> bool { | ||
uint16_t rpm = (uint16_t(response[4]) << 8) | uint16_t(response[5]); | ||
// Set current RPM value? Somewhere? | ||
return true; | ||
}; | ||
} | ||
|
||
H2A::response_parser H2A::get_current_direction(ModbusCommand& data) { | ||
// NOTE: data length is excluding the CRC16 checksum. | ||
data.tx_length = 6; | ||
data.rx_length = 6; | ||
|
||
// Send: 01 03 30 00 00 01 | ||
data.msg[1] = 0x03; // READ | ||
data.msg[2] = 0x30; // Command group ID | ||
data.msg[3] = 0x00; | ||
data.msg[4] = 0x00; // Message ID | ||
data.msg[5] = 0x01; | ||
|
||
// Receive: 01 03 00 02 00 02 | ||
// ----- status | ||
|
||
// TODO: What are we going to do with this? Update sys.spindle_speed? Update vfd state? | ||
return [](const uint8_t* response, Spindles::VFD* vfd) -> bool { return true; }; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#pragma once | ||
|
||
#include "VFDSpindle.h" | ||
|
||
/* | ||
H2ASpindle.h | ||
Part of Grbl_ESP32 | ||
2020 - Stefan de Bruijn | ||
Grbl 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. | ||
Grbl 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. | ||
You should have received a copy of the GNU General Public License | ||
along with Grbl. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
namespace Spindles { | ||
class H2A : public VFD { | ||
protected: | ||
void default_modbus_settings(uart_config_t& uart) override; | ||
|
||
void direction_command(uint8_t mode, ModbusCommand& data) override; | ||
void set_speed_command(uint32_t rpm, ModbusCommand& data) override; | ||
|
||
response_parser get_max_rpm(ModbusCommand& data) override; | ||
response_parser get_current_rpm(ModbusCommand& data) override; | ||
response_parser get_current_direction(ModbusCommand& data) override; | ||
response_parser get_status_ok(ModbusCommand& data) override { return nullptr; } | ||
}; | ||
} |
Oops, something went wrong.