mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-22 16:14:37 +08:00
introduce GPIO modes
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
# Unreleased Features
|
||||
Please add a note of your changes below this heading if you make a Pull Request.
|
||||
|
||||
### API Miration Notes
|
||||
|
||||
* `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`.
|
||||
|
||||
### Added
|
||||
* AC Induction Motor support.
|
||||
* Tracking of rotor flux through rotor time constant
|
||||
@@ -30,6 +35,7 @@ Please add a note of your changes below this heading if you make a Pull Request.
|
||||
* Added scripts for building via docker.
|
||||
* Added ability to change uart baudrate via fibre
|
||||
* Introduced `odrive-interface.yaml` as a root source for the ODrive's API. `odrivetool` connects much faster as a side effect.
|
||||
* Introduced GPIO modes. GPIOs now need to be explicitly set to the mode corresponding to the feature that they are used by. See `<odrv>.config.gpioX_mode`.
|
||||
|
||||
### Changed
|
||||
* Changed ratiometric `motor.config.current_lim_tolerance` to absolute `motor.config.current_lim_margin`
|
||||
|
||||
@@ -18,23 +18,26 @@
|
||||
|
||||
#include <arm_math.h>
|
||||
|
||||
#if HW_VERSION_MAJOR == 3
|
||||
#if HW_VERSION_MINOR <= 3
|
||||
#define SHUNT_RESISTANCE (675e-6f)
|
||||
#else
|
||||
#define SHUNT_RESISTANCE (500e-6f)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define AXIS_COUNT (2)
|
||||
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR <= 4
|
||||
#define GPIO_COUNT (5)
|
||||
#elif HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 5
|
||||
#define GPIO_COUNT (8)
|
||||
// Total count of GPIOs, including encoder pins, CAN pins and a dummy GPIO0.
|
||||
// ODrive v3.4 and earlier don't have GPIOs 6, 7 and 8 but to keep the numbering
|
||||
// consistent we just leave a gap in the counting scheme.
|
||||
#define GPIO_COUNT (17)
|
||||
|
||||
#if HW_VERSION_MINOR >= 5 && HW_VERSION_VOLTAGE >= 48
|
||||
#define DEFAULT_BRAKE_RESISTANCE (2.0f) // [ohm]
|
||||
#else
|
||||
#define DEFAULT_BRAKE_RESISTANCE (0.47f) // [ohm]
|
||||
#endif
|
||||
|
||||
#define GPIO_AF_NONE ((uint8_t)0xff)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <Drivers/STM32/stm32_gpio.hpp>
|
||||
@@ -51,6 +54,7 @@ extern Motor motors[AXIS_COUNT];
|
||||
extern OnboardThermistorCurrentLimiter fet_thermistors[AXIS_COUNT];
|
||||
extern Encoder encoders[AXIS_COUNT];
|
||||
extern Stm32Gpio gpios[GPIO_COUNT];
|
||||
extern uint8_t alternate_functions[GPIO_COUNT][6];
|
||||
extern uint32_t pwm_in_gpios[4];
|
||||
|
||||
#include <Drivers/STM32/stm32_spi_arbiter.hpp>
|
||||
|
||||
@@ -106,12 +106,6 @@ void MX_GPIO_Init(void)
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : PBPin PBPin */
|
||||
GPIO_InitStruct.Pin = GPIO_6_Pin|GPIO_8_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : PtPin */
|
||||
GPIO_InitStruct.Pin = EN_GATE_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
@@ -119,12 +113,6 @@ void MX_GPIO_Init(void)
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(EN_GATE_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : PtPin */
|
||||
GPIO_InitStruct.Pin = GPIO_7_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIO_7_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : PtPin */
|
||||
GPIO_InitStruct.Pin = nFAULT_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
|
||||
@@ -84,23 +84,11 @@ void MX_I2C1_Init(uint8_t addr)
|
||||
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
|
||||
{
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
if(i2cHandle->Instance==I2C1)
|
||||
{
|
||||
/* USER CODE BEGIN I2C1_MspInit 0 */
|
||||
|
||||
/* USER CODE END I2C1_MspInit 0 */
|
||||
|
||||
/**I2C1 GPIO Configuration
|
||||
PB8 ------> I2C1_SCL
|
||||
PB9 ------> I2C1_SDA
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* I2C1 clock enable */
|
||||
__HAL_RCC_I2C1_CLK_ENABLE();
|
||||
|
||||
@@ -451,19 +451,19 @@ void ADC_IRQ_Dispatch(ADC_HandleTypeDef* hadc, ADC_handler_t callback) {
|
||||
void decode_tim_capture(TIM_HandleTypeDef *htim, TIM_capture_callback_t callback) {
|
||||
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1)) {
|
||||
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
|
||||
callback(1, htim->Instance->CCR1);
|
||||
callback(0, htim->Instance->CCR1);
|
||||
}
|
||||
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2)) {
|
||||
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
|
||||
callback(2, htim->Instance->CCR2);
|
||||
callback(1, htim->Instance->CCR2);
|
||||
}
|
||||
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3)) {
|
||||
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
|
||||
callback(3, htim->Instance->CCR3);
|
||||
callback(2, htim->Instance->CCR3);
|
||||
}
|
||||
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4)) {
|
||||
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
|
||||
callback(4, htim->Instance->CCR4);
|
||||
callback(3, htim->Instance->CCR4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -462,7 +462,6 @@ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
|
||||
void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
|
||||
{
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
if(tim_encoderHandle->Instance==TIM3)
|
||||
{
|
||||
/* USER CODE BEGIN TIM3_MspInit 0 */
|
||||
@@ -470,17 +469,6 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
|
||||
/* USER CODE END TIM3_MspInit 0 */
|
||||
/* TIM3 clock enable */
|
||||
__HAL_RCC_TIM3_CLK_ENABLE();
|
||||
|
||||
/**TIM3 GPIO Configuration
|
||||
PB4 ------> TIM3_CH1
|
||||
PB5 ------> TIM3_CH2
|
||||
*/
|
||||
GPIO_InitStruct.Pin = M0_ENC_A_Pin|M0_ENC_B_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN TIM3_MspInit 1 */
|
||||
|
||||
@@ -493,17 +481,6 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
|
||||
/* USER CODE END TIM4_MspInit 0 */
|
||||
/* TIM4 clock enable */
|
||||
__HAL_RCC_TIM4_CLK_ENABLE();
|
||||
|
||||
/**TIM4 GPIO Configuration
|
||||
PB6 ------> TIM4_CH1
|
||||
PB7 ------> TIM4_CH2
|
||||
*/
|
||||
GPIO_InitStruct.Pin = M1_ENC_A_Pin|M1_ENC_B_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN TIM4_MspInit 1 */
|
||||
|
||||
@@ -514,7 +491,6 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
|
||||
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef* tim_icHandle)
|
||||
{
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
if(tim_icHandle->Instance==TIM5)
|
||||
{
|
||||
/* USER CODE BEGIN TIM5_MspInit 0 */
|
||||
@@ -522,17 +498,6 @@ void HAL_TIM_IC_MspInit(TIM_HandleTypeDef* tim_icHandle)
|
||||
/* USER CODE END TIM5_MspInit 0 */
|
||||
/* TIM5 clock enable */
|
||||
__HAL_RCC_TIM5_CLK_ENABLE();
|
||||
|
||||
/**TIM5 GPIO Configuration
|
||||
PA2 ------> TIM5_CH3
|
||||
PA3 ------> TIM5_CH4
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_3_Pin|GPIO_4_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF2_TIM5;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* TIM5 interrupt Init */
|
||||
HAL_NVIC_SetPriority(TIM5_IRQn, 5, 0);
|
||||
|
||||
@@ -83,7 +83,6 @@ void MX_UART4_Init(void)
|
||||
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
|
||||
{
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
if(uartHandle->Instance==UART4)
|
||||
{
|
||||
/* USER CODE BEGIN UART4_MspInit 0 */
|
||||
@@ -91,24 +90,6 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
|
||||
/* USER CODE END UART4_MspInit 0 */
|
||||
/* UART4 clock enable */
|
||||
__HAL_RCC_UART4_CLK_ENABLE();
|
||||
|
||||
/**UART4 GPIO Configuration
|
||||
PA0-WKUP ------> UART4_TX
|
||||
PA1 ------> UART4_RX
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_1_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
|
||||
HAL_GPIO_Init(GPIO_1_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_2_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
|
||||
HAL_GPIO_Init(GPIO_2_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/* UART4 DMA Init */
|
||||
/* UART4_RX Init */
|
||||
|
||||
@@ -80,24 +80,54 @@ Encoder encoders[AXIS_COUNT] = {
|
||||
};
|
||||
|
||||
|
||||
// Note that GPIO1 as labeled on the board corresponds to gpios[0] in code.
|
||||
#if (HW_VERSION_MINOR == 1) || (HW_VERSION_MINOR == 2)
|
||||
Stm32Gpio gpios[] = {
|
||||
{nullptr, 0}, // dummy GPIO0 so that PCB labels and software numbers match
|
||||
|
||||
{GPIOB, GPIO_PIN_2},
|
||||
{GPIOA, GPIO_PIN_5},
|
||||
{GPIOA, GPIO_PIN_4},
|
||||
{GPIOA, GPIO_PIN_3}
|
||||
{GPIOA, GPIO_PIN_3},
|
||||
{nullptr, 0},
|
||||
{nullptr, 0},
|
||||
{nullptr, 0},
|
||||
{nullptr, 0},
|
||||
|
||||
{GPIOB, GPIO_PIN_4}, // ENC0_A
|
||||
{GPIOB, GPIO_PIN_5}, // ENC0_B
|
||||
{GPIOA, GPIO_PIN_15}, // ENC0_Z
|
||||
{GPIOB, GPIO_PIN_6}, // ENC1_A
|
||||
{GPIOB, GPIO_PIN_7}, // ENC1_B
|
||||
{GPIOB, GPIO_PIN_3}, // ENC1_Z
|
||||
{GPIOB, GPIO_PIN_8}, // CAN_R
|
||||
{GPIOB, GPIO_PIN_9}, // CAN_D
|
||||
};
|
||||
#elif (HW_VERSION_MINOR == 3) || (HW_VERSION_MINOR == 4)
|
||||
Stm32Gpio gpios[] = {
|
||||
{nullptr, 0}, // dummy GPIO0 so that PCB labels and software numbers match
|
||||
|
||||
{GPIOA, GPIO_PIN_0},
|
||||
{GPIOA, GPIO_PIN_1},
|
||||
{GPIOA, GPIO_PIN_2},
|
||||
{GPIOA, GPIO_PIN_3},
|
||||
{GPIOB, GPIO_PIN_2}
|
||||
{GPIOB, GPIO_PIN_2},
|
||||
{nullptr, 0},
|
||||
{nullptr, 0},
|
||||
{nullptr, 0},
|
||||
|
||||
{GPIOB, GPIO_PIN_4}, // ENC0_A
|
||||
{GPIOB, GPIO_PIN_5}, // ENC0_B
|
||||
{GPIOA, GPIO_PIN_15}, // ENC0_Z
|
||||
{GPIOB, GPIO_PIN_6}, // ENC1_A
|
||||
{GPIOB, GPIO_PIN_7}, // ENC1_B
|
||||
{GPIOB, GPIO_PIN_3}, // ENC1_Z
|
||||
{GPIOB, GPIO_PIN_8}, // CAN_R
|
||||
{GPIOB, GPIO_PIN_9}, // CAN_D
|
||||
};
|
||||
#elif (HW_VERSION_MINOR == 5) || (HW_VERSION_MINOR == 6)
|
||||
Stm32Gpio gpios[] = {
|
||||
Stm32Gpio gpios[GPIO_COUNT] = {
|
||||
{nullptr, 0}, // dummy GPIO0 so that PCB labels and software numbers match
|
||||
|
||||
{GPIOA, GPIO_PIN_0},
|
||||
{GPIOA, GPIO_PIN_1},
|
||||
{GPIOA, GPIO_PIN_2},
|
||||
@@ -105,12 +135,50 @@ Stm32Gpio gpios[] = {
|
||||
{GPIOC, GPIO_PIN_4},
|
||||
{GPIOB, GPIO_PIN_2},
|
||||
{GPIOA, GPIO_PIN_15},
|
||||
{GPIOB, GPIO_PIN_3}
|
||||
{GPIOB, GPIO_PIN_3},
|
||||
|
||||
{GPIOB, GPIO_PIN_4}, // ENC0_A
|
||||
{GPIOB, GPIO_PIN_5}, // ENC0_B
|
||||
{GPIOC, GPIO_PIN_9}, // ENC0_Z
|
||||
{GPIOB, GPIO_PIN_6}, // ENC1_A
|
||||
{GPIOB, GPIO_PIN_7}, // ENC1_B
|
||||
{GPIOC, GPIO_PIN_15}, // ENC1_Z
|
||||
{GPIOB, GPIO_PIN_8}, // CAN_R
|
||||
{GPIOB, GPIO_PIN_9}, // CAN_D
|
||||
};
|
||||
#else
|
||||
#error "unknown GPIOs"
|
||||
#endif
|
||||
|
||||
#define GPIO_AF_NONE ((uint8_t)0xff)
|
||||
uint8_t alternate_functions[GPIO_COUNT][6] = {
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
|
||||
#if HW_VERSION_MINOR >= 3
|
||||
{GPIO_AF8_UART4, GPIO_AF2_TIM5, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF8_UART4, GPIO_AF2_TIM5, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF2_TIM5, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
#else
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
#endif
|
||||
{GPIO_AF_NONE, GPIO_AF2_TIM5, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF2_TIM3, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF2_TIM3, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF4_I2C1, GPIO_AF_NONE, GPIO_AF2_TIM4},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF4_I2C1, GPIO_AF_NONE, GPIO_AF2_TIM4},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF9_CAN1, GPIO_AF4_I2C1, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
{GPIO_AF_NONE, GPIO_AF_NONE, GPIO_AF9_CAN1, GPIO_AF4_I2C1, GPIO_AF_NONE, GPIO_AF_NONE},
|
||||
};
|
||||
|
||||
#if HW_VERSION_MINOR <= 2
|
||||
uint32_t pwm_in_gpios[4] = { 0, 0, 0, 4 }; // 0 means not in use
|
||||
#else
|
||||
|
||||
@@ -38,6 +38,52 @@ IRQn_Type get_irq_number(uint16_t pin_number) {
|
||||
}
|
||||
}
|
||||
|
||||
#define GPIO_MODE 0x00000003U
|
||||
#define GPIO_OUTPUT_TYPE 0x00000010U
|
||||
|
||||
|
||||
bool Stm32Gpio::config(uint32_t mode, uint32_t pull, uint32_t speed) {
|
||||
if (!port_)
|
||||
return false;
|
||||
|
||||
size_t position = get_pin_number();
|
||||
|
||||
// The following code is mostly taken from HAL_GPIO_Init
|
||||
|
||||
/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
|
||||
uint32_t temp = port_->MODER;
|
||||
temp &= ~(GPIO_MODER_MODER0 << (position * 2U));
|
||||
temp |= ((mode & GPIO_MODE) << (position * 2U));
|
||||
port_->MODER = temp;
|
||||
|
||||
/* In case of Output or Alternate function mode selection */
|
||||
if((mode == GPIO_MODE_OUTPUT_PP) || (mode == GPIO_MODE_AF_PP) ||
|
||||
(mode == GPIO_MODE_OUTPUT_OD) || (mode == GPIO_MODE_AF_OD))
|
||||
{
|
||||
/* Check the Speed parameter */
|
||||
assert_param(IS_GPIO_SPEED(speed));
|
||||
/* Configure the IO Speed */
|
||||
temp = port_->OSPEEDR;
|
||||
temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U));
|
||||
temp |= (speed << (position * 2U));
|
||||
port_->OSPEEDR = temp;
|
||||
|
||||
/* Configure the IO Output Type */
|
||||
temp = port_->OTYPER;
|
||||
temp &= ~(GPIO_OTYPER_OT_0 << position) ;
|
||||
temp |= (((mode & GPIO_OUTPUT_TYPE) >> 4U) << position);
|
||||
port_->OTYPER = temp;
|
||||
}
|
||||
|
||||
/* Activate the Pull-up or Pull down resistor for the current IO */
|
||||
temp = port_->PUPDR;
|
||||
temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U));
|
||||
temp |= ((pull) << (position * 2U));
|
||||
port_->PUPDR = temp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Stm32Gpio::subscribe(bool rising_edge, bool falling_edge, void (*callback)(void*), void* ctx) {
|
||||
uint32_t pin_number = get_pin_number();
|
||||
if (pin_number >= N_EXTI) {
|
||||
|
||||
@@ -17,21 +17,9 @@ public:
|
||||
*
|
||||
* This can be done regardless of the current state of the GPIO.
|
||||
*
|
||||
* TODO: make glitch-free if the configuration is the same as before
|
||||
* TODO: avoid disabling interrupt if it is enabled
|
||||
* If any subscription is in place, it is not disabled by this function.
|
||||
*/
|
||||
bool config(uint32_t mode, uint32_t pull) {
|
||||
if (!port_)
|
||||
return false;
|
||||
HAL_GPIO_DeInit(port_, pin_mask_);
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Pin = pin_mask_;
|
||||
GPIO_InitStruct.Mode = mode;
|
||||
GPIO_InitStruct.Pull = pull;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(port_, &GPIO_InitStruct);
|
||||
return true;
|
||||
}
|
||||
bool config(uint32_t mode, uint32_t pull, uint32_t speed = GPIO_SPEED_FREQ_LOW);
|
||||
|
||||
void write(bool state) {
|
||||
if (port_) {
|
||||
|
||||
@@ -148,7 +148,9 @@ void Axis::set_step_dir_active(bool active) {
|
||||
step_gpio_.config(GPIO_MODE_INPUT, GPIO_PULLDOWN);
|
||||
|
||||
// Subscribe to rising edges of the step GPIO
|
||||
step_gpio_.subscribe(true, false, step_cb_wrapper, this);
|
||||
if (!step_gpio_.subscribe(true, false, step_cb_wrapper, this)) {
|
||||
odrv.misconfigured_ = true;
|
||||
}
|
||||
|
||||
step_dir_active_ = true;
|
||||
} else {
|
||||
|
||||
@@ -104,7 +104,9 @@ void Encoder::enc_index_cb() {
|
||||
void Encoder::set_idx_subscribe(bool override_enable) {
|
||||
if (config_.use_index && (override_enable || !config_.find_idx_on_lockin_only)) {
|
||||
index_gpio_.config(GPIO_MODE_INPUT, GPIO_PULLDOWN);
|
||||
index_gpio_.subscribe(true, false, enc_index_cb_wrapper, this);
|
||||
if (!index_gpio_.subscribe(true, false, enc_index_cb_wrapper, this)) {
|
||||
odrv.misconfigured_ = true;
|
||||
}
|
||||
} else if (!config_.use_index || config_.find_idx_on_lockin_only) {
|
||||
index_gpio_.unsubscribe();
|
||||
}
|
||||
@@ -444,18 +446,9 @@ void Encoder::abs_spi_cb() {
|
||||
}
|
||||
|
||||
void Encoder::abs_spi_cs_pin_init(){
|
||||
// Decode cs pin
|
||||
// Decode and init cs pin
|
||||
abs_spi_cs_gpio_ = get_gpio(config_.abs_spi_cs_gpio_pin);
|
||||
|
||||
// Init cs pin
|
||||
// TODO: absorb into Stm32Gpio class
|
||||
HAL_GPIO_DeInit(abs_spi_cs_gpio_.port_, abs_spi_cs_gpio_.pin_mask_);
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Pin = abs_spi_cs_gpio_.pin_mask_;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(abs_spi_cs_gpio_.port_, &GPIO_InitStruct);
|
||||
abs_spi_cs_gpio_.config(GPIO_MODE_OUTPUT_PP, GPIO_PULLUP);
|
||||
|
||||
// Write pin high
|
||||
abs_spi_cs_gpio_.write(true);
|
||||
|
||||
@@ -537,12 +537,6 @@ void update_brake_current() {
|
||||
/* RC PWM input --------------------------------------------------------------*/
|
||||
|
||||
void pwm_in_init() {
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF2_TIM5;
|
||||
|
||||
TIM_IC_InitTypeDef sConfigIC;
|
||||
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;
|
||||
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
|
||||
@@ -552,16 +546,8 @@ void pwm_in_init() {
|
||||
uint32_t channels[] = {TIM_CHANNEL_1, TIM_CHANNEL_2, TIM_CHANNEL_3, TIM_CHANNEL_4};
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
uint32_t gpio_num = pwm_in_gpios[i];
|
||||
if (gpio_num < 1 || gpio_num > GPIO_COUNT)
|
||||
if (!fibre::is_endpoint_ref_valid(odrv.config_.pwm_mappings[i].endpoint))
|
||||
continue;
|
||||
if (!fibre::is_endpoint_ref_valid(odrv.config_.pwm_mappings[gpio_num - 1].endpoint))
|
||||
continue;
|
||||
|
||||
Stm32Gpio gpio = gpios[gpio_num];
|
||||
GPIO_InitStruct.Pin = gpio.pin_mask_;
|
||||
HAL_GPIO_DeInit(gpio.port_, gpio.pin_mask_);
|
||||
HAL_GPIO_Init(gpio.port_, &GPIO_InitStruct);
|
||||
HAL_TIM_IC_ConfigChannel(&htim5, &sConfigIC, channels[i]);
|
||||
HAL_TIM_IC_Start_IT(&htim5, channels[i]);
|
||||
}
|
||||
@@ -575,7 +561,10 @@ void pwm_in_init() {
|
||||
#define PWM_MAX_LEGAL_HIGH_TIME ((TIM_2_5_CLOCK_HZ / 1000000UL) * 2500UL) // ignore high periods longer than 2.5ms
|
||||
#define PWM_INVERT_INPUT false
|
||||
|
||||
void handle_pulse(int gpio_num, uint32_t high_time) {
|
||||
/**
|
||||
* @param channel: A channel number in [0, 3]
|
||||
*/
|
||||
void handle_pulse(int channel, uint32_t high_time) {
|
||||
if (high_time < PWM_MIN_LEGAL_HIGH_TIME || high_time > PWM_MAX_LEGAL_HIGH_TIME)
|
||||
return;
|
||||
|
||||
@@ -584,33 +573,36 @@ void handle_pulse(int gpio_num, uint32_t high_time) {
|
||||
if (high_time > PWM_MAX_HIGH_TIME)
|
||||
high_time = PWM_MAX_HIGH_TIME;
|
||||
float fraction = (float)(high_time - PWM_MIN_HIGH_TIME) / (float)(PWM_MAX_HIGH_TIME - PWM_MIN_HIGH_TIME);
|
||||
float value = odrv.config_.pwm_mappings[gpio_num - 1].min +
|
||||
(fraction * (odrv.config_.pwm_mappings[gpio_num - 1].max - odrv.config_.pwm_mappings[gpio_num - 1].min));
|
||||
float value = odrv.config_.pwm_mappings[channel].min +
|
||||
(fraction * (odrv.config_.pwm_mappings[channel].max - odrv.config_.pwm_mappings[channel].min));
|
||||
|
||||
fibre::set_endpoint_from_float(odrv.config_.pwm_mappings[gpio_num - 1].endpoint, value);
|
||||
fibre::set_endpoint_from_float(odrv.config_.pwm_mappings[channel].endpoint, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel: A channel number in [0, 3]
|
||||
*/
|
||||
void pwm_in_cb(int channel, uint32_t timestamp) {
|
||||
static uint32_t last_timestamp[GPIO_COUNT] = { 0 };
|
||||
static bool last_pin_state[GPIO_COUNT] = { false };
|
||||
static bool last_sample_valid[GPIO_COUNT] = { false };
|
||||
static uint32_t last_timestamp[4] = { 0 };
|
||||
static bool last_pin_state[4] = { false };
|
||||
static bool last_sample_valid[4] = { false };
|
||||
|
||||
if (channel >= 4)
|
||||
return;
|
||||
int gpio_num = pwm_in_gpios[channel];
|
||||
if (gpio_num < 1 || gpio_num > GPIO_COUNT)
|
||||
Stm32Gpio gpio = get_gpio(pwm_in_gpios[channel]);
|
||||
if (!gpio)
|
||||
return;
|
||||
bool current_pin_state = get_gpio(gpio_num).read();
|
||||
bool current_pin_state = gpio.read();
|
||||
|
||||
if (last_sample_valid[gpio_num - 1]
|
||||
&& (last_pin_state[gpio_num - 1] != PWM_INVERT_INPUT)
|
||||
if (last_sample_valid[channel]
|
||||
&& (last_pin_state[channel] != PWM_INVERT_INPUT)
|
||||
&& (current_pin_state == PWM_INVERT_INPUT)) {
|
||||
handle_pulse(gpio_num, timestamp - last_timestamp[gpio_num - 1]);
|
||||
handle_pulse(channel, timestamp - last_timestamp[channel]);
|
||||
}
|
||||
|
||||
last_timestamp[gpio_num - 1] = timestamp;
|
||||
last_pin_state[gpio_num - 1] = current_pin_state;
|
||||
last_sample_valid[gpio_num - 1] = true;
|
||||
last_timestamp[channel] = timestamp;
|
||||
last_pin_state[channel] = current_pin_state;
|
||||
last_sample_valid[channel] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -630,7 +622,7 @@ static void analog_polling_thread(void *)
|
||||
struct PWMMapping_t *map = &odrv.config_.analog_mappings[i];
|
||||
|
||||
if (fibre::is_endpoint_ref_valid(map->endpoint))
|
||||
update_analog_endpoint(map, i + 1);
|
||||
update_analog_endpoint(map, i);
|
||||
}
|
||||
osDelay(10);
|
||||
}
|
||||
|
||||
+100
-51
@@ -154,42 +154,28 @@ void ODrive::enter_dfu_mode() {
|
||||
|
||||
extern "C" int construct_objects(){
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
|
||||
if (odrv.config_.enable_i2c_instead_of_can) {
|
||||
if (odrv.config_.enable_i2c0) {
|
||||
// Set up the direction GPIO as input
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
get_gpio(3).config(GPIO_MODE_INPUT, GPIO_PULLUP);
|
||||
get_gpio(4).config(GPIO_MODE_INPUT, GPIO_PULLUP);
|
||||
get_gpio(5).config(GPIO_MODE_INPUT, GPIO_PULLUP);
|
||||
|
||||
GPIO_InitStruct.Pin = I2C_A0_PIN;
|
||||
HAL_GPIO_Init(I2C_A0_PORT, &GPIO_InitStruct);
|
||||
GPIO_InitStruct.Pin = I2C_A1_PIN;
|
||||
HAL_GPIO_Init(I2C_A1_PORT, &GPIO_InitStruct);
|
||||
GPIO_InitStruct.Pin = I2C_A2_PIN;
|
||||
HAL_GPIO_Init(I2C_A2_PORT, &GPIO_InitStruct);
|
||||
|
||||
osDelay(1);
|
||||
osDelay(1); // This has no effect but was here before.
|
||||
i2c_stats_.addr = (0xD << 3);
|
||||
i2c_stats_.addr |= HAL_GPIO_ReadPin(I2C_A0_PORT, I2C_A0_PIN) != GPIO_PIN_RESET ? 0x1 : 0;
|
||||
i2c_stats_.addr |= HAL_GPIO_ReadPin(I2C_A1_PORT, I2C_A1_PIN) != GPIO_PIN_RESET ? 0x2 : 0;
|
||||
i2c_stats_.addr |= HAL_GPIO_ReadPin(I2C_A2_PORT, I2C_A2_PIN) != GPIO_PIN_RESET ? 0x4 : 0;
|
||||
i2c_stats_.addr |= get_gpio(3).read() ? 0x1 : 0;
|
||||
i2c_stats_.addr |= get_gpio(4).read() ? 0x2 : 0;
|
||||
i2c_stats_.addr |= get_gpio(5).read() ? 0x4 : 0;
|
||||
MX_I2C1_Init(i2c_stats_.addr);
|
||||
} else
|
||||
}
|
||||
#elif HW_VERSION_MAJOR != 3
|
||||
#error "unsupported hardware"
|
||||
#endif
|
||||
MX_CAN1_Init();
|
||||
|
||||
|
||||
HAL_UART_DeInit(&huart4);
|
||||
huart4.Init.BaudRate = odrv.config_.uart_baudrate;
|
||||
huart4.Init.BaudRate = odrv.config_.uart0_baudrate;
|
||||
HAL_UART_Init(&huart4);
|
||||
|
||||
// Init general user ADC on some GPIOs.
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
for (Stm32Gpio& gpio: gpios) {
|
||||
GPIO_InitStruct.Pin = gpio.pin_mask_;
|
||||
HAL_GPIO_Init(gpio.port_, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
// Construct all objects.
|
||||
odCAN = new ODriveCAN(can_config, &hcan1);
|
||||
for (size_t i = 0; i < AXIS_COUNT; ++i) {
|
||||
@@ -250,33 +236,96 @@ int odrive_main(void) {
|
||||
// Init timers
|
||||
board_init();
|
||||
|
||||
// Init GPIOs according to their configured mode
|
||||
for (size_t i = 0; i < GPIO_COUNT; ++i) {
|
||||
// Skip unavailable GPIOs
|
||||
if (!get_gpio(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ODriveIntf::GpioMode mode = odrv.config_.gpio_modes[i];
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Pin = get_gpio(i).pin_mask_;
|
||||
GPIO_InitStruct.Alternate = 0;
|
||||
|
||||
switch (mode) {
|
||||
case ODriveIntf::GPIO_MODE_DIGITAL: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
} break;
|
||||
case ODriveIntf::GPIO_MODE_ANALOG_IN: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
} break;
|
||||
case ODriveIntf::GPIO_MODE_UART0: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = (i == 0) ? GPIO_PULLDOWN : GPIO_PULLUP; // this is probably swapped but imitates old behavior
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = alternate_functions[i][0];
|
||||
if (!odrv.config_.enable_uart0) {
|
||||
odrv.misconfigured_ = true;
|
||||
}
|
||||
} break;
|
||||
case ODriveIntf::GPIO_MODE_PWM0: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = alternate_functions[i][1];
|
||||
} break;
|
||||
case ODriveIntf::GPIO_MODE_CAN0: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = alternate_functions[i][2];
|
||||
if (!odrv.config_.enable_can0) {
|
||||
odrv.misconfigured_ = true;
|
||||
}
|
||||
} break;
|
||||
case ODriveIntf::GPIO_MODE_I2C0: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = alternate_functions[i][3];
|
||||
if (!odrv.config_.enable_i2c0) {
|
||||
odrv.misconfigured_ = true;
|
||||
}
|
||||
} break;
|
||||
case ODriveIntf::GPIO_MODE_ENC0: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = alternate_functions[i][4];
|
||||
} break;
|
||||
case ODriveIntf::GPIO_MODE_ENC1: {
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = alternate_functions[i][5];
|
||||
} break;
|
||||
default: {
|
||||
GPIO_InitStruct.Alternate = GPIO_AF_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// The selected mode is invalid for this GPIO. Leave GPIO uninitialized.
|
||||
if (GPIO_InitStruct.Alternate == GPIO_AF_NONE) {
|
||||
odrv.misconfigured_ = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
HAL_GPIO_Init(get_gpio(i).port_, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
// Some peripherals must be initialized after the GPIOs are set up.
|
||||
if (odrv.config_.enable_can0) {
|
||||
MX_CAN1_Init();
|
||||
}
|
||||
|
||||
// Start ADC for temperature measurements and user measurements
|
||||
start_general_purpose_adc();
|
||||
|
||||
// TODO: make dynamically reconfigurable
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
|
||||
if (odrv.config_.enable_uart) {
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
// make sure nothing is hogging the GPIO's
|
||||
Stm32Gpio{GPIO_1_GPIO_Port, GPIO_1_Pin}.unsubscribe();
|
||||
Stm32Gpio{GPIO_2_GPIO_Port, GPIO_2_Pin}.unsubscribe();
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_1_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
|
||||
HAL_GPIO_Init(GPIO_1_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_2_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
|
||||
HAL_GPIO_Init(GPIO_2_GPIO_Port, &GPIO_InitStruct);
|
||||
}
|
||||
#endif
|
||||
//osDelay(100);
|
||||
// Init communications (this requires the axis objects to be constructed)
|
||||
init_communication();
|
||||
|
||||
@@ -58,15 +58,33 @@ struct PWMMapping_t {
|
||||
|
||||
// @brief general user configurable board configuration
|
||||
struct BoardConfig_t {
|
||||
bool enable_uart = true;
|
||||
bool enable_i2c_instead_of_can = false;
|
||||
ODriveIntf::GpioMode gpio_modes[GPIO_COUNT] = {
|
||||
ODriveIntf::GPIO_MODE_DIGITAL,
|
||||
ODriveIntf::GPIO_MODE_UART0,
|
||||
ODriveIntf::GPIO_MODE_UART0,
|
||||
ODriveIntf::GPIO_MODE_ANALOG_IN,
|
||||
ODriveIntf::GPIO_MODE_ANALOG_IN,
|
||||
ODriveIntf::GPIO_MODE_ANALOG_IN,
|
||||
ODriveIntf::GPIO_MODE_DIGITAL,
|
||||
ODriveIntf::GPIO_MODE_DIGITAL,
|
||||
ODriveIntf::GPIO_MODE_DIGITAL,
|
||||
ODriveIntf::GPIO_MODE_ENC0,
|
||||
ODriveIntf::GPIO_MODE_ENC0,
|
||||
ODriveIntf::GPIO_MODE_DIGITAL,
|
||||
ODriveIntf::GPIO_MODE_ENC1,
|
||||
ODriveIntf::GPIO_MODE_ENC1,
|
||||
ODriveIntf::GPIO_MODE_DIGITAL,
|
||||
ODriveIntf::GPIO_MODE_CAN0,
|
||||
ODriveIntf::GPIO_MODE_CAN0,
|
||||
};
|
||||
|
||||
bool enable_uart0 = true;
|
||||
uint32_t uart0_baudrate = 115200;
|
||||
bool enable_can0 = true;
|
||||
bool enable_i2c0 = false;
|
||||
bool enable_ascii_protocol_on_usb = true;
|
||||
float max_regen_current = 0.0f;
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 5 && HW_VERSION_VOLTAGE >= 48
|
||||
float brake_resistance = 2.0f; // [ohm]
|
||||
#else
|
||||
float brake_resistance = 0.47f; // [ohm]
|
||||
#endif
|
||||
float brake_resistance = DEFAULT_BRAKE_RESISTANCE;
|
||||
float dc_bus_undervoltage_trip_level = 8.0f; //<! [V] minimum voltage below which the motor stops operating
|
||||
float dc_bus_overvoltage_trip_level = 1.07f * HW_VERSION_VOLTAGE; //<! [V] maximum voltage above which the motor stops operating.
|
||||
//<! This protects against cases in which the power supply fails to dissipate
|
||||
@@ -96,34 +114,8 @@ struct BoardConfig_t {
|
||||
|
||||
float dc_max_positive_current = INFINITY; // Max current [A] the power supply can source
|
||||
float dc_max_negative_current = -0.000001f; // Max current [A] the power supply can sink. You most likely want a non-positive value here. Set to -INFINITY to disable.
|
||||
PWMMapping_t pwm_mappings[GPIO_COUNT];
|
||||
PWMMapping_t pwm_mappings[4];
|
||||
PWMMapping_t analog_mappings[GPIO_COUNT];
|
||||
|
||||
/**
|
||||
* Defines the baudrate used on the UART interface.
|
||||
* Some baudrates will have a small timing error due to hardware limitations.
|
||||
*
|
||||
* Here's an (incomplete) list of baudrates for ODrive v3.x:
|
||||
*
|
||||
* Configured | Actual | Error [%]
|
||||
* -------------|---------------|-----------
|
||||
* 1.2 KBps | 1.2 KBps | 0
|
||||
* 2.4 KBps | 2.4 KBps | 0
|
||||
* 9.6 KBps | 9.6 KBps | 0
|
||||
* 19.2 KBps | 19.195 KBps | 0.02
|
||||
* 38.4 KBps | 38.391 KBps | 0.02
|
||||
* 57.6 KBps | 57.613 KBps | 0.02
|
||||
* 115.2 KBps | 115.068 KBps | 0.11
|
||||
* 230.4 KBps | 230.769 KBps | 0.16
|
||||
* 460.8 KBps | 461.538 KBps | 0.16
|
||||
* 921.6 KBps | 913.043 KBps | 0.93
|
||||
* 1.792 MBps | 1.826 MBps | 1.9
|
||||
* 1.8432 MBps | 1.826 MBps | 0.93
|
||||
*
|
||||
* For more information refer to Section 30.3.4 and Table 142 (the column with f_PCLK = 42 MHz) in the STM datasheet:
|
||||
* https://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf
|
||||
*/
|
||||
uint32_t uart_baudrate = 115200;
|
||||
};
|
||||
|
||||
// Forward Declarations
|
||||
@@ -176,7 +168,7 @@ extern const unsigned char fw_version_unreleased_;
|
||||
}
|
||||
|
||||
static Stm32Gpio get_gpio(size_t gpio_num) {
|
||||
return (gpio_num >= 1 && gpio_num <= GPIO_COUNT) ? gpios[gpio_num - 1] : GPIO_COUNT ? gpios[0] : Stm32Gpio::none;
|
||||
return (gpio_num < GPIO_COUNT) ? gpios[gpio_num] : GPIO_COUNT ? gpios[0] : Stm32Gpio::none;
|
||||
}
|
||||
|
||||
// general system functions defined in main.cpp
|
||||
@@ -244,6 +236,7 @@ public:
|
||||
|
||||
BoardConfig_t config_;
|
||||
bool user_config_loaded_;
|
||||
bool misconfigured_ = false;
|
||||
|
||||
uint32_t test_property_ = 0;
|
||||
};
|
||||
|
||||
@@ -64,9 +64,10 @@ void communication_task(void * ctx) {
|
||||
|
||||
start_uart_server();
|
||||
start_usb_server();
|
||||
if (odrv.config_.enable_i2c_instead_of_can) {
|
||||
if (odrv.config_.enable_i2c0) {
|
||||
start_i2c_server();
|
||||
} else {
|
||||
}
|
||||
if (odrv.config_.enable_can0) {
|
||||
odCAN->start_can_server();
|
||||
}
|
||||
|
||||
|
||||
@@ -81,10 +81,28 @@ interfaces:
|
||||
config:
|
||||
c_is_class: False
|
||||
attributes:
|
||||
enable_uart:
|
||||
# TODO: add support for arrays
|
||||
gpio1_mode: {type: GpioMode, doc: Mode of GPIO1 (changes take effect after reboot), c_name: 'gpio_modes[1]'}
|
||||
gpio2_mode: {type: GpioMode, doc: Mode of GPIO2 (changes take effect after reboot), c_name: 'gpio_modes[2]'}
|
||||
gpio3_mode: {type: GpioMode, doc: Mode of GPIO3 (changes take effect after reboot), c_name: 'gpio_modes[3]'}
|
||||
gpio4_mode: {type: GpioMode, doc: Mode of GPIO4 (changes take effect after reboot), c_name: 'gpio_modes[4]'}
|
||||
gpio5_mode: {type: GpioMode, doc: Mode of GPIO5 (changes take effect after reboot), c_name: 'gpio_modes[5]'}
|
||||
gpio6_mode: {type: GpioMode, doc: Mode of GPIO6 (changes take effect after reboot), c_name: 'gpio_modes[6]'}
|
||||
gpio7_mode: {type: GpioMode, doc: Mode of GPIO7 (changes take effect after reboot), c_name: 'gpio_modes[7]'}
|
||||
gpio8_mode: {type: GpioMode, doc: Mode of GPIO8 (changes take effect after reboot), c_name: 'gpio_modes[8]'}
|
||||
gpio9_mode: {type: GpioMode, doc: Mode of GPIO9 (changes take effect after reboot), c_name: 'gpio_modes[9]'}
|
||||
gpio10_mode: {type: GpioMode, doc: Mode of GPIO10 (changes take effect after reboot), c_name: 'gpio_modes[10]'}
|
||||
gpio11_mode: {type: GpioMode, doc: Mode of GPIO11 (changes take effect after reboot), c_name: 'gpio_modes[11]'}
|
||||
gpio12_mode: {type: GpioMode, doc: Mode of GPIO12 (changes take effect after reboot), c_name: 'gpio_modes[12]'}
|
||||
gpio13_mode: {type: GpioMode, doc: Mode of GPIO13 (changes take effect after reboot), c_name: 'gpio_modes[13]'}
|
||||
gpio14_mode: {type: GpioMode, doc: Mode of GPIO14 (changes take effect after reboot), c_name: 'gpio_modes[14]'}
|
||||
gpio15_mode: {type: GpioMode, doc: Mode of GPIO15 (changes take effect after reboot), c_name: 'gpio_modes[15]'}
|
||||
gpio16_mode: {type: GpioMode, doc: Mode of GPIO16 (changes take effect after reboot), c_name: 'gpio_modes[16]'}
|
||||
|
||||
enable_uart0:
|
||||
type: bool
|
||||
doc: 'TODO: changing this currently requires a reboot - fix this'
|
||||
uart_baudrate:
|
||||
uart0_baudrate:
|
||||
type: uint32
|
||||
doc: |
|
||||
Defines the baudrate used on the UART interface.
|
||||
@@ -109,9 +127,17 @@ interfaces:
|
||||
|
||||
For more information refer to Section 30.3.4 and Table 142 (the column with f_PCLK = 42 MHz) in the
|
||||
[STM datasheet](https://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf).
|
||||
enable_i2c_instead_of_can:
|
||||
enable_can0:
|
||||
type: bool
|
||||
doc: Changing this requires a reboot.
|
||||
doc: |
|
||||
Enables CAN. Changing this setting requires a reboot.
|
||||
enable_i2c0:
|
||||
type: bool
|
||||
doc: |
|
||||
Enables I2C. The I2C pins on ODrive v3.x are in conflict with CAN.
|
||||
This setting has no effect if `enable_can0` is also true.
|
||||
This setting has no effect on ODrive v3.2 or earlier.
|
||||
Changing this setting requires a reboot.
|
||||
enable_ascii_protocol_on_usb: bool
|
||||
max_regen_current: float32
|
||||
brake_resistance:
|
||||
@@ -173,13 +199,26 @@ interfaces:
|
||||
brief: Max current the power supply can sink.
|
||||
doc: You most likely want a non-positive value here. Set to -INFINITY to disable.
|
||||
|
||||
gpio1_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[0]'} # TODO: disable for ODrive v3.2 and older
|
||||
gpio2_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[1]'} # TODO: disable for ODrive v3.2 and older
|
||||
gpio3_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[2]'} # TODO: disable for ODrive v3.2 and older
|
||||
gpio4_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[3]'}
|
||||
gpio3_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[2]'}
|
||||
gpio4_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[3]'}
|
||||
gpio1_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[0]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.}
|
||||
gpio2_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[1]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.}
|
||||
gpio3_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[2]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.}
|
||||
gpio4_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[3]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_PWM0`.}
|
||||
gpio3_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[3]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_ANALOG_IN`.}
|
||||
gpio4_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[4]', doc: Make sure the corresponding GPIO is in `GPIO_MODE_ANALOG_IN`.}
|
||||
user_config_loaded: readonly bool
|
||||
misconfigured:
|
||||
type: readonly bool
|
||||
doc: |
|
||||
If this property is true, something is bad in the configuration. The
|
||||
ODrive can still be used in this state but the user should investigate
|
||||
which setting is problematic. This variable does not cover all
|
||||
misconfigurations.
|
||||
|
||||
Possible causes:
|
||||
- A GPIO was set to a mode that it doesn't support
|
||||
- A GPIO was set to a mode for which the corresponding feature was
|
||||
not enabled. Example: `GPIO_MODE_UART0` was used without enabling
|
||||
`config.enable_uart0`.
|
||||
|
||||
axis0: {type: Axis, c_name: get_axis(0)}
|
||||
axis1: {type: Axis, c_name: get_axis(1)}
|
||||
@@ -189,7 +228,7 @@ interfaces:
|
||||
functions:
|
||||
test_function: {in: {delta: int32}, out: {cnt: int32}}
|
||||
get_oscilloscope_val: {in: {index: uint32}, out: {val: float32}}
|
||||
get_adc_voltage: {in: {gpio: uint32}, out: {voltage: float32}}
|
||||
get_adc_voltage: {in: {gpio: uint32}, out: {voltage: float32}, doc: Reads the ADC voltage of the specified GPIO. The GPIO should be in `GPIO_MODE_ANALOG_IN`.}
|
||||
save_configuration:
|
||||
erase_configuration:
|
||||
reboot:
|
||||
@@ -323,7 +362,7 @@ interfaces:
|
||||
enable_step_dir:
|
||||
type: bool
|
||||
doc: Enable step/dir input after calibration.
|
||||
For M0 this has no effect if `config.enable_uart` is true.
|
||||
Make sure to set the corresponding GPIO's mode to `GPIO_MODE_DIGITAL`.
|
||||
step_dir_always_on:
|
||||
type: bool
|
||||
doc: Keep step/dir enabled while the motor is disabled.
|
||||
@@ -766,7 +805,7 @@ interfaces:
|
||||
mode: Mode
|
||||
use_index: {type: bool, c_setter: set_use_index}
|
||||
find_idx_on_lockin_only: {type: bool, c_setter: set_find_idx_on_lockin_only}
|
||||
abs_spi_cs_gpio_pin: {type: uint16, c_setter: set_abs_spi_cs_gpio_pin}
|
||||
abs_spi_cs_gpio_pin: {type: uint16, c_setter: set_abs_spi_cs_gpio_pin, doc: Make sure that the GPIO is in `GPIO_MODE_DIGITAL`.}
|
||||
zero_count_on_find_idx: bool
|
||||
cpr: int32
|
||||
offset: int32
|
||||
@@ -779,8 +818,12 @@ interfaces:
|
||||
calib_scan_omega: float32
|
||||
idx_search_unidirectional: bool
|
||||
ignore_illegal_hall_state: bool
|
||||
sincos_gpio_pin_sin: uint16
|
||||
sincos_gpio_pin_cos: uint16
|
||||
sincos_gpio_pin_sin:
|
||||
type: uint16
|
||||
doc: Analog sine signal of a sin/cos encoder. The corresponding GPIO must be in `GPIO_MODE_ANALOG_IN`.
|
||||
sincos_gpio_pin_cos:
|
||||
type: uint16
|
||||
doc: Analog cosine signal of a sin/cos encoder. The corresponding GPIO must be in `GPIO_MODE_ANALOG_IN`.
|
||||
functions:
|
||||
set_linear_count: {in: {count: int32}}
|
||||
|
||||
@@ -823,7 +866,7 @@ interfaces:
|
||||
config:
|
||||
c_is_class: False
|
||||
attributes:
|
||||
gpio_num: {type: uint16, c_setter: set_gpio_num}
|
||||
gpio_num: {type: uint16, c_setter: set_gpio_num, doc: Make sure the corresponding GPIO is in `GPIO_MODE_DIGITAL`.}
|
||||
enabled: {type: bool, c_setter: set_enabled}
|
||||
offset: float32
|
||||
is_active_high: bool
|
||||
@@ -832,6 +875,23 @@ interfaces:
|
||||
|
||||
|
||||
valuetypes:
|
||||
ODrive.GpioMode:
|
||||
values:
|
||||
Digital:
|
||||
doc: |
|
||||
The pin can be used for one or more of these functions:
|
||||
Step, dir, enable, encoder index, hall effect encoder, SPI encoder nCS (this one is exclusive).
|
||||
AnalogIn:
|
||||
doc: |
|
||||
The pin can be used for one or more of these functions:
|
||||
Sin/cos encoders, analog input, `get_adc_voltage`.
|
||||
Uart0: {doc: See `config.enable_uart0`.}
|
||||
Pwm0: {doc: See `config.gpio0_pwm_mapping`.}
|
||||
Can0: {doc: See `config.enable_can0`.}
|
||||
I2c0: {doc: See `config.enable_i2c0`.}
|
||||
Enc0: {doc: The pin is used by quadrature encoder 0.}
|
||||
Enc1: {doc: The pin is used by quadrature encoder 1.}
|
||||
|
||||
ODrive.Can.Protocol:
|
||||
values: {Simple: }
|
||||
|
||||
|
||||
+27
-13
@@ -18,24 +18,38 @@ The ODrive can be controlled over various ports and protocols. If you're comfort
|
||||
|
||||
## Pinout
|
||||
|
||||
| GPIO | primary | step/dir | other |
|
||||
|-----------|-----------|---------------|-------------------------|
|
||||
| GPIO1 | UART TX | Axis0 Step | Analog input, PWM input |
|
||||
| GPIO2 | UART RX | Axis0 Dir | Analog input, PWM input |
|
||||
| GPIO3 | | Axis1 Step (+)| Analog input, PWM input |
|
||||
| GPIO4 | | Axis1 Dir (+) | Analog input, PWM input |
|
||||
| GPIO5 | | | Analog input (*) |
|
||||
| GPIO6 (*) | | | |
|
||||
| GPIO7 (*) | | Axis1 Step (*)| |
|
||||
| GPIO8 (*) | | Axis1 Dir (*) | |
|
||||
| # | Label | `GPIO_MODE_DIGITAL` | `GPIO_MODE_ANALOG_IN` | `GPIO_MODE_UART0` | `GPIO_MODE_PWM0` | `GPIO_MODE_CAN0` | `GPIO_MODE_I2C0` | `GPIO_MODE_ENC0` | `GPIO_MODE_ENC1` |
|
||||
|----|---------------|------------------------|-----------------------|-------------------|------------------|------------------|------------------|------------------|------------------|
|
||||
| 0 | _not a pin_ | | | | | | | | |
|
||||
| 1 | GPIO1 (+) | general purpose | analog input | **UART0.TX** | PWM0.0 | | | | |
|
||||
| 2 | GPIO2 (+) | general purpose | analog input | **UART0.RX** | PWM0.1 | | | | |
|
||||
| 3 | GPIO3 | general purpose | **analog input** | | PWM0.2 | | | | |
|
||||
| 4 | GPIO4 | general purpose | **analog input** | | PWM0.3 | | | | |
|
||||
| 5 | GPIO5 | general purpose | **analog input** (*) | | | | | | |
|
||||
| 6 | GPIO6 (*) (+) | **general purpose** | | | | | | | |
|
||||
| 7 | GPIO7 (*) (+) | **general purpose** | | | | | | | |
|
||||
| 8 | GPIO8 (*) (+) | **general purpose** | | | | | | | |
|
||||
| 9 | M0.A | general purpose | | | | | | **ENC0.A** | |
|
||||
| 10 | M0.B | general purpose | | | | | | **ENC0.B** | |
|
||||
| 11 | M0.Z | **general purpose** | | | | | | | |
|
||||
| 12 | M1.A | general purpose | | | | | I2C.SCL | | **ENC1.A** |
|
||||
| 13 | M1.B | general purpose | | | | | I2C.SDA | | **ENC1.B** |
|
||||
| 14 | M1.Z | **general purpose** | | | | | | | |
|
||||
| 15 | _not exposed_ | general purpose | | | | **CAN0.RX** | I2C.SCL | | |
|
||||
| 16 | _not exposed_ | general purpose | | | | **CAN0.TX** | I2C.SDA | | |
|
||||
|
||||
(+) on ODrive v3.4 and earlier <br>
|
||||
(*) ODrive v3.5 and later
|
||||
|
||||
(*) ODrive v3.5 and later <br>
|
||||
(+) On ODrive v3.5 and later these pins have noise suppression filters. This is useful for step/dir input. <br>
|
||||
|
||||
Notes:
|
||||
* Changes to the pin configuration only take effect after `odrv0.save_configuration()` and `odrv0.reboot()`
|
||||
* Bold font marks the default configuration.
|
||||
* If a GPIO is set to an unsupported mode it will be left uninitialized.
|
||||
* When setting a GPIO to a special purpose mode (e.g. `GPIO_MODE_UART0`) you must also enable the corresponding feature (e.g. `<odrv>.config.enable_uart`).
|
||||
* Digital mode is a general purpose mode that can be used for these functions: step, dir, enable, encoder index, hall effect encoder, SPI encoder nCS.
|
||||
* You must also connect GND between ODrive and your other board.
|
||||
* ODrive v3.3 and onward have 5V tolerant GPIO pins.
|
||||
* ODrive v3.5 and later have some noise suppression filters on the default step/dir pins
|
||||
* You can change the step/dir pins using `axis.config.<step/dir>_gpio_pin`.
|
||||
|
||||
### Pin function priorities
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
# To regenerate this file, nagivate to the top level of the ODrive repository and run:
|
||||
# python Firmware/interface_generator_stub.py --definitions Firmware/odrive-interface.yaml --template tools/enums_template.j2 --output tools/odrive/enums.py
|
||||
|
||||
# ODrive.GpioMode
|
||||
GPIO_MODE_DIGITAL = 0
|
||||
GPIO_MODE_ANALOG_IN = 1
|
||||
GPIO_MODE_UART0 = 2
|
||||
GPIO_MODE_PWM0 = 3
|
||||
GPIO_MODE_CAN0 = 4
|
||||
GPIO_MODE_I2C0 = 5
|
||||
GPIO_MODE_ENC0 = 6
|
||||
GPIO_MODE_ENC1 = 7
|
||||
|
||||
# ODrive.Can.Protocol
|
||||
PROTOCOL_SIMPLE = 0
|
||||
|
||||
|
||||
@@ -91,7 +91,8 @@ class TestAnalogInput():
|
||||
None, #odrive.handle.config.gpio5_analog_mapping,
|
||||
][analog_in_num]
|
||||
|
||||
odrive.unuse_gpios()
|
||||
odrive.disable_mappings()
|
||||
setattr(odrive.handle.config, 'gpio' + str(analog_in_num+1) + '_mode', GPIO_MODE_ANALOG_IN)
|
||||
analog_mapping.endpoint = odrive.handle.axis0.controller._remote_attributes['input_pos']
|
||||
analog_mapping.min = min_val
|
||||
analog_mapping.max = max_val
|
||||
|
||||
@@ -107,9 +107,11 @@ class TestSimpleCAN():
|
||||
yield (odrive, can_interfaces, 0xfedcba, True) # extended ID
|
||||
|
||||
def run_test(self, odrive: ODriveComponent, canbus: CanInterfaceComponent, node_id: int, extended_id: bool, logger: Logger):
|
||||
|
||||
# make sure no gpio input is overwriting our values
|
||||
odrive.unuse_gpios()
|
||||
odrive.disable_mappings()
|
||||
odrive.handle.config.gpio15_mode = GPIO_MODE_CAN0
|
||||
odrive.handle.config.gpio16_mode = GPIO_MODE_CAN0
|
||||
odrive.handle.config.enable_can0 = True
|
||||
odrive.save_config_and_reboot()
|
||||
|
||||
axis = odrive.handle.axis0
|
||||
axis.config.enable_watchdog = False
|
||||
|
||||
@@ -185,7 +185,9 @@ class TestSinCosEncoder(TestEncoderBase):
|
||||
teensy.compile_and_program(code)
|
||||
|
||||
if enc.handle.config.mode != ENCODER_MODE_SINCOS:
|
||||
enc.parent.unuse_gpios()
|
||||
enc.parent.disable_mappings()
|
||||
enc.parent.handle.config.gpio3_mode = GPIO_MODE_ANALOG_IN
|
||||
enc.parent.handle.config.gpio4_mode = GPIO_MODE_ANALOG_IN
|
||||
enc.handle.config.mode = ENCODER_MODE_SINCOS
|
||||
enc.parent.save_config_and_reboot()
|
||||
else:
|
||||
@@ -255,6 +257,14 @@ class TestHallEffectEncoder(TestEncoderBase):
|
||||
teensy.compile_and_program(code)
|
||||
|
||||
if enc.handle.config.mode != ENCODER_MODE_HALL:
|
||||
if enc.num:
|
||||
enc.parent.handle.config.gpio9_mode = GPIO_MODE_DIGITAL
|
||||
enc.parent.handle.config.gpio10_mode = GPIO_MODE_DIGITAL
|
||||
enc.parent.handle.config.gpio11_mode = GPIO_MODE_DIGITAL
|
||||
else:
|
||||
enc.parent.handle.config.gpio12_mode = GPIO_MODE_DIGITAL
|
||||
enc.parent.handle.config.gpio13_mode = GPIO_MODE_DIGITAL
|
||||
enc.parent.handle.config.gpio14_mode = GPIO_MODE_DIGITAL
|
||||
enc.handle.config.mode = ENCODER_MODE_HALL
|
||||
enc.parent.save_config_and_reboot()
|
||||
else:
|
||||
@@ -450,6 +460,7 @@ class TestSpiEncoder(TestEncoderBase):
|
||||
|
||||
logger.debug(f'Configuring absolute encoder in mode 0x{self.mode:x}...')
|
||||
enc.handle.config.mode = self.mode
|
||||
setattr(enc.parent.handle.config, 'gpio' + str(odrive_ncs_gpio) + '_mode', GPIO_MODE_ANALOG_IN)
|
||||
enc.handle.config.abs_spi_cs_gpio_pin = odrive_ncs_gpio
|
||||
enc.handle.config.cpr = true_cpr
|
||||
# Also put the other encoder into SPI mode to make it more interesting
|
||||
|
||||
@@ -61,7 +61,7 @@ class TestPwmInput():
|
||||
teensy.compile_and_program(code)
|
||||
|
||||
logger.debug("Set up PWM input...")
|
||||
odrive.unuse_gpios()
|
||||
odrive.disable_mappings()
|
||||
|
||||
pwm_mapping = [
|
||||
odrive.handle.config.gpio1_pwm_mapping,
|
||||
@@ -70,6 +70,7 @@ class TestPwmInput():
|
||||
odrive.handle.config.gpio4_pwm_mapping
|
||||
][odrive_gpio_num - 1]
|
||||
|
||||
setattr(odrive.handle.config, 'gpio' + str(odrive_gpio_num) + '_mode', GPIO_MODE_PWM0)
|
||||
pwm_mapping.endpoint = odrive.handle.axis0.controller._remote_attributes['input_pos']
|
||||
pwm_mapping.min = min_val
|
||||
pwm_mapping.max = max_val
|
||||
|
||||
@@ -37,15 +37,16 @@ class TestStepDir():
|
||||
|
||||
yield (odrive.axes[1], 7, gpio_conns[6], 8, gpio_conns[7])
|
||||
|
||||
def run_test(self, axis: ODriveAxisComponent, step_gpio_num: int, step_gpio: LinuxGpioComponent, dir_gpio_num: int, dir_gpio: LinuxGpioComponent, logger: Logger):
|
||||
def run_test(self, axis: ODriveAxisComponent, step_gpio_num: int, step_gpio: LinuxGpioComponent, dir_gpio_num: int, dir_gpio: LinuxGpioComponent, logger: Logger):
|
||||
step_gpio.config(output=True)
|
||||
step_gpio.write(False)
|
||||
dir_gpio.config(output=True)
|
||||
dir_gpio.write(True)
|
||||
|
||||
axis.parent.erase_config_and_reboot()
|
||||
if axis.num == 0:
|
||||
axis.parent.handle.config.enable_uart = False
|
||||
setattr(axis.parent.handle.config, 'gpio' + str(step_gpio_num) + '_mode', GPIO_MODE_DIGITAL)
|
||||
setattr(axis.parent.handle.config, 'gpio' + str(dir_gpio_num) + '_mode', GPIO_MODE_DIGITAL)
|
||||
axis.parent.save_config_and_reboot()
|
||||
axis.handle.config.enable_step_dir = True
|
||||
axis.handle.config.step_dir_always_on = True # needed for testing
|
||||
axis.handle.config.step_gpio_pin = step_gpio_num
|
||||
|
||||
@@ -247,11 +247,8 @@ class ODriveComponent(Component):
|
||||
for axis_idx, axis_ctx in enumerate(self.axes):
|
||||
axis_ctx.handle = self.handle.__dict__['axis{}'.format(axis_idx)]
|
||||
|
||||
def unuse_gpios(self):
|
||||
self.handle.config.enable_uart = False
|
||||
self.handle.axis0.config.enable_step_dir = False
|
||||
self.handle.axis1.config.enable_step_dir = False
|
||||
self.handle.config.gpio1_pwm_mapping.endpoint = None
|
||||
def disable_mappings(self):
|
||||
self.handle.config.gpio1_pwm_mapping.endpoint = None # here
|
||||
self.handle.config.gpio2_pwm_mapping.endpoint = None
|
||||
self.handle.config.gpio3_pwm_mapping.endpoint = None
|
||||
self.handle.config.gpio4_pwm_mapping.endpoint = None
|
||||
|
||||
@@ -48,7 +48,9 @@ class TestUartAscii():
|
||||
# GPIOs might be in use by something other than UART and some components
|
||||
# might be configured so that they would fail in the later test.
|
||||
odrive.erase_config_and_reboot()
|
||||
odrive.handle.config.enable_uart = True
|
||||
odrive.handle.config.enable_uart0 = True
|
||||
odrive.handle.config.gpio1_mode = GPIO_MODE_UART0
|
||||
odrive.handle.config.gpio2_mode = GPIO_MODE_UART0
|
||||
|
||||
with port.open(115200) as ser:
|
||||
# reset port to known state
|
||||
@@ -161,10 +163,11 @@ class TestUartBaudrate():
|
||||
yield (odrive, ports)
|
||||
|
||||
def run_test(self, odrive: ODriveComponent, port: SerialPortComponent, logger: Logger):
|
||||
odrive.handle.axis0.config.enable_step_dir = False
|
||||
odrive.handle.config.enable_uart = True
|
||||
odrive.handle.config.enable_uart0 = True
|
||||
odrive.handle.config.gpio1_mode = GPIO_MODE_UART0
|
||||
odrive.handle.config.gpio2_mode = GPIO_MODE_UART0
|
||||
|
||||
odrive.handle.config.uart_baudrate = 9600
|
||||
odrive.handle.config.uart0_baudrate = 9600
|
||||
odrive.save_config_and_reboot()
|
||||
|
||||
# Control test: talk to the ODrive with the wrong baudrate
|
||||
@@ -184,7 +187,7 @@ class TestUartBaudrate():
|
||||
response = float(ser.readline().strip())
|
||||
test_assert_eq(response, odrive.handle.vbus_voltage, accuracy=0.1)
|
||||
|
||||
odrive.handle.config.uart_baudrate = 115200
|
||||
odrive.handle.config.uart0_baudrate = 115200
|
||||
odrive.save_config_and_reboot()
|
||||
|
||||
|
||||
@@ -202,8 +205,9 @@ class TestUartBurnIn():
|
||||
yield (odrive, ports)
|
||||
|
||||
def run_test(self, odrive: ODriveComponent, port: SerialPortComponent, logger: Logger):
|
||||
odrive.handle.axis0.config.enable_step_dir = False
|
||||
odrive.handle.config.enable_uart = True
|
||||
odrive.handle.config.enable_uart0 = True
|
||||
odrive.handle.config.gpio1_mode = GPIO_MODE_UART0
|
||||
odrive.handle.config.gpio2_mode = GPIO_MODE_UART0
|
||||
|
||||
with port.open(115200) as ser:
|
||||
with open('/dev/random', 'rb') as rand:
|
||||
@@ -258,8 +262,9 @@ class TestUartNoise():
|
||||
noise_enable.write(False)
|
||||
time.sleep(0.1)
|
||||
|
||||
odrive.handle.axis0.config.enable_step_dir = False
|
||||
odrive.handle.config.enable_uart = True
|
||||
odrive.handle.config.enable_uart0 = True
|
||||
odrive.handle.config.gpio1_mode = GPIO_MODE_UART0
|
||||
odrive.handle.config.gpio2_mode = GPIO_MODE_UART0
|
||||
|
||||
with port.open(115200) as ser:
|
||||
# reset port to known state
|
||||
|
||||
Reference in New Issue
Block a user