diff --git a/Firmware/communication/can_simple.cpp b/Firmware/communication/can_simple.cpp index bfe35858..607495d4 100644 --- a/Firmware/communication/can_simple.cpp +++ b/Firmware/communication/can_simple.cpp @@ -97,6 +97,12 @@ void CANSimple::handle_can_message(CAN_message_t& msg) { case MSG_GET_SENSORLESS_ESTIMATES: get_sensorless_estimates_callback(axis, msg); break; + case MSG_RESET_ODRIVE: + NVIC_SystemReset(); + break; + case MSG_GET_VBUS_VOLTAGE: + get_vbus_voltage_callback(axis, msg); + break; default: break; } @@ -307,6 +313,31 @@ void CANSimple::get_iq_callback(Axis* axis, CAN_message_t& msg){ odCAN->write(txmsg); } +void CANSimple::get_vbus_voltage_callback(Axis* axis, CAN_message_t& msg) { + CAN_message_t txmsg; + + txmsg.id = axis->config_.can_node_id << NUM_CMD_ID_BITS; + txmsg.id += MSG_GET_VBUS_VOLTAGE; + txmsg.isExt = false; + txmsg.len = 8; + + uint32_t floatBytes; + static_assert(sizeof vbus_voltage == sizeof floatBytes); + std::memcpy(&floatBytes, &vbus_voltage, sizeof floatBytes); + + // This also works in principle, but I don't have hardware to verify endianness + // std::memcpy(&txmsg.buf[0], &vbus_voltage, sizeof vbus_voltage); + + txmsg.buf[0] = floatBytes; + txmsg.buf[1] = floatBytes >> 8; + txmsg.buf[2] = floatBytes >> 16; + txmsg.buf[3] = floatBytes >> 24; + + txmsg.buf[4] = 0; + txmsg.buf[5] = 0; + txmsg.buf[6] = 0; + txmsg.buf[7] = 0; +} void CANSimple::send_heartbeat(Axis* axis) { CAN_message_t txmsg; diff --git a/Firmware/communication/can_simple.hpp b/Firmware/communication/can_simple.hpp index 4ed630af..fd078c5a 100644 --- a/Firmware/communication/can_simple.hpp +++ b/Firmware/communication/can_simple.hpp @@ -29,6 +29,8 @@ class CANSimple { MSG_SET_TRAJ_A_PER_CSS, MSG_GET_IQ, MSG_GET_SENSORLESS_ESTIMATES, + MSG_RESET_ODRIVE, + MSG_GET_VBUS_VOLTAGE, }; static void handle_can_message(CAN_message_t& msg); @@ -56,7 +58,8 @@ class CANSimple { static void set_traj_accel_limits_callback(Axis* axis, CAN_message_t& msg); static void set_traj_A_per_css_callback(Axis* axis, CAN_message_t& msg); static void get_iq_callback(Axis* axis, CAN_message_t& msg); - static void get_sensorless_estimates_callback(Axis* axis, CAN_message_t& ms); + static void get_sensorless_estimates_callback(Axis* axis, CAN_message_t& msg); + static void get_vbus_voltage_callback(Axis* axis, CAN_message_t& msg); // Utility functions diff --git a/docs/can-protocol.md b/docs/can-protocol.md index e704439c..c66a5d7b 100644 --- a/docs/can-protocol.md +++ b/docs/can-protocol.md @@ -57,9 +57,12 @@ CMD ID | Name | Sender | Signals | Start byte 0x013 | Set Traj A per Count / s^2 | Master | Traj A per CSS | 0 0x014 | Get IQ\* | Axis | Iq Setpoint
Iq Measured | 0
4 0x015 | Get Sensorless Estimates\* | Master | Sensorless Pos Estimate
Sensorless Vel Estimate | 0
4 +0x016 | Reboot ODrive | Master\*\*\* | | +0x017 | Get Vbus Voltage | Master\*\*\* | Vbus Voltage | 0 \* Note: These messages are call & response. The Master node sends a message with no payload, and the axis responds with the same ID and specified payload. \*\* Note: These CANOpen messages are reserved to avoid bus collisions with CANOpen devices. They are not used by CAN Simple. +\*\*\* Note: These messages can be sent to either address on a given ODrive board. --- ### Signals @@ -91,6 +94,7 @@ Iq Setpoint | IEEE 754 Float | 32 | 1 | 0 | Intel Iq Measured | IEEE 754 Float | 32 | 1 | 0 | Intel Sensorless Pos Estimate | IEEE 754 Float | 32 | 1 | 0 | Intel Sensorless Vel Estimate | IEEE 754 Float | 32 | 1 | 0 | Intel +Vbus Voltage | IEEE 754 Float | 32 | 1 | 0 | Intel --- ## Configuring ODrive for CAN