5
5
6
6
#include " ../VFDSpindle.h"
7
7
8
- #include " ../.. /string_util.h"
8
+ #include " src /string_util.h"
9
9
#include < algorithm>
10
10
11
11
namespace Spindles {
12
12
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 ) {
17
15
return false ;
18
16
}
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 = " " ;
25
24
}
26
25
return true ;
27
26
}
@@ -41,15 +40,15 @@ namespace Spindles {
41
40
scale_str = scale_str.substr (1 );
42
41
string_util::split_prefix (scale_str, numerator_str, ' /' );
43
42
uint32_t numerator;
44
- if (from_decimal (numerator_str, numerator)) {
43
+ if (string_util:: from_decimal (numerator_str, numerator)) {
45
44
n *= numerator;
46
45
} else {
47
46
log_error (spindle->name () << " : bad decimal number " << numerator_str);
48
47
return ;
49
48
}
50
49
if (!scale_str.empty ()) {
51
50
uint32_t denominator;
52
- if (from_decimal (scale_str, denominator)) {
51
+ if (string_util:: from_decimal (scale_str, denominator)) {
53
52
divider *= denominator;
54
53
} else {
55
54
log_error (spindle->name () << " : bad decimal number " << scale_str);
@@ -59,7 +58,7 @@ namespace Spindles {
59
58
} else if (scale_str[0 ] == ' /' ) {
60
59
std::string_view denominator_str (scale_str.substr (1 ));
61
60
uint32_t denominator;
62
- if (from_decimal (denominator_str, denominator)) {
61
+ if (string_util:: from_decimal (denominator_str, denominator)) {
63
62
divider *= denominator;
64
63
} else {
65
64
log_error (spindle->name () << " : bad decimal number " << scale_str);
@@ -70,35 +69,6 @@ namespace Spindles {
70
69
n /= divider;
71
70
}
72
71
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
- }
102
72
bool GenericProtocol::set_data (std::string_view token, std::basic_string_view<uint8_t >& response_view, const char * name, uint32_t & data) {
103
73
if (string_util::starts_with_ignore_case (token, name)) {
104
74
uint32_t rval = (response_view[0 ] << 8 ) + (response_view[1 ] & 0xff );
@@ -142,7 +112,7 @@ namespace Spindles {
142
112
log_debug (spindle->name () << " : got maxRPM " << instance->_maxRPM );
143
113
continue ;
144
114
}
145
- if (from_hex (token, val)) {
115
+ if (string_util:: from_hex (token, val)) {
146
116
if (val != response_view[0 ]) {
147
117
log_debug (spindle->name () << " : response mismatch - expected " << to_hex (val) << " got " << to_hex (response_view[0 ]));
148
118
return false ;
@@ -178,7 +148,7 @@ namespace Spindles {
178
148
scale (out, token.substr (strlen (" rpm" )), _maxRPM);
179
149
data.msg [data.tx_length ++] = out >> 8 ;
180
150
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 ])) {
182
152
++data.tx_length ;
183
153
} else {
184
154
log_error (spindle->name () << " :Bad hex number " << token);
@@ -198,7 +168,7 @@ namespace Spindles {
198
168
if (string_util::starts_with_ignore_case (token, " rpm" ) || string_util::starts_with_ignore_case (token, " minrpm" ) ||
199
169
string_util::starts_with_ignore_case (token, " maxrpm" ) || string_util::starts_with_ignore_case (token, " ignore" )) {
200
170
data.rx_length += 2 ;
201
- } else if (from_hex (token, x)) {
171
+ } else if (string_util:: from_hex (token, x)) {
202
172
++data.rx_length ;
203
173
} else {
204
174
log_error (spindle->name () << " : bad hex number " << token);
@@ -269,6 +239,122 @@ namespace Spindles {
269
239
return nullptr ;
270
240
}
271
241
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
+
272
358
// Configuration registration
273
359
namespace {
274
360
SpindleFactory::DependentInstanceBuilder<VFDSpindle, GenericProtocol> registration (" ModbusVFD" );
0 commit comments