반응형

https://youtube.com/live/IDd-IVeSmGE

[STM32#08] PWM의 듀티비를 변화시켜서 서보모터(SERVO)인 SG90의 각도를 제어하는 방법 알아보기!(녹칸다 내맘대로 STM32)

심심한녹칸다의 내맘대로 STM32시리즈이다!

STM32시리즈의 모든 자료는 구글 슬라이드에 작성하고 모두에게 공유되어있음!
https://docs.google.com/presentation/d/1myA5iYbjuKsLWLqtRLKAiRfwUwvqB1d1RGjiMIIgp3I/edit?slide=id.g39fc004f5bb_2_169#slide=id.g39fc004f5bb_2_169

이번편은 녹칸다의 STM32쉴드에 SG90을 연결해서 각도를 제어해보도록 한다!

 

(회로도)


1.서보모터(SG90)의 IOC설정을 하고 0도와 180도를 1초 간격으로 왔다갔다 하는 예제를 구현하시오!

/* USER CODE BEGIN 2 */
 //PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //서보모터가 0도 위치로 이동한다!
	  TIM2->CCR4 = 600;
	  //1초쉰다!
	  HAL_Delay(1000);
	  //서보모터가 180도 위치로 이동한다!
	  TIM2->CCR4 = 2400;
	  //1초쉰다!
	  HAL_Delay(1000);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


2.예제1번에서 0도부터 180도사이의 각도를 입력하면 각도대로 CCR4의 값을 설정하는 똑똑한 함수를 만들어보시오!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 //PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //서보모터가 0도 위치로 이동한다!
	  set_servo(0);
	  //1초쉰다!
	  HAL_Delay(1000);
	  //서보모터가 180도 위치로 이동한다!
	  set_servo(180);
	  //1초쉰다!
	  HAL_Delay(1000);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


3.서보모터를 0도부터 180도까지 10밀리초간격으로 1도씩 올리고, 180도부터 0도까지 10밀리초간격으로 내려서 왔다갔다 하는 예제를 만드시오!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 //PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //0도부터 180도까지 1도씩 10밀리초간격으로 올라간다!
	  for(int i = 0;i<=180;i++){
		  set_servo(i);
		  HAL_Delay(10);
	  }
	  //180도부터 0도까지 1도씩 10밀리초간격으로 내려간다!
	  for(int i = 180;i>=0;i--){
		  set_servo(i);
		  HAL_Delay(10);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


4.버튼5개(PB1,PA8,PB2,PB6,PC5)를 사용해서 PB1은 0도위치, PA8은 45도위치, PB2는 90도위치, PB6은 135도위치, PC5는 180도위치로 이동하는 예제를 구현하시오!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 //PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PB1을 누르면 0도로 이동한다!
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0){
		  set_servo(0);
	  }
	  //PA8을 누르면 45도로 이동한다!
	  if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == 0){
		  set_servo(45);
	  }
	  //PB2을 누르면 90도로 이동한다!
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == 0){
		  set_servo(90);
	  }
	  //PB6을 누르면 135도로 이동한다!
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == 0){
		  set_servo(135);
	  }
	  //PC5을 누르면 180도로 이동한다!
	  if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5) == 0){
		  set_servo(180);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }

 


5.PA8버튼을 누르면 누르고 있는 동안에 서보모터의 각도가 1도씩 증가하고 최대 180을 넘지않는다! PB1을 누르면 각도가 1도씩 내려가고 0도이하로 내려가지는 않는다!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
/* USER CODE END 0 */
//중략
//PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 int16_t degree = 0;
 set_servo(degree); //시작할때 서보모터는 0도 위치!
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PB1을 누르면 1도씩 내려간다!(하한값 0)
	  if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0){
		  degree++;
		  if(degree > 180) degree = 180;
		  set_servo(degree);
		  HAL_Delay(10);
	  }
	  //PA8을 누르면 1도씩 증가한다! (상한값 180)
	  if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == 0){
		  degree--;
		  if(degree < 0) degree = 0; //오류 발생!
		  set_servo(degree);
		  HAL_Delay(10);
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


6.로터리엔코더(PA11,PA12)를 시계방향으로 돌리면 서보모터의 각도가 1도씩 올라가고, 반시계방향으로 돌리면 1도씩 내려가도록 하시오!(범위는 0~180도)

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
/* USER CODE END 0 */
//중략
//PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 int16_t degree = 0;
 set_servo(degree); //시작할때 서보모터는 0도 위치!
 uint8_t old_A = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  uint8_t now_A = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
	  if(old_A == 0 && now_A == 1){
		  uint8_t now_B = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12);
		  if(!now_B){
			  //시계
			  degree-=3; //원래 degree가 가지고있는값에 3을 뺀다!
			  if(degree < 0) degree = 0;
			  set_servo(degree);
		  }else{
			  //반시계
			  degree+=3; //원래 degree가 가지고있는값에 3을 더한다!
			  if(degree > 180) degree = 180;
			  set_servo(degree);
		  }
	  }
	  old_A = now_A;
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


