New Text Document
New Text Document
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;
//Motor---------------------------
int enc_right=0,enc_pre_right=0,delta_enc_right=0;
int enc_left=0,enc_pre_left=0,delta_enc_left;
float rpm_left =0,rpm_right=0;
//---------------------------SYSTEM
VARIABLES-----------------------------------------------------
//He thong
float Ts = 0.01, flag =0, re=0;
//float v_control, w_control, v_reponse, w_reponse;//* ta_control,
tb_control
float k1 = 0, k2 = 150, k3 =9.9;//*
float v, w, r = 0.0425, b = 0.196;
float vr = 0.4, vtb = 0, wr = 0,v_A=0, v_B=0;
float e1_line = 0, e2_line = 0, e3_line = 0;
int empty = 1, outline = 0; //Ban dau empty de kiem tra cho dung line
den //Khai bao emty ,outline
int counter = 0;
int stop = 0;
float setpoint_r = 0, setpoint_l = 0; //duty_cycle cua he thong
int check =0;
int top=0, below=0;
/* USER CODE END PV */
////-------------------------------------------------------------------------------
----------------------------------
// Kiem tra co line den khong de chay
void no_line_no_run() {
//AdcValue nho hon 1000 thi dang o line trang
//Tay ca sensor
if((AdcValues[0] <= 600 && AdcValues[1] <= 600 && AdcValues[2] <= 600 &&
AdcValues[3] <= 600 && AdcValues[4] <= 600))
{
stop = 1;
outline = 1;
}
else outline =0;
if(empty ==1 && flag ==0 &&((AdcValues[0] >= 1000 && AdcValues[1] >= 1000 &&
AdcValues[4]<1000)
||(AdcValues[1] >= 1000 && AdcValues[2] >= 1000 &&
AdcValues[4]<1000)
||(AdcValues[2] >= 1000 && AdcValues[3] >= 1000 &&
AdcValues[0]<1000)
||(AdcValues[2] >= 1000 && AdcValues[0] <= 1000 &&
AdcValues[4] <= 1000 && AdcValues[3] <= 1000 && AdcValues[1] <= 1000)
|| (AdcValues[3]>1000 && AdcValues[4] >= 1000 &&
AdcValues[0]<1000)))
{
stop=0;
cho=1;
flag =1;
}
}
////-------------------------------------------------------------------------------
-----------------------------------
//-------------------------Giam toc--------------------------
//void Speed_down()
//{
// if(below ==1 && below_road ==0 && m==1)
// {
// m=2;
// setpoint_l =96;
// setpoint_r = 78;
// }
// if(m ==2)
// {
// m=3;
// for(int q =0; q<=100; q++)
// {
// setpoint_l=84;
// setpoint_r =92;
// }
// if(m ==3 || vtb > 0.41)
// {
// for (int w=0; w<= 20; w++)
// {
// setpoint_l =54;
// setpoint_r = 109;
// }
// m=0;
// }
// }
//}
//--------------------------------------------
////Ham kiem tra nen chay hay dung khi den noi nhan hang
void stop_or_run()
{
//Xem mấy cảm biến nhận
if(empty==1 &&((AdcValues[0]>=1000 &&AdcValues[1] >= 1000&& AdcValues[2] >= 1000 &&
AdcValues[4]<=1000 ) //111_0
||(AdcValues[0]<=1000 && AdcValues[1] >= 1000 && AdcValues[2] >= 1000
&& AdcValues[3] >= 1000 && AdcValues[4]<=1000)//1110
||(AdcValues[0]<=1000 && AdcValues[2] >= 1000 && AdcValues[3] >= 1000
&& AdcValues[4] >= 1000) //00111
||(AdcValues[0]<=1000 && AdcValues[1] >= 1000 && AdcValues[2] >= 1000
&& AdcValues[3] >= 1000 && AdcValues[4] >= 1000)
||(AdcValues[0]>=1000 && AdcValues[1] >= 1000 && AdcValues[2] >= 1000
&& AdcValues[3] >= 1000 && AdcValues[4] <= 1000)
)) //01111)
{
stop = 1;
}
//Nen de xe doc gia tri thoi gian khoang 1s khi gia tri ADC lien tuc phu hop
stop =1;
}
//day cam bien line duoc xac dinh gia tri
////----------------------------------------SENSOR
CALIB--------------------------------------------------------------------------
//sensorline
void CaculatorFuntionSensor(void)
{
A[0] = (float) ( Ymax - Ymin ) / ( ADCMaxValue[0] - ADCMinValue[0] );
A[1] = (float) ( Ymax - Ymin ) / ( ADCMaxValue[1] - ADCMinValue[1] );
A[2] = (float) ( Ymax - Ymin ) / ( ADCMaxValue[2] - ADCMinValue[2] );
A[3] = (float) ( Ymax - Ymin ) / ( ADCMaxValue[3] - ADCMinValue[3] );
A[4] = (float) ( Ymax - Ymin ) / ( ADCMaxValue[4] - ADCMinValue[4] );
}
void CalibrationSenrsorValue(uint16_t *ADCValue)
{
AdcValuesAfterCalib[0] = (uint16_t) (Ymin + A[0]*( ADCValue[0] -
ADCMinValue[0]));
AdcValuesAfterCalib[1] = (uint16_t) (Ymin + A[1]*( ADCValue[1] -
ADCMinValue[1]));
AdcValuesAfterCalib[2] = (uint16_t) (Ymin + A[2]*( ADCValue[2] -
ADCMinValue[2]));
AdcValuesAfterCalib[3] = (uint16_t) (Ymin + A[3]*( ADCValue[3] -
ADCMinValue[3]));
AdcValuesAfterCalib[4] = (uint16_t) (Ymin + A[4]*( ADCValue[4] -
ADCMinValue[4]));
}
void CalibSensorDependOnEnvironment(void)
{
for(int i = 0; i < 5; i++)
{
if(AdcValues[i] != 0)
{
if(AdcValues[i] > ADCMaxValue[i])
ADCMaxValue[i] = AdcValues[i];
if(AdcValues[i] < ADCMinValue[i])
ADCMinValue[i] = AdcValues[i];
}
sumADCmax += ADCMaxValue[i];
sumADCmin += ADCMinValue[i];
}
Ymax = sumADCmax/5;
Ymin = sumADCmin/5;
sumADCmax = 0;
sumADCmin = 0;
}
float ErrorLine(void)
{
CalibrationSenrsorValue(AdcValues);
sum_Adcvalues = (AdcValuesAfterCalib[0] + AdcValuesAfterCalib[1] +
AdcValuesAfterCalib[2] + AdcValuesAfterCalib[3] + AdcValuesAfterCalib[4]);
e2_line = (2*(AdcValuesAfterCalib[4] - AdcValuesAfterCalib[0]) +
(AdcValuesAfterCalib[3] - AdcValuesAfterCalib[1]))*17/sum_Adcvalues;
e2_line = (e2_line + 1.25977)/1.241049;
return e2_line;
//Sai so cua line
}
//-----------------------------------------------------------------------
//-----------------Speed-------------------//
void find_speed(void)
{
enc_right =__HAL_TIM_GET_COUNTER(&htim4); //v2 banh right
if (enc_right < enc_pre_right) {
delta_enc_right = 65535 -enc_pre_right +enc_right ;
}
else {
delta_enc_right = enc_right - enc_pre_right;
}
enc_left =__HAL_TIM_GET_COUNTER(&htim3); //v1 banh left
if (enc_left < enc_pre_left) {
delta_enc_left = 65535 -enc_pre_left +enc_left ;
}
else {
delta_enc_left = enc_left - enc_pre_left;
}
rpm_right = 60 * (delta_enc_right) / (1980 * Ts);
rpm_left = 60 * (delta_enc_left) / (1980 * Ts);
enc_pre_left =enc_left;
enc_pre_right =enc_right;
v_A = abs_(rpm_left*2*PI*r/60); //m/s
v_B = abs_(rpm_right*2*PI*r/60); //m/s
vtb = (v_A+v_B)/2; //m/s
}
//-------------Control motor right-----//
float PI_Motor_Right(float right, float exp_right)
{
err_right_pre = err_right;
err_right_pre_pre = err_right_pre;
err_right = exp_right-right;
duty_right_pre=duty_right;
P_right = kp_right*(err_right-err_right_pre);
I_right = 0.5*ki_right*(err_right + err_right_pre)*Ts;
duty_right= duty_right_pre + P_right+ I_right;
err_left_pre_pre = err_left_pre;
err_left = exp_left-left;
duty_left_pre = duty_left;
P_left = kp_left*(err_left-err_left_pre);
I_left = 0.5*ki_left*(err_left + err_left_pre)*Ts;
duty_left= duty_left_pre+ P_left+I_left;
//-------------------------------------
void find_e2_e3(void) {
CalibSensorDependOnEnvironment();
CaculatorFuntionSensor();
CalibrationSenrsorValue(AdcValues);
e1_line = 0;
e2=ErrorLine();//m
if(vtb != 0){
e3 = atan((e2 - pre_e2)/ (vtb*0.01*1000));//rad
}
else e3 = 0;
}
void stepping1(void)//*
{
wr = -e3;
v = vr * cos(e3) + k1 * e1_line; //m/s vr gia tri mong muon
w = wr + vr * k2 * e2/1000 + k3 * vr * sin(e3); //rad/s wr là gì
setpoint_r = (1 / r) * (v - b*w/2) * (60 / (2 * PI)); //rpm
setpoint_l = (1 / r) * (v + b*w/2) * (60 / (2 * PI)); //rpm
if(setpoint_l<0){
setpoint_l = 0;
}
if(setpoint_r < 0) {
setpoint_r = 0;
}
if(setpoint_r > 133) {
setpoint_r = 133;
}
if(setpoint_l>133){
setpoint_l = 133;
}
}
}
else
{
if(current_weight > 1600000 )
{
top_road = 0;
below_road = 1;
empty = 0;
// stop=0;
cho=0;
k2 =550;
k3 = 7;
// k2 =210;
// k3=9.9;
vr=0.38;
}
}
}
//--------------Loadcell
int32_t getHX711(void)
{
uint32_t data = 0;
uint32_t startTime = HAL_GetTick();
while(HAL_GPIO_ReadPin(DT_PORT, DT_PIN) == GPIO_PIN_SET)
{
if(HAL_GetTick() - startTime > 200)
return 0;
}
for(int8_t len=0; len<24 ; len++)
{
HAL_GPIO_WritePin(SCK_PORT, SCK_PIN, GPIO_PIN_SET);
// microDelay(1);
data = data << 1;
HAL_GPIO_WritePin(SCK_PORT, SCK_PIN, GPIO_PIN_RESET);
//microDelay(1);
if(HAL_GPIO_ReadPin(DT_PORT, DT_PIN) == GPIO_PIN_SET)
data ++;
}
data = data ^ 0x800000;
HAL_GPIO_WritePin(SCK_PORT, SCK_PIN, GPIO_PIN_SET);
// microDelay(1);
HAL_GPIO_WritePin(SCK_PORT, SCK_PIN, GPIO_PIN_RESET);
// microDelay(1);
return data;
}
int weigh()
{
int32_t total = 0;
int32_t samples = 15;
int milligram;
float coefficient;
for(uint16_t i=0 ; i<samples ; i++)
{
total += getHX711();
}
int32_t average = (int32_t)(total / samples);
coefficient = knownOriginal / knownHX711;
milligram = (int)(average-tare)*coefficient;
return milligram;
}
/* USER CODE END PFP */
}
// Speed_down();
//--------------no line no run and stop to get goods-------------
no_line_no_run();
stop_or_run(); //den vach tai hang hoac ra khoi line se dung
'stop = 1'
//-----------------------
// if((below_road==1 || top_road ==1) && vtb >0.475)
// {
// setpoint_l =85;
// setpoint_r =85;
// }
//-------------------Nga 3 re huong
---------------------------------------------------
if((top_road == 1 || below_road ==1) && outline == 0)
{
stop = 0;
////Tại ngã 3 cb rẽ nhánh
if(empty == 0 && (
(AdcValues[0] < 1000 &&
AdcValues[1] > 1000 && AdcValues[2] < 1000 && AdcValues[3] > 1000 )
//0101_ ok
|| (AdcValues[0] < 1000
&& AdcValues[1] > 1100 && AdcValues[2] > 1100 && AdcValues[3] < 1000 &&
AdcValues[4] > 1000) //01101 ok
|| (AdcValues[0] < 1000
&& AdcValues[1] > 1100 && AdcValues[2] > 1100 && AdcValues[3] < 1000 &&
AdcValues[4] > 1000) //01101 ok
// || (AdcValues[0] < 1000
&& AdcValues[1] > 1000 && AdcValues[2] < 1000 && AdcValues[3] > 1000 &&
AdcValues[4] > 1000) //01011 ok
|| (AdcValues[0] < 1000
&& AdcValues[1] < 1000 && AdcValues[3] > 1000 && AdcValues[4] > 1000)
//00_11 ok
|| (AdcValues[1] > 1100 && AdcValues[0] < 1000 && AdcValues[4] < 1000
&& AdcValues[3] > 1100) //01_10
||(AdcValues[1] < 1000 && AdcValues[2] < 1000 && AdcValues[3] > 1100 &&
AdcValues[4] > 1000) //_0011 ok
|| (AdcValues[0] > 1100
&& AdcValues[1] < 1000 && AdcValues[2] < 1000 && AdcValues[3] < 1000 &&
AdcValues[4] > 1000) //10001 ok
|| (AdcValues[0] > 1100
&& AdcValues[1] < 1000 && AdcValues[2] < 1000 && AdcValues[3] < 1000 &&
AdcValues[4] > 1000) //10001 ok
|| (AdcValues[0] > 1100
&& AdcValues[1] < 1000 && AdcValues[2] < 1000 && AdcValues[3] > 1000 &&
AdcValues[4] > 1000) //10011 ok
|| (AdcValues[0] > 1100
&& AdcValues[1] > 1100 && AdcValues[2] < 1000 && AdcValues[4] < 1000)
//110_0 ok
|| (AdcValues[0] > 1100
&& AdcValues[1] > 1100 && AdcValues[2] < 1100 && AdcValues[3] > 1100 &&
AdcValues[4] > 1000) //11011 ok
|| (AdcValues[0] > 1100
&& AdcValues[1] < 1000 && AdcValues[2] > 1100 && AdcValues[3] > 1100 &&
AdcValues[4] < 1000) //10110 ok
|| (AdcValues[0] < 1000
&& AdcValues[1] > 1100 && AdcValues[2] > 1100 && AdcValues[3] < 1000 &&
AdcValues[4] > 1000) //11001 ok
|| (AdcValues[0] > 1100
&& AdcValues[1] > 1000 && AdcValues[2] > 1000 && AdcValues[3] < 1000 )
//1110_ ok
|| (AdcValues[0] > 1100
&& AdcValues[1] < 1000 && AdcValues[3] < 1000 && AdcValues[4] > 1100)
//10_01
|| (AdcValues[0] > 1100
&& AdcValues[1] > 1100 && AdcValues[3] > 1100 && AdcValues[4] > 1100 &&
AdcValues[2] < 1000))) //11110 ok
{
if(top_road == 1)
{
if((AdcValues[0] <
1000 && AdcValues[1] > 1000 && AdcValues[2] > 1000 && AdcValues[3] < 1000 &&
AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] < 1000 && AdcValues[2] > 1000 && AdcValues[3]
> 1000 && AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] > 1000 && AdcValues[2] < 1000 && AdcValues[3]
< 1000 && AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] < 1000 && AdcValues[2] > 1000 && AdcValues[3]
< 1000 && AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] < 1000 && AdcValues[2] < 1000 && AdcValues[3]
> 1000 && AdcValues[4] < 1000))
{top_road=0;}
for(int z =0;
z<=7; z++ ){
setpoint_r=109;
setpoint_l = 48;
}
}
if(below_road == 1)
{
if((AdcValues[0] <
1000 && AdcValues[1] > 1000 && AdcValues[2] > 1000 && AdcValues[3] < 1000 &&
AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] < 1000 && AdcValues[2] > 1000 && AdcValues[3]
> 1000 && AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] > 1000 && AdcValues[2] < 1000 && AdcValues[3]
< 1000 && AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] < 1000 && AdcValues[2] > 1000 && AdcValues[3]
< 1000 && AdcValues[4] < 1000)
||
(AdcValues[0] < 1000 && AdcValues[1] < 1000 && AdcValues[2] < 1000 && AdcValues[3]
> 1000 && AdcValues[4] < 1000))
{below_road=0;}
for(int z =0;
z<=5; z++ ){
setpoint_r=66;
}
// for(int cham =0;
cham<=1; cham++ ){
// setpoint_l =
72;
//
setpoint_r=90;
// }
below =1;
// m=1;
// below_road=0;
//k2 = 400;
//k3 =15;
//k2=550;
//k3=15;
}// DK below
} // DK nga 3
}// Khi bat dau co hang
//-----------------------------find error------------------------------
find_e2_e3();
//Speed
find_speed();
if(counter ==10)
{
// sau 100ms thì sẽ trả tín hiệu của DK hệ thống
counter =0;
//fl tracking (lyapunov)
stepping1();
}
//Xuat PWM
PWM_right= PI_Motor_Right(rpm_right, setpoint_r);
PWM_left=PI_Motor_Left(rpm_left, setpoint_l);
pre_e2 = e2;
if(stop ==0)
{
Set_PWM_DutyCycle_left(PWM_left);
Set_PWM_DutyCycle_right(PWM_right);
}
else{
TIM1->CCR3 = 99;
TIM1->CCR4 = 99;
duty_right_pre=0;
duty_left_pre=0;
duty_right=0;
duty_left=0;
}
} // Ngat TIM2
} // End Period...
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
//CCR thay doi do rong Duty cycle (%), CNT dem den CCR thi PWM ve muc 0
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/**
* @brief ADC1 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC1_Init(void)
{
/**
* @brief TIM1 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/**
* @brief TIM2 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM2_Init(void)
{
/**
* @brief TIM3 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM3_Init(void)
{
/**
* @brief TIM4 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM4_Init(void)
{
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */