1 Commits

Author SHA1 Message Date
8ecfc46ece Implement angleDelta accumulation 2020-05-24 13:08:07 +02:00
3 changed files with 85 additions and 73 deletions

View File

@ -2,11 +2,6 @@
#define PWM_FREQ 16000 // PWM frequency in Hz #define PWM_FREQ 16000 // PWM frequency in Hz
#define DEAD_TIME 48 // PWM deadtime #define DEAD_TIME 48 // PWM deadtime
#ifdef VARIANT_TRANSPOTTER
#define DELAY_IN_MAIN_LOOP 2
#else
#define DELAY_IN_MAIN_LOOP 5 // in ms. default 5. it is independent of all the timing critical stuff. do not touch if you do not know what you are doing.
#endif
#define TIMEOUT 5 // number of wrong / missing input commands before emergency off #define TIMEOUT 5 // number of wrong / missing input commands before emergency off
#define A2BIT_CONV 50 // A to bit for current conversion on ADC. Example: 1 A = 50, 2 A = 100, etc #define A2BIT_CONV 50 // A to bit for current conversion on ADC. Example: 1 A = 50, 2 A = 100, etc

151
main.cpp
View File

@ -22,6 +22,7 @@
*/ */
#include <algorithm> #include <algorithm>
#include <cmath>
#include "stm32f1xx_hal.h" #include "stm32f1xx_hal.h"
@ -76,9 +77,6 @@ int16_t offsetrr2 = 2000;
int16_t offsetdcl = 2000; int16_t offsetdcl = 2000;
int16_t offsetdcr = 2000; int16_t offsetdcr = 2000;
int16_t batVoltage = (400 * BAT_CELLS * BAT_CALIB_ADC) / BAT_CALIB_REAL_VOLTAGE;
int32_t batVoltageFixdt = (400 * BAT_CELLS * BAT_CALIB_ADC) / BAT_CALIB_REAL_VOLTAGE << 20; // Fixed-point filter output initialized at 400 V*100/cell = 4 V/cell converted to fixed-point
int32_t board_temp_adcFixdt = adc_buffer.temp << 20; // Fixed-point filter output initialized with current ADC converted to fixed-point int32_t board_temp_adcFixdt = adc_buffer.temp << 20; // Fixed-point filter output initialized with current ADC converted to fixed-point
int16_t board_temp_adcFilt = adc_buffer.temp; int16_t board_temp_adcFilt = adc_buffer.temp;
int16_t board_temp_deg_c; int16_t board_temp_deg_c;
@ -93,6 +91,8 @@ struct {
MotorState state; MotorState state;
uint32_t chops = 0; uint32_t chops = 0;
int16_T lastAngle = 0;
int32_t angleDelta = 0;
} left, right; } left, right;
struct { struct {
@ -215,7 +215,7 @@ int main()
HAL_UART_Receive_DMA(&huart2, (uint8_t *)&command, sizeof(command)); HAL_UART_Receive_DMA(&huart2, (uint8_t *)&command, sizeof(command));
for (;;) { for (;;) {
HAL_Delay(DELAY_IN_MAIN_LOOP); //delay in ms HAL_Delay(1); //delay in ms
parseCommand(); parseCommand();
@ -262,11 +262,6 @@ void updateMotors()
return; return;
} }
if (buzzer.timer % 1000 == 0) { // because you get float rounding errors if it would run every time -> not any more, everything converted to fixed-point
filtLowPass32(adc_buffer.batt1, BAT_FILT_COEF, &batVoltageFixdt);
batVoltage = (int16_t)(batVoltageFixdt >> 20); // convert fixed-point to integer
}
// Get Left motor currents // Get Left motor currents
int16_t curL_phaA = (int16_t)(offsetrl1 - adc_buffer.rl1); int16_t curL_phaA = (int16_t)(offsetrl1 - adc_buffer.rl1);
int16_t curL_phaB = (int16_t)(offsetrl2 - adc_buffer.rl2); int16_t curL_phaB = (int16_t)(offsetrl2 - adc_buffer.rl2);
@ -285,6 +280,36 @@ void updateMotors()
if (chopR) if (chopR)
right.chops++; right.chops++;
const auto doTheAngleThing = [](auto &motor){
if (motor.rtY.a_elecAngle < motor.lastAngle)
{
if (motor.lastAngle - motor.rtY.a_elecAngle < 180)
{
motor.angleDelta -= motor.lastAngle - motor.rtY.a_elecAngle;
}
else
{
// wrap
}
}
else
{
if (motor.rtY.a_elecAngle - motor.lastAngle < 180)
{
motor.angleDelta += motor.rtY.a_elecAngle - motor.lastAngle;
}
else
{
// wrap
}
}
motor.lastAngle = motor.rtY.a_elecAngle;
};
doTheAngleThing(left);
doTheAngleThing(right);
// Disable PWM when current limit is reached (current chopping) // Disable PWM when current limit is reached (current chopping)
// This is the Level 2 of current protection. The Level 1 should kick in first given by I_MOT_MAX // This is the Level 2 of current protection. The Level 1 should kick in first given by I_MOT_MAX
if(chopL || timeout > TIMEOUT || left.state.enable == 0) { if(chopL || timeout > TIMEOUT || left.state.enable == 0) {
@ -967,17 +992,15 @@ void MX_ADC2_Init() {
} }
void poweroff() { void poweroff() {
// if (abs(speed) < 20) { // wait for the speed to drop, then shut down -> this is commented out for SAFETY reasons buzzer.state.pattern = 0;
buzzer.state.pattern = 0; left.state.enable = right.state.enable = 0;
left.state.enable = right.state.enable = 0; for (uint8_t i = 0; i < 8; i++) {
for (int i = 0; i < 8; i++) { buzzer.state.freq = i;
buzzer.state.freq = (uint8_t)i; HAL_Delay(50);
HAL_Delay(50); }
} HAL_GPIO_WritePin(OFF_PORT, OFF_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(OFF_PORT, OFF_PIN, GPIO_PIN_RESET); for (int i = 0; i < 5; i++)
for (int i = 0; i < 5; i++) HAL_Delay(1000);
HAL_Delay(1000);
// }
} }
void parseCommand() void parseCommand()
@ -1012,9 +1035,9 @@ void parseCommand()
if (!any_parsed) if (!any_parsed)
{ {
if (timeoutCntSerial++ >= 100) // Timeout qualification if (timeoutCntSerial++ >= 500) // Timeout qualification
{ {
timeoutCntSerial = 100; // Limit timout counter value timeoutCntSerial = 500; // Limit timout counter value
left.state = right.state = {.enable=true}; left.state = right.state = {.enable=true};
@ -1034,45 +1057,49 @@ void parseCommand()
void sendFeedback() void sendFeedback()
{ {
if (main_loop_counter % 50 == 0) { // Send data periodically if(UART_DMA_CHANNEL->CNDTR == 0)
if(UART_DMA_CHANNEL->CNDTR == 0) { {
feedback.start = Feedback::VALID_HEADER; feedback.start = Feedback::VALID_HEADER;
feedback.left.angle = left.rtY.a_elecAngle; feedback.left.angle = left.rtY.a_elecAngle;
feedback.right.angle = right.rtY.a_elecAngle; feedback.right.angle = right.rtY.a_elecAngle;
feedback.left.speed = left.rtY.n_mot; feedback.left.speed = left.rtY.n_mot;
feedback.right.speed = right.rtY.n_mot; feedback.right.speed = right.rtY.n_mot;
feedback.left.error = left.rtY.z_errCode; feedback.left.error = left.rtY.z_errCode;
feedback.right.error = right.rtY.z_errCode; feedback.right.error = right.rtY.z_errCode;
feedback.left.current = left.rtU.i_DCLink; feedback.left.current = left.rtU.i_DCLink;
feedback.right.current = right.rtU.i_DCLink; feedback.right.current = right.rtU.i_DCLink;
feedback.left.chops = left.chops; feedback.left.chops = left.chops;
feedback.right.chops = right.chops; feedback.right.chops = right.chops;
left.chops = 0; left.chops = 0;
right.chops = 0; right.chops = 0;
feedback.left.hallA = left.rtU.b_hallA; feedback.left.angleDelta = left.angleDelta;
feedback.left.hallB = left.rtU.b_hallB; feedback.right.angleDelta = right.angleDelta;
feedback.left.hallC = left.rtU.b_hallC; left.angleDelta = 0;
feedback.right.hallA = right.rtU.b_hallA; right.angleDelta = 0;
feedback.right.hallB = right.rtU.b_hallB;
feedback.right.hallC = right.rtU.b_hallC;
feedback.batVoltage = batVoltage * BAT_CALIB_REAL_VOLTAGE / BAT_CALIB_ADC; feedback.left.hallA = left.rtU.b_hallA;
feedback.boardTemp = board_temp_deg_c; feedback.left.hallB = left.rtU.b_hallB;
feedback.timeoutCntSerial = timeoutCntSerial; feedback.left.hallC = left.rtU.b_hallC;
feedback.right.hallA = right.rtU.b_hallA;
feedback.right.hallB = right.rtU.b_hallB;
feedback.right.hallC = right.rtU.b_hallC;
feedback.checksum = calculateChecksum(feedback); feedback.batVoltage = adc_buffer.batt1 * BAT_CALIB_REAL_VOLTAGE / BAT_CALIB_ADC;
feedback.boardTemp = board_temp_deg_c;
feedback.timeoutCntSerial = timeoutCntSerial;
UART_DMA_CHANNEL->CCR &= ~DMA_CCR_EN; feedback.checksum = calculateChecksum(feedback);
UART_DMA_CHANNEL->CNDTR = sizeof(feedback);
UART_DMA_CHANNEL->CMAR = uint64_t(&feedback); UART_DMA_CHANNEL->CCR &= ~DMA_CCR_EN;
UART_DMA_CHANNEL->CCR |= DMA_CCR_EN; UART_DMA_CHANNEL->CNDTR = sizeof(feedback);
} UART_DMA_CHANNEL->CMAR = uint64_t(&feedback);
UART_DMA_CHANNEL->CCR |= DMA_CCR_EN;
} }
} }
@ -1101,8 +1128,7 @@ extern "C" void HardFault_Handler() {
/* USER CODE BEGIN HardFault_IRQn 0 */ /* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */ /* USER CODE END HardFault_IRQn 0 */
while(1) { for (;;);
}
/* USER CODE BEGIN HardFault_IRQn 1 */ /* USER CODE BEGIN HardFault_IRQn 1 */
/* USER CODE END HardFault_IRQn 1 */ /* USER CODE END HardFault_IRQn 1 */
@ -1115,8 +1141,7 @@ extern "C" void MemManage_Handler() {
/* USER CODE BEGIN MemoryManagement_IRQn 0 */ /* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */ /* USER CODE END MemoryManagement_IRQn 0 */
while(1) { for (;;);
}
/* USER CODE BEGIN MemoryManagement_IRQn 1 */ /* USER CODE BEGIN MemoryManagement_IRQn 1 */
/* USER CODE END MemoryManagement_IRQn 1 */ /* USER CODE END MemoryManagement_IRQn 1 */
@ -1129,8 +1154,7 @@ extern "C" void BusFault_Handler() {
/* USER CODE BEGIN BusFault_IRQn 0 */ /* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */ /* USER CODE END BusFault_IRQn 0 */
while(1) { for (;;);
}
/* USER CODE BEGIN BusFault_IRQn 1 */ /* USER CODE BEGIN BusFault_IRQn 1 */
/* USER CODE END BusFault_IRQn 1 */ /* USER CODE END BusFault_IRQn 1 */
@ -1143,8 +1167,7 @@ extern "C" void UsageFault_Handler() {
/* USER CODE BEGIN UsageFault_IRQn 0 */ /* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */ /* USER CODE END UsageFault_IRQn 0 */
while(1) { for (;;);
}
/* USER CODE BEGIN UsageFault_IRQn 1 */ /* USER CODE BEGIN UsageFault_IRQn 1 */
/* USER CODE END UsageFault_IRQn 1 */ /* USER CODE END UsageFault_IRQn 1 */
@ -1189,10 +1212,6 @@ extern "C" void PendSV_Handler() {
/** /**
* @brief This function handles System tick timer. * @brief This function handles System tick timer.
*/ */
#ifdef CONTROL_PPM
extern "C" void PPM_SysTick_Callback();
#endif
extern "C" void SysTick_Handler() { extern "C" void SysTick_Handler() {
/* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE BEGIN SysTick_IRQn 0 */
@ -1200,9 +1219,7 @@ extern "C" void SysTick_Handler() {
HAL_IncTick(); HAL_IncTick();
HAL_SYSTICK_IRQHandler(); HAL_SYSTICK_IRQHandler();
/* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE BEGIN SysTick_IRQn 1 */
#ifdef CONTROL_PPM
PPM_SysTick_Callback();
#endif
/* USER CODE END SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */
} }