7.녹칸다가 사용하는 putty에서 ‘0’을 입력하면 0도, ‘1’을 입력하면 45도, ’2’를 입력하면 90도, ‘3’을 입력하면 135도, ‘4’를 입력하면 180도로 이동되도록 하시오! STM32가 현재 설정된 각도가 몇도인지를 시리얼로 피드백 하도록 하시오!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 //PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 set_servo(0); //시작할때 서보모터는 0도 위치!
 char recv;
 char buff[50];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  //PC에서 문자 1개가 수신되기로 약속되어있다!(0.5초 대기)
	  if(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
		  //recv PC에서 보낸 1개의 문자가 들어있는 상태
		  if(recv == '0'){
			  set_servo(0);
			  sprintf(buff,"NOW DEGREE = %d\n",0);
			  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
		  }else if(recv == '1'){
			  set_servo(45);
			  sprintf(buff,"NOW DEGREE = %d\n",45);
			  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
		  }else if(recv == '2'){
			  set_servo(90);
			  sprintf(buff,"NOW DEGREE = %d\n",90);
			  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
		  }else if(recv == '3'){
			  set_servo(135);
			  sprintf(buff,"NOW DEGREE = %d\n",135);
			  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
		  }else if(recv == '4'){
			  set_servo(180);
			  sprintf(buff,"NOW DEGREE = %d\n",180);
			  HAL_UART_Transmit(&huart2, buff, strlen(buff), 100);
		  }
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


8.녹칸다가 “0”부터 “180”까지의 각도값을 STM32로 전송하면 그 각도대로 서보모터가 회전되도록 하시오!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
/* USER CODE END 0 */
//중략
/* USER CODE BEGIN 2 */
 //PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 set_servo(0); //시작할때 서보모터는 0도 위치!
 char recv;
 int rx_index = 0;
 char rx_buff[50];
 char tx_buff[50];
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  rx_index = 0;
	  while(HAL_UART_Receive(&huart2, &recv, 1, 500) == HAL_OK){
		  rx_buff[rx_index] = recv;
		  rx_index++;
		  if(recv == '\r'){
			  //PC에서 보낸 종료문자 확인!
			  rx_buff[rx_index] = '\0';
			  //rx_buff에 각도값이 들어있는건 알겠는데.. 숫자로 바꿔야하는데?
			  int degree = atoi(rx_buff);
			  //0~180도 사이로 입력이 되도록 설정
			  if(degree > 180) degree = 180;
			  if(degree < 0) degree = 0;
			  sprintf(tx_buff,"NOW DEGREE = %d\n",degree);
			  HAL_UART_Transmit(&huart2, tx_buff, strlen(tx_buff), 100);
			  set_servo(degree);
		  }
	  }
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }


9.PA0에 연결된 가변저항을 이용해서 서보모터의 각도를 회전시키시오!

/* USER CODE BEGIN 0 */
void set_servo(uint8_t degree){
	//degree는 0~180도 범위이고 CCR4는 600부터 2400의 범위이다!
	TIM2->CCR4 = (uint32_t)(600+(2400-600)*degree/180.0);
}
uint16_t map(uint16_t analog){
	return 180*analog/4095.0;
}
/* USER CODE END 0 */

//중략
/* USER CODE BEGIN 2 */
 //PB11이 사용하는 TIM2_CH4를 시작하겠다!
 HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
 HAL_ADC_Start(&hadc1); //딱 한번만 호출(ADC1에 지정했을때)
 uint16_t adc_value0 = 0;
 /* USER CODE END 2 */
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
	  {
		  // 값 처리
		  adc_value0 = HAL_ADC_GetValue(&hadc1); //0~4095
		  //0~4095를 0~180도 범위로 조정해야한다!
		  set_servo(map(adc_value0));
	  }
	  HAL_Delay(10);
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
 }
반응형
Posted by 덕력킹
,