본문 바로가기
# Semiconductor/- Semicon Academy

[Harman 세미콘 아카데미] 53일차 - ARM 및 RTOS 활용(Mission : LED Controller)

by Graffitio 2023. 9. 11.
[Harman 세미콘 아카데미] 53일차 - ARM 및 RTOS 활용(Mission : LED Controller)
728x90
반응형
[Mission]

 

📌 Mission

      : 조이스틱을 이용한 밝기 제어

      M1. 조이스틱을 이용하여 밝기를 제어한다.

      M2. ADC 기능을 활용하여 조이스틱 입력 처리를 구현한다.

             (Timer, Interrupt, DMA 방식 중 택1)

      M3. FreeRTOS를 사용하여 조이스틱의 입력에 따라 LED 밝기를 조절하고

             LED를 점멸 속도를 조정하는 두 가지 동시 작업을 관리한다.

 

      수행 기간 : 6 hours

 


 

[Result]

 

📌 Flow Chart

 

Flow Chart Description 

 

    1. 각 기능들 초기화

    2. Read Joystick Value

    3. zVal = 1이면, LED Off

        zVal = 0이면, LED On

    4. xVal : Blink Speed Control

    5. yVal : Brightness Control

 


 

📌 Pin Configuration

Pin Configuration
Description

 


 

📌 Pin Setting

 

GPIO Setting

 

 

조이스틱의 z(swtich) 값을 입력 받아야 하므로 Input mode

플로팅 현상 방지를 위해 내부 풀업 설정

 

 

ADC Setting

 

ADC Conversion 1회마다 x, y 값을 하나씩 번갈아가며 받아올 것이므로 Discontinuous conversion mode Enable

Resolution(해상도)이 12bit이므로 Sampling Time은 그보다 큰 84 cycle로 설정

Interrupt 방식으로 값을 불러올 것이므로 Globle Interrupt Enavle

 

 

PWM Setting

 

LED 밝기가 부드럽게 변하게 하기 위해 840-1 / 840-1로 설정

 

 

RTOS Setting

 

    1. Default Task : 인터럽트 발생 반복

    2. LED Speed : LED Bling speed control

    3. LED Lum : LED Brightness control

    4, Time Base Source : TIM1(systick보다 HAL_TIM이 더 정확하다.)

    5. NEWLIB Reentrant : Enable

 


 

📌 Code Description

 

Initial Code

 

// 변수 선언
/* USER CODE BEGIN PV */
int xVal;
int yVal;
int zVal;
int count;
int led_OnOff;
/* USER CODE END PV */

 

  // Initialization
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_TIM11_Init();
  HAL_ADC_Start_IT(&hadc1);
  HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1);

 

 

Callback

 

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if(count == 0) xVal = HAL_ADC_GetValue(&hadc1);
	else if(count == 1)
	{
		yVal = HAL_ADC_GetValue(&hadc1);
	}
	count++; // callback 1회 호출 시마다 value 하나씩 가져옴
	if(count > 1) count = 0;
	zVal = HAL_GPIO_ReadPin(z_Value_GPIO_Port, z_Value_Pin);
	HAL_ADC_Start_IT(&hadc1);
}

 

    1. ADC Callback 함수에서 HAL_ADC_Start()를 사용 못하는 이유는 

        이미 컨버젼이 완료된 이후에 Callback 함수가 호출되기 때문이다.

        따라서 start 없이 GetValue 함수를 각각 호출해줘야 한다.

    2. Count 변수를 활용하여 Interrupt 1회 당 x, y 값을 번갈아가며 입력받도록 코딩

    3. Callback 함수는 한 번 호출되면 Interrupt Flag가 리셋되기 때문에

        HAL_ADC_Start_IT(); 를 다시 호출해주어야 계속해서 인터럽트가 발생할 수 있다.

 

 

Task

 

void StartDefaultTask(void const * argument)
{
  for(;;)
  {
	HAL_ADC_Start_IT(&hadc1);
    osDelay(5);
  }
}

 

    Callback 함수는 인터럽트가 발생하면 Flag가 리셋되기 떄문에

    Default Task로 ADC Interrupt의 반복 실행이 필요하다.

 

 

void led_spd_cntr(void const * argument)
{
  int led_spd = 0;
  for(;;)
  {
    led_spd = xVal/2;
    if(led_spd <= 100) led_spd = 100;
    osDelay(led_spd);
    led_OnOff = ~led_OnOff;
  }
}

 

    조이스틱으로 입력되는 x값에 따라서 led_speed가 조정되도록 설정했고,

    이 변수에 따라  Delay가 달라진다.

    Delay 이후에 led_OnOff 변수를 토글시켜

    LED가 딜레이에 따라 점멸하도록 설계하였다.

 

 

void led_lum_cntr(void const * argument)
{
  int led_lum = 0;
  for(;;)
  {
	htim11.Instance->CCR1 = led_lum;
	if(zVal) led_lum = 0;
	else
	{
		if(led_OnOff) led_lum = 0;
		else led_lum = yVal*1000/4095;
		osDelay(30);
	}
  }
}

 

    조이스틱으로 입력되는 y값에 따라서 Led_lum 변수가 조정되도록 설정했고,

    이 변수에 따라 CCR값이 변화하며, 이렇게 변화한 CCR 값에 따라 LED 밝기가 결정된다.

    또한 조이스틱 버튼이 눌렸을 때,(zVal = 1)만 LED가 동작하도록 On/Off 기능을 추가했다.

 


 

📌 Operation

 

LED Blink Speed Control

 

 

 

LED Brightness Control

 

 

 

LED On/Off

 

 


 

📌 Review

 

Error

 

Error

LED 점멸 속도와 밝기 조절 기능을 나눠서 시뮬레이션해보던 중,

둘 다 조이스틱의 y값만 받아서 동작하는 오류를 발견했다.

 

ADC Setting 중, Discontinious Conversion mode를 Disable 시켜놓은 것이 원인이었고

이로 인해 인터럽트 발생 시 xVal, yVal 변수에 y값만 받아오고 있었다.

 

해당 부분을 Enable로 수정하니, 오류가 해결되고 정상적으로 동작하였다.

 

 

 

아쉬웠던 점

 

짧은 기간에 수행된 프로젝트다 보니,

추가로 구현해보고 싶었던 기능들을 구상만 해놓고 구현하지 못해 아쉬움이 남았다.

  - 여러 개의 LED를 동시에 컨트롤 

  - RGB LED로 모든 색을 표현하는 기능

  - I2C LCD로 현재 밝기 및 속도 표시 기능

 

미리 실력을 더 쌓아뒀더라면,

짧은 시간일지라도 위 기능들을 충분히 구현하지 않았을까? 하는

생각이 들었고 이를 자기반성의 기회로 여겨 더욱 더 발전하는

내가 되는 계기로 삼고자 한다.

 


 

 

728x90
반응형