Exploding brake resistors

I’m really pissed off right now, two brake resistors overheated and exploded and I can’t figure out why.

I tried all the steps in the docs, reading every note and comment. But when I try to calibrate the encoder, I hear the power supply fans turning faster (delivering more amps), and after 2 seconds the brake resistor explodes.

Yesterday it happened when I did the AXIS_STATE_FULL_CALIBRATION_SEQUENCE and today after sending the command AXIS_STATE_ENCODER_OFFSET_CALIBRATION.

Here is the full view of commands I sent today:

Connected to ODrive 376236503137 as odrv0
Connected to ODrive 366833663037 as odrv1
In [1]: odrv0
Out[1]:
vbus_voltage = 47.95876693725586 (float)
serial_number = 376236503137 (int)
hw_version_major = 3 (int)
hw_version_minor = 5 (int)
hw_version_variant = 48 (int)
fw_version_major = 0 (int)
fw_version_minor = 4 (int)
fw_version_revision = 6 (int)
fw_version_unreleased = 0 (int)
user_config_loaded = True (bool)
brake_resistor_armed = True (bool)
system_stats:
  uptime = 179853 (int)
  min_heap_space = 18264 (int)
  min_stack_space_axis0 = 7820 (int)
  min_stack_space_axis1 = 7820 (int)
  min_stack_space_comms = 384 (int)
  min_stack_space_usb = 1324 (int)
  min_stack_space_uart = 3964 (int)
  min_stack_space_usb_irq = 1812 (int)
  min_stack_space_startup = 556 (int)
  usb: ...
  i2c: ...
config:
  brake_resistance = 2.0 (float)
  enable_uart = True (bool)
  enable_i2c_instead_of_can = False (bool)
  enable_ascii_protocol_on_usb = True (bool)
  dc_bus_undervoltage_trip_level = 8.0 (float)
  dc_bus_overvoltage_trip_level = 51.840003967285156 (float)
  gpio1_pwm_mapping: ...
  gpio2_pwm_mapping: ...
  gpio3_pwm_mapping: ...
  gpio4_pwm_mapping: ...
axis0:
  error = 0x0004 (int)
  enable_step_dir = False (bool)
  current_state = 1 (int)
  requested_state = 0 (int)
  loop_counter = 1469160 (int)
  config: ...
  get_temp()
  motor: ...
  controller: ...
  encoder: ...
  sensorless_estimator: ...
  trap_traj: ...
axis1:
  error = 0x0005 (int)
  enable_step_dir = False (bool)
  current_state = 1 (int)
  requested_state = 0 (int)
  loop_counter = 1469158 (int)
  config: ...
  get_temp()
  motor: ...
  controller: ...
  encoder: ...
  sensorless_estimator: ...
  trap_traj: ...
can:
  node_id = 0 (int)
  TxMailboxCompleteCallbackCnt = 0 (int)
  TxMailboxAbortCallbackCnt = 0 (int)
  received_msg_cnt = 0 (int)
  received_ack = 0 (int)
  unexpected_errors = 0 (int)
  unhandled_messages = 0 (int)
test_property = 0 (int)
test_function(delta: int)
get_oscilloscope_val(index: int)
get_adc_voltage(gpio: int)
save_configuration()
erase_configuration()
reboot()
enter_dfu_mode()

In [2]: odrv0.error
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~\Anaconda3\lib\site-packages\fibre\shell.py in <module>()
----> 1 odrv0.error

~\Anaconda3\lib\site-packages\fibre\remote_object.py in __getattribute__(self, name)
    243             return attr
    244         else:
--> 245             return object.__getattribute__(self, name)
    246             #raise AttributeError("Attribute {} not found".format(name))
    247

AttributeError: 'RemoteObject' object has no attribute 'error'

In [3]: odrv0.axis0.error
Out[3]: 4

In [4]: odrv0.axis1.error
Out[4]: 5

In [5]: odrv0.axis0.encoder.error
Out[5]: 0

In [6]: odrv0.axis0.motor.error
Out[6]: 0

