void updateRobotNew(void){ //odometry from book //update previous tick double cm; RobotNew.prevTickL = RobotNew.tickL; RobotNew.prevTickR = RobotNew.tickR; //update tick RobotNew.tickL = __HAL_TIM_GET_COUNTER(&encoderL); RobotNew.tickR = __HAL_TIM_GET_COUNTER(&encoderR); cm = (2*M_PI*R)/CPM; //update speed of robot //Forward move if((RobotNew.prevTickL>RobotNew.tickL && RobotNew.dirL == FORWARD) && (RobotNew.prevTickR>RobotNew.tickR && RobotNew.dirR == FORWARD)){ //both encoder counters overflow pote omws return; } else if(RobotNew.prevTickL>RobotNew.tickL && RobotNew.dirL == FORWARD){ //only Left enc overflow RobotNew.sR = cm*(RobotNew.tickR - RobotNew.prevTickR); return; } else if(RobotNew.prevTickR>RobotNew.tickR && RobotNew.dirR == FORWARD){ //only Right enc overflow RobotNew.sL = cm*(RobotNew.tickL - RobotNew.prevTickL); return; } //Backward move else if((RobotNew.prevTickL<RobotNew.tickL && RobotNew.dirL == BACKWARD) && (RobotNew.prevTickR<RobotNew.tickR && RobotNew.dirR == BACKWARD)){ //both encoder counters underflow return; } else if(RobotNew.prevTickL<RobotNew.tickL && RobotNew.dirL == BACKWARD){ //only Left enc underflow RobotNew.sR = cm*(RobotNew.prevTickR - RobotNew.tickR); RobotNew.wR = RobotNew.sR/UPDTIME; RobotNew.s = (RobotNew.sL + RobotNew.sR)/2.0; return; } else if(RobotNew.prevTickR<RobotNew.tickR && RobotNew.dirR == BACKWARD){ RobotNew.sL = cm*(RobotNew.prevTickL - RobotNew.tickL); RobotNew.wL = RobotNew.sL/UPDTIME; RobotNew.s = (RobotNew.sL + RobotNew.sR)/2.0; return; } if(RobotNew.dirR == FORWARD){ RobotNew.sR = cm*(RobotNew.tickR - RobotNew.prevTickR); } else{ RobotNew.sR = cm*(RobotNew.prevTickR - RobotNew.tickR); } if(RobotNew.dirL == FORWARD){ RobotNew.sL = cm*(RobotNew.tickL - RobotNew.prevTickL); } else{ RobotNew.sL = cm*(RobotNew.prevTickL - RobotNew.tickL); } RobotNew.s = (RobotNew.sL + RobotNew.sR)/2.0; RobotNew.wR = RobotNew.sR/UPDTIME; RobotNew.wL = RobotNew.sL/UPDTIME; }
//################# Motion Control ################// void updateRobot(void){ //update previous tick Robot.prevTickL = Robot.tickL; Robot.prevTickR = Robot.tickR; //update tick Robot.tickL = __HAL_TIM_GET_COUNTER(&encoderL); Robot.tickR = __HAL_TIM_GET_COUNTER(&encoderR); //update speed of robot //Forward move if((Robot.prevTickL>Robot.tickL && Robot.dirL == FORWARD) && (Robot.prevTickR>Robot.tickR && Robot.dirR == FORWARD)){ //both encoder counters overflow pote omws return; } else if(Robot.prevTickL>Robot.tickL && Robot.dirL == FORWARD){ //only Left enc overflow Robot.wR = (2*M_PI)/CPM*(Robot.tickR - Robot.prevTickR)/UPDTIME; return; } else if(Robot.prevTickR>Robot.tickR && Robot.dirR == FORWARD){ //only Right enc overflow Robot.wL = (2*M_PI)/CPM*(Robot.tickL - Robot.prevTickL)/UPDTIME; return; } //Backward move else if((Robot.prevTickL<Robot.tickL && Robot.dirL == BACKWARD) && (Robot.prevTickR<Robot.tickR && Robot.dirR == BACKWARD)){ //both encoder counters underflow return; } else if(Robot.prevTickL<Robot.tickL && Robot.dirL == BACKWARD){ //only Left enc underflow Robot.wR = (2*M_PI)/CPM*(Robot.prevTickR - Robot.tickR)/UPDTIME; return; } else if(Robot.prevTickR<Robot.tickR && Robot.dirR == BACKWARD){ Robot.wL = (2*M_PI)/CPM*(Robot.prevTickL - Robot.tickL)/UPDTIME; return; } if(Robot.dirR == FORWARD){ Robot.wR = (2*M_PI)/CPM*(Robot.tickR - Robot.prevTickR)/UPDTIME; } else{ Robot.wR = (2*M_PI)/CPM*(Robot.prevTickR - Robot.tickR)/UPDTIME; } if(Robot.dirL == FORWARD){ Robot.wL = (2*M_PI)/CPM*(Robot.tickL - Robot.prevTickL)/UPDTIME; } else{ Robot.wL = (2*M_PI)/CPM*(Robot.prevTickL - Robot.tickL)/UPDTIME; } }
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration----------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM1_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_1 | TIM_CHANNEL_2); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ c = __HAL_TIM_GET_COUNTER(&htim1); printf("%d\n", c); HAL_Delay(250); } /* USER CODE END 3 */ }
int main(void) { HAL_Init(); Nucleo_BSP_Init(); MX_TIM1_Init(); MX_TIM3_Init(); HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1); HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2); cnt1 = __HAL_TIM_GET_COUNTER(&htim3); tick = HAL_GetTick(); while (1) { if (HAL_GetTick() - tick > 1000L) { cnt2 = __HAL_TIM_GET_COUNTER(&htim3); if (__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3)) { if (cnt2 < cnt1) /* Check for counter underflow */ diff = cnt1 - cnt2; else diff = (65535 - cnt2) + cnt1; } else { if (cnt2 > cnt1) /* Check for counter overflow */ diff = cnt2 - cnt1; else diff = (65535 - cnt1) + cnt2; } sprintf(msg, "Difference: %d\r\n", diff); HAL_UART_Transmit(&huart2, (uint8_t*) msg, strlen(msg), HAL_MAX_DELAY); speed = ((diff / PULSES_PER_REVOLUTION) / 60); /* If the first three bits of SMCR register are set to 0x3 * then the timer is set in X4 mode (TIM_ENCODERMODE_TI12) * and we need to divide the pulses counter by two, because * they include the pulses for both the channels */ if ((TIM3->SMCR & 0x3) == 0x3) speed /= 2; sprintf(msg, "Speed: %d RPM\r\n", speed); HAL_UART_Transmit(&huart2, (uint8_t*) msg, strlen(msg), HAL_MAX_DELAY); dir = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3); sprintf(msg, "Direction: %d\r\n", dir); HAL_UART_Transmit(&huart2, (uint8_t*) msg, strlen(msg), HAL_MAX_DELAY); tick = HAL_GetTick(); cnt1 = __HAL_TIM_GET_COUNTER(&htim3); } if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET) { /* Invert rotation by swapping CH1 and CH2 CCR value */ tim1_ch1_pulse = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_1); tim1_ch2_pulse = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, tim1_ch2_pulse); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, tim1_ch1_pulse); } } }
/** * @brief This function handles TIM interrupt request. * @param None * @retval None */ void TIM7_IRQHandler(void) { present_encoder_count = __HAL_TIM_GET_COUNTER(&TimHandle_Enc1); speed = present_encoder_count - previous_encoder_count ; local_time++; /* If control is PBC, turn off the motor when the present_encoder_count is greater than or equal to pOn */ if(control == PBC && ((dir == pos && present_encoder_count >= pOn) || (dir == rev && present_encoder_count <= pOn))) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8 , GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET); isHigh = 1; // Calculate PCC for adaptation } /* If control is TBC, turn off the motor when the local_time is greater than or equal to tOn */ if(control == TBC && local_time>=tOn) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8 , GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET); } /* Wait until motor settles */ if(speed_count == 10 ) { pS = present_encoder_count ; if(isHigh) // If the control was PBC, calculate PCC for adaptation { pcc = (((float)x*pcc)+((float)y*pcc*((float)local_demand/(float)(absolute(pS - pSa)))))/((float)x+(float)y); isHigh = 0;} error = demand - pS; local_demand = absolute(error); pSa = __HAL_TIM_GET_COUNTER(&TimHandle_Enc1); if(local_demand <= 6); // If error is less than 6 pulses, exit the control loop else if(local_demand <= 100){ // If error is less than 100 pulses, use Time Based Control control = TBC; local_time=0; isDemandChanged=1;} else { // If error is greater tha 100 pulses, use Position Based Control control = PBC; isDemandChanged=1;} /* Set direction depending on the sign of the error */ if(error < 0) dir = rev; else dir = pos; /* Disable Timer Interrupt */ HAL_TIM_Base_Stop(&TimHandle_int); /* Reset Speed count*/ speed_count = 0; } /* Wait for 10ms after speed becomes 0 ie., until the motor settles */ if(speed == 0) speed_count++; // If speed is 0, increment speed count else speed_count = 0; // Else reset speed count previous_encoder_count = present_encoder_count; HAL_TIM_IRQHandler(&TimHandle_int); }
/* 过零点触发中断 回调函数 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin != ZERO) return; bool wave_is_rise; // 读Pin,判断是上升沿还是下降沿 if (HAL_GPIO_ReadPin(PORT_ZERO, ZERO) == GPIO_PIN_RESET) { wave_is_rise = true; } else { wave_is_rise = false; } // t 顺序: 1 3 4 6 // 上升沿 if (wave_is_rise) { t4 = __HAL_TIM_GET_COUNTER(&htim3); // 上升沿是否valid? // if (!it_is_valid(t4_prev, t4)) { // t4_prev = t4; // r++; // return; // } //r++; } else { // 下降沿 t6 = __HAL_TIM_GET_COUNTER(&htim3); // 下降沿是否valid? // if (!it_is_valid(t6_prev, t6)) { // t6_prev = t6; // f++; // return; // } //f++; } if (wave_is_rise) // 只在波谷计算,否则退出 return; is_lower_blow = true; // 设置波谷flag is_lower_exchange = true; is_lower_feed = true; /* 下降沿时计算下一个零点 */ // t2 if (t3 < t1) t2 = (0xffff + t1 + t3) / 2; else t2 = (t1 + t3) / 2; // t5 if (t6 < t4) t5 = (0xffff + t4 + t6) / 2; else t5 = (t4 + t6) / 2; // 交流电源周期 if (t5 < t2) T1 = 0xffff + t5 - t2; else T1 = t5 - t2; // 下一个零点 if (t5 < t4) t7 = t5 + 0xffff - t4 + (T1 / 4); /* 计算不对 ! */ else t7 = t5 - t4 + (T1 / 4); // counter++; // if (counter >=299) { // //printf("t4:%d,t5:%d,t6:%d,t7:%d,T1:%d\r\n", t4,t5,t6,t7,T1); // printf("delay:%d\r\n", t7 + TOTAL_TIME - triac_cur.fan_smoke_delay * 100); // counter = 0; // } // 更新数值 t1 = t4; t2 = t5; t3 = t6; // 计数器复位 __HAL_TIM_SET_COUNTER (&htim1, 0); __HAL_TIM_SET_COUNTER (&htim4, 0); // 检查Q_Triac队列,更新输出的控制状态 if (Q_TriacHandle != NULL) { // 读取值 osEvent evt = osMessageGet(Q_TriacHandle, 0); if (evt.status == osEventMessage) { triac_cur = *((Triac *)evt.value.p); // 更新送料duty on_count = triac_cur.feed_duty * 100; off_count = 1000 - on_count; // 10s = 10000ms 10000 / 10 = 1000 // 返还内存 osStatus status = osPoolFree(pool_TriacHandle, evt.value.p); if (status != osOK) printf("Free Triac memory error:%x\r\n", status); } } // 设置period __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, t7 + TOTAL_TIME - triac_cur.fan_smoke_delay * 100); // 80÷100×10×1000 = 80×100 __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, t7 + TOTAL_TIME - triac_cur.fan_exchange_delay * 100); __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, t7); /* 输出: 条件判断 */ HAL_StatusTypeDef status; //排烟通道 if (triac_cur.fan_smoke_is_on) { status = HAL_TIM_OC_Start_IT(&htim4, TIM_CHANNEL_1); if (status != HAL_OK) printf("time4 c1 failed at zero:%x\r\n", status); } //循环通道 if (triac_cur.fan_exchange_is_on) { status = HAL_TIM_OC_Start_IT(&htim4, TIM_CHANNEL_2); if (status != HAL_OK) printf("time4 c2 failed:%x\r\n", status); } //送料通道 ON计数 OFF计数 if (triac_cur.feed_is_on) { // 送料 if (running_feed) { if (on_cnt < on_count) { // 输出 送料: On HAL_TIM_OC_Start_IT(&htim4, TIM_CHANNEL_3); on_cnt++; } else { on_cnt = 0; off_cnt = 0; running_feed = false; waiting_feed = true; } } // 不送料 if (waiting_feed) { off_cnt ++; if (off_cnt >= off_count) { on_cnt = 0; off_cnt = 0; running_feed = true; waiting_feed = false; } } } // }
/* 过零点触发中断 回调函数 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin != ZERO) return; bool rising_edge; // 读Pin,判断是上升沿还是下降沿 if (HAL_GPIO_ReadPin(PORT_ZERO, ZERO) == GPIO_PIN_SET) { rising_edge = true; } else { rising_edge = false; } // t 顺序: 1 3 4 6 // 上升沿 if (rising_edge) { t6 = __HAL_TIM_GET_COUNTER(&htim3); } else { // 下降沿 t4 = __HAL_TIM_GET_COUNTER(&htim3); } if (!rising_edge) // 只在波谷计算,否则退出 return; /*----------------------------------------------------------------------------*/ is_lower_blow = true; // 设置波谷flag is_lower_exchange = true; is_lower_feed = true; /* 下降沿时计算下一个零点 */ // t1 t3 t4 t6 if ((t1<t3) && (t3<t4) && (t4<t6)) { t2 = (t1+t3) / 2; t5 = (t4+t6) / 2; } else if(t3<t1) { t2 = (t1+t3+0xffff) / 2; t5 = (t4+t6)/2 + 0xffff; } else if(t4<t3) { t2 = (t1+t3) / 2; t5 = (t4+t6)/2 + 0xffff; } else if(t6<t4) { t2 = (t1+t3) / 2; t5 = (t4+t6+0xffff) / 2; } T1 = t5 - t2; // 下一个零点 if (t6<t5) { t7 = t5 + T1/4 - t6 -0xffff; } else { t7 = t5 + T1/4 - t6; } // debug // counter++; // if (counter >= 149) { // Zero *z; // z = (Zero*)osPoolAlloc(pool_ZeroHandle); // if (z!=NULL) { // z->t1 = t1; // z->t3 = t3; // z->t4 = t4; // z->t6 = t6; // z->t7 = t7; // z->T1 = T1; // osMessagePut(Q_ErrorHandle, (uint32_t)z, 0); // } // // counter = 0; // } // // 更新数值 t1 = t4; t3 = t6; /*--------------------------------------------------------------------------*/ // 只处理下半波 if (t7 == 0) { t7 = 220; } is_lower_blow = true; // 设置波谷flag is_lower_exchange = true; is_lower_feed = true; //uint32_t compare = 0; // 检查Q_Triac队列,更新输出的控制状态 if (Q_TriacHandle != NULL) { // 读取值 osEvent evt = osMessageGet(Q_TriacHandle, 0); if (evt.status == osEventMessage) { Triac *p = (Triac *)evt.value.p; triac_cur.fan_exchange_delay = p->fan_exchange_delay; triac_cur.fan_exchange_is_on = p->fan_exchange_is_on; triac_cur.fan_smoke_is_on = p->fan_smoke_is_on; triac_cur.fan_smoke_power = p->fan_smoke_power; triac_cur.feed_by_manual = p->feed_by_manual; triac_cur.feed_duty = p->feed_duty; triac_cur.feed_full = p->feed_full; triac_cur.feed_is_on = p->feed_is_on; // 更新送料duty if (triac_cur.feed_duty != 0) { // 500×triac_cur.feed_duty÷100 on_count = 5 * triac_cur.feed_duty; off_count = 500 - on_count; // 10s = 10000ms 10000 / 20 = 500 } // 返还内存 osStatus status = osPoolFree(pool_TriacHandle, evt.value.p); if (status != osOK) printf("Free Triac memory error:%x\r\n", status); } } /*----------------------------------------------------------------------------*/ // 设置period if (triac_cur.fan_smoke_power == 0) { triac_cur.fan_smoke_power = 60; } // 最低延时2.5ms,最高延时6ms uint32_t delay = t7 + triac_cur.fan_smoke_power; if (delay>8999) { delay = last_delay; } else { last_delay = delay; } // 计数器复位 __HAL_TIM_SET_COUNTER (&htim2, 0); __HAL_TIM_SET_COUNTER (&htim4, 0); __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, delay); __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, t7+T1/4); __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, t7+T1/4); /* 输出: 条件判断 */ //排烟通道 if (triac_cur.fan_smoke_is_on) { __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC1); } //循环通道 if (triac_cur.fan_exchange_is_on) { __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC2); } //送料通道 if ((triac_cur.feed_by_manual || triac_cur.feed_full) && (!triac_cur.feed_is_on)) { __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC3); } //送料通道 ON计数 OFF计数 if (triac_cur.feed_is_on && (!triac_cur.feed_by_manual)) { // 0 // 送料 if (feed_run) { __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC3); count_feed ++; if (count_feed >= on_count) { count_feed = 0; feed_run = false; } } else { // 不送料 count_feed ++; if (count_feed >= off_count) { count_feed = 0; feed_run = true; } } } // if 0 }
/* TIM4 打开触发脉冲 */ void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { uint32_t compare = 0; /* TIM4 */ if (htim->Instance == TIM4) { // 1 // 排烟风机 通道 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { // 排烟风机 delay_on, 打开输出 if (!is_lower_blow) { __HAL_TIM_DISABLE_IT(&htim4, TIM_IT_CC1); } ON_SMOKE; // 延时关断 compare = __HAL_TIM_GET_COUNTER(&htim2) + uS_DELAY_OFF; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, compare); __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_CC1); // 下一个半波 if (is_lower_blow) { is_lower_blow = false; compare = __HAL_TIM_GET_COUNTER(&htim4) + HALF_T1; __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, compare); //__HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC1); } } // 2 // 循环风机通道 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { // 循环风机 delay_on, 打开输出 if (!is_lower_exchange){ __HAL_TIM_DISABLE_IT(&htim4, TIM_IT_CC2); } ON_EXCHANGE; // 延时关断 compare = __HAL_TIM_GET_COUNTER(&htim2) + uS_DELAY_OFF; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, compare); __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_CC2); // 下一个半波 if (is_lower_exchange) { is_lower_exchange = false; compare = __HAL_TIM_GET_COUNTER(&htim4) + HALF_T1; __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, compare); //__HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC2); } } // 3 // 送料电机 通道 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3) { // 送料 if (!is_lower_feed) { __HAL_TIM_DISABLE_IT(&htim4, TIM_IT_CC3); } ON_FEED; // 延时关断 compare = __HAL_TIM_GET_COUNTER(&htim2) + uS_DELAY_OFF; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, compare); __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC3); // 下一个半波 if (is_lower_feed){ is_lower_feed = false; compare = __HAL_TIM_GET_COUNTER(&htim4) + HALF_T1; __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, compare); //__HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC3); } } // } /* TIM2 关闭触发脉冲 */ // 延时x us关闭触发 if (htim->Instance == TIM2) { // 1 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { OFF_SMOKE; __HAL_TIM_DISABLE_IT(&htim2, TIM_IT_CC1); } // 2 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { // 输出 循环:Off OFF_EXCHANGE; __HAL_TIM_DISABLE_IT(&htim2, TIM_IT_CC2); } // 3 if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3) { // 输出 送料: Off OFF_FEED; __HAL_TIM_DISABLE_IT(&htim2, TIM_IT_CC3); } } // TIM2 // }
int16_t TIM4_GetCount(void) { return __HAL_TIM_GET_COUNTER(&htim4); }