Skip to content

Commit 2307881

Browse files
authored
Merge branch 'main' into STMLoader
2 parents cde1e50 + c1b3a2c commit 2307881

File tree

8 files changed

+186
-70
lines changed

8 files changed

+186
-70
lines changed

FluidNC/src/Spindles/DacSpindle.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace Spindles {
3131
return;
3232
}
3333

34+
_enable_pin.setAttr(Pin::Attr::Output);
3435
_direction_pin.setAttr(Pin::Attr::Output);
3536

3637
is_reversable = _direction_pin.defined();
@@ -45,10 +46,13 @@ namespace Spindles {
4546
}
4647

4748
void Dac::config_message() {
48-
log_info(name() << " Spindle Out:" << _output_pin.name() << " Dir:" << _direction_pin.name() << " Res:8bits" << atc_info());
49+
log_info(name() << " Spindle Ena:" << _enable_pin.name() << " Out:" << _output_pin.name() << " Dir:" << _direction_pin.name()
50+
<< " Res:8bits" << atc_info());
4951
}
5052

51-
void IRAM_ATTR Dac::setSpeedfromISR(uint32_t speed) { set_output(speed); };
53+
void IRAM_ATTR Dac::setSpeedfromISR(uint32_t speed) {
54+
set_output(speed);
55+
};
5256
void IRAM_ATTR Dac::set_output(uint32_t duty) {
5357
if (_gpio_ok) {
5458
auto outputNative = _output_pin.getNative(Pin::Capabilities::DAC);

FluidNC/src/Spindles/VFD/GenericProtocol.cpp

+132-46
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,22 @@
55

66
#include "../VFDSpindle.h"
77

8-
#include "../../string_util.h"
8+
#include "src/string_util.h"
99
#include <algorithm>
1010

1111
namespace Spindles {
1212
namespace VFD {
13-
14-
bool GenericProtocol::from_decimal(std::string_view str, uint32_t& value) {
15-
value = 0;
16-
if (str.size() == 0) {
13+
bool GenericProtocol::split(std::string_view& input, std::string_view& token, const char* delims) {
14+
if (input.size() == 0) {
1715
return false;
1816
}
19-
while (str.size()) {
20-
if (!isdigit(str[0])) {
21-
return false;
22-
}
23-
value = value * 10 + str[0] - '0';
24-
str = str.substr(1);
17+
auto pos = input.find_first_of(delims);
18+
if (pos != std::string_view::npos) {
19+
token = input.substr(0, pos);
20+
input = input.substr(pos + 1);
21+
} else {
22+
token = input;
23+
input = "";
2524
}
2625
return true;
2726
}
@@ -41,15 +40,15 @@ namespace Spindles {
4140
scale_str = scale_str.substr(1);
4241
string_util::split_prefix(scale_str, numerator_str, '/');
4342
uint32_t numerator;
44-
if (from_decimal(numerator_str, numerator)) {
43+
if (string_util::from_decimal(numerator_str, numerator)) {
4544
n *= numerator;
4645
} else {
4746
log_error(spindle->name() << ": bad decimal number " << numerator_str);
4847
return;
4948
}
5049
if (!scale_str.empty()) {
5150
uint32_t denominator;
52-
if (from_decimal(scale_str, denominator)) {
51+
if (string_util::from_decimal(scale_str, denominator)) {
5352
divider *= denominator;
5453
} else {
5554
log_error(spindle->name() << ": bad decimal number " << scale_str);
@@ -59,7 +58,7 @@ namespace Spindles {
5958
} else if (scale_str[0] == '/') {
6059
std::string_view denominator_str(scale_str.substr(1));
6160
uint32_t denominator;
62-
if (from_decimal(denominator_str, denominator)) {
61+
if (string_util::from_decimal(denominator_str, denominator)) {
6362
divider *= denominator;
6463
} else {
6564
log_error(spindle->name() << ": bad decimal number " << scale_str);
@@ -70,35 +69,6 @@ namespace Spindles {
7069
n /= divider;
7170
}
7271

73-
bool GenericProtocol::from_xdigit(char c, uint8_t& value) {
74-
if (isdigit(c)) {
75-
value = c - '0';
76-
return true;
77-
}
78-
c = tolower(c);
79-
if (c >= 'a' && c <= 'f') {
80-
value = 10 + c - 'a';
81-
return true;
82-
}
83-
return false;
84-
}
85-
86-
bool GenericProtocol::from_hex(std::string_view str, uint8_t& value) {
87-
value = 0;
88-
if (str.size() == 0 || str.size() > 2) {
89-
return false;
90-
}
91-
uint8_t x;
92-
while (str.size()) {
93-
value <<= 4;
94-
if (!from_xdigit(str[0], x)) {
95-
return false;
96-
}
97-
value += x;
98-
str = str.substr(1);
99-
}
100-
return true;
101-
}
10272
bool GenericProtocol::set_data(std::string_view token, std::basic_string_view<uint8_t>& response_view, const char* name, uint32_t& data) {
10373
if (string_util::starts_with_ignore_case(token, name)) {
10474
uint32_t rval = (response_view[0] << 8) + (response_view[1] & 0xff);
@@ -142,7 +112,7 @@ namespace Spindles {
142112
log_debug(spindle->name() << ": got maxRPM " << instance->_maxRPM);
143113
continue;
144114
}
145-
if (from_hex(token, val)) {
115+
if (string_util::from_hex(token, val)) {
146116
if (val != response_view[0]) {
147117
log_debug(spindle->name() << ": response mismatch - expected " << to_hex(val) << " got " << to_hex(response_view[0]));
148118
return false;
@@ -178,7 +148,7 @@ namespace Spindles {
178148
scale(out, token.substr(strlen("rpm")), _maxRPM);
179149
data.msg[data.tx_length++] = out >> 8;
180150
data.msg[data.tx_length++] = out & 0xff;
181-
} else if (from_hex(token, data.msg[data.tx_length])) {
151+
} else if (string_util::from_hex(token, data.msg[data.tx_length])) {
182152
++data.tx_length;
183153
} else {
184154
log_error(spindle->name() << ":Bad hex number " << token);
@@ -198,7 +168,7 @@ namespace Spindles {
198168
if (string_util::starts_with_ignore_case(token, "rpm") || string_util::starts_with_ignore_case(token, "minrpm") ||
199169
string_util::starts_with_ignore_case(token, "maxrpm") || string_util::starts_with_ignore_case(token, "ignore")) {
200170
data.rx_length += 2;
201-
} else if (from_hex(token, x)) {
171+
} else if (string_util::from_hex(token, x)) {
202172
++data.rx_length;
203173
} else {
204174
log_error(spindle->name() << ": bad hex number " << token);
@@ -269,6 +239,122 @@ namespace Spindles {
269239
return nullptr;
270240
}
271241

242+
struct VFDtype {
243+
const char* name;
244+
uint32_t min_rpm;
245+
uint32_t max_rpm;
246+
const char* cw_cmd;
247+
const char* ccw_cmd;
248+
const char* off_cmd;
249+
const char* set_rpm_cmd;
250+
const char* get_rpm_cmd;
251+
const char* get_min_rpm_cmd;
252+
const char* get_max_rpm_cmd;
253+
} VFDtypes[] = {
254+
{
255+
"YL620",
256+
0xffffffff,
257+
0xffffffff,
258+
"06 20 00 00 12 > echo",
259+
"06 20 00 00 22 > echo",
260+
"06 20 00 00 01 > echo",
261+
"06 20 01 rpm*10/60 > echo",
262+
"03 20 0b 00 01 > 03 02 rpm*6",
263+
"",
264+
"03 03 08 00 02 > 03 04 minrpm*60/10 maxrpm*6",
265+
},
266+
{
267+
"Huanyang",
268+
0xffffffff,
269+
0xffffffff,
270+
"03 01 01 > echo",
271+
"03 01 11 > echo",
272+
"03 01 08 > echo",
273+
"05 02 rpm*100/60 > echo",
274+
"04 03 01 00 00 > 04 03 01 rpm*60/100",
275+
"01 03 0b 00 00 > 01 03 0B minRPM*60/100",
276+
"01 03 05 00 00 > 01 03 05 maxRPM*60/100",
277+
},
278+
{
279+
"H2A",
280+
6000,
281+
0xffffffff,
282+
"06 20 00 00 01 > echo",
283+
"06 20 00 00 02 > echo",
284+
"06 20 00 00 06 > echo",
285+
"06 10 00 rpm%*100 > echo",
286+
"03 70 0C 00 01 > 03 00 02 rpm", // or "03 70 0C 00 02 > 03 00 04 rpm 00 00",
287+
"",
288+
"03 B0 05 00 01 > 03 00 02 maxrpm", // or "03 B0 05 00 02 > 03 00 04 maxrpm 03 F6",
289+
290+
},
291+
{
292+
"H100",
293+
0xffffffff,
294+
0xffffffff,
295+
"05 00 49 ff 00 > echo",
296+
"05 00 4A ff 00 > echo",
297+
"05 00 4B ff 00 > echo",
298+
"06 02 01 rpm%*4 > echo",
299+
"04 00 00 00 02 > 04 04 rpm%*4 ignore",
300+
"03 00 0B 00 01 > 03 02 minrpm*60",
301+
"03 00 05 00 01 > 03 02 maxrpm*60",
302+
},
303+
{
304+
"NowForever",
305+
0xffffffff,
306+
0xffffffff,
307+
"10 09 00 00 01 02 00 01 > echo",
308+
"10 09 00 00 01 02 00 03 > echo",
309+
"10 09 00 00 01 02 00 00 > echo",
310+
"10 09 01 00 01 02 rpm/6 > echo",
311+
"03 05 02 00 01 > 03 02 rpm%*4",
312+
"",
313+
"03 00 07 00 02 > 03 04 maxrpm*6 minrpm*6",
314+
},
315+
{
316+
"SiemensV20",
317+
0,
318+
24000,
319+
"06 00 63 0C 7F > echo",
320+
"06 00 63 04 7F > echo",
321+
"06 00 63 0C 7E > echo",
322+
"06 00 64 rpm%*16384/100 > echo",
323+
"03 00 6E 00 01 > 03 02 rpm%*16384/100",
324+
"",
325+
"",
326+
},
327+
};
328+
void GenericProtocol::afterParse() {
329+
for (auto const& vfd : VFDtypes) {
330+
if (string_util::equal_ignore_case(_model, vfd.name)) {
331+
log_debug("Using predefined ModbusVFD " << vfd.name);
332+
if (_cw_cmd.empty()) {
333+
_cw_cmd = vfd.cw_cmd;
334+
}
335+
if (_ccw_cmd.empty()) {
336+
_ccw_cmd = vfd.ccw_cmd;
337+
}
338+
if (_off_cmd.empty()) {
339+
_off_cmd = vfd.off_cmd;
340+
}
341+
if (_set_rpm_cmd.empty()) {
342+
_set_rpm_cmd = vfd.set_rpm_cmd;
343+
}
344+
if (_get_rpm_cmd.empty()) {
345+
_get_rpm_cmd = vfd.get_rpm_cmd;
346+
}
347+
if (_get_max_rpm_cmd.empty()) {
348+
_get_max_rpm_cmd = vfd.get_max_rpm_cmd;
349+
}
350+
if (_get_min_rpm_cmd.empty()) {
351+
_get_min_rpm_cmd = vfd.get_min_rpm_cmd;
352+
}
353+
return;
354+
}
355+
}
356+
}
357+
272358
// Configuration registration
273359
namespace {
274360
SpindleFactory::DependentInstanceBuilder<VFDSpindle, GenericProtocol> registration("ModbusVFD");

FluidNC/src/Spindles/VFD/GenericProtocol.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@ namespace Spindles {
1212
namespace VFD {
1313
class GenericProtocol : public VFDProtocol, Configuration::Configurable {
1414
private:
15-
bool from_decimal(std::string_view str, uint32_t& value);
15+
bool split(std::string_view& input, std::string_view& token, const char* delims);
1616
void scale(uint32_t& n, std::string_view scale_str, uint32_t maxRPM);
17-
bool from_xdigit(char c, uint8_t& value);
18-
bool from_hex(std::string_view str, uint8_t& value);
1917
bool set_data(std::string_view token, std::basic_string_view<uint8_t>& response_view, const char* name, uint32_t& data);
2018

2119
protected:
@@ -52,10 +50,11 @@ namespace Spindles {
5250
void setup_speeds(VFDSpindle* vfd);
5351

5452
public:
53+
void afterParse() override;
5554
void group(Configuration::HandlerBase& handler) override {
5655
handler.item("model", _model);
57-
handler.item("min_RPM", _minRPM, 0xffffffff);
58-
handler.item("max_RPM", _maxRPM, 0xffffffff);
56+
handler.item("min_RPM", _minRPM);
57+
handler.item("max_RPM", _maxRPM);
5958
handler.item("cw_cmd", _cw_cmd);
6059
handler.item("ccw_cmd", _ccw_cmd);
6160
handler.item("off_cmd", _off_cmd);

FluidNC/src/Spindles/VFD/VFDProtocol.h

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace Spindles {
2323
uint8_t msg[VFD_RS485_MAX_MSG_SIZE];
2424
};
2525
virtual void group(Configuration::HandlerBase& handler) {};
26+
virtual void afterParse() {};
2627

2728
protected:
2829
// Enable spindown / spinup settings:

FluidNC/src/Spindles/VFDSpindle.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ namespace Spindles {
212212
Assert(_uart != nullptr || _uart_num != -1, "VFD: missing UART configuration");
213213
}
214214

215+
void VFDSpindle::afterParse() {
216+
detail_->afterParse();
217+
}
218+
215219
void VFDSpindle::group(Configuration::HandlerBase& handler) {
216220
if (handler.handlerType() == Configuration::HandlerType::Generator) {
217221
if (_uart_num == -1) {

FluidNC/src/Spindles/VFDSpindle.h

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace Spindles {
6262

6363
// Configuration handlers:
6464
void validate() override;
65+
void afterParse() override;
6566
void group(Configuration::HandlerBase& handler) override;
6667

6768
virtual ~VFDSpindle() {}

FluidNC/src/string_util.cpp

+35-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "string_util.h"
22
#include <cstdlib>
3+
#include <cctype>
34

45
namespace string_util {
56
char tolower(char c) {
@@ -53,27 +54,46 @@ namespace string_util {
5354
return end == s.cend();
5455
}
5556

56-
bool split(std::string_view& input, std::string_view& next, char delim) {
57-
auto pos = input.find_first_of(delim);
58-
if (pos != std::string_view::npos) {
59-
next = input.substr(pos + 1);
60-
input = input.substr(0, pos);
57+
bool from_xdigit(char c, uint8_t& value) {
58+
if (isdigit(c)) {
59+
value = c - '0';
60+
return true;
61+
}
62+
c = tolower(c);
63+
if (c >= 'a' && c <= 'f') {
64+
value = 10 + c - 'a';
6165
return true;
6266
}
63-
next = "";
6467
return false;
6568
}
66-
bool split_prefix(std::string_view& rest, std::string_view& prefix, char delim) {
67-
if (rest.empty()) {
69+
70+
bool from_hex(std::string_view str, uint8_t& value) {
71+
value = 0;
72+
if (str.size() == 0 || str.size() > 2) {
73+
return false;
74+
}
75+
uint8_t x;
76+
while (str.size()) {
77+
value <<= 4;
78+
if (!from_xdigit(str[0], x)) {
79+
return false;
80+
}
81+
value += x;
82+
str = str.substr(1);
83+
}
84+
return true;
85+
}
86+
bool from_decimal(std::string_view str, uint32_t& value) {
87+
value = 0;
88+
if (str.size() == 0) {
6889
return false;
6990
}
70-
auto pos = rest.find_first_of(delim);
71-
if (pos != std::string_view::npos) {
72-
prefix = rest.substr(0, pos);
73-
rest = rest.substr(pos + 1);
74-
} else {
75-
prefix = rest;
76-
rest = "";
91+
while (str.size()) {
92+
if (!isdigit(str[0])) {
93+
return false;
94+
}
95+
value = value * 10 + str[0] - '0';
96+
str = str.substr(1);
7797
}
7898
return true;
7999
}

0 commit comments

Comments
 (0)