In [7]: odrv0.config
Out[7]:
brake_resistance = 2.0 (float)
enable_uart = True (bool)
enable_i2c_instead_of_can = False (bool)
enable_ascii_protocol_on_usb = True (bool)
dc_bus_undervoltage_trip_level = 8.0 (float)
dc_bus_overvoltage_trip_level = 51.840003967285156 (float)
gpio1_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)
gpio2_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)
gpio3_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)
gpio4_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)

In [8]: odrv0.axis0.config
Out[8]:
startup_motor_calibration = False (bool)
startup_encoder_index_search = True (bool)
startup_encoder_offset_calibration = False (bool)
startup_closed_loop_control = True (bool)
startup_sensorless_control = False (bool)
enable_step_dir = False (bool)
counts_per_step = 2.0 (float)
ramp_up_time = 0.4000000059604645 (float)
ramp_up_distance = 12.566370964050293 (float)
spin_up_current = 10.0 (float)
spin_up_acceleration = 400.0 (float)
spin_up_target_vel = 400.0 (float)

In [9]: odrv0.axis0.motor.config
Out[9]:
pre_calibrated = True (bool)
pole_pairs = 7 (int)
calibration_current = 10.0 (float)
resistance_calib_max_voltage = 2.0 (float)
phase_inductance = 2.084625702991616e-05 (float)
phase_resistance = 0.03450365364551544 (float)
direction = 1 (int)
motor_type = 0 (int)
current_lim = 10.0 (float)
requested_current_range = 70.0 (float)
current_control_bandwidth = 1000.0 (float)

In [10]: odrv0.axis0.encoder.config
Out[10]:
mode = 0 (int)
use_index = True (bool)
pre_calibrated = True (bool)
idx_search_speed = -10.0 (float)
cpr = 8192 (int)
offset = 4259 (int)
offset_float = 1.4473516941070557 (float)
bandwidth = 1000.0 (float)
calib_range = 0.019999999552965164 (float)

In [11]: odrv0.axis0.motor.config.pre_calibrated = False

In [12]: odrv0.axis0.encoder.config.pre_calibrated = False

In [13]: odrv0.axis1.motor.config.pre_calibrated = False

In [14]: odrv0.axis1.encoder.config.pre_calibrated = False

In [15]: odrv0.axis0.motor.config
Out[15]:
pre_calibrated = False (bool)
pole_pairs = 7 (int)
calibration_current = 10.0 (float)
resistance_calib_max_voltage = 2.0 (float)
phase_inductance = 2.084625702991616e-05 (float)
phase_resistance = 0.03450365364551544 (float)
direction = 1 (int)
motor_type = 0 (int)
current_lim = 10.0 (float)
requested_current_range = 70.0 (float)
current_control_bandwidth = 1000.0 (float)

In [16]: odrv0.axis0.encoder.config
Out[16]:
mode = 0 (int)
use_index = True (bool)
pre_calibrated = False (bool)
idx_search_speed = -10.0 (float)
cpr = 8192 (int)
offset = 4259 (int)
offset_float = 1.4473516941070557 (float)
bandwidth = 1000.0 (float)
calib_range = 0.019999999552965164 (float)

In [17]: odrv0.config
Out[17]:
brake_resistance = 2.0 (float)
enable_uart = True (bool)
enable_i2c_instead_of_can = False (bool)
enable_ascii_protocol_on_usb = True (bool)
dc_bus_undervoltage_trip_level = 8.0 (float)
dc_bus_overvoltage_trip_level = 51.840003967285156 (float)
gpio1_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)
gpio2_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)
gpio3_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)
gpio4_pwm_mapping:
  endpoint = (0, 0) (RemoteProperty)
  min = 0.0 (float)
  max = 0.0 (float)

In [18]: odrv0.axis0.config
Out[18]:
startup_motor_calibration = False (bool)
startup_encoder_index_search = True (bool)
startup_encoder_offset_calibration = False (bool)
startup_closed_loop_control = True (bool)
startup_sensorless_control = False (bool)
enable_step_dir = False (bool)
counts_per_step = 2.0 (float)
ramp_up_time = 0.4000000059604645 (float)
ramp_up_distance = 12.566370964050293 (float)
spin_up_current = 10.0 (float)
spin_up_acceleration = 400.0 (float)
spin_up_target_vel = 400.0 (float)

