/// Data received interrupt
ISR(RS485_RXC_vect) {
- state.response[state.bytes++] = RS485_PORT.DATA;
+ state.response[state.bytes] = RS485_PORT.DATA;
+
+ // Ignore leading zeros
+ if (state.bytes || state.response[0]) state.bytes++;
if (state.bytes == state.response_length) {
_set_rxc_interrupt(false);
static void _read_cb(uint8_t func, uint8_t bytes, const uint8_t *data) {
- if (func == MODBUS_READ_OUTPUT_REG && bytes == 3 && data[0] == 2) {
- if (state.rw_cb) state.rw_cb(true, state.addr, _read_word(data, false));
+ if (func == MODBUS_READ_OUTPUT_REG && data[0] == bytes - 1) {
+ if (state.rw_cb)
+ for (uint8_t i = 0; i < bytes >> 1; i++)
+ state.rw_cb(true, state.addr + i, _read_word(data + i * 2 + 1, false));
return;
}
}
-void modbus_read(uint16_t addr, modbus_rw_cb_t cb) {
+void modbus_read(uint16_t addr, uint16_t count, modbus_rw_cb_t cb) {
state.rw_cb = cb;
state.addr = addr;
- uint8_t cmd[4] = {0, 0, 0, 1};
+ uint8_t cmd[4];
_write_word(cmd, addr, false);
- modbus_func(MODBUS_READ_OUTPUT_REG, 4, cmd, 3, _read_cb);
+ _write_word(cmd + 2, count, false);
+ modbus_func(MODBUS_READ_OUTPUT_REG, 4, cmd, 2 * count + 1, _read_cb);
}
REG_FREQ_READ,
REG_FREQ_SIGN_READ,
+ REG_FREQ_ACTECH_READ,
REG_DISCONNECT_WRITE,
} vfd_reg_type_t;
// NOTE, Modbus reg = AC Tech reg + 1
const vfd_reg_t ac_tech_regs[] PROGMEM = {
- {REG_CONNECT_WRITE, 49, 19}, // Password unlock
- {REG_CONNECT_WRITE, 2, 512}, // Manual mode
- {REG_MAX_FREQ_READ, 63, 0}, // Max frequency
- {REG_FREQ_SET, 41, 0}, // Frequency
- {REG_STOP_WRITE, 2, 4}, // Stop drive
- {REG_FWD_WRITE, 2, 128}, // Forward
- {REG_FWD_WRITE, 2, 8}, // Start drive
- {REG_REV_WRITE, 2, 64}, // Reverse
- {REG_REV_WRITE, 2, 8}, // Start drive
- {REG_FREQ_READ, 26, 0}, // Actual speed
- {REG_DISCONNECT_WRITE, 2, 2}, // Lock controls and parameters
+ {REG_CONNECT_WRITE, 48, 19}, // Password unlock
+ {REG_CONNECT_WRITE, 1, 512}, // Manual mode
+ {REG_MAX_FREQ_READ, 62, 0}, // Max frequency
+ {REG_FREQ_SET, 40, 0}, // Frequency
+ {REG_STOP_WRITE, 1, 4}, // Stop drive
+ {REG_FWD_WRITE, 1, 128}, // Forward
+ {REG_FWD_WRITE, 1, 8}, // Start drive
+ {REG_REV_WRITE, 1, 64}, // Reverse
+ {REG_REV_WRITE, 1, 8}, // Start drive
+ {REG_FREQ_ACTECH_READ, 24, 0}, // Actual speed
+ {REG_DISCONNECT_WRITE, 1, 2}, // Lock controls and parameters
+ {REG_DISABLED},
+};
+
+
+const vfd_reg_t fr_d700_regs[] PROGMEM = {
+ {REG_MAX_FREQ_READ, 1000, 0}, // Max frequency
+ {REG_FREQ_SET, 13, 0}, // Frequency
+ {REG_STOP_WRITE, 8, 1}, // Stop drive
+ {REG_FWD_WRITE, 8, 2}, // Forward
+ {REG_REV_WRITE, 8, 4}, // Reverse
+ {REG_FREQ_READ, 200, 0}, // Output freq
{REG_DISABLED},
};
static struct {
vfd_reg_type_t state;
int8_t reg;
+ uint8_t read_count;
bool changed;
bool shutdown;
static bool _next_state() {
switch (vfd.state) {
+ case REG_MAX_FREQ_FIXED:
+ if (!vfd.speed) vfd.state = REG_STOP_WRITE;
+ else vfd.state = REG_FREQ_SET;
+ break;
+
case REG_FREQ_SIGN_SET:
if (vfd.speed < 0) vfd.state = REG_REV_WRITE;
else if (0 < vfd.speed) vfd.state = REG_FWD_WRITE;
vfd.state = REG_FREQ_READ;
break;
- case REG_FREQ_SIGN_READ:
+ case REG_FREQ_ACTECH_READ:
if (vfd.shutdown) vfd.state = REG_DISCONNECT_WRITE;
else if (vfd.changed) {
if (vfd.reg == VFDREG) {
vfd.reg = -1;
+ vfd.read_count = 0;
if (!_next_state()) break;
} else if (regs[vfd.reg].type == vfd.state && _exec_command()) break;
}
// Handle read result
+ vfd.read_count++;
+
switch (regs[vfd.reg].type) {
case REG_MAX_FREQ_READ: vfd.max_freq = value; break;
case REG_FREQ_READ: vfd.actual_speed = value / (float)vfd.max_freq; break;
vfd.actual_speed = (int16_t)value / (float)vfd.max_freq;
break;
+ case REG_FREQ_ACTECH_READ:
+ if (vfd.read_count == 2) vfd.actual_speed = value / (float)vfd.max_freq;
+ if (vfd.read_count < 6) return;
+ break;
+
default: break;
}
if (vfd.wait) return true;
vfd_reg_t reg = regs[vfd.reg];
+ uint16_t words = 1;
bool read = false;
bool write = false;
write = true;
break;
+ case REG_FREQ_ACTECH_READ:
+ words = 6;
+
case REG_FREQ_READ:
case REG_FREQ_SIGN_READ:
case REG_MAX_FREQ_READ:
break;
}
- if (read) modbus_read(reg.addr, _modbus_cb);
+ if (read) modbus_read(reg.addr, words, _modbus_cb);
else if (write) modbus_write(reg.addr, reg.value, _modbus_cb);
else return false;
case SPINDLE_TYPE_CUSTOM: memcpy(regs, custom_regs, sizeof(regs)); break;
case SPINDLE_TYPE_YL600: _load(yl600_regs); break;
case SPINDLE_TYPE_AC_TECH: _load(ac_tech_regs); break;
+ case SPINDLE_TYPE_FR_D700: _load(fr_d700_regs); break;
default: break;
}