diff --git a/CHANGELOG.md b/CHANGELOG.md index 2137766a..ea1c76d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,14 +5,16 @@ Please add a note of your changes below this heading if you make a Pull Request. * Added periodic sending of encoder position on CAN ### Changed - +* Modified encoder offset calibration to work correctly when calib_scan_distance is not a multiple of 4pi +* Moved thermistors from being a top level object to belonging to Motor objects. Also changed errors: thermistor errors rolled into motor errors * Use DMA for DRV8301 setup * Make NVM configuration code more dynamic so that the layout doesn't have to be known at compile time. * GPIO initialization logic was changed. GPIOs now need to be explicitly set to the mode corresponding to the feature that they are used by. See `.config.gpioX_mode`. * Previously, if two components used the same interrupt pin (e.g. step input for axis0 and axis1) then the one that was configured later would override the other one. Now this is no longer the case (the old component remains the owner of the pin). -### API Miration Notes +### API Migration Notes +* `odrive.axis.fet_thermistor`, `odrive.axis.motor_thermistor` moved to `odrive.axis.motor` object * `enable_uart` and `uart_baudrate` were renamed to `enable_uart0` and `uart0_baudrate`. * `enable_i2c_instead_of_can` was replaced by the separate settings `enable_i2c0` and `enable_can0`. * `.motor.gate_driver` was moved to `.gate_driver`. diff --git a/Firmware/Board/v3/board.cpp b/Firmware/Board/v3/board.cpp index d2b0afbb..716329cf 100644 --- a/Firmware/Board/v3/board.cpp +++ b/Firmware/Board/v3/board.cpp @@ -58,20 +58,26 @@ OnboardThermistorCurrentLimiter fet_thermistors[AXIS_COUNT] = { } }; +OffboardThermistorCurrentLimiter motor_thermistors[AXIS_COUNT]; + Motor motors[AXIS_COUNT] = { { &htim1, // timer TIM_1_8_PERIOD_CLOCKS, // control_deadline 1.0f / SHUNT_RESISTANCE, // shunt_conductance [S] m0_gate_driver, // gate_driver - m0_gate_driver // opamp + m0_gate_driver, // opamp + fet_thermistors[0], + motor_thermistors[0] }, { &htim8, // timer (3 * TIM_1_8_PERIOD_CLOCKS) / 2, // control_deadline 1.0f / SHUNT_RESISTANCE, // shunt_conductance [S] m1_gate_driver, // gate_driver - m1_gate_driver // opamp + m1_gate_driver, // opamp + fet_thermistors[1], + motor_thermistors[1] } }; @@ -101,7 +107,6 @@ MechanicalBrake mechanical_brakes[AXIS_COUNT]; SensorlessEstimator sensorless_estimators[AXIS_COUNT]; Controller controllers[AXIS_COUNT]; TrapezoidalTrajectory trap[AXIS_COUNT]; -OffboardThermistorCurrentLimiter motor_thermistors[AXIS_COUNT]; std::array axes{{ { @@ -112,8 +117,6 @@ std::array axes{{ encoders[0], // encoder sensorless_estimators[0], // sensorless_estimator controllers[0], // controller - fet_thermistors[0], // fet_thermistor - motor_thermistors[0], // motor_thermistor motors[0], // motor trap[0], // trap endstops[0], endstops[1], // min_endstop, max_endstop @@ -132,8 +135,6 @@ std::array axes{{ encoders[1], // encoder sensorless_estimators[1], // sensorless_estimator controllers[1], // controller - fet_thermistors[1], // fet_thermistor - motor_thermistors[1], // motor_thermistor motors[1], // motor trap[1], // trap endstops[2], endstops[3], // min_endstop, max_endstop diff --git a/Firmware/MotorControl/axis.cpp b/Firmware/MotorControl/axis.cpp index 649d4dd2..5b685d87 100644 --- a/Firmware/MotorControl/axis.cpp +++ b/Firmware/MotorControl/axis.cpp @@ -14,8 +14,6 @@ Axis::Axis(int axis_num, Encoder& encoder, SensorlessEstimator& sensorless_estimator, Controller& controller, - OnboardThermistorCurrentLimiter& fet_thermistor, - OffboardThermistorCurrentLimiter& motor_thermistor, Motor& motor, TrapezoidalTrajectory& trap, Endstop& min_endstop, @@ -28,25 +26,15 @@ Axis::Axis(int axis_num, encoder_(encoder), sensorless_estimator_(sensorless_estimator), controller_(controller), - fet_thermistor_(fet_thermistor), - motor_thermistor_(motor_thermistor), motor_(motor), trap_traj_(trap), min_endstop_(min_endstop), max_endstop_(max_endstop), - mechanical_brake_(mechanical_brake), - current_limiters_(make_array( - static_cast(&fet_thermistor), - static_cast(&motor_thermistor))), - thermistors_(make_array( - static_cast(&fet_thermistor), - static_cast(&motor_thermistor))) + mechanical_brake_(mechanical_brake) { encoder_.axis_ = this; sensorless_estimator_.axis_ = this; controller_.axis_ = this; - fet_thermistor_.axis_ = this; - motor_thermistor.axis_ = this; motor_.axis_ = this; trap_traj_.axis_ = this; min_endstop_.axis_ = this; @@ -180,9 +168,6 @@ bool Axis::do_checks() { // Sub-components should use set_error which will propegate to this error_ motor_.effective_current_lim(); - for (ThermistorCurrentLimiter* thermistor : thermistors_) { - thermistor->do_checks(); - } motor_.do_checks(); // encoder_.do_checks(); // sensorless_estimator_.do_checks(); @@ -201,11 +186,10 @@ bool Axis::do_checks() { // @brief Update all esitmators bool Axis::do_updates() { // Sub-components should use set_error which will propegate to this error_ - for (ThermistorCurrentLimiter* thermistor : thermistors_) { - thermistor->update(); - } encoder_.update(); sensorless_estimator_.update(); + motor_.fet_thermistor_.update(); + motor_.motor_thermistor_.update(); min_endstop_.update(); max_endstop_.update(); bool ret = check_for_errors(); diff --git a/Firmware/MotorControl/axis.hpp b/Firmware/MotorControl/axis.hpp index c25a4dc1..a128c688 100644 --- a/Firmware/MotorControl/axis.hpp +++ b/Firmware/MotorControl/axis.hpp @@ -97,8 +97,6 @@ public: Encoder& encoder, SensorlessEstimator& sensorless_estimator, Controller& controller, - OnboardThermistorCurrentLimiter& fet_thermistor, - OffboardThermistorCurrentLimiter& motor_thermistor, Motor& motor, TrapezoidalTrajectory& trap, Endstop& min_endstop, @@ -227,19 +225,12 @@ public: Encoder& encoder_; SensorlessEstimator& sensorless_estimator_; Controller& controller_; - OnboardThermistorCurrentLimiter& fet_thermistor_; - OffboardThermistorCurrentLimiter& motor_thermistor_; Motor& motor_; TrapezoidalTrajectory& trap_traj_; Endstop& min_endstop_; Endstop& max_endstop_; MechanicalBrake& mechanical_brake_; - // List of current_limiters and thermistors to - // provide easy iteration. - std::array current_limiters_; - std::array thermistors_; - osThreadId thread_id_; const uint32_t stack_size_ = 2048; // Bytes volatile bool thread_id_valid_ = false; diff --git a/Firmware/MotorControl/encoder.cpp b/Firmware/MotorControl/encoder.cpp index 4fe75689..06ee616b 100644 --- a/Firmware/MotorControl/encoder.cpp +++ b/Firmware/MotorControl/encoder.cpp @@ -228,10 +228,13 @@ bool Encoder::run_offset_calibration() { else return false; - // go to motor zero phase for start_lock_duration to get ready to scan + // go to start position of forward scan for start_lock_duration to get ready to scan int i = 0; axis_->run_control_loop([&](){ - if (!axis_->motor_.enqueue_voltage_timings(voltage_magnitude, 0.0f)) + float phase = wrap_pm_pi(0 - config_.calib_scan_distance / 2.0f); + float v_alpha = voltage_magnitude * our_arm_cos_f32(phase); + float v_beta = voltage_magnitude * our_arm_sin_f32(phase); + if (!axis_->motor_.enqueue_voltage_timings(v_alpha, v_beta)) return false; // error set inside enqueue_voltage_timings axis_->motor_.log_timing(TIMING_LOG_ENC_CALIB); return ++i < start_lock_duration * current_meas_hz; diff --git a/Firmware/MotorControl/main.cpp b/Firmware/MotorControl/main.cpp index 27d7be86..301fe1c4 100644 --- a/Firmware/MotorControl/main.cpp +++ b/Firmware/MotorControl/main.cpp @@ -50,8 +50,8 @@ static bool config_read_all() { config_manager.read(&axes[i].max_endstop_.config_) && config_manager.read(&axes[i].mechanical_brake_.config_) && config_manager.read(&motors[i].config_) && - config_manager.read(&fet_thermistors[i].config_) && - config_manager.read(&axes[i].motor_thermistor_.config_) && + config_manager.read(&motors[i].fet_thermistor_.config_) && + config_manager.read(&motors[i].motor_thermistor_.config_) && config_manager.read(&axes[i].config_); } return success; @@ -70,8 +70,8 @@ static bool config_write_all() { config_manager.write(&axes[i].max_endstop_.config_) && config_manager.write(&axes[i].mechanical_brake_.config_) && config_manager.write(&motors[i].config_) && - config_manager.write(&fet_thermistors[i].config_) && - config_manager.write(&axes[i].motor_thermistor_.config_) && + config_manager.write(&motors[i].fet_thermistor_.config_) && + config_manager.write(&motors[i].motor_thermistor_.config_) && config_manager.write(&axes[i].config_); } return success; @@ -90,8 +90,8 @@ static void config_clear_all() { axes[i].max_endstop_.config_ = {}; axes[i].mechanical_brake_.config_ = {}; motors[i].config_ = {}; - fet_thermistors[i].config_ = {}; - axes[i].motor_thermistor_.config_ = {}; + motors[i].fet_thermistor_.config_ = {}; + motors[i].motor_thermistor_.config_ = {}; axes[i].clear_config(); } } @@ -104,6 +104,7 @@ static bool config_apply_all() { && axes[i].min_endstop_.apply_config() && axes[i].max_endstop_.apply_config() && motors[i].apply_config() + && motors[i].motor_thermistor_.apply_config() && axes[i].apply_config(); } return success; diff --git a/Firmware/MotorControl/motor.cpp b/Firmware/MotorControl/motor.cpp index 95526d1d..bb4e9f58 100644 --- a/Firmware/MotorControl/motor.cpp +++ b/Firmware/MotorControl/motor.cpp @@ -10,13 +10,19 @@ Motor::Motor(TIM_HandleTypeDef* timer, uint16_t control_deadline, float shunt_conductance, TGateDriver& gate_driver, - TOpAmp& opamp) : + TOpAmp& opamp, + OnboardThermistorCurrentLimiter& fet_thermistor, + OffboardThermistorCurrentLimiter& motor_thermistor) : timer_(timer), control_deadline_(control_deadline), shunt_conductance_(shunt_conductance), gate_driver_(gate_driver), - opamp_(opamp) { + opamp_(opamp), + fet_thermistor_(fet_thermistor), + motor_thermistor_(motor_thermistor) { apply_config(); + fet_thermistor_.motor_ = this; + motor_thermistor_.motor_ = this; } // @brief Arms the PWM outputs that belong to this motor. @@ -110,7 +116,16 @@ bool Motor::do_checks() { set_error(ERROR_DRV_FAULT); return false; } - + if (!motor_thermistor_.do_checks()) { + axis_->error_ |= Axis::ERROR_MOTOR_FAILED; + set_error(ERROR_MOTOR_THERMISTOR_OVER_TEMP); + return false; + } + if (!fet_thermistor_.do_checks()) { + axis_->error_ |= Axis::ERROR_MOTOR_FAILED; + set_error(ERROR_FET_THERMISTOR_OVER_TEMP); + return false; + } return true; } @@ -124,11 +139,9 @@ float Motor::effective_current_lim() { current_lim = std::min(current_lim, axis_->motor_.current_control_.max_allowed_current); } - // Apply axis current limiters - for (const CurrentLimiter* const limiter : axis_->current_limiters_) { - current_lim = std::min(current_lim, limiter->get_current_limit(config_.current_lim)); - } - + // Apply thermistor current limiters + current_lim = std::min(current_lim, motor_thermistor_.get_current_limit(config_.current_lim)); + current_lim = std::min(current_lim, fet_thermistor_.get_current_limit(config_.current_lim)); effective_current_lim_ = current_lim; return effective_current_lim_; diff --git a/Firmware/MotorControl/motor.hpp b/Firmware/MotorControl/motor.hpp index 3f61725a..088b300a 100644 --- a/Firmware/MotorControl/motor.hpp +++ b/Firmware/MotorControl/motor.hpp @@ -99,7 +99,9 @@ public: uint16_t control_deadline, float shunt_conductance, TGateDriver& gate_driver, - TOpAmp& opamp); + TOpAmp& opamp, + OnboardThermistorCurrentLimiter& fet_thermistor, + OffboardThermistorCurrentLimiter& motor_thermistor); bool arm(); void disarm(); @@ -130,6 +132,8 @@ public: const float shunt_conductance_; TGateDriver& gate_driver_; TOpAmp& opamp_; + OnboardThermistorCurrentLimiter& fet_thermistor_; + OffboardThermistorCurrentLimiter& motor_thermistor_; Config_t config_; Axis* axis_ = nullptr; // set by Axis constructor diff --git a/Firmware/MotorControl/thermistor.cpp b/Firmware/MotorControl/thermistor.cpp index 4d16ae61..755b2908 100644 --- a/Firmware/MotorControl/thermistor.cpp +++ b/Firmware/MotorControl/thermistor.cpp @@ -14,8 +14,7 @@ ThermistorCurrentLimiter::ThermistorCurrentLimiter(uint16_t adc_channel, temperature_(NAN), temp_limit_lower_(temp_limit_lower), temp_limit_upper_(temp_limit_upper), - enabled_(enabled), - error_(ERROR_NONE) + enabled_(enabled) { } @@ -26,8 +25,6 @@ void ThermistorCurrentLimiter::update() { bool ThermistorCurrentLimiter::do_checks() { if (enabled_ && temperature_ >= temp_limit_upper_ + 5) { - error_ = ERROR_OVER_TEMP; - axis_->error_ |= Axis::ERROR_OVER_TEMP; return false; } return true; @@ -69,6 +66,12 @@ OffboardThermistorCurrentLimiter::OffboardThermistorCurrentLimiter() : decode_pin(); } +bool OffboardThermistorCurrentLimiter::apply_config() { + config_.parent = this; + decode_pin(); + return true; +} + void OffboardThermistorCurrentLimiter::decode_pin() { adc_channel_ = channel_from_gpio(get_gpio(config_.gpio_pin)); } diff --git a/Firmware/MotorControl/thermistor.hpp b/Firmware/MotorControl/thermistor.hpp index a7c29cfe..757a40fa 100644 --- a/Firmware/MotorControl/thermistor.hpp +++ b/Firmware/MotorControl/thermistor.hpp @@ -1,7 +1,7 @@ #ifndef __THERMISTOR_HPP #define __THERMISTOR_HPP -class Axis; // declared in axis.hpp +class Motor; // declared in motor.hpp #include "current_limiter.hpp" #include @@ -28,8 +28,7 @@ public: const float& temp_limit_lower_; const float& temp_limit_upper_; const bool& enabled_; - Error error_; - Axis* axis_ = nullptr; // set by Axis constructor + Motor* motor_ = nullptr; // set by Motor::apply_config() }; class OnboardThermistorCurrentLimiter : public ThermistorCurrentLimiter, public ODriveIntf::OnboardThermistorCurrentLimiterIntf { @@ -68,6 +67,8 @@ public: Config_t config_; + bool apply_config(); + private: void decode_pin(); }; diff --git a/Firmware/fibre/python/fibre/discovery.py b/Firmware/fibre/python/fibre/discovery.py index 72548ce8..d8781c7c 100644 --- a/Firmware/fibre/python/fibre/discovery.py +++ b/Firmware/fibre/python/fibre/discovery.py @@ -109,10 +109,13 @@ def find_all(path, serial_number, # Save JSON to cache if not cache_path is None: logger.debug("Creating new JSON cache file {}".format(cache_path)) - os.makedirs(cache_dir, exist_ok=True) - with open(cache_path, 'w+') as json_cache: - json_cache.write(json_string) - logger.debug("Saved JSON to cache file {}".format(cache_path)) + try: + os.makedirs(cache_dir, exist_ok=True) + with open(cache_path, 'w+') as json_cache: + json_cache.write(json_string) + logger.debug("Saved JSON to cache file {}".format(cache_path)) + except Exception as ex: + logger.warn("Failed to cache JSON: {}".format(ex)) channel._interface_definition_crc = json_crc16 diff --git a/Firmware/odrive-interface.yaml b/Firmware/odrive-interface.yaml index 1d2583f1..a5d04289 100644 --- a/Firmware/odrive-interface.yaml +++ b/Firmware/odrive-interface.yaml @@ -355,7 +355,8 @@ interfaces: bit: 17 doc: the min endstop was not enabled during homing OverTemp: - doc: Check `fet_thermistor.error` and `motor_thermistor.error` for more information. + # unused + doc: Check `motor.error` for more details. step_dir_active: readonly bool current_state: readonly AxisState requested_state: AxisState @@ -440,8 +441,6 @@ interfaces: # status_reg_2: readonly uint32 # ctrl_reg_1: readonly uint32 # ctrl_reg_2: readonly uint32 - fet_thermistor: OnboardThermistorCurrentLimiter - motor_thermistor: OffboardThermistorCurrentLimiter motor: Motor controller: Controller encoder: Encoder @@ -495,7 +494,6 @@ interfaces: ODrive.OnboardThermistorCurrentLimiter: c_is_class: True attributes: - error: ThermistorCurrentLimiter.Error temperature: readonly float32 config: c_is_class: False @@ -511,7 +509,6 @@ interfaces: ODrive.OffboardThermistorCurrentLimiter: c_is_class: True attributes: - error: ThermistorCurrentLimiter.Error temperature: readonly float32 config: c_is_class: False @@ -609,6 +606,8 @@ interfaces: DcBusOverRegenCurrent: {doc: too much current pushed into the power supply} DcBusOverCurrent: {doc: too much current pulled out of the power supply} ModulationIsNan: + MotorThermistorOverTemp: {doc: The motor thermistor measured a temperature above motor.motor_thermistor.config.temp_limit_upper} + FetThermistorOverTemp: {doc: The inverter thermistor measured a temperature above motor.fet_thermistor.config.temp_limit_upper} armed_state: typeargs: {fibre.Property.mode: readonly} values: @@ -623,6 +622,8 @@ interfaces: DC_calib_phC: {type: float32, c_name: DC_calib_.phC} phase_current_rev_gain: float32 effective_current_lim: readonly float32 + fet_thermistor: OnboardThermistorCurrentLimiter + motor_thermistor: OffboardThermistorCurrentLimiter current_control: c_is_class: False attributes: @@ -1024,12 +1025,6 @@ valuetypes: doc: Endstops must be enabled to use this feature. - ODrive.ThermistorCurrentLimiter.Error: - nullflag: None - flags: - OverTemp: - doc: The thermistor temperature upper limit was exceeded. - ODrive.Encoder.Mode: values: Incremental: diff --git a/GUI/server/odrive_server.py b/GUI/server/odrive_server.py index 0ee37692..7501d7fa 100644 --- a/GUI/server/odrive_server.py +++ b/GUI/server/odrive_server.py @@ -58,8 +58,12 @@ def discovered_device(device): while globals()['inUse']: time.sleep(0.1) globals()['odrives'][odrive_name] = device + globals()['odrives_status'][odrive_name] = True print("Found " + str(serial_number)) print("odrive list: " + str([key for key in globals()['odrives'].keys()])) + # tell GUI the status of known ODrives (previously connected and then disconnected ODrives will be "False") + socketio.emit('odrives-status', json.dumps(globals()['odrives_status'])) + # triggers a getODrives socketio message socketio.emit('odrive-found') def start_discovery(): @@ -68,9 +72,12 @@ def start_discovery(): shutdown = fibre.Event() fibre.find_all("usb", None, discovered_device, shutdown, shutdown, log) -def handle_disconnect(): +def handle_disconnect(odrive_name): print("lost odrive") - #socketio.emit('odrive-disconnected') + globals()['odrives_status'][odrive_name] = False + # emit the whole list of odrive statuses + # in the GUI, mark and use status as ODrive state. + socketio.emit('odrives-status', json.dumps(globals()['odrives_status'])) @socketio.on('findODrives') def getODrives(message): @@ -115,8 +122,9 @@ def get_odrives(data): odriveDict = {} #for (index, odrv) in enumerate(globals()['odrives']): # odriveDict["odrive" + str(index)] = dictFromRO(odrv) - for key in globals()['odrives'].keys(): - odriveDict[key] = dictFromRO(globals()['odrives'][key]) + for key in globals()['odrives_status'].keys(): + if globals()['odrives_status'][key] == True: + odriveDict[key] = dictFromRO(globals()['odrives'][key]) globals()['inUse'] = False emit('odrives', json.dumps(odriveDict)) @@ -126,10 +134,11 @@ def get_property(message): # will be {"path": "odriveX.axisY.blah.blah"} while globals()['inUse']: time.sleep(0.1) - globals()['inUse'] = True - val = getVal(globals()['odrives'], message["path"].split('.')) - globals()['inUse'] = False - emit('ODriveProperty', json.dumps({"path": message["path"], "val": val})) + if globals()['odrives_status'][message["path"].split('.')[0]]: + globals()['inUse'] = True + val = getVal(globals()['odrives'], message["path"].split('.')) + globals()['inUse'] = False + emit('ODriveProperty', json.dumps({"path": message["path"], "val": val})) @socketio.on('setProperty') def set_property(message): @@ -194,7 +203,7 @@ def postVal(odrives, keyList, value, argType): else: pass # dont support that type yet except fibre.protocol.ChannelBrokenException: - handle_disconnect() + handle_disconnect(odrv) except: print("exception in postVal") @@ -210,7 +219,7 @@ def getVal(odrives, keyList): else: return RO.get_value() except fibre.protocol.ChannelBrokenException: - handle_disconnect() + handle_disconnect(odrv) except: print("exception in getVal") return 0 @@ -235,7 +244,7 @@ def callFunc(odrives, keyList): if isinstance(RO, fibre.remote_object.RemoteFunction): RO.__call__() except fibre.protocol.ChannelBrokenException: - handle_disconnect() + handle_disconnect(odrv) except: print("fcn call failed") @@ -252,7 +261,11 @@ if __name__ == "__main__": import odrive.utils # for dump_errors() import fibre + # global for holding references to all connected odrives globals()['odrives'] = {} + # global dict {'odriveX': True/False} where True/False reflects status of connection + # on handle_disconnect, set it to False. On connection, set it to True + globals()['odrives_status'] = {} globals()['discovered_devices'] = [] # spinlock globals()['inUse'] = False diff --git a/GUI/src/App.vue b/GUI/src/App.vue index 2c9f52e6..fd64070a 100644 --- a/GUI/src/App.vue +++ b/GUI/src/App.vue @@ -56,9 +56,6 @@ :axis="axis.name" :odrives="odrives" > - @@ -129,22 +126,6 @@ export default { currentDash: function () { return this.$store.state.currentDash; }, - ODriveConnected: function () { - // if server and odrive disconnected, disconnected - // if server connected and odrive disco, connecting - // if server and odrive connected, connected - let ret; - if (this.$store.state.serverConnected && this.$store.state.ODriveConnected) { - ret = "connected"; - } - else if (this.$store.state.serverConnected && !this.$store.state.ODriveConnected) { - ret = "connecting..."; - } - else { - ret = "disconnected"; - } - return ret; - }, samplingText: function () { let ret; if (this.$store.state.sampling) { diff --git a/GUI/src/assets/odriveEnums.json b/GUI/src/assets/odriveEnums.json index 3bc38b81..02dbc47a 100644 --- a/GUI/src/assets/odriveEnums.json +++ b/GUI/src/assets/odriveEnums.json @@ -29,9 +29,6 @@ "AXIS_STATE_ENCODER_DIR_FIND" : 10, "AXIS_STATE_HOMING" : 11, -"THERMISTOR_CURRENT_LIMITER_ERROR_NONE" : 0, -"THERMISTOR_CURRENT_LIMITER_ERROR_OVER_TEMP" : 1, - "ENCODER_MODE_INCREMENTAL" : 0, "ENCODER_MODE_HALL" : 1, "ENCODER_MODE_SINCOS" : 2, @@ -102,6 +99,8 @@ "MOTOR_ERROR_DC_BUS_OVER_REGEN_CURRENT" : 16384, "MOTOR_ERROR_DC_BUS_OVER_CURRENT" : 32768, "MOTOR_ERROR_MODULATION_IS_NAN" : 65536, +"MOTOR_ERROR_MOTOR_THERMISTOR_OVER_TEMP" : 131072, +"MOTOR_ERROR_FET_THERMISTOR_OVER_TEMP" : 262144, "ARMED_STATE_DISARMED" : 0, "ARMED_STATE_WAITING_FOR_TIMINGS" : 1, diff --git a/GUI/src/assets/wizard/configTemplate.json b/GUI/src/assets/wizard/configTemplate.json index e6406e96..6fbae6a0 100644 --- a/GUI/src/assets/wizard/configTemplate.json +++ b/GUI/src/assets/wizard/configTemplate.json @@ -17,7 +17,8 @@ "config": { "mode": null, "use_index": null, - "cpr": null + "cpr": null, + "calib_scan_distance": null } }, "controller": { @@ -51,7 +52,8 @@ "config": { "mode": null, "use_index": null, - "cpr": null + "cpr": null, + "calib_scan_distance": null } }, "controller": { diff --git a/GUI/src/background.js b/GUI/src/background.js index c21e39a4..382155fe 100644 --- a/GUI/src/background.js +++ b/GUI/src/background.js @@ -23,25 +23,42 @@ protocol.registerSchemesAsPrivileged([ // function to get determine correct command for python function getPyCmd() { - let spawnRet = spawnSync('python',['-V']); - let vString; - if (spawnRet.stdout.toString().length > 1){ - vString = spawnRet.stdout.toString(); + // call both 'python' and 'python3' to figure out the correct command + let spawnRet = spawnSync('python', ['-V']); + let success = spawnRet.status != null; + let outputString; + let cmd = ''; + if (success) { + if (spawnRet.stdout.toString().length > 1) { + outputString = spawnRet.stdout.toString(); + } + else { + outputString = spawnRet.stderr.toString(); + } + if (outputString.includes("Python 3")) { + cmd = 'python'; + } } - else { - vString = spawnRet.stderr.toString(); - } - - if (vString.split(' ')[1].split('.')[0] == '2') { - return 'python3'; - } - else { - return 'python'; + if (cmd == '') { + spawnRet = spawnSync('python3', ['-V']); + success = spawnRet.status != null; + if (success) { + if (spawnRet.stdout.toString().length > 1) { + outputString = spawnRet.stdout.toString(); + } + else { + outputString = spawnRet.stderr.toString(); + } + if (outputString.includes("Python 3")) { + cmd = 'python3'; + } + } } + return cmd; } function createWindow() { - + // Create the browser window. win = new BrowserWindow({ width: 800, @@ -125,15 +142,19 @@ app.on('ready', async () => { // launch python server on event from renderer process (gui) and pipe stdout/stderr to it ipcMain.on('start-server', () => { server = spawn(getPyCmd(), effectiveCommand); - server.stdout.on('data',function(data) { - console.log(data.toString('utf8')); + server.stdout.on('data', function (data) { + try { + console.log(data.toString('utf8')); + } catch (error) { + console.log(error); + } try { win.webContents.send('server-stdout', String(data.toString('utf8'))); } catch (error) { console.log(error); } }); - server.stderr.on('data',function(data) { + server.stderr.on('data', function (data) { console.log(data.toString('utf8')); try { win.webContents.send('server-stderr', String(data.toString('utf8'))); diff --git a/GUI/src/components/Axis.vue b/GUI/src/components/Axis.vue index 0bd9f87d..8d0806ba 100644 --- a/GUI/src/components/Axis.vue +++ b/GUI/src/components/Axis.vue @@ -2,7 +2,7 @@
{{ axis }}
@@ -66,6 +66,9 @@ const motorErrors = { 0x00002000: "MOTOR_ERROR_BRAKE_DUTY_CYCLE_NAN", 0x00004000: "MOTOR_ERROR_DC_BUS_OVER_REGEN_CURRENT", 0x00008000: "MOTOR_ERROR_DC_BUS_OVER_CURRENT", + 0x00010000: "MOTOR_ERROR_MODULATION_IS_NAN", + 0x00020000: "MOTOR_ERROR_MOTOR_THERMISTOR_OVER_TEMP", + 0x00040000: "MOTOR_ERROR_FET_THERMISTOR_OVER_TEMP", }; let encoderErrors = { @@ -107,6 +110,9 @@ export default { }; }, computed: { + connected() { + return this.$store.state.ODrivesConnected[this.axis.split('.')[0]]; + }, axisErrorMsg() { let retMsg = "none"; let errCode = this.axisErr; @@ -125,10 +131,7 @@ export default { errs.push(axisErrors[errKey]); } } - retMsg = ""; - for (const err of errs) { - retMsg = retMsg + " " + err; - } + retMsg = errs.join(', '); } return retMsg; @@ -150,10 +153,7 @@ export default { errs.push(motorErrors[errKey]); } } - retMsg = ""; - for (const err of errs) { - retMsg = retMsg + " " + err; - } + retMsg = errs.join(', '); } return retMsg; @@ -175,10 +175,7 @@ export default { errs.push(encoderErrors[errKey]); } } - retMsg = ""; - for (const err of errs) { - retMsg = retMsg + " " + err; - } + retMsg = errs.join(', '); } return retMsg; @@ -195,10 +192,7 @@ export default { errs.push(controllerErrors[errKey]); } } - retMsg = ""; - for (const err of errs) { - retMsg = retMsg + " " + err; - } + retMsg = errs.join(', '); } return retMsg; @@ -238,14 +232,18 @@ export default { created() { // set up timeout loop for grabbing axis error values let update = () => { - fetchParam(this.axis + ".error"); - fetchParam(this.axis + '.motor.error'); - fetchParam(this.axis + '.controller.error'); - fetchParam(this.axis + '.encoder.error'); - this.axisErr = getVal(this.axis + '.error'); - this.motorErr = getVal(this.axis + '.motor.error'); - this.controllerErr = getVal(this.axis + '.controller.error'); - this.encoderErr = getVal(this.axis + '.encoder.error'); + // Do we have an active connection to the ODrive that contains this axis? + if (this.$store.state.ODrivesConnected[this.axis.split('.')[0]]) { + fetchParam(this.axis + ".error"); + fetchParam(this.axis + '.motor.error'); + fetchParam(this.axis + '.controller.error'); + fetchParam(this.axis + '.encoder.error'); + this.axisErr = getVal(this.axis + '.error'); + this.motorErr = getVal(this.axis + '.motor.error'); + this.controllerErr = getVal(this.axis + '.controller.error'); + this.encoderErr = getVal(this.axis + '.encoder.error'); + } + // ODrive not connected setTimeout(update, 1000); } update(); @@ -279,4 +277,8 @@ export default { color: black; margin-left: 0px; } + +.inactive { + color: grey; +} \ No newline at end of file diff --git a/GUI/src/components/actions/Action.vue b/GUI/src/components/actions/Action.vue index ce896c31..d78948b6 100644 --- a/GUI/src/components/actions/Action.vue +++ b/GUI/src/components/actions/Action.vue @@ -40,7 +40,7 @@ export default { methods: { newVal: function (e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.value = val; console.log("input = " + e.target.value + ", val = " + this.value); this.$store.commit("setActionVal", {dashID: this.dashID, actionID: this.id, val: this.value}); diff --git a/GUI/src/components/controls/CtrlNumeric.vue b/GUI/src/components/controls/CtrlNumeric.vue index 752dbce6..2e3af0a6 100644 --- a/GUI/src/components/controls/CtrlNumeric.vue +++ b/GUI/src/components/controls/CtrlNumeric.vue @@ -47,8 +47,9 @@ export default { putVal: function (e) { let keys = this.path.split('.'); keys.shift(); + console.log("input recieved: " + e.target.value); let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { putVal(keys.join('.'), val); } }, diff --git a/GUI/src/components/wizard/choices/wizardBrake.vue b/GUI/src/components/wizard/choices/wizardBrake.vue index caef2057..42a69e73 100644 --- a/GUI/src/components/wizard/choices/wizardBrake.vue +++ b/GUI/src/components/wizard/choices/wizardBrake.vue @@ -37,7 +37,7 @@ export default { setBR(e) { console.log("from setBR " + e.target.value); let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.brake_resistance = val; let configStub = undefined; configStub = { diff --git a/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue b/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue index 6395f921..2c296abd 100644 --- a/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue +++ b/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue @@ -26,7 +26,7 @@ export default { methods: { setCPR(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.cpr = val; let configStub = undefined; if (this.data.axis == "axis0") { diff --git a/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue b/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue index 79baa12a..85357d41 100644 --- a/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue +++ b/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue @@ -27,7 +27,7 @@ export default { methods: { setCPR(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.cpr = val; let configStub = undefined; if (this.data.axis == "axis0") { diff --git a/GUI/src/components/wizard/choices/wizardMisc.vue b/GUI/src/components/wizard/choices/wizardMisc.vue index 9aa8f39f..f5aaa484 100644 --- a/GUI/src/components/wizard/choices/wizardMisc.vue +++ b/GUI/src/components/wizard/choices/wizardMisc.vue @@ -100,7 +100,7 @@ export default { }, setVelocityLimit(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.vel_limit = parseFloat(e.target.value); this.vel_set = true; this.sendConfig(); @@ -108,7 +108,7 @@ export default { }, setCurrentLimit(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.current_lim = parseFloat(e.target.value); this.current_set = true; this.sendConfig(); diff --git a/GUI/src/components/wizard/page_components/wizardMotorCal.vue b/GUI/src/components/wizard/page_components/wizardMotorCal.vue index 84dfc84f..43961c4d 100644 --- a/GUI/src/components/wizard/page_components/wizardMotorCal.vue +++ b/GUI/src/components/wizard/page_components/wizardMotorCal.vue @@ -5,8 +5,8 @@