In [19]: odrv0.axis0.error
Out[19]: 4

In [20]: odrv0.axis0.error = 0

In [21]: odrv0.axis1.error
Out[21]: 5

In [22]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH

In [23]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION

Reconnected to ODrive 366833663037 as odrv1
In [24]:
1 Like

Hm I have never seen that before, and of course that shouldn’t happen. I’m very interested to find out what the issue could be, so we can prevent that from happening again.

I had a look at your configs, as far as I can tell they look fine. I think the next step is to try to find out what components of the brake current command has a problem and when. Can you run some tests with no brake resistor connected (so it doesn’t blow up :wink:) ?

Let’s start on a clean state:

Connected to ODrive 2062376F3548 as odrv0
In [1]: odrv0.erase_configuration()

In [2]: odrv0.reboot()

Wait for the odrive to show up again. Now we want to plot the bus voltage and the brake current, so we can start the liveplotter. Note the -48 offset so they fit nicely around zero. Adjust this if your nominal bus voltage is something else.

In [6]: start_liveplotter(lambda: [odrv0.vbus_voltage-48, odrv0.axis0.motor.current_control.Ibus])
Out[6]: <fibre.utils.Event at 0x1b0605fb438>

Be ready to quickly do a screenshot, because there is no easy way to pause the liveplotter when there is something interesting that happens. Run the following two commands (allowing about 5s for the first one to finish before running the second).

In [7]: odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION

In [8]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION

On my ODrive the result was some small noise on the bus voltage and a perfect flatline of the brake current command. If the ODrive is trying to melt the brake resistor, the yellow line should be holding a large negative value. It will be interesting to see what your ODrive does.

On my plot it looked like this basically the whole time during both commands:

Can you run some tests with no brake resistor connected (so it doesn’t blow up :wink:) ?

I read that when there is no brake resistor connected, the current flows back to the power supply. I’d rather have an exploding resistor than a exploding €300 power supply. Or doesn’t this happen on calibration?

Can you post the exact commands and order of commands I have to use to calibrate the motor and encoder (CUI with index). And enable index search and closed loop control on startup?

I followed the steps on the Getting Started page of the docs, and also the steps on the Encoders page. But encoder calibration WITH index starts with <axis>.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH and then <axis>.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION. But it doesn’t mention AXIS_STATE_MOTOR_CALIBRATION or AXIS_STATE_FULL_CALIBRATION_SEQUENCE.

Or is AXIS_STATE_FULL_CALIBRATION_SEQUENCE the same as all the steps on the Encoders page when use_index set to True?

I forgot to mention that the reason why I tried to recalibrate the ODrive is because on startup the motor spins really fast and directly slows down again. Then odrv0.axis0.error is 0x0004. I had this problem before and solved it, but I can’t remember how.

1 Like

I got the ODrive working again, without exploding resistors.

The commands I used now are:

odrv0.erase_configuration()
odrv0.reboot()
odrv0.axis0.used_index = True
odrv0.axis0.encoder.config.idx_search_speed = -10
odrv0.save_configuration()
odrv0.reboot()
odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.axis0.encoder.config.pre_calibrated = True
odrv0.axis0.config.startup_encoder_index_search = True
odrv0.axis0.motor.config.pre_calibrated = True
odrv0.save_configuration()
odrv0.reboot()

After sending AXIS_STATE_CLOSED_LOOP_CONTROL I could successfully send position commands to the ODrive. I did the same with the other axis, without any problems.

But then I sent:

In [31]: odrv0.axis0.config.startup_closed_loop_control = True
In [32]: odrv0.axis1.config.startup_closed_loop_control = True
In [33]: odrv0.save_configuration()
In [34]: odrv0.reboot()

And then something goes wrong. On startup axis0 starts spinning fast and directly stops again. The error codes I get are:

