diff --git a/ArduinoI2C/ArduinoI2C.ino b/ArduinoI2C/ArduinoI2C.ino index 39d491a7..3a5008dd 100644 --- a/ArduinoI2C/ArduinoI2C.ino +++ b/ArduinoI2C/ArduinoI2C.ino @@ -51,6 +51,12 @@ void loop() { if (!success) Serial.println("error"); + success = odrive::trigger(odrive_num); + if (!success) + Serial.println("error"); + else + Serial.println("saved config"); + delay(500); } diff --git a/ArduinoI2C/odrive.h b/ArduinoI2C/odrive.h index fb89ccb5..88680cce 100644 --- a/ArduinoI2C/odrive.h +++ b/ArduinoI2C/odrive.h @@ -5,12 +5,16 @@ * - Implement the C function I2C_transaction to provide low level I2C access. * - Use read_property() to read properties from the ODrive. * - Use write_property() to modify properties on the ODrive. +* - Use trigger() to trigger a function (such as reboot or save_configuration) * - Use endpoint_type_t to retrieve the underlying type * of a given property. +* - Refer to PropertyId for a list of available properties. * -* To regenerate the interface definitions, flash an ODrive with the new -* firmware, then run -* ../tools/odrivetool generate-code --output odrive_endpoints.h +* To regenerate the interface definitions, flash an ODrive with +* the new firmware, connect it to your PC via USB and then run +* ../tools/odrivetool generate-code --output [path to odrive_endpoints.h] +* This step can be done with any ODrive, it doesn't have to be the +* one that you'll be controlling over I2C. */ @@ -140,4 +144,22 @@ namespace odrive { return I2C_transaction(i2c_addr + num, i2c_tx_buffer, sizeof(i2c_tx_buffer), nullptr, 0); } + /* @brief Write to an endpoint on the ODrive + * + * Usage example: + * success = odrive::trigger(0); + * + * @param num Selects the ODrive. For instance the value 4 selects + * the ODrive that has [A2, A1, A0] connected to [VCC, GND, GND]. + * @return true if the I2C transaction succeeded, false otherwise + */ + template>::value>::type> + bool trigger(uint8_t num) { + uint8_t i2c_tx_buffer[4]; + write_le(i2c_tx_buffer, IPropertyId); + write_le(i2c_tx_buffer + sizeof(i2c_tx_buffer) - 2, json_crc); + return I2C_transaction(i2c_addr + num, i2c_tx_buffer, sizeof(i2c_tx_buffer), nullptr, 0); + } + } diff --git a/ArduinoI2C/odrive_endpoints.h b/ArduinoI2C/odrive_endpoints.h index e8e4ee98..fe5e1b30 100644 --- a/ArduinoI2C/odrive_endpoints.h +++ b/ArduinoI2C/odrive_endpoints.h @@ -110,6 +110,7 @@ enum { AXIS0__CONTROLLER__CONFIG__VEL_GAIN = 93, AXIS0__CONTROLLER__CONFIG__VEL_INTEGRATOR_GAIN = 94, AXIS0__CONTROLLER__CONFIG__VEL_LIMIT = 95, + AXIS0__CONTROLLER__START_ANTICOGGING_CALIBRATION = 105, AXIS0__ENCODER__ERROR = 106, AXIS0__ENCODER__IS_READY = 107, AXIS0__ENCODER__INDEX_FOUND = 108, @@ -197,6 +198,7 @@ enum { AXIS1__CONTROLLER__CONFIG__VEL_GAIN = 190, AXIS1__CONTROLLER__CONFIG__VEL_INTEGRATOR_GAIN = 191, AXIS1__CONTROLLER__CONFIG__VEL_LIMIT = 192, + AXIS1__CONTROLLER__START_ANTICOGGING_CALIBRATION = 202, AXIS1__ENCODER__ERROR = 203, AXIS1__ENCODER__IS_READY = 204, AXIS1__ENCODER__INDEX_FOUND = 205, @@ -222,6 +224,10 @@ enum { AXIS1__SENSORLESS_ESTIMATOR__PLL_KP = 225, AXIS1__SENSORLESS_ESTIMATOR__PLL_KI = 226, TEST_PROPERTY = 227, + SAVE_CONFIGURATION = 234, + ERASE_CONFIGURATION = 235, + REBOOT = 236, + ENTER_DFU_MODE = 237, }; template @@ -322,6 +328,7 @@ template<> struct endpoint_type { typedef f template<> struct endpoint_type { typedef float type; }; template<> struct endpoint_type { typedef float type; }; template<> struct endpoint_type { typedef float type; }; +template<> struct endpoint_type { typedef void type; }; template<> struct endpoint_type { typedef uint8_t type; }; template<> struct endpoint_type { typedef bool type; }; template<> struct endpoint_type { typedef bool type; }; @@ -409,6 +416,7 @@ template<> struct endpoint_type { typedef f template<> struct endpoint_type { typedef float type; }; template<> struct endpoint_type { typedef float type; }; template<> struct endpoint_type { typedef float type; }; +template<> struct endpoint_type { typedef void type; }; template<> struct endpoint_type { typedef uint8_t type; }; template<> struct endpoint_type { typedef bool type; }; template<> struct endpoint_type { typedef bool type; }; @@ -434,6 +442,10 @@ template<> struct endpoint_type { typedef template<> struct endpoint_type { typedef float type; }; template<> struct endpoint_type { typedef float type; }; template<> struct endpoint_type { typedef uint32_t type; }; +template<> struct endpoint_type { typedef void type; }; +template<> struct endpoint_type { typedef void type; }; +template<> struct endpoint_type { typedef void type; }; +template<> struct endpoint_type { typedef void type; }; template @@ -441,4 +453,4 @@ using endpoint_type_t = typename endpoint_type::type; } -#endif __ODRIVE_ENDPOINTS_HPP \ No newline at end of file +#endif // __ODRIVE_ENDPOINTS_HPP \ No newline at end of file diff --git a/tools/odrive/code_generator.py b/tools/odrive/code_generator.py index a3c9c096..45c01c22 100644 --- a/tools/odrive/code_generator.py +++ b/tools/odrive/code_generator.py @@ -13,6 +13,12 @@ def get_flat_endpoint_list(json, prefix): is_property = True elif item['type'] in {'bool', 'float'}: is_property = True + elif item['type'] in {'function'}: + if len(item.get('arguments', [])) == 0 and len(item.get('inputs', [])) == 0 and len(item.get('outputs', [])) == 0: + item['type'] = 'void' + is_property = True + else: + is_property = False else: is_property = False if is_property: diff --git a/tools/odrive_header_template.h.in b/tools/odrive_header_template.h.in index 05e96376..c07e0174 100644 --- a/tools/odrive_header_template.h.in +++ b/tools/odrive_header_template.h.in @@ -31,4 +31,4 @@ using endpoint_type_t = typename endpoint_type::type; } -#endif __ODRIVE_ENDPOINTS_HPP +#endif // __ODRIVE_ENDPOINTS_HPP