티스토리 뷰

반응형

안녕하세요. 바쁜 한 달간 좀더 집중해야하는 일 들이 있어 간만에 블로그를 작성합니다.

오늘은 nRF 칩 기반에서 PWM Frequency에 대한 제어를 어떻게하는 설명할텐데요. 우선 PWM이 무엇인지 부터 확인해 보도록 하겠습니다.

PWM (Pulse Width Modulation)

펄스의 폭을 제어한다는 뜻인데요. 못 느끼시겠지만 우리 실 생황에서 PWM 방식으로 아래와 같이 제어 되고 있습니다.

모니터와 핸드폰 같은 경우 60hz네, 120hz 주파수인데 머가 좋네 안좋네 이런말들 많이하고, 좀더 제어를 하시는 분들은 모터제어할때 이 주파수가 RPM과도 연관되어 있으니, 어떤 주파수로 하느냐에 따라 동작하는게 많이 다를 수 있습니다. 저는 오늘 그중에서 LED 제어를 위한 PWM Frequency에 대해서 이야기를 해볼게요.

저 위에 언급해 드린 펄스의 폭은 굉장히 촘촘해진다면 0과 1이 지속적으로 빠르게 반복하기 때문에 좀더 많은 전류를 사용하게 되고, 밝기가 밝아진다고 이해하시면 편하고, 그 반대면 좀더 밝기가 어두워지겠지요. 다만 저 폭 1개 자체는 Period라는 주기로 표현하고 전체 폭을 어떤 듀티비로 하냐에 따라 밝기 제어가 가능하며 Frequency 좀 더 상위에 있는 개념입니다. 좀더 설명해보면 PWM 은 주파수라고 말하고 이 주파수는 0과 1의 반복되는 현상이며 사람 눈에 60hz 자체도 인지하기 어렵지만 카메라로 찍으면 모니터나 핸드폰의 화면이 줄이 가있는 모습을 볼 수 있습니다. 요즘엔 모니터와 핸드폰의 표준인 60hz나 120hz의 경우는 소프트웨어적으로 처리하여 이런 부분이 사진에 나오지 않게 처리했다고 하는데요 그래도 좀더 높은 셔터스피드의 카메라로 찍으면 바로 확인 하 실수 있습니다. 그리고 높은 주파수의 형태로 출력을 하기 위해서는 제어하는 CPU, 마이크로칩의 성능이 좋아야 하는데요. 훨씬 더 빠른 속도로 0과 1을 반복해야하기 때문에 이는 클럭이 높아야 가능하고 클럭이 높다는 것은 기본적으로 칩의 성능과 직결되어 있다고 볼 수 있습니다.

듀티비를 제어하는 것은 검색해보면 많은 글들이 있습니다. 레졸루션이라고 표현해서 0~1024, 0~512, 0~256 이런 형태로 밝기의 단계를 세분화해서 하는 정도로 보시면 되는데, 이 것은 다시 한번 말씀드리지만 Frequency를 기본 적으로 세팅한뒤 이를 듀티의 max 값으로 나눈 것이 최종 Frequency라고 말 할 수 있습니다. 사용하고 있는 칩의 클럭과 맞닿아 있는 내용이라 클럭과 맟닿은 내용은 빼고 쉬운 이해를 위해서 아래와 같이 설명해 보겠습니다.

  • 1Khz 기본 값 * 0.01 (100 step 듀티비 맥스 단계) = 10hz
  • 1Mhz 기본 값 * 0.001(1000 step 듀티비 맥스 단계) = 1Khz

여기서 듀티비를 0~100%로 표현할 수 도 있는데, 듀티 사이클의 단계가 1000이면 1000/1000인경우 100% 라고 생각하시면 됩니다. 그럼 1Khz나 1Mhz에 해당하는 값은 어떻게 정할 수 있을까요? 그건 앞서 말한대로 자신이 사용하는 칩의 성능에 따라 다르고, 그 성능을 어떻게 세팅하느냐에 따라 다릅니다. 빠른 성능을 사용하고자하면 그에맞는 전류와 여러 제어가 가능해야하는지 확인해야하기 때문에 적정한 속도를 세팅해 놓아서 최종단계의 스펙을 정하곤 합니다. 그럼 우선 어느정도의 주파수가 적당할까요? 검색해보면 플리커에 대한 이슈는 눈으로는 인식할 수 없어도 뇌에 영향을 미칠 수 있다는 우려때문입니다. 미국 에너지부 산하 퍼시픽노스웨스트국립연구소는 지난 2012년 LED조명의 플리커 현상이 간질성 발작에 동반되는 신경계 질환, 두통, 피곤함, 몽롱함, 눈의 피로, 시각 활동 감소, 산만함 등을 일으킬 수 있다고 발표했습니다. 의학계에서는 장기적으로 노출되면 시력 저하도 있을 수 있다고 지적하고 특히 장시간 반복적으로 봐야 하는 자동차 후미등에 플리커 현상이 있으면 단순한 피로감뿐만 아니라 안전사고 위험도 있다고 합니다. 또한 가청주파수 영역대(~20Khz)로 설정되는 경우 미세한 소음을 발생할 수 도 있는데요. 다만 플리커는 디지털 제어에서 없을 순 없기에 어디에도 정확하게 플리커프리의 기준이 무엇이다, 가장 좋은 주파수가 무엇이다라는 명확한 내용은 아직 못찾았습니다. 다만 아래와 같은 기준을 찾을 수 있는데요 듀티비 20% 이하일때 100hz 이상은 되어야한다는 내용입니다. 공식문서를 찾지못해 건너건너 찾은 내용이 정확하지 않을 수 있음을 이해부탁드립니다. 이 정도는 제가 생각한 기준보다 너무 낮은데요, 적어도 현존하는 카메라의 프로모드에서 지원하는 가장 높은 셔터스피드에서도 잡지못하는 정도는 되어야하지 않을까 생각됩니다. 그럼 이제 nRF 칩에서 설정할 수 있는 곳을 찾아보도록 하겠습니다.