In [37]: hex(odrv0.axis0.error)
Out[37]: '0x30'
In [38]: hex(odrv0.axis1.error)
Out[38]: '0x10'
In [39]: hex(odrv0.axis0.encoder.error)
Out[39]: '0x0'
In [40]: hex(odrv0.axis0.motor.error)
Out[40]: '0x40'
In [41]: hex(odrv0.axis1.encoder.error)
Out[41]: '0x0'
In [42]: hex(odrv0.axis1.motor.error)
Out[42]: '0x40'

I want to use SimTools just like Zennix to control the ODrive. Do I need odrv0.axis0.config.startup_closed_loop_control = True for this to use serial ASCII commands?

The main case where you will have reverse current is when absorbing the kinetic energy from a moving mass. If you don’t have a heavy load on and don’t spin the motor fast, you should be okay.

Great, glad to hear that. Yes those commands look good, except I think it’s not
odrv0.axis0.used_index = True but instead odrv0.axis0.encoder.config.use_index = True.

When you did automatic closed loop control on startup, did you see it do the index search too on startup?

except I think it’s not
odrv0.axis0.used_index = True but instead odrv0.axis0.encoder.config.use_index = True .

Yeah, used that one.

When you did automatic closed loop control on startup, did you see it do the index search too on startup?

No, it doesn’t search for an index when I set startup_closed_loop_control = True. When I change it to False again, it does search for the index. I made a video of the startup. You can hear the fan of the power supply turning on. Then it starts spinning: https://youtu.be/LhM7Tkg5IGU

Do you have a solution yet?

I guess the problem has something to do with task_chain_.

Your description seems clear enough that I should be able to reproduce it. Looking at this is item number 2 on my todo list right now.

I tried the exact commands you supplied, and it behaves as expected for me:

I also put breakpoints in the code, and it does do the required states in order, also as expected. So I’m not sure what the issue could be for you. If you know where the index location is, can you position the rotor away from there to make sure you can spot if it is doing the index search state? Are you sure that the difference really is startup_closed_loop_control = True, or if it was a random noise that got into the index pulse line that time?

I had a very similar issue, where the motors would stop responding after between 3-10 commands were given. I opened odrivetool and got this:

In [ **1** ]: hex(odrv0.axis0.encoder.error)

Out[ **1** ]: '0x0'

In [ **2** ]: hex(odrv0.axis0.error)

Out[ **2** ]: '0x30'

In [ **3** ]: hex(odrv0.axis1.error)

Out[ **3** ]: '0x30'

In [ **4** ]: hex(odrv0.axis1.motor.error)

Out[ **4** ]: '0x40'

I changed the brake resister setting from 20 to 0 and it worked. I have no idea what the issue was but I hope this helps :slight_smile:

I checked the wires and found that the shielding of the motor and encoder cables werent yet connected to earth. I connected them and powered everything up again. But now it doesn’t search for an index on startup. I can hear a slight click, but the motors don’t turn.

I’m worried that if I now would sent a closed loop command, I get another exploding resistor or even fried ODrive.

These are the settings right after rebooting:

Reconnected to ODrive 376236503137 as odrv0
In [29]: odrv0.axis0.error
Out[29]: 0

In [30]: odrv0.axis0.encoder
Out[30]:
error = 0x0000 (int)
is_ready = True (bool)
index_found = True (bool)
shadow_count = 0 (int)
count_in_cpr = 0 (int)
interpolation = 0.5 (float)
phase = 2.261843681335449 (float)
pos_estimate = 0.0 (float)
pos_cpr = 0.0 (float)
hall_state = 2 (int)
vel_estimate = 0.0 (float)
config:
  mode = 0 (int)
  use_index = True (bool)
  pre_calibrated = True (bool)
  idx_search_speed = -10.0 (float)
  cpr = 8192 (int)
  offset = 4259 (int)
  offset_float = 1.359285831451416 (float)
  bandwidth = 1000.0 (float)
  calib_range = 0.019999999552965164 (float)

