From: Joseph Coffland Date: Fri, 30 Mar 2018 18:22:20 +0000 (-0700) Subject: More work on modbus VFDs X-Git-Url: https://git.buildbotics.com/?a=commitdiff_plain;h=2cf110dff423b81c35d108ed81cdd31d46836a22;p=bbctrl-firmware More work on modbus VFDs --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e15bb5..b68f7e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Buildbotics CNC Controller Firmware Changelog ## v0.3.21 - Implemented M70-M73 modal state save/restore. - Added support for modbus VFDs. + - Start Huanyang spindle with out first pressing Start button on VFD. ## v0.3.20 - Eliminated drift caused by miscounting half microsteps. diff --git a/package.json b/package.json index d5e7a28..674f55c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bbctrl", - "version": "0.3.21", + "version": "0.3.21.1", "homepage": "http://buildbotics.com/", "repository": "https://github.com/buildbotics/bbctrl-firmware", "license": "GPL-3.0+", diff --git a/src/avr/Makefile b/src/avr/Makefile index 2c00a07..122921d 100644 --- a/src/avr/Makefile +++ b/src/avr/Makefile @@ -4,8 +4,10 @@ MCU = atxmega192a3u CLOCK = 32000000 # SRC -SRC = $(wildcard src/*.c) $(wildcard src/*.cpp) -OBJ = $(patsubst src/%.cpp,build/%.o,$(patsubst src/%.c,build/%.o,$(SRC))) +SRC = $(wildcard src/*.c) $(wildcard src/*.cpp) $(wildcard src/vfd/*.c) +OBJ := $(patsubst src/%.c,build/%.o,$(SRC)) +OBJ := $(patsubst src/%.cpp,build/%.o,$(OBJ)) +OBJ := $(patsubst src/vfd/%.c,build/vfd/%.o,$(OBJ)) JSON = vars command messages JSON := $(patsubst %,build/%.json,$(JSON)) diff --git a/src/avr/src/huanyang.c b/src/avr/src/huanyang.c deleted file mode 100644 index 6d96abc..0000000 --- a/src/avr/src/huanyang.c +++ /dev/null @@ -1,339 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#include "huanyang.h" -#include "config.h" -#include "modbus.h" -#include "report.h" - -#include -#include - - -/* - Huanyang is not quite Modbus compliant. - - Message format is: - - [id][func][length][data][checksum] - - Where: - - id - 1-byte Peer ID - func - 1-byte One of hy_func_t - length - 1-byte Length data in bytes - data - length bytes - Command arguments - checksum - 16-bit CRC: x^16 + x^15 + x^2 + 1 (0xa001) initial: 0xffff -*/ - - -// See VFD manual pg56 3.1.3 -typedef enum { - HUANYANG_FUNC_READ = 1, // [len=1][hy_addr_t] - HUANYANG_FUNC_WRITE, // [len=3][hy_addr_t][data] - HUANYANG_CTRL_WRITE, // [len=1][hy_ctrl_state_t] - HUANYANG_CTRL_READ, // [len=1][hy_ctrl_addr_t] - HUANYANG_FREQ_WRITE, // [len=2][freq] - HUANYANG_RESERVED_1, - HUANYANG_RESERVED_2, - HUANYANG_LOOP_TEST, -} hy_func_t; - - -// Sent in HUANYANG_CTRL_WRITE -// See VFD manual pg57 3.1.3.c -typedef enum { - HUANYANG_RUN = 1 << 0, - HUANYANG_FORWARD = 1 << 1, - HUANYANG_REVERSE = 1 << 2, - HUANYANG_STOP = 1 << 3, - HUANYANG_REV_FWD = 1 << 4, - HUANYANG_JOG = 1 << 5, - HUANYANG_JOG_FORWARD = 1 << 6, - HUANYANG_JOG_REVERSE = 1 << 7, -} hy_ctrl_state_t; - - -// Returned by HUANYANG_CTRL_WRITE -// See VFD manual pg57 3.1.3.c -typedef enum { - HUANYANG_STATUS_RUN = 1 << 0, - HUANYANG_STATUS_JOG = 1 << 1, - HUANYANG_STATUS_COMMAND_REV = 1 << 2, - HUANYANG_STATUS_RUNNING = 1 << 3, - HUANYANG_STATUS_JOGGING = 1 << 4, - HUANYANG_STATUS_JOGGING_REV = 1 << 5, - HUANYANG_STATUS_BRAKING = 1 << 6, - HUANYANG_STATUS_TRACK_START = 1 << 7, -} hy_ctrl_status_t; - - -// Sent in HUANYANG_CTRL_READ -// See VFD manual pg57 3.1.3.d -typedef enum { - HUANYANG_TARGET_FREQ, - HUANYANG_ACTUAL_FREQ, - HUANYANG_ACTUAL_CURRENT, - HUANYANG_ACTUAL_RPM, - HUANYANG_DCV, - HUANYANG_ACV, - HUANYANG_COUNTER, - HUANYANG_TEMPERATURE, -} hy_ctrl_addr_t; - - -static struct { - uint8_t id; - - uint8_t state; - hy_func_t func; - uint8_t data[4]; - uint8_t bytes; - uint8_t response; - - bool shutdown; - bool changed; - float speed; - - float actual_freq; - float actual_current; - uint16_t actual_rpm; - uint16_t temperature; - - float max_freq; - float min_freq; - uint16_t rated_rpm; - - uint8_t status; -} hy = {1}; // Default ID - - -static void _func_read(hy_addr_t addr) { - hy.func = HUANYANG_FUNC_READ; - hy.bytes = 2; - hy.response = 4; - hy.data[0] = 1; - hy.data[1] = addr; -} - - -static void _ctrl_write(hy_ctrl_state_t state) { - hy.func = HUANYANG_CTRL_WRITE; - hy.bytes = 2; - hy.response = 2; - hy.data[0] = 1; - hy.data[1] = state; -} - - -static void _ctrl_read(hy_ctrl_addr_t addr) { - hy.func = HUANYANG_CTRL_READ; - hy.bytes = 2; - hy.response = 4; - hy.data[0] = 1; - hy.data[1] = addr; -} - - -static void _freq_write(uint16_t freq) { - hy.func = HUANYANG_FREQ_WRITE; - hy.bytes = 3; - hy.response = 3; - hy.data[0] = 2; - hy.data[1] = freq >> 8; - hy.data[2] = freq; -} - - -static void _func_read_response(hy_addr_t addr, uint16_t value) { - switch (addr) { - case HY_PD005_MAX_FREQUENCY: hy.max_freq = value * 0.01; break; - case HY_PD011_FREQUENCY_LOWER_LIMIT: hy.min_freq = value * 0.01; break; - case HY_PD144_RATED_MOTOR_RPM: hy.rated_rpm = value; break; - default: break; - } -} - - -static void _ctrl_read_response(hy_ctrl_addr_t addr, uint16_t value) { - switch (addr) { - case HUANYANG_ACTUAL_FREQ: hy.actual_freq = value * 0.01; break; - case HUANYANG_ACTUAL_CURRENT: hy.actual_current = value * 0.01; break; - case HUANYANG_ACTUAL_RPM: hy.actual_rpm = value; break; - case HUANYANG_TEMPERATURE: hy.temperature = value; break; - default: break; - } -} - - -static uint16_t _read_word(const uint8_t *data) { - return (uint16_t)data[0] << 8 | data[1]; -} - - -static void _handle_response(hy_func_t func, const uint8_t *data) { - switch (func) { - case HUANYANG_FUNC_READ: - _func_read_response((hy_addr_t)*data, _read_word(data + 1)); - break; - - case HUANYANG_FUNC_WRITE: break; - case HUANYANG_CTRL_WRITE: hy.status = *data; break; - - case HUANYANG_CTRL_READ: - _ctrl_read_response((hy_ctrl_addr_t)*data, _read_word(data + 1)); - break; - - case HUANYANG_FREQ_WRITE: break; - default: break; - } -} - - -static void _next_command(); - - -static void _reset(bool halt) { - // Save settings - uint8_t id = hy.id; - float speed = hy.speed; - - // Clear state - memset(&hy, 0, sizeof(hy)); - - // Restore settings - hy.id = id; - hy.speed = speed; - hy.changed = true; - - if (!halt) _next_command(); -} - - -static void _modbus_cb(uint8_t slave, uint8_t func, uint8_t bytes, - const uint8_t *data) { - if (!data) _reset(true); - - else if (bytes == *data + 1) { - _handle_response((hy_func_t)func, data + 1); - - if (func == HUANYANG_CTRL_WRITE && hy.shutdown) { - _reset(true); - modbus_deinit(); - return; - } - - // Next command - if (++hy.state == 9) { - hy.state = 5; - report_request(); - } - - // Update freq - if (hy.shutdown || (hy.changed && 4 < hy.state)) hy.state = 0; - } - - _next_command(); -} - - -static void _next_command() { - switch (hy.state) { - case 0: { // Update direction - hy_ctrl_state_t state = HUANYANG_STOP; - if (!hy.shutdown) { - if (0 < hy.speed) state = HUANYANG_RUN; - else if (hy.speed < 0) - state = (hy_ctrl_state_t)(HUANYANG_RUN | HUANYANG_REV_FWD); - } - - _ctrl_write(state); - break; - } - - case 1: _func_read(HY_PD005_MAX_FREQUENCY); break; - case 2: _func_read(HY_PD011_FREQUENCY_LOWER_LIMIT); break; - case 3: _func_read(HY_PD144_RATED_MOTOR_RPM); break; - - case 4: { // Update freqency - // Compute frequency in Hz - float freq = fabs(hy.speed * 50 / hy.rated_rpm); - - // Clamp frequency - if (hy.max_freq < freq) freq = hy.max_freq; - if (freq < hy.min_freq) freq = hy.min_freq; - - // Frequency write command - _freq_write(freq * 100); - hy.changed = false; - break; - } - - case 5: _ctrl_read(HUANYANG_ACTUAL_FREQ); break; - case 6: _ctrl_read(HUANYANG_ACTUAL_CURRENT); break; - case 7: _ctrl_read(HUANYANG_ACTUAL_RPM); break; - case 8: _ctrl_read(HUANYANG_TEMPERATURE); break; - } - - // Send command - modbus_func(hy.id, hy.func, hy.bytes, hy.data, hy.response, _modbus_cb); -} - - -void hy_init() { - modbus_init(); - _reset(false); -} - - -void hy_deinit() {hy.shutdown = true;} - - -void hy_set(float speed) { - if (hy.speed != speed) { - hy.speed = speed; - hy.changed = true; - } -} - - -void hy_stop() { - hy_set(0); - _reset(false); -} - - -uint8_t get_hy_id() {return hy.id;} -void set_hy_id(uint8_t value) {hy.id = value;} -float get_hy_freq() {return hy.actual_freq;} -float get_hy_current() {return hy.actual_current;} -uint16_t get_hy_rpm() {return hy.actual_rpm;} -uint16_t get_hy_temp() {return hy.temperature;} -float get_hy_max_freq() {return hy.max_freq;} -float get_hy_min_freq() {return hy.min_freq;} -uint16_t get_hy_rated_rpm() {return hy.rated_rpm;} -float get_hy_status() {return hy.status;} diff --git a/src/avr/src/huanyang.h b/src/avr/src/huanyang.h deleted file mode 100644 index 739199d..0000000 --- a/src/avr/src/huanyang.h +++ /dev/null @@ -1,225 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#pragma once - -#include "spindle.h" - - -void hy_init(); -void hy_deinit(); -void hy_set(float speed); -void hy_stop(); - - -/// See Huanyang VFD user manual -typedef enum { - HY_PD000_PARAMETER_LOCK, - HY_PD001_SOURCE_OF_OPERATION_COMMANDS, - HY_PD002_SOURCE_OF_OPERATING_FREQUENCY, - HY_PD003_MAIN_FREQUENCY, - HY_PD004_BASE_FREQUENCY, - HY_PD005_MAX_FREQUENCY, - HY_PD006_INTERMEDIATE_FREQUENCY, - HY_PD007_MIN_FREQUENCY, - HY_PD008_MAX_VOLTAGE, - HY_PD009_INTERMEDIATE_VOLTAGE, - HY_PD010_MIN_VOLTAGE, - HY_PD011_FREQUENCY_LOWER_LIMIT, - HY_PD012_RESERVED, - HY_PD013_PARAMETER_RESET, - HY_PD014_ACCEL_TIME_1, - HY_PD015_DECEL_TIME_1, - HY_PD016_ACCEL_TIME_2, - HY_PD017_DECEL_TIME_2, - HY_PD018_ACCEL_TIME_3, - HY_PD019_DECEL_TIME_3, - HY_PD020_ACCEL_TIME_4, - HY_PD021_DECEL_TIME_4, - HY_PD022_FACTORY_RESERVED, - HY_PD023_REV_ROTATION_SELECT, - HY_PD024_STOP_KEY, - HY_PD025_STARTING_MODE, - HY_PD026_STOPPING_MODE, - HY_PD027_STARTING_FREQUENCY, - HY_PD028_STOPPING_FREQUENCY, - HY_PD029_DC_BRAKING_TIME_AT_START, - HY_PD030_DC_BRAKING_TIME_AT_STOP, - HY_PD031_DC_BRAKING_VOLTAGE_LEVEL, - HY_PD032_FREQUENCY_TRACK_TIME, - HY_PD033_CURRENT_LEVEL_FOR_FREQUENCY_TRACK, - HY_PD034_VOLTAGE_RISE_TIME_FOR_FREQUENCY_TRACK, - HY_PD035_FREQUENCY_STEP_LENGTH, - HY_PD036, - HY_PD037, - HY_PD038, - HY_PD039, - HY_PD040, - HY_PD041_CARRIER_FREQUENCY, - HY_PD042_JOGGING_FREQUENCY, - HY_PD043_S_CURVE_TIME, - HY_PD044_MULTI_INPUT_FOR, - HY_PD045_MULTI_INPUT_REV, - HY_PD046_MULTI_INPUT_RST, - HY_PD047_MULTI_INPUT_SPH, - HY_PD048_MULTI_INPUT_SPM, - HY_PD049_MULTI_INPUT_SPL, - HY_PD050_MULTI_OUTPUT_DRV, - HY_PD051_MULTI_OUTPUT_UPF, - HY_PD052_MULTI_OUTPUT_FA_FB_FC, - HY_PD053_MULTI_OUTPUT_KA_KB, - HY_PD054_MULTI_OUTPUT_AM, - HY_PD055_AM_ANALOG_OUTPUT_GAIN, - HY_PD056_SKIP_FREQUENCY_1, - HY_PD057_SKIP_FREQUENCY_2, - HY_PD058_SKIP_FREQUENCY_3, - HY_PD059_SKIP_FREQUENCY_RANGE, - HY_PD060_UNIFORM_FREQUENCY_1, - HY_PD061_UNIFORM_FREQUENCY_2, - HY_PD062_UNIFORM_FREQUENCY_RANGE, - HY_PD063_TIMER_1_TIME, - HY_PD064_TIMER_2_TIME, - HY_PD065_COUNTING_VALUE, - HY_PD066_INTERMEDIATE_COUNTER, - HY_PD067, - HY_PD068, - HY_PD069, - HY_PD070_ANALOG_INPUT, - HY_PD071_ANALOG_FILTERING_CONSTANT, - HY_PD072_HIGHER_ANALOG_FREQUENCY, - HY_PD073_LOWER_ANALOG_FREQUENCY, - HY_PD074_BIAS_DIRECTION_AT_HIGHER_FREQUENCY, - HY_PD075_BIAS_DIRECTION_AT_LOWER_FREQUENCY, - HY_PD076_ANALOG_NEGATIVE_BIAS_REVERSE, - HY_PD077_UP_DOWN_FUNCTION, - HY_PD078_UP_DOWN_SPEED, - HY_PD079, - HY_PD080_PLC_OPERATION, - HY_PD081_AUTO_PLC, - HY_PD082_PLC_RUNNING_DIRECTION, - HY_PD083, - HY_PD084_PLC_RAMP_TIME, - HY_PD085, - HY_PD086_FREQUENCY_2, - HY_PD087_FREQUENCY_3, - HY_PD088_FREQUENCY_4, - HY_PD089_FREQUENCY_5, - HY_PD090_FREQUENCY_6, - HY_PD091_FREQUENCY_7, - HY_PD092_FREQUENCY_8, - HY_PD093, - HY_PD094, - HY_PD095, - HY_PD096, - HY_PD097, - HY_PD098, - HY_PD099, - HY_PD100, - HY_PD101_TIMER_1, - HY_PD102_TIMER_2, - HY_PD103_TIMER_3, - HY_PD104_TIMER_4, - HY_PD105_TIMER_5, - HY_PD106_TIMER_6, - HY_PD107_TIMER_7, - HY_PD108_TIMER_8, - HY_PD109, - HY_PD110, - HY_PD111, - HY_PD112, - HY_PD113, - HY_PD114, - HY_PD115, - HY_PD116, - HY_PD117_AUTOPLC_MEMORY_FUNCTION, - HY_PD118_OVER_VOLTAGE_STALL_PREVENTION, - HY_PD119_STALL_PREVENTION_LEVEL_AT_RAMP_UP, - HY_PD120_STALL_PREVENTION_LEVEL_AT_CONSTANT_SPEED, - HY_PD121_DECEL_TIME_FOR_STALL_PREVENTION_AT_CONSTANT_SPEED, - HY_PD122_STALL_PREVENTION_LEVEL_AT_DECELERATION, - HY_PD123_OVER_TORQUE_DETECT_MODE, - HY_PD124_OVER_TORQUE_DETECT_LEVEL, - HY_PD125_OVER_TORQUE_DETECT_TIME, - HY_PD126, - HY_PD127, - HY_PD128, - HY_PD129, - HY_PD130_NUMBER_OF_AUXILIARY_PUMP, - HY_PD131_CONTINUOUS_RUNNING_TIME_OF_AUXILIARY_PUMPS, - HY_PD132_INTERLOCKING_TIME_OF_AUXILIARY_PUMP, - HY_PD133_HIGH_SPEED_RUNNING_TIME, - HY_PD134_LOW_SPEED_RUNNING_TIME, - HY_PD135_STOPPING_VOLTAGE_LEVEL, - HY_PD136_LASTING_TIME_OF_STOPPING_VOLTAGE_LEVEL, - HY_PD137_WAKEUP_VOLTAGE_LEVEL, - HY_PD138_SLEEP_FREQUENCY, - HY_PD139_LASTING_TIME_OF_SLEEP_FREQUENCY, - HY_PD140, - HY_PD141_RATED_MOTOR_VOLTAGE, - HY_PD142_RATED_MOTOR_CURRENT, - HY_PD143_MOTOR_POLE_NUMBER, - HY_PD144_RATED_MOTOR_RPM, - HY_PD145_AUTO_TORQUE_COMPENSATION, - HY_PD146_MOTOR_NO_LOAD_CURRENT, - HY_PD147_MOTOR_SLIP_COMPENSATION, - HY_PD148, - HY_PD149, - HY_PD150_AUTO_VOLTAGE_REGULATION, - HY_PD151_AUTO_ENERGY_SAVING, - HY_PD152_FAULT_RESTART_TIME, - HY_PD153_RESTART_AFTER_INSTANTANEOUS_STOP, - HY_PD154_ALLOWABLE_POWER_BREAKDOWN_TIME, - HY_PD155_NUMBER_OF_ABNORMAL_RESTART, - HY_PD156_PROPORTIONAL_CONSTANT, - HY_PD157_INTEGRAL_TIME, - HY_PD158_DIFFERENTIAL_TIME, - HY_PD159_TARGET_VALUE, - HY_PD160_PID_TARGET_VALUE, - HY_PD161_PID_UPPER_LIMIT, - HY_PD162_PID_LOWER_LIMIT, - HY_PD163_COMMUNICATION_ADDRESSES, - HY_PD164_COMMUNICATION_BAUD_RATE, - HY_PD165_COMMUNICATION_DATA_METHOD, - HY_PD166, - HY_PD167, - HY_PD168, - HY_PD169, - HY_PD170_DISPLAY_ITEMS, - HY_PD171_DISPLAY_ITEMS_OPEN, - HY_PD172_FAULT_CLEAR, - HY_PD173, - HY_PD174_RATED_CURRENT_OF_INVERTER, - HY_PD175_INVERTER_MODEL, - HY_PD176_INVERTER_FREQUENCY_STANDARD, - HY_PD177_FAULT_RECORD_1, - HY_PD178_FAULT_RECORD_2, - HY_PD179_FAULT_RECORD_3, - HY_PD180_FAULT_RECORD_4, - HY_PD181_SOFTWARE_VERSION, - HY_PD182_MANUFACTURE_DATE, - HY_PD183_SERIAL_NO, -} hy_addr_t; diff --git a/src/avr/src/main.c b/src/avr/src/main.c index 5877224..94b3da7 100644 --- a/src/avr/src/main.c +++ b/src/avr/src/main.c @@ -29,7 +29,6 @@ #include "stepper.h" #include "motor.h" #include "switch.h" -#include "spindle.h" #include "usart.h" #include "drv8711.h" #include "vars.h" @@ -65,7 +64,6 @@ int main() { stepper_init(); // steppers motor_init(); // motors switch_init(); // switches - spindle_init(); // spindles exec_init(); // motion exec vars_init(); // configuration variables estop_init(); // emergency stop handler diff --git a/src/avr/src/modbus.c b/src/avr/src/modbus.c index 1d76f51..9921770 100644 --- a/src/avr/src/modbus.c +++ b/src/avr/src/modbus.c @@ -42,7 +42,10 @@ static struct { bool debug; - uint8_t baud; + uint8_t id; + baud_t baud; + parity_t parity; + stop_t stop; uint8_t bytes; uint8_t command[MODBUS_BUF_SIZE]; @@ -52,11 +55,15 @@ static struct { modbus_cb_t receive_cb; + uint16_t addr; + modbus_read_cb_t read_cb; + modbus_write_cb_t write_cb; + uint32_t last; uint8_t retry; bool connected; bool busy; -} mb = {false, USART_BAUD_9600}; +} mb = {false, 1, USART_BAUD_9600, USART_NONE, USART_1STOP}; static uint16_t _crc16(const uint8_t *buffer, unsigned length) { @@ -138,13 +145,11 @@ static void _handle_response() { mb.last = 0; // Clear timeout timer mb.retry = 0; // Reset retry counter - - if (mb.receive_cb) - mb.receive_cb(mb.response[0], mb.response[1], mb.response_length - 4, - mb.response + 2); - mb.connected = true; mb.busy = false; + + if (mb.receive_cb) + mb.receive_cb(mb.response[1], mb.response_length - 4, mb.response + 2); } @@ -182,6 +187,31 @@ ISR(RS485_RXC_vect) { } +void _read_cb(uint8_t func, uint8_t bytes, const uint8_t *data) { + if (func == MODBUS_READ_OUTPUT_REG && bytes == 3 && data[0] == 2) { + uint16_t value = (uint16_t)data[1] << 8 | data[2]; + if (mb.read_cb) mb.read_cb(true, mb.addr, value); + return; + } + + if (mb.read_cb) mb.read_cb(false, mb.addr, 0); +} + + +void _write_cb(uint8_t func, uint8_t bytes, const uint8_t *data) { + if (func == MODBUS_WRITE_OUTPUT_REG && bytes == 4) { + uint16_t addr = (uint16_t)data[0] << 8 | data[1]; + + if (addr == mb.addr) { + if (mb.write_cb) mb.write_cb(true, mb.addr); + return; + } + } + + if (mb.write_cb) mb.write_cb(false, mb.addr); +} + + static void _reset() { _set_dre_interrupt(false); _set_txc_interrupt(false); @@ -195,14 +225,20 @@ static void _reset() { // Save settings bool debug = mb.debug; - uint8_t baud = mb.baud; + uint8_t id = mb.id; + baud_t baud = mb.baud; + parity_t parity = mb.parity; + stop_t stop = mb.stop; // Clear state memset(&mb, 0, sizeof(mb)); // Restore settings mb.debug = debug; + mb.id = id; mb.baud = baud; + mb.parity = parity; + mb.stop = stop; } @@ -231,13 +267,12 @@ static void _timeout() { if (mb.debug) STATUS_DEBUG("modbus: timedout"); modbus_cb_t cb = mb.receive_cb; - uint8_t id = mb.command[0]; uint8_t func = mb.command[1]; _reset(); // Notify caller - if (cb) cb(id, func, 0, 0); + if (cb) cb(func, 0, 0); } @@ -250,18 +285,7 @@ void modbus_init() { OUTSET_PIN(RS485_RW_PIN); // High DIRSET_PIN(RS485_RW_PIN); // Output - usart_set_port_baud(&RS485_PORT, mb.baud); - - // No parity, 8 data bits, 1 stop bit - RS485_PORT.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | - USART_CHSIZE_8BIT_gc; - - // Enable receiver and transmitter - RS485_PORT.CTRLB |= USART_RXEN_bm | USART_TXEN_bm; - - // TODO remove this - PINCTRL_PIN(RS485_RO_PIN) ^= PORT_INVEN_bm; - PINCTRL_PIN(RS485_DI_PIN) ^= PORT_INVEN_bm; + usart_init_port(&RS485_PORT, mb.baud, mb.parity, USART_8BITS, mb.stop); _reset(); } @@ -282,28 +306,46 @@ void modbus_deinit() { bool modbus_busy() {return mb.busy;} -void modbus_func(uint8_t slave, uint8_t func, uint8_t send, const uint8_t *data, +void modbus_func(uint8_t func, uint8_t send, const uint8_t *data, uint8_t receive, modbus_cb_t receive_cb) { ASSERT(send + 4 <= MODBUS_BUF_SIZE); ASSERT(receive + 4 <= MODBUS_BUF_SIZE); - _reset(); - - mb.command[0] = slave; + mb.command[0] = mb.id; mb.command[1] = func; memcpy(mb.command + 2, data, send); uint16_t crc = _crc16(mb.command, send + 2); mb.command[send + 2] = crc; mb.command[send + 3] = crc >> 8; + mb.bytes = 0; mb.command_length = send + 4; mb.response_length = receive + 4; mb.receive_cb = receive_cb; + mb.last = 0; + mb.retry = 0; _set_dre_interrupt(true); } +void modbus_read(uint16_t addr, modbus_read_cb_t cb) { + mb.read_cb = cb; + mb.addr = addr; + uint8_t cmd[4] = {(uint8_t)(addr >> 8), (uint8_t)addr, 0, 1}; + modbus_func(MODBUS_READ_OUTPUT_REG, 4, cmd, 3, _read_cb); +} + + +void modbus_write(uint16_t addr, uint16_t value, modbus_write_cb_t cb) { + mb.write_cb = cb; + mb.addr = addr; + uint8_t cmd[4] = {(uint8_t)(addr >> 8), (uint8_t)addr, (uint8_t)(value >> 8), + (uint8_t)value}; + modbus_func(MODBUS_WRITE_OUTPUT_REG, 4, cmd, 4, _write_cb); +} + + void modbus_rtc_callback() { if (!mb.last || !rtc_expired(mb.last + MODBUS_TIMEOUT)) return; @@ -327,12 +369,32 @@ void modbus_rtc_callback() { // Variable callbacks bool get_modbus_debug() {return mb.debug;} void set_modbus_debug(bool value) {mb.debug = value;} +uint8_t get_modbus_id() {return mb.id;} +void set_modbus_id(uint8_t id) {mb.id = id;} uint8_t get_modbus_baud() {return mb.baud;} void set_modbus_baud(uint8_t baud) { - mb.baud = baud; - usart_set_port_baud(&RS485_PORT, baud); + mb.baud = (baud_t)baud; + usart_set_baud(&RS485_PORT, mb.baud); +} + + +uint8_t get_modbus_parity() {return mb.parity;} + + +void set_modbus_parity(uint8_t parity) { + mb.parity = (parity_t)parity; + usart_set_parity(&RS485_PORT, mb.parity); +} + + +uint8_t get_modbus_stop() {return mb.stop;} + + +void set_modbus_stop(uint8_t stop) { + mb.stop = (stop_t)stop; + usart_set_stop(&RS485_PORT, mb.stop); } diff --git a/src/avr/src/modbus.h b/src/avr/src/modbus.h index 802791e..0a36d32 100644 --- a/src/avr/src/modbus.h +++ b/src/avr/src/modbus.h @@ -98,12 +98,15 @@ typedef enum { } modbus_base_addrs_t; -typedef void (*modbus_cb_t)(uint8_t slave, uint8_t func, uint8_t bytes, - const uint8_t *data); +typedef void (*modbus_cb_t)(uint8_t func, uint8_t bytes, const uint8_t *data); +typedef void (*modbus_read_cb_t)(bool ok, uint16_t addr, uint16_t value); +typedef void (*modbus_write_cb_t)(bool ok, uint16_t addr); void modbus_init(); void modbus_deinit(); bool modbus_busy(); -void modbus_func(uint8_t slave, uint8_t func, uint8_t send, const uint8_t *data, - uint8_t receive, modbus_cb_t receive_cb); +void modbus_func(uint8_t func, uint8_t send, const uint8_t *data, + uint8_t receive, modbus_cb_t cb); +void modbus_read(uint16_t addr, modbus_read_cb_t cb); +void modbus_write(uint16_t addr, uint16_t value, modbus_write_cb_t cb); void modbus_rtc_callback(); diff --git a/src/avr/src/pwm_spindle.c b/src/avr/src/pwm_spindle.c index f93a9cf..80d2d8a 100644 --- a/src/avr/src/pwm_spindle.c +++ b/src/avr/src/pwm_spindle.c @@ -36,8 +36,6 @@ typedef struct { uint16_t freq; // base frequency for PWM driver, in Hz - float min_rpm; - float max_rpm; float min_duty; float max_duty; float duty; @@ -62,7 +60,7 @@ static void _update_pwm() { float speed = spindle.speed; // Disable - if (speed <= spindle.min_rpm || estop_triggered()) { + if (!speed || estop_triggered()) { TIMER_PWM.CTRLA = 0; OUTCLR_PIN(SPIN_PWM_PIN); _set_enable(false); @@ -71,15 +69,12 @@ static void _update_pwm() { _set_enable(true); // 100% duty - if (spindle.max_rpm <= speed && spindle.max_duty == 1) { + if (speed == 1 && spindle.max_duty == 1) { TIMER_PWM.CTRLB = 0; OUTSET_PIN(SPIN_PWM_PIN); return; } - // Clamp speed - if (spindle.max_rpm < speed) speed = spindle.max_rpm; - // Set clock period and optimal prescaler value float prescale = (float)(F_CPU >> 16) / spindle.freq; if (prescale <= 1) { @@ -104,10 +99,9 @@ static void _update_pwm() { } else TIMER_PWM.CTRLA = 0; - // Map RPM to duty cycle + // Compute duty cycle spindle.duty = - (speed - spindle.min_rpm) / (spindle.max_rpm - spindle.min_rpm) * - (spindle.max_duty - spindle.min_duty) + spindle.min_duty; + speed * (spindle.max_duty - spindle.min_duty) + spindle.min_duty; // Configure clock TIMER_PWM.CTRLB = TC1_CCAEN_bm | TC_WGMODE_SINGLESLOPE_gc; @@ -144,14 +138,11 @@ void pwm_spindle_set(float speed) { } +float pwm_spindle_get() {return spindle.speed;} void pwm_spindle_stop() {pwm_spindle_set(0);} -// TODO these need more effort and should work with the huanyang spindle too -float get_max_spin() {return spindle.max_rpm;} -void set_max_spin(float value) {spindle.max_rpm = value; _update_pwm();} -float get_min_spin() {return spindle.min_rpm;} -void set_min_spin(float value) {spindle.min_rpm = value; _update_pwm();} +// Var callbacks float get_pwm_min_duty() {return spindle.min_duty * 100;} diff --git a/src/avr/src/pwm_spindle.h b/src/avr/src/pwm_spindle.h index fe29f28..996020d 100644 --- a/src/avr/src/pwm_spindle.h +++ b/src/avr/src/pwm_spindle.h @@ -31,4 +31,5 @@ void pwm_spindle_init(); void pwm_spindle_deinit(); void pwm_spindle_set(float speed); +float pwm_spindle_get(); void pwm_spindle_stop(); diff --git a/src/avr/src/spindle.c b/src/avr/src/spindle.c index bc931ad..0af9ccb 100644 --- a/src/avr/src/spindle.c +++ b/src/avr/src/spindle.c @@ -28,56 +28,90 @@ #include "spindle.h" #include "config.h" -#include "pwm_spindle.h" -#include "huanyang.h" #include "pgmspace.h" +#include + typedef enum { SPINDLE_TYPE_DISABLED, - SPINDLE_TYPE_PWM, - SPINDLE_TYPE_HUANYANG, +#define SPINDLE(NAME) SPINDLE_TYPE_##NAME, +#include "spindle.def" +#undef SPINDLE } spindle_type_t; +// Function decls +#define SPINDLE(NAME) \ + void NAME##_init(); \ + void NAME##_deinit(); \ + void NAME##_set(float speed); \ + float NAME##_get(); \ + void NAME##_stop(); +#include "spindle.def" +#undef SPINDLE + + typedef struct { spindle_type_t type; float speed; bool reversed; + float min_rpm; + float max_rpm; } spindle_t; static spindle_t spindle = {SPINDLE_TYPE_DISABLED,}; -void spindle_init() {} - - void spindle_set_speed(float speed) { spindle.speed = speed; + bool negative = speed < 0; + if (spindle.max_rpm <= fabs(speed)) speed = negative ? -1 : 1; + else if (fabs(speed) < spindle.min_rpm) speed = 0; + else speed /= spindle.max_rpm; + if (spindle.reversed) speed = -speed; switch (spindle.type) { case SPINDLE_TYPE_DISABLED: break; - case SPINDLE_TYPE_PWM: pwm_spindle_set(speed); break; - case SPINDLE_TYPE_HUANYANG: hy_set(speed); break; +#define SPINDLE(NAME) case SPINDLE_TYPE_##NAME: NAME##_set(speed); break; +#include "spindle.def" +#undef SPINDLE } } -float spindle_get_speed() {return spindle.speed;} +float spindle_get_speed() { + float speed = 0; + + switch (spindle.type) { + case SPINDLE_TYPE_DISABLED: break; +#define SPINDLE(NAME) case SPINDLE_TYPE_##NAME: speed = NAME##_get(); break; +#include "spindle.def" +#undef SPINDLE + } + + return speed * spindle.max_rpm; +} void spindle_stop() { switch (spindle.type) { case SPINDLE_TYPE_DISABLED: break; - case SPINDLE_TYPE_PWM: pwm_spindle_stop(); break; - case SPINDLE_TYPE_HUANYANG: hy_stop(); break; +#define SPINDLE(NAME) case SPINDLE_TYPE_##NAME: NAME##_stop(); break; +#include "spindle.def" +#undef SPINDLE } } +bool spindle_is_reversed() {return spindle.reversed;} +static void _update_speed() {spindle_set_speed(spindle.speed);} + + +// Var callbacks uint8_t get_spindle_type() {return spindle.type;} @@ -87,16 +121,18 @@ void set_spindle_type(uint8_t value) { switch (spindle.type) { case SPINDLE_TYPE_DISABLED: break; - case SPINDLE_TYPE_PWM: pwm_spindle_deinit(); break; - case SPINDLE_TYPE_HUANYANG: hy_deinit(); break; +#define SPINDLE(NAME) case SPINDLE_TYPE_##NAME: NAME##_deinit(); break; +#include "spindle.def" +#undef SPINDLE } spindle.type = (spindle_type_t)value; switch (spindle.type) { case SPINDLE_TYPE_DISABLED: break; - case SPINDLE_TYPE_PWM: pwm_spindle_init(); break; - case SPINDLE_TYPE_HUANYANG: hy_init(); break; +#define SPINDLE(NAME) case SPINDLE_TYPE_##NAME: NAME##_init(); break; +#include "spindle.def" +#undef SPINDLE } spindle_set_speed(speed); @@ -104,7 +140,8 @@ void set_spindle_type(uint8_t value) { } -bool spindle_is_reversed() {return spindle.reversed;} +void set_speed(float speed) {spindle_set_speed(speed);} +float get_speed() {return spindle_get_speed();} bool get_spin_reversed() {return spindle.reversed;} @@ -116,6 +153,7 @@ void set_spin_reversed(bool reversed) { } -// Var callbacks -void set_speed(float speed) {spindle_set_speed(speed);} -float get_speed() {return spindle_get_speed();} +float get_max_spin() {return spindle.max_rpm;} +void set_max_spin(float value) {spindle.max_rpm = value; _update_speed();} +float get_min_spin() {return spindle.min_rpm;} +void set_min_spin(float value) {spindle.min_rpm = value; _update_speed();} diff --git a/src/avr/src/spindle.def b/src/avr/src/spindle.def new file mode 100644 index 0000000..1022568 --- /dev/null +++ b/src/avr/src/spindle.def @@ -0,0 +1,30 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2018, Buildbotics LLC + All rights reserved. + + This file ("the software") is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License, + version 2 as published by the Free Software Foundation. You should + have received a copy of the GNU General Public License, version 2 + along with the software. If not, see . + + The software 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the software. If not, see + . + + For information regarding this software email: + "Joseph Coffland" + +\******************************************************************************/ + +SPINDLE(pwm_spindle) +SPINDLE(huanyang) +SPINDLE(yl600) diff --git a/src/avr/src/spindle.h b/src/avr/src/spindle.h index 5473877..b15eb00 100644 --- a/src/avr/src/spindle.h +++ b/src/avr/src/spindle.h @@ -29,7 +29,7 @@ #include -void spindle_init(); + void spindle_set_speed(float speed); float spindle_get_speed(); void spindle_stop(); diff --git a/src/avr/src/usart.c b/src/avr/src/usart.c index 55876a6..a8e4658 100644 --- a/src/avr/src/usart.c +++ b/src/avr/src/usart.c @@ -95,7 +95,86 @@ static int _usart_putchar(char c, FILE *f) { } -void usart_init(void) { +static void _set_baud(USART_t *port, uint16_t bsel, uint8_t bscale) { + port->BAUDCTRLB = (uint8_t)((bscale << 4) | (bsel >> 8)); + port->BAUDCTRLA = bsel; + port->CTRLB |= USART_CLK2X_bm; +} + + +void usart_set_baud(USART_t *port, baud_t baud) { + // The BSEL / BSCALE values provided below assume a 32 Mhz clock + // With CTRLB CLK2X is set + // See http://www.avrcalc.elektronik-projekt.de/xmega/baud_rate_calculator + + switch (baud) { + case USART_BAUD_9600: _set_baud(port, 3325, 0b1101); break; + case USART_BAUD_19200: _set_baud(port, 3317, 0b1100); break; + case USART_BAUD_38400: _set_baud(port, 3301, 0b1011); break; + case USART_BAUD_57600: _set_baud(port, 1095, 0b1100); break; + case USART_BAUD_115200: _set_baud(port, 1079, 0b1011); break; + case USART_BAUD_230400: _set_baud(port, 1047, 0b1010); break; + case USART_BAUD_460800: _set_baud(port, 983, 0b1001); break; + case USART_BAUD_921600: _set_baud(port, 107, 0b1011); break; + case USART_BAUD_500000: _set_baud(port, 1, 0b0010); break; + case USART_BAUD_1000000: _set_baud(port, 1, 0b0001); break; + } +} + + +void usart_set_parity(USART_t *port, parity_t parity) { + uint8_t reg = port->CTRLC & ~USART_PMODE_gm; + + switch (parity) { + case USART_NONE: reg |= USART_PMODE_DISABLED_gc; break; + case USART_EVEN: reg |= USART_PMODE_EVEN_gc; break; + case USART_ODD: reg |= USART_PMODE_ODD_gc; break; + } + + port->CTRLC = reg; +} + + +void usart_set_stop(USART_t *port, stop_t stop) { + switch (stop) { + case USART_1STOP: port->CTRLC &= ~USART_SBMODE_bm; break; + case USART_2STOP: port->CTRLC |= USART_SBMODE_bm; break; + } +} + + +void usart_set_bits(USART_t *port, bits_t bits) { + uint8_t reg = port->CTRLC & ~USART_CHSIZE_gm; + + switch (bits) { + case USART_5BITS: reg |= USART_CHSIZE_5BIT_gc; break; + case USART_6BITS: reg |= USART_CHSIZE_6BIT_gc; break; + case USART_7BITS: reg |= USART_CHSIZE_7BIT_gc; break; + case USART_8BITS: reg |= USART_CHSIZE_8BIT_gc; break; + case USART_9BITS: reg |= USART_CHSIZE_9BIT_gc; break; + } + + port->CTRLC = reg; +} + + +void usart_init_port(USART_t *port, baud_t baud, parity_t parity, bits_t bits, + stop_t stop) { + // Set baud rate + usart_set_baud(port, baud); + + // Async, no parity, 8 data bits, 1 stop bit + port->CTRLC = USART_CMODE_ASYNCHRONOUS_gc; + usart_set_parity(port, parity); + usart_set_bits(port, bits); + usart_set_stop(port, stop); + + // Configure receiver and transmitter + port->CTRLB |= USART_RXEN_bm | USART_TXEN_bm; +} + + +void usart_init() { // Setup ring buffer tx_buf_init(); rx_buf_init(); @@ -109,15 +188,9 @@ void usart_init(void) { DIRSET_PIN(SERIAL_TX_PIN); // Tx Output DIRCLR_PIN(SERIAL_RX_PIN); // Rx Input - // Set baud rate - usart_set_baud(SERIAL_BAUD); - - // No parity, 8 data bits, 1 stop bit - SERIAL_PORT.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | - USART_CHSIZE_8BIT_gc; - - // Configure receiver and transmitter - SERIAL_PORT.CTRLB |= USART_RXEN_bm | USART_TXEN_bm; + // Configure port + usart_init_port(&SERIAL_PORT, SERIAL_BAUD, USART_NONE, USART_8BITS, + USART_1STOP); PMIC.CTRL |= PMIC_HILVLEN_bm; // Interrupt level on @@ -135,37 +208,6 @@ void usart_init(void) { } -static void _set_baud(USART_t *port, uint16_t bsel, uint8_t bscale) { - port->BAUDCTRLB = (uint8_t)((bscale << 4) | (bsel >> 8)); - port->BAUDCTRLA = bsel; - port->CTRLB |= USART_CLK2X_bm; -} - - -void usart_set_port_baud(USART_t *port, int baud) { - // The BSEL / BSCALE values provided below assume a 32 Mhz clock - // With CTRLB CLK2X is set - // See http://www.avrcalc.elektronik-projekt.de/xmega/baud_rate_calculator - - switch (baud) { - case USART_BAUD_9600: _set_baud(port, 3325, 0b1101); break; - case USART_BAUD_19200: _set_baud(port, 3317, 0b1100); break; - case USART_BAUD_38400: _set_baud(port, 3301, 0b1011); break; - case USART_BAUD_57600: _set_baud(port, 1095, 0b1100); break; - case USART_BAUD_115200: _set_baud(port, 1079, 0b1011); break; - case USART_BAUD_230400: _set_baud(port, 1047, 0b1010); break; - case USART_BAUD_460800: _set_baud(port, 983, 0b1001); break; - case USART_BAUD_921600: _set_baud(port, 107, 0b1011); break; - case USART_BAUD_500000: _set_baud(port, 1, 0b0010); break; - case USART_BAUD_1000000: _set_baud(port, 1, 0b0001); break; - } -} - - -void usart_set_baud(int baud) { - usart_set_port_baud(&SERIAL_PORT, baud); -} - void usart_set(int flag, bool enable) { if (enable) usart_flags |= flag; diff --git a/src/avr/src/usart.h b/src/avr/src/usart.h index 77a6349..b61bc42 100644 --- a/src/avr/src/usart.h +++ b/src/avr/src/usart.h @@ -37,7 +37,7 @@ #define USART_RX_RING_BUF_SIZE 256 -enum { +typedef enum { USART_BAUD_9600, USART_BAUD_19200, USART_BAUD_38400, @@ -48,7 +48,8 @@ enum { USART_BAUD_921600, USART_BAUD_500000, USART_BAUD_1000000 -}; +} baud_t; + enum { USART_CRLF = 1 << 0, @@ -57,9 +58,37 @@ enum { USART_FLUSH = 1 << 3, }; + +typedef enum { + USART_NONE, + USART_EVEN, + USART_ODD, +} parity_t; + + +typedef enum { + USART_1STOP, + USART_2STOP, +} stop_t; + + +typedef enum { + USART_5BITS, + USART_6BITS, + USART_7BITS, + USART_8BITS, + USART_9BITS, +} bits_t; + + +void usart_set_baud(USART_t *port, baud_t baud); +void usart_set_parity(USART_t *port, parity_t parity); +void usart_set_stop(USART_t *port, stop_t stop); +void usart_set_bits(USART_t *port, bits_t bits); +void usart_init_port(USART_t *port, baud_t baud, parity_t parity, bits_t bits, + stop_t stop); + void usart_init(); -void usart_set_port_baud(USART_t *port, int baud); -void usart_set_baud(int baud); void usart_set(int flag, bool enable); bool usart_is_set(int flags); void usart_putc(char c); diff --git a/src/avr/src/vars.def b/src/avr/src/vars.def index c2d3246..91a8b95 100644 --- a/src/avr/src/vars.def +++ b/src/avr/src/vars.def @@ -83,36 +83,37 @@ VAR(analog_input, ai, f32, ANALOG, 0, 0, "Analog input pins") // Spindle VAR(spindle_type, st, u8, 0, 1, 1, "DISABLED=0, PWM=1 or HUANYANG=2") +VAR(speed, s, f32, 0, 1, 1, "Current spindle speed") VAR(spin_reversed, sr, b8, 0, 1, 1, "Reverse spin") VAR(max_spin, sx, f32, 0, 1, 1, "Maximum spindle speed") VAR(min_spin, sm, f32, 0, 1, 1, "Minimum spindle speed") + +// PWM spindle +VAR(pwm_invert, pi, b8, 0, 1, 1, "Inverted spindle PWM") VAR(pwm_min_duty, nd, f32, 0, 1, 1, "Minimum PWM duty cycle") VAR(pwm_max_duty, md, f32, 0, 1, 1, "Maximum PWM duty cycle") VAR(pwm_duty, pd, f32, 0, 0, 1, "Current PWM duty cycle") VAR(pwm_freq, sf, u16, 0, 1, 1, "Spindle PWM frequency in Hz") -// PWM spindle -VAR(pwm_invert, pi, b8, 0, 1, 1, "Inverted spindle PWM") - // Modbus spindle VAR(modbus_debug, hb, b8, 0, 1, 1, "Modbus debugging") +VAR(modbus_id, hi, u8, 0, 1, 1, "Modbus ID") VAR(modbus_baud, mb, u8, 0, 1, 1, "Modbus BAUD rate") +VAR(modbus_parity, ma, u8, 0, 1, 1, "Modbus parity") +VAR(modbus_stop, ms, u8, 0, 1, 1, "Modbus stop bits") VAR(modbus_connected, he, b8, 0, 0, 1, "Modbus connected") // Huanyang spindle -VAR(hy_id, hi, u8, 0, 1, 1, "Modbus ID") -VAR(hy_freq, hz, f32, 0, 0, 1, "Modbus actual freq") -VAR(hy_current, hc, f32, 0, 0, 1, "Modbus actual current") -VAR(hy_rpm, hr, u16, 0, 0, 1, "Modbus actual RPM") -VAR(hy_temp, ht, u16, 0, 0, 1, "Modbus temperature") -VAR(hy_max_freq, hx, f32, 0, 0, 1, "Modbus max freq") -VAR(hy_min_freq, hm, f32, 0, 0, 1, "Modbus min freq") -VAR(hy_rated_rpm, hq, u16, 0, 0, 1, "Modbus rated RPM") -VAR(hy_status, hs, u8, 0, 0, 1, "Modbus status flags") +VAR(hy_freq, hz, f32, 0, 0, 1, "Huanyang actual freq") +VAR(hy_current, hc, f32, 0, 0, 1, "Huanyang actual current") +VAR(hy_temp, ht, u16, 0, 0, 1, "Huanyang temperature") +VAR(hy_max_freq, hx, f32, 0, 0, 1, "Huanyang max freq") +VAR(hy_min_freq, hm, f32, 0, 0, 1, "Huanyang min freq") +VAR(hy_rated_rpm, hq, u16, 0, 0, 1, "Huanyang rated RPM") +VAR(hy_status, hs, u8, 0, 0, 1, "Huanyang status flags") // Machine state VAR(id, id, u32, 0, 1, 1, "Last executed command ID") -VAR(speed, s, f32, 0, 1, 1, "Current spindle speed") VAR(feed_override, fo, f32, 0, 1, 1, "Feed rate override") VAR(speed_override, so, f32, 0, 1, 1, "Spindle speed override") VAR(optional_pause, op, b8, 0, 1, 1, "Optional pause state") diff --git a/src/avr/src/vfd/huanyang.c b/src/avr/src/vfd/huanyang.c new file mode 100644 index 0000000..259c006 --- /dev/null +++ b/src/avr/src/vfd/huanyang.c @@ -0,0 +1,331 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2018, Buildbotics LLC + All rights reserved. + + This file ("the software") is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License, + version 2 as published by the Free Software Foundation. You should + have received a copy of the GNU General Public License, version 2 + along with the software. If not, see . + + The software 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the software. If not, see + . + + For information regarding this software email: + "Joseph Coffland" + +\******************************************************************************/ + +#include "huanyang.h" +#include "config.h" +#include "modbus.h" +#include "report.h" + +#include +#include + + +/* + Huanyang is not quite Modbus compliant. + + Message format is: + + [id][func][length][data][checksum] + + Where: + + id - 1-byte Peer ID + func - 1-byte One of hy_func_t + length - 1-byte Length data in bytes + data - length bytes - Command arguments + checksum - 16-bit CRC: x^16 + x^15 + x^2 + 1 (0xa001) initial: 0xffff +*/ + + +// See VFD manual pg56 3.1.3 +typedef enum { + HUANYANG_FUNC_READ = 1, // [len=1][hy_addr_t] + HUANYANG_FUNC_WRITE, // [len=3][hy_addr_t][data] + HUANYANG_CTRL_WRITE, // [len=1][hy_ctrl_state_t] + HUANYANG_CTRL_READ, // [len=1][hy_ctrl_addr_t] + HUANYANG_FREQ_WRITE, // [len=2][freq] + HUANYANG_RESERVED_1, + HUANYANG_RESERVED_2, + HUANYANG_LOOP_TEST, +} hy_func_t; + + +// Sent in HUANYANG_CTRL_WRITE +// See VFD manual pg57 3.1.3.c +typedef enum { + HUANYANG_RUN = 1 << 0, + HUANYANG_FORWARD = 1 << 1, + HUANYANG_REVERSE = 1 << 2, + HUANYANG_STOP = 1 << 3, + HUANYANG_REV_FWD = 1 << 4, + HUANYANG_JOG = 1 << 5, + HUANYANG_JOG_FORWARD = 1 << 6, + HUANYANG_JOG_REVERSE = 1 << 7, +} hy_ctrl_state_t; + + +// Returned by HUANYANG_CTRL_WRITE +// See VFD manual pg57 3.1.3.c +typedef enum { + HUANYANG_STATUS_RUN = 1 << 0, + HUANYANG_STATUS_JOG = 1 << 1, + HUANYANG_STATUS_COMMAND_REV = 1 << 2, + HUANYANG_STATUS_RUNNING = 1 << 3, + HUANYANG_STATUS_JOGGING = 1 << 4, + HUANYANG_STATUS_JOGGING_REV = 1 << 5, + HUANYANG_STATUS_BRAKING = 1 << 6, + HUANYANG_STATUS_TRACK_START = 1 << 7, +} hy_ctrl_status_t; + + +// Sent in HUANYANG_CTRL_READ +// See VFD manual pg57 3.1.3.d +typedef enum { + HUANYANG_TARGET_FREQ, + HUANYANG_ACTUAL_FREQ, + HUANYANG_ACTUAL_CURRENT, + HUANYANG_ACTUAL_RPM, + HUANYANG_DCV, + HUANYANG_ACV, + HUANYANG_COUNTER, + HUANYANG_TEMPERATURE, +} hy_ctrl_addr_t; + + +static struct { + uint8_t state; + hy_func_t func; + uint8_t data[4]; + uint8_t bytes; + uint8_t response; + + bool shutdown; + bool changed; + float speed; + + float actual_freq; + float actual_current; + uint16_t actual_rpm; + uint16_t temperature; + + float max_freq; + float min_freq; + uint16_t rated_rpm; + + uint8_t status; +} hy = {0}; + + +static void _func_read(hy_addr_t addr) { + hy.func = HUANYANG_FUNC_READ; + hy.bytes = 2; + hy.response = 4; + hy.data[0] = 1; + hy.data[1] = addr; +} + + +static void _ctrl_write(hy_ctrl_state_t state) { + hy.func = HUANYANG_CTRL_WRITE; + hy.bytes = 2; + hy.response = 2; + hy.data[0] = 1; + hy.data[1] = state; +} + + +static void _ctrl_read(hy_ctrl_addr_t addr) { + hy.func = HUANYANG_CTRL_READ; + hy.bytes = 2; + hy.response = 4; + hy.data[0] = 1; + hy.data[1] = addr; +} + + +static void _freq_write(uint16_t freq) { + hy.func = HUANYANG_FREQ_WRITE; + hy.bytes = 3; + hy.response = 3; + hy.data[0] = 2; + hy.data[1] = freq >> 8; + hy.data[2] = freq; +} + + +static void _func_read_response(hy_addr_t addr, uint16_t value) { + switch (addr) { + case HY_PD005_MAX_FREQUENCY: hy.max_freq = value * 0.01; break; + case HY_PD011_FREQUENCY_LOWER_LIMIT: hy.min_freq = value * 0.01; break; + case HY_PD144_RATED_MOTOR_RPM: hy.rated_rpm = value; break; + default: break; + } +} + + +static void _ctrl_read_response(hy_ctrl_addr_t addr, uint16_t value) { + switch (addr) { + case HUANYANG_ACTUAL_FREQ: hy.actual_freq = value * 0.01; break; + case HUANYANG_ACTUAL_CURRENT: hy.actual_current = value * 0.01; break; + case HUANYANG_ACTUAL_RPM: hy.actual_rpm = value; break; + case HUANYANG_TEMPERATURE: hy.temperature = value; break; + default: break; + } +} + + +static uint16_t _read_word(const uint8_t *data) { + return (uint16_t)data[0] << 8 | data[1]; +} + + +static void _handle_response(hy_func_t func, const uint8_t *data) { + switch (func) { + case HUANYANG_FUNC_READ: + _func_read_response((hy_addr_t)*data, _read_word(data + 1)); + break; + + case HUANYANG_FUNC_WRITE: break; + case HUANYANG_CTRL_WRITE: hy.status = *data; break; + + case HUANYANG_CTRL_READ: + _ctrl_read_response((hy_ctrl_addr_t)*data, _read_word(data + 1)); + break; + + case HUANYANG_FREQ_WRITE: break; + default: break; + } +} + + +static void _next_command(); + + +static void _reset(bool halt) { + // Save settings + float speed = hy.speed; + + // Clear state + memset(&hy, 0, sizeof(hy)); + + // Restore settings + hy.speed = speed; + hy.changed = true; + + if (!halt) _next_command(); +} + + +static void _modbus_cb(uint8_t func, uint8_t bytes, const uint8_t *data) { + if (!data) _reset(true); + + else if (bytes == *data + 1) { + _handle_response((hy_func_t)func, data + 1); + + if (func == HUANYANG_CTRL_WRITE && hy.shutdown) { + _reset(true); + modbus_deinit(); + return; + } + + // Next command + if (++hy.state == 9) { + hy.state = 5; + report_request(); + } + + // Update freq + if (hy.shutdown || (hy.changed && 4 < hy.state)) hy.state = 0; + } + + _next_command(); +} + + +static void _next_command() { + switch (hy.state) { + case 0: { // Update direction + hy_ctrl_state_t state = HUANYANG_STOP; + if (!hy.shutdown) { + if (0 < hy.speed) + state = (hy_ctrl_state_t)(HUANYANG_RUN | HUANYANG_FORWARD); + else if (hy.speed < 0) + state = (hy_ctrl_state_t)(HUANYANG_RUN | HUANYANG_REV_FWD); + } + + _ctrl_write(state); + break; + } + + case 1: _func_read(HY_PD005_MAX_FREQUENCY); break; + case 2: _func_read(HY_PD011_FREQUENCY_LOWER_LIMIT); break; + case 3: _func_read(HY_PD144_RATED_MOTOR_RPM); break; + + case 4: { // Update freqency + // Compute frequency in Hz + float freq = fabs(hy.speed * hy.max_freq); + + // Frequency write command + _freq_write(freq * 100); + hy.changed = false; + break; + } + + case 5: _ctrl_read(HUANYANG_ACTUAL_FREQ); break; + case 6: _ctrl_read(HUANYANG_ACTUAL_CURRENT); break; + case 7: _ctrl_read(HUANYANG_ACTUAL_RPM); break; + case 8: _ctrl_read(HUANYANG_TEMPERATURE); break; + } + + // Send command + modbus_func(hy.func, hy.bytes, hy.data, hy.response, _modbus_cb); +} + + +void huanyang_init() { + modbus_init(); + _reset(false); +} + + +void huanyang_deinit() {hy.shutdown = true;} + + +void huanyang_set(float speed) { + if (hy.speed != speed) { + hy.speed = speed; + hy.changed = true; + } +} + + +float huanyang_get() {return hy.actual_freq / hy.max_freq;} + + +void huanyang_stop() { + huanyang_set(0); + _reset(false); +} + + +float get_hy_freq() {return hy.actual_freq;} +float get_hy_current() {return hy.actual_current;} +uint16_t get_hy_temp() {return hy.temperature;} +float get_hy_max_freq() {return hy.max_freq;} +float get_hy_min_freq() {return hy.min_freq;} +uint16_t get_hy_rated_rpm() {return hy.rated_rpm;} +float get_hy_status() {return hy.status;} diff --git a/src/avr/src/vfd/huanyang.h b/src/avr/src/vfd/huanyang.h new file mode 100644 index 0000000..c5b88af --- /dev/null +++ b/src/avr/src/vfd/huanyang.h @@ -0,0 +1,224 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2018, Buildbotics LLC + All rights reserved. + + This file ("the software") is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License, + version 2 as published by the Free Software Foundation. You should + have received a copy of the GNU General Public License, version 2 + along with the software. If not, see . + + The software 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the software. If not, see + . + + For information regarding this software email: + "Joseph Coffland" + +\******************************************************************************/ + +#pragma once + + +void huanyang_init(); +void huanyang_deinit(); +void huanyang_set(float speed); +float huanyang_get(); +void huanyang_stop(); + + +/// See Huanyang VFD user manual +typedef enum { + HY_PD000_PARAMETER_LOCK, + HY_PD001_SOURCE_OF_OPERATION_COMMANDS, + HY_PD002_SOURCE_OF_OPERATING_FREQUENCY, + HY_PD003_MAIN_FREQUENCY, + HY_PD004_BASE_FREQUENCY, + HY_PD005_MAX_FREQUENCY, + HY_PD006_INTERMEDIATE_FREQUENCY, + HY_PD007_MIN_FREQUENCY, + HY_PD008_MAX_VOLTAGE, + HY_PD009_INTERMEDIATE_VOLTAGE, + HY_PD010_MIN_VOLTAGE, + HY_PD011_FREQUENCY_LOWER_LIMIT, + HY_PD012_RESERVED, + HY_PD013_PARAMETER_RESET, + HY_PD014_ACCEL_TIME_1, + HY_PD015_DECEL_TIME_1, + HY_PD016_ACCEL_TIME_2, + HY_PD017_DECEL_TIME_2, + HY_PD018_ACCEL_TIME_3, + HY_PD019_DECEL_TIME_3, + HY_PD020_ACCEL_TIME_4, + HY_PD021_DECEL_TIME_4, + HY_PD022_FACTORY_RESERVED, + HY_PD023_REV_ROTATION_SELECT, + HY_PD024_STOP_KEY, + HY_PD025_STARTING_MODE, + HY_PD026_STOPPING_MODE, + HY_PD027_STARTING_FREQUENCY, + HY_PD028_STOPPING_FREQUENCY, + HY_PD029_DC_BRAKING_TIME_AT_START, + HY_PD030_DC_BRAKING_TIME_AT_STOP, + HY_PD031_DC_BRAKING_VOLTAGE_LEVEL, + HY_PD032_FREQUENCY_TRACK_TIME, + HY_PD033_CURRENT_LEVEL_FOR_FREQUENCY_TRACK, + HY_PD034_VOLTAGE_RISE_TIME_FOR_FREQUENCY_TRACK, + HY_PD035_FREQUENCY_STEP_LENGTH, + HY_PD036, + HY_PD037, + HY_PD038, + HY_PD039, + HY_PD040, + HY_PD041_CARRIER_FREQUENCY, + HY_PD042_JOGGING_FREQUENCY, + HY_PD043_S_CURVE_TIME, + HY_PD044_MULTI_INPUT_FOR, + HY_PD045_MULTI_INPUT_REV, + HY_PD046_MULTI_INPUT_RST, + HY_PD047_MULTI_INPUT_SPH, + HY_PD048_MULTI_INPUT_SPM, + HY_PD049_MULTI_INPUT_SPL, + HY_PD050_MULTI_OUTPUT_DRV, + HY_PD051_MULTI_OUTPUT_UPF, + HY_PD052_MULTI_OUTPUT_FA_FB_FC, + HY_PD053_MULTI_OUTPUT_KA_KB, + HY_PD054_MULTI_OUTPUT_AM, + HY_PD055_AM_ANALOG_OUTPUT_GAIN, + HY_PD056_SKIP_FREQUENCY_1, + HY_PD057_SKIP_FREQUENCY_2, + HY_PD058_SKIP_FREQUENCY_3, + HY_PD059_SKIP_FREQUENCY_RANGE, + HY_PD060_UNIFORM_FREQUENCY_1, + HY_PD061_UNIFORM_FREQUENCY_2, + HY_PD062_UNIFORM_FREQUENCY_RANGE, + HY_PD063_TIMER_1_TIME, + HY_PD064_TIMER_2_TIME, + HY_PD065_COUNTING_VALUE, + HY_PD066_INTERMEDIATE_COUNTER, + HY_PD067, + HY_PD068, + HY_PD069, + HY_PD070_ANALOG_INPUT, + HY_PD071_ANALOG_FILTERING_CONSTANT, + HY_PD072_HIGHER_ANALOG_FREQUENCY, + HY_PD073_LOWER_ANALOG_FREQUENCY, + HY_PD074_BIAS_DIRECTION_AT_HIGHER_FREQUENCY, + HY_PD075_BIAS_DIRECTION_AT_LOWER_FREQUENCY, + HY_PD076_ANALOG_NEGATIVE_BIAS_REVERSE, + HY_PD077_UP_DOWN_FUNCTION, + HY_PD078_UP_DOWN_SPEED, + HY_PD079, + HY_PD080_PLC_OPERATION, + HY_PD081_AUTO_PLC, + HY_PD082_PLC_RUNNING_DIRECTION, + HY_PD083, + HY_PD084_PLC_RAMP_TIME, + HY_PD085, + HY_PD086_FREQUENCY_2, + HY_PD087_FREQUENCY_3, + HY_PD088_FREQUENCY_4, + HY_PD089_FREQUENCY_5, + HY_PD090_FREQUENCY_6, + HY_PD091_FREQUENCY_7, + HY_PD092_FREQUENCY_8, + HY_PD093, + HY_PD094, + HY_PD095, + HY_PD096, + HY_PD097, + HY_PD098, + HY_PD099, + HY_PD100, + HY_PD101_TIMER_1, + HY_PD102_TIMER_2, + HY_PD103_TIMER_3, + HY_PD104_TIMER_4, + HY_PD105_TIMER_5, + HY_PD106_TIMER_6, + HY_PD107_TIMER_7, + HY_PD108_TIMER_8, + HY_PD109, + HY_PD110, + HY_PD111, + HY_PD112, + HY_PD113, + HY_PD114, + HY_PD115, + HY_PD116, + HY_PD117_AUTOPLC_MEMORY_FUNCTION, + HY_PD118_OVER_VOLTAGE_STALL_PREVENTION, + HY_PD119_STALL_PREVENTION_LEVEL_AT_RAMP_UP, + HY_PD120_STALL_PREVENTION_LEVEL_AT_CONSTANT_SPEED, + HY_PD121_DECEL_TIME_FOR_STALL_PREVENTION_AT_CONSTANT_SPEED, + HY_PD122_STALL_PREVENTION_LEVEL_AT_DECELERATION, + HY_PD123_OVER_TORQUE_DETECT_MODE, + HY_PD124_OVER_TORQUE_DETECT_LEVEL, + HY_PD125_OVER_TORQUE_DETECT_TIME, + HY_PD126, + HY_PD127, + HY_PD128, + HY_PD129, + HY_PD130_NUMBER_OF_AUXILIARY_PUMP, + HY_PD131_CONTINUOUS_RUNNING_TIME_OF_AUXILIARY_PUMPS, + HY_PD132_INTERLOCKING_TIME_OF_AUXILIARY_PUMP, + HY_PD133_HIGH_SPEED_RUNNING_TIME, + HY_PD134_LOW_SPEED_RUNNING_TIME, + HY_PD135_STOPPING_VOLTAGE_LEVEL, + HY_PD136_LASTING_TIME_OF_STOPPING_VOLTAGE_LEVEL, + HY_PD137_WAKEUP_VOLTAGE_LEVEL, + HY_PD138_SLEEP_FREQUENCY, + HY_PD139_LASTING_TIME_OF_SLEEP_FREQUENCY, + HY_PD140, + HY_PD141_RATED_MOTOR_VOLTAGE, + HY_PD142_RATED_MOTOR_CURRENT, + HY_PD143_MOTOR_POLE_NUMBER, + HY_PD144_RATED_MOTOR_RPM, + HY_PD145_AUTO_TORQUE_COMPENSATION, + HY_PD146_MOTOR_NO_LOAD_CURRENT, + HY_PD147_MOTOR_SLIP_COMPENSATION, + HY_PD148, + HY_PD149, + HY_PD150_AUTO_VOLTAGE_REGULATION, + HY_PD151_AUTO_ENERGY_SAVING, + HY_PD152_FAULT_RESTART_TIME, + HY_PD153_RESTART_AFTER_INSTANTANEOUS_STOP, + HY_PD154_ALLOWABLE_POWER_BREAKDOWN_TIME, + HY_PD155_NUMBER_OF_ABNORMAL_RESTART, + HY_PD156_PROPORTIONAL_CONSTANT, + HY_PD157_INTEGRAL_TIME, + HY_PD158_DIFFERENTIAL_TIME, + HY_PD159_TARGET_VALUE, + HY_PD160_PID_TARGET_VALUE, + HY_PD161_PID_UPPER_LIMIT, + HY_PD162_PID_LOWER_LIMIT, + HY_PD163_COMMUNICATION_ADDRESSES, + HY_PD164_COMMUNICATION_BAUD_RATE, + HY_PD165_COMMUNICATION_DATA_METHOD, + HY_PD166, + HY_PD167, + HY_PD168, + HY_PD169, + HY_PD170_DISPLAY_ITEMS, + HY_PD171_DISPLAY_ITEMS_OPEN, + HY_PD172_FAULT_CLEAR, + HY_PD173, + HY_PD174_RATED_CURRENT_OF_INVERTER, + HY_PD175_INVERTER_MODEL, + HY_PD176_INVERTER_FREQUENCY_STANDARD, + HY_PD177_FAULT_RECORD_1, + HY_PD178_FAULT_RECORD_2, + HY_PD179_FAULT_RECORD_3, + HY_PD180_FAULT_RECORD_4, + HY_PD181_SOFTWARE_VERSION, + HY_PD182_MANUFACTURE_DATE, + HY_PD183_SERIAL_NO, +} hy_addr_t; diff --git a/src/avr/src/vfd/yl600.c b/src/avr/src/vfd/yl600.c new file mode 100644 index 0000000..e91e901 --- /dev/null +++ b/src/avr/src/vfd/yl600.c @@ -0,0 +1,128 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2018, Buildbotics LLC + All rights reserved. + + This file ("the software") is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License, + version 2 as published by the Free Software Foundation. You should + have received a copy of the GNU General Public License, version 2 + along with the software. If not, see . + + The software 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the software. If not, see + . + + For information regarding this software email: + "Joseph Coffland" + +\******************************************************************************/ + + +#include "modbus.h" + +#include + + +#define P(H, L) ((H) << 8 | (L)) + + +enum { + P00_00_MAIN_FREQ = P(0, 0), + P00_01_START_STOP_SOURCE = P(0, 1), + P00_04_HIGEST_OUTPUT_FREQ = P(0, 4), + P01_00_DIRECTION = P(1, 0), + P07_00_FREQ_1 = P(7, 0), + P07_08_FREQ_SOURCE_1 = P(7, 8), +}; + + +static struct { + uint8_t state; + bool changed; + bool shutdown; + + float speed; + uint16_t max_freq; + float actual_speed; +} s = {0}; + + +static void _next_command(); + + +static uint16_t _speed2freq(float speed) {return fabs(speed) * s.max_freq;} +static float _freq2speed(uint16_t freq) {return (float)freq / s.max_freq;} + + +static void _next_state(bool ok) { + if (!ok) s.state = 0; + + else if (s.changed) { + s.changed = false; + s.state = 0; + + } else if (++s.state == 5) s.state = 4; + + _next_command(); +} + + +static void _read_cb(bool ok, uint16_t addr, uint16_t value) { + if (ok) + switch (addr) { + case P00_04_HIGEST_OUTPUT_FREQ: s.max_freq = value; break; + case P07_00_FREQ_1: s.actual_speed = _freq2speed(value); break; + } + + _next_state(ok); +} + + +static void _write_cb(bool ok, uint16_t addr) {_next_state(ok);} + + +static void _next_command() { + if (s.shutdown) { + modbus_deinit(); + return; + } + + // TODO spin direction + switch (s.state) { + case 0: modbus_read(P00_04_HIGEST_OUTPUT_FREQ, _read_cb); break; + case 1: modbus_write(P00_01_START_STOP_SOURCE, 1, _write_cb); break; + case 2: modbus_write(P07_08_FREQ_SOURCE_1, 1, _write_cb); break; + case 3: modbus_write(P07_00_FREQ_1, _speed2freq(s.speed), _write_cb); break; + case 4: modbus_read(P07_00_FREQ_1, _read_cb); break; + } +} + + +void yl600_init() { + modbus_init(); + s.shutdown = false; + _next_command(); +} + + +void yl600_deinit() {s.shutdown = true;} + + +void yl600_set(float speed) { + if (s.speed != speed) { + s.speed = speed; + s.changed = true; + } +} + + +float yl600_get() {return s.actual_speed;} +void yl600_stop() {yl600_set(0);} diff --git a/src/jade/templates/indicators.jade b/src/jade/templates/indicators.jade index b3d1163..17a4c90 100644 --- a/src/jade/templates/indicators.jade +++ b/src/jade/templates/indicators.jade @@ -182,11 +182,11 @@ script#indicators-template(type="text/x-template") th Current tr - td {{state['hr']}} RPM + td {{state['s']}} RPM th Speed th.separator - td {{state['ht']}} ℃ - th Temp + td + th table.legend tr diff --git a/src/jade/templates/tool-view.jade b/src/jade/templates/tool-view.jade index d22e5d3..8be586f 100644 --- a/src/jade/templates/tool-view.jade +++ b/src/jade/templates/tool-view.jade @@ -41,16 +41,8 @@ script#tool-view-template(type="text/x-template") templated-input(v-for="templ in template['pwm-spindle']", :name="$key", :model.sync="pwmSpindle[$key]", :template="templ") - div(v-if="get_type() == 'HUANYANG'") - h2 Huanyang VFD - form.pure-form.pure-form-aligned - fieldset - templated-input(v-for="templ in template['huanyang-spindle']", - :name="$key", :model.sync="huanyangSpindle[$key]", - :template="templ") - - div(v-if="get_type() == 'MODBUS'") - h2 Modbus Compatiable VFD + div(v-if="get_type() != 'DISABLED' && get_type() != 'PWM'") + h2 Modbus Configuration form.pure-form.pure-form-aligned fieldset templated-input(v-for="templ in template['modbus-spindle']", diff --git a/src/js/tool-view.js b/src/js/tool-view.js index 731942b..498fe3c 100644 --- a/src/js/tool-view.js +++ b/src/js/tool-view.js @@ -37,7 +37,6 @@ module.exports = { return { tool: {}, pwmSpindle: {}, - huanyangSpindle: {}, modbusSpindle: {} } }, @@ -82,7 +81,6 @@ module.exports = { this.$set('tool["' + key + '"]', template[key].default); this.update_tool('pwm'); - this.update_tool('huanyang'); this.update_tool('modbus'); }.bind(this)); } diff --git a/src/resources/config-template.json b/src/resources/config-template.json index c1bf508..412698e 100644 --- a/src/resources/config-template.json +++ b/src/resources/config-template.json @@ -153,7 +153,7 @@ "tool": { "spindle-type": { "type": "enum", - "values": ["Disabled", "PWM", "Huanyang", "Modbus"], + "values": ["Disabled", "PWM", "Huanyang", "YL600"], "default": "Disabled", "code": "st" }, @@ -162,6 +162,20 @@ "default": "false", "code": "sr" }, + "max-spin": { + "type": "float", + "unit": "RPM", + "min": 0, + "default": 10000, + "code": "sx" + }, + "min-spin": { + "type": "float", + "unit": "RPM", + "min": 0, + "default": 0, + "code": "sm" + }, "tool-enable-mode": { "type": "enum", "values": ["disabled", "lo-hi", "hi-lo", "tri-lo", "tri-hi", "lo-tri", @@ -178,37 +192,33 @@ } }, - "huanyang-spindle": { + "modbus-spindle": { "bus-id": { "type": "int", "default": "1", "code": "hi" - } - }, - - "modbus-spindle": { - "modbus-id": { - "type": "int", + }, + "baud": { + "type": "enum", + "values": ["9600", "19200", "38400", "57600", "115200"], + "default": "9600", + "code": "mb" + }, + "parity": { + "type": "enum", + "values": ["None", "Even", "Odd"], + "default": "None", + "code": "ma" + }, + "stop-bits": { + "type": "enum", + "values": ["1", "2"], "default": "1", - "code": "bi" + "code": "ms" } }, "pwm-spindle": { - "max-spin": { - "type": "float", - "unit": "RPM", - "min": 0, - "default": 10000, - "code": "sx" - }, - "min-spin": { - "type": "float", - "unit": "RPM", - "min": 0, - "default": 0, - "code": "sm" - }, "pwm-inverted": { "type": "bool", "default": "false",