제가 사용하는 nRF 칩에서 클럭은 외부클럭 16Mhz를 사용하고 있으므로 기본적으로 16Mhz 클럭으로 동작할 것인데, 프리스케일러가 있어 어느정도의 분주비로 할 것인지 정하 수 있습니다. 1/2/4/8/16 이렇게 정할 수 있는데. 16으로 분주비를 선택시에는 16Mhz의 클럭을 사용하지만 1Mhz로 사용하는 것과 같습니다. 만약 듀티비를 1000스텝 즉 0.001초로 하는 경우 1Khz의 Frequency로 동작하는 것이죠, 카메라 셔터 스피드로 말하면 1/1000 을 넘으면 깜빡깜빡하는 모습을 발견 할 수 있습니다.

#define MAX_PWM_CH	2

#define PWM_CH_1	0
#define PWM_CH_2	1

uint16_t pwm_value[MAX_PWM_CH] = { PWM0_PERIOD_MAX, PWM0_PERIOD_MAX };

void pwm_init(int8_t pin_1, int8_t pin_2)
{
    // PORT
    nrf_gpio_cfg_output(PWM_CH_1);
    nrf_gpio_pin_clear(PWM_CH_1);
    
    nrf_gpio_cfg_output(PWM_CH_2);
    nrf_gpio_pin_clear(PWM_CH_2);
    
    NRF_PWM0->PSEL.OUT[PWM_CH_1] = ((int)pin_1 << PWM_PSEL_OUT_PIN_Pos) | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM0->PSEL.OUT[PWM_CH_2] = ((int)pin_2 << PWM_PSEL_OUT_PIN_Pos) | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);

    NRF_PWM0->ENABLE     = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
    NRF_PWM0->MODE       = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos);
    NRF_PWM0->PRESCALER  = (PWM_PRESCALER_PRESCALER_DIV_16 << PWM_PRESCALER_PRESCALER_Pos);
    NRF_PWM0->COUNTERTOP = (PWM0_PERIOD_MAX << PWM_COUNTERTOP_COUNTERTOP_Pos);
    NRF_PWM0->LOOP       = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos);
    NRF_PWM0->DECODER    = (PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos) | (PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);

    NRF_PWM0->SEQ[0].PTR = (uint32_t) pwm_value;
    NRF_PWM0->SEQ[0].CNT = (4 << PWM_SEQ_CNT_CNT_Pos);
    NRF_PWM0->SEQ[0].REFRESH  = 0;
    NRF_PWM0->SEQ[0].ENDDELAY = 0;

    NRF_PWM0->TASKS_SEQSTART[0] = 0;
}

위 코드에서 보면 PWM0 의 레지스터를 직접 세팅해서 PWM의 기본 값을 설정하는 것을 볼 수 있습니다. 여기서 중요한 것은 NRF_PWM0->PRESCALER 부분인데요 분주비 16을 설정했습니다. 다라서 16Mhz인 경우 1Mhz로 될 것이고, pwm_value 값을 보면 Max(듀티 값의 맥스)에 따라서 최종 frequency가 설정될 수 있습니다. 1000이라면 1Khz일 것이고 500이라면 2Khz 일 것이지요. 다만 갤럭시와 같이 프로모드의 촬영을 제공하는 카메라는 1/24000 (24Khz)까지 촬영이 가능합니다. 적어도 이 셔텨스피드 값은 넘겨버리고 싶다면 아래와 같이 세팅하면 됩니다.

  • PRESCALER 갑 16 대신 1
  • 듀티 값 맥스 500

이렇게 계산하면 아래와 같고 이러면 갤럭시 핸드폰의 프로모드의 맥스값 셔터스피드에서도 찍힐 수 없습니다.

16Mhz / 1 * 0.002 (500 step의 경우) = 32Khz

듀티값을 1000으로도 할 수 있지만 프리퀀시가 빨라지는 경우 LED 드라이버가 리니어하게 켜지는 것을 확인 하면서 결정할 필요가 있습니다. 제가 사용하는 LED 드라이버와 호환성을 확인해보니 듀티값 맥스를 1000으로 하게되면 디밍 자체가 자연스럽게 되지 않는 문제가 있어 500으로 설정하였고, 이 렇게 하면 밝기를 변화시키는 단계는 줄어들지만 또 생각해보면 사람이 인지할 수 있는 단계는 500이든 1000단계는 이미 넘어 섰고 이를 좀더 자연스럽게 켤 수 있느냐 없느냐가 판단의 요소일 것입니다. 

반응형
댓글