In [31]: odrv0.axis0.motor
Out[31]:
error = 0x0000 (int)
armed_state = 0 (int)
is_calibrated = True (bool)
current_meas_phB = -0.0039980411529541016 (float)
current_meas_phC = -0.0012733936309814453 (float)
DC_calib_phB = -1.6474026441574097 (float)
DC_calib_phC = -1.1266703605651855 (float)
phase_current_rev_gain = 0.02500000037252903 (float)
current_control:
  p_gain = 0.021295808255672455 (float)
  i_gain = 34.4830207824707 (float)
  v_current_control_integral_d = 0.0 (float)
  v_current_control_integral_q = 0.0 (float)
  Ibus = 0.0 (float)
  final_v_alpha = 0.0 (float)
  final_v_beta = 0.0 (float)
  Iq_setpoint = 0.0 (float)
  Iq_measured = 0.0 (float)
  max_allowed_current = 71.99999237060547 (float)
gate_driver:
  drv_fault = 0 (int)
timing_log:
  TIMING_LOG_GENERAL = 0 (int)
  TIMING_LOG_ADC_CB_I = 1425 (int)
  TIMING_LOG_ADC_CB_DC = 11187 (int)
  TIMING_LOG_MEAS_R = 0 (int)
  TIMING_LOG_MEAS_L = 0 (int)
  TIMING_LOG_ENC_CALIB = 0 (int)
  TIMING_LOG_IDX_SEARCH = 4559 (int)
  TIMING_LOG_FOC_VOLTAGE = 4495 (int)
  TIMING_LOG_FOC_CURRENT = 0 (int)
config:
  pre_calibrated = True (bool)
  pole_pairs = 7 (int)
  calibration_current = 10.0 (float)
  resistance_calib_max_voltage = 2.0 (float)
  phase_inductance = 2.1295807528076693e-05 (float)
  phase_resistance = 0.03448301926255226 (float)
  direction = 1 (int)
  motor_type = 0 (int)
  current_lim = 10.0 (float)
  requested_current_range = 70.0 (float)
  current_control_bandwidth = 1000.0 (float)

In [32]: odrv0.axis0.config
Out[32]:
startup_motor_calibration = False (bool)
startup_encoder_index_search = True (bool)
startup_encoder_offset_calibration = False (bool)
startup_closed_loop_control = False (bool)
startup_sensorless_control = False (bool)
enable_step_dir = False (bool)
counts_per_step = 2.0 (float)
ramp_up_time = 0.4000000059604645 (float)
ramp_up_distance = 12.566370964050293 (float)
spin_up_current = 10.0 (float)
spin_up_acceleration = 400.0 (float)
spin_up_target_vel = 400.0 (float)

In [33]:

When I disconnect the shielding, it does start with a proper index search. Then I only connected the motor shielding, only motor M1 did a successful index search.

How should the shielding of the cables be connected? I got a Meanwell power supply. A grounding wire goes to a central grounding point. From there all shielding is connected. I guess that is the wrong way? I noticed that the original encoder cables supplied by ODrive have shielding connected to GND.

What would be the best way to connect motor and encoder cable shielding?

Yes it would seem that you are getting spurious edges on the index line from noise.

You should connect the encoder shielding to a pin marked GND on the board, this is a “signal ground”. The ones on the encoder header should do fine.
You should connect the motor cable shields to DC-. This “power ground”.

It turned out to be shielding/noise issues…
My own stupid mistake…

I had all cable shields and “earth” wires connected to eachother and to AC earth.

Now I got the encoder cable shields connected to the GND pins. The motor cable shields are connected to DC-. And earth/ground wires are connected to AC earth.

Now the startup sequence is successful. But I’m having an other problem, similar to Odrive unresponsive after entering closed loop control

After changing some settings, saving and rebooting the ODrive doesn’t respond to odrivetool anymore. I have to restart Anaconda and disconnect/reconnect the power supply to continue.

EDIT: Now it isn’t even connecting after reconnecting the power supply and restarting odrivetool. It seems to be too “busy” with close loop control to connect to the pc.

These are the errors I get:

In [7]: odrv0.axis0.config.startup_closed_loop_control = True

In [8]: odrv0.save_configuration()

In [9]: odrv0.reboot()
---------------------------------------------------------------------------
ChannelBrokenException                    Traceback (most recent call last)
~\Anaconda3\lib\site-packages\fibre\shell.py in <module>()
----> 1 odrv0.reboot()

~\Anaconda3\lib\site-packages\fibre\remote_object.py in __call__(self, *args)
    160         for i in range(len(args)):
    161             self._inputs[i].set_value(args[i])
--> 162         self._parent.__channel__.remote_endpoint_operation(self._trigger_id, None, True, 0)
    163         if len(self._outputs) > 0:
    164             return self._outputs[0].get_value()

~\Anaconda3\lib\site-packages\fibre\protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, outpu
t_length)
    313                     return self._responses.pop(seq_no)
    314                     # TODO: record channel statistics
--> 315                 raise ChannelBrokenException() # Too many resend attempts
    316             finally:
    317                 self._expected_acks.pop(seq_no)

ChannelBrokenException:

Reconnected to ODrive 376236503137 as odrv0
In [10]: odrv0.axis1.config.startup_closed_loop_control = True
---------------------------------------------------------------------------
ChannelBrokenException                    Traceback (most recent call last)
~\Anaconda3\lib\site-packages\fibre\shell.py in <module>()
----> 1 odrv0.axis1.config.startup_closed_loop_control = True

~\Anaconda3\lib\site-packages\fibre\remote_object.py in __setattr__(self, name, value)
    250         if isinstance(attr, RemoteProperty):
    251             if attr._can_write:
--> 252                 attr.set_value(value)
    253             else:
    254                 raise Exception("Cannot write to property {}".format(name))

~\Anaconda3\lib\site-packages\fibre\remote_object.py in set_value(self, value)
     76         buffer = self._codec.serialize(value)
     77         # TODO: Currenly we wait for an ack here. Settle on the default guarantee.
---> 78         self._parent.__channel__.remote_endpoint_operation(self._id, buffer, True, 0)
     79
     80     def _dump(self):

~\Anaconda3\lib\site-packages\fibre\protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, output_length)
    313                     return self._responses.pop(seq_no)
    314                     # TODO: record channel statistics
--> 315                 raise ChannelBrokenException() # Too many resend attempts
    316             finally:
    317                 self._expected_acks.pop(seq_no)

ChannelBrokenException:

In [11]:

And:

In [18]: odrv0.save_configuration()

In [19]: odrv0.reboot()
---------------------------------------------------------------------------
ChannelBrokenException                    Traceback (most recent call last)
~\Anaconda3\lib\site-packages\fibre\shell.py in <module>()
----> 1 odrv0.reboot()

~\Anaconda3\lib\site-packages\fibre\remote_object.py in __call__(self, *args)
    160         for i in range(len(args)):
    161             self._inputs[i].set_value(args[i])
--> 162         self._parent.__channel__.remote_endpoint_operation(self._trigger_id, None, True, 0)
    163         if len(self._outputs) > 0:
    164             return self._outputs[0].get_value()

~\Anaconda3\lib\site-packages\fibre\protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, output_length)
    313                     return self._responses.pop(seq_no)
    314                     # TODO: record channel statistics
--> 315                 raise ChannelBrokenException() # Too many resend attempts
    316             finally:
    317                 self._expected_acks.pop(seq_no)

ChannelBrokenException:

In [20]:

I’ve now tried to communicatie using the serial COM port. I’m using PuTTY as testing interface at 115200 baud, default settings. First time PuTTY couldn’t connect to the COM port and gave an error. I rebooted the ODrive (power supply off/on) and tried again. This time I got to the serial window, but after pressing the “h” key, PuTTY displayed an error: Error writing to serial device.

Third time I was able to send “h” and got a valid response. But after waiting a few seconds and trying again, I got the same error: Error writing to serial device.

I really want to get this project (race sim) working! Who has got suggestions?