2012-03-14 3 views
1

이것은 학문적 인 질문입니다. (필자는 반드시 그런 일을 할 계획이 아니지만) 어떻게 작동하는지 궁금합니다. 나는 유저 랜드 소프트웨어 (하드웨어가 아닌) 솔루션을 생각하고있다.CPU를 손상시키지 않고 소프트웨어 PWM을 사용할 수 있습니까?

나는 PWM 신호를 생성하고 싶다. (디지털 GPIO 핀 수가 적지 만 1 개 이상이라면). 아마도 Pthread를 생성 한 프로그램을 작성한 다음 해당 스레드에서 적절한 sleep() 등을 사용하여 듀티 사이클 동안 무한대로 루프를 반복하여 비율을 올바르게 얻을 수 있습니다.

CPU가 끔찍하게 들썩 거리지 않습니까? 나는 주파수가 100 Hz 표기 어딘가에있을 것이라고 상상한다. 나는 전에 이런 식으로 아무것도하지 않았지만 상수 반복, 컨텍스트 스위치 등 멀티 태스킹이나 CPU 사용에 좋지 않을 것이라고 상상할 수 있습니다.

이 경우 CPU 사용 및 멀티 태스킹에 대한 조언이 필요하십니까? FWIW 나는 싱글 코어 프로세서에 대해서 생각하고있다. 나는 응답이 에서 시스템의 사용을 불가능하게 만들 수 있습니다. to '관련 숫자는 현대 프로세서에 영향을 미치는 것보다 작습니다.'!

C가 가장 적합한 것으로 가정합니다.

EDIT : 하드웨어 GPIO 핀에 액세스 할 수있는 컴퓨터에서 Linux 또는 기타 범용 POSIX 운영 체제를 사용한다고 가정합니다.

EDIT : 나는 수면 모드로 PWM을 구현하는 방법이 분명하다고 가정했다. 이 같은 의심의 회피, 뭔가 :

while (TRUE) 
{ 
    // Set all channels high 
    for (int c = 0; x < NUM_CHANNELS) 
    { 
     set_gpio_pin(c, 1); 
    } 

    // Loop over units within duty cycle 
    for (int x = 0; x < DUTY_CYCLE_UNITS; x++) 
    { 
     // Set channels low when their number is up 
     for (int c = 0; x < NUM_CHANNELS) 
     { 
      if (x > CHANNELS[c]) 
      { 
       set_gpio_pin(c, 0); 
      } 
     } 

     sleep(DUTY_CYCLE_UNIT); 
    } 
} 
+0

듀티 사이클은 핀이 높은 시간과 신호의주기 사이의 비율을 나타내며 백분율로 표시됩니다. 100Hz는 신호 주파수이며 10ms의주기를가집니다. – guga

+1

PWM의 특성, 특히 출력 신호의 정확도와 안정성을 지정해야합니다. 듀티 사이클 또는 기본 주파수에서 PWM 신호의 지터를 조정할 수 있습니까? 소프트웨어 PWM은 타이밍 지터가 많이 발생합니다. –

+0

그냥 취미 목적으로, 예를 들어 조명 조광기를 운전. 정확성은 그다지 중요하지 않습니다. 나는 지터가 예상된다고 생각한다. 내가 말했듯이, 학문적 인 질문이지, 내가 반드시 만들어야 할 것이 아닙니다. – Joe

답변

2

가능한 경우 드라이버를 사용하십시오. 임베디드 디바이스에 PWM 컨트롤러가있는 경우 하드웨어 타이머를 PWM 간격을 생성하고 GPIO 핀을 구동하는 데 사용하십시오.

사용자 수준에서이 작업을 수행해야하는 경우 프로세스/스레드를 높은 우선 순위로 설정하고 sleep() 호출을 사용하면 많은 지터와 불량 펄스 폭 범위가 생성됩니다.

+0

그게 내가 의심했던 것이다. – Joe

+0

대부분의 최신 컨트롤러에는 여러 가지 하드웨어 타이머가있는 것으로 보이지만 모든 인터럽트 우선 순위가 높지는 않습니다. 리눅스에 대해서는 잘 모르지만 다른 임베디드 커널에서는 OS 타이머 설정을 해킹하여 OS 타이머 간격을 100us로 줄이고 PWM을 실행하기위한 인터럽트를 처리하고 10/100 인터럽트마다 OS 스케줄러 항목을 호출합니다. . –

+1

효율적으로 작성된 인터럽트 기능을 사용하면 CPU 시간에 눈에 띄지 않습니다. 배터리 수명은 다른 이야기입니다 (예 : 100x/초의 절전 모드에서 깨어나면 많은 에너지 비용). 타이머 기능에 대한 데이터 시트를 읽으십시오. 많은 사람들이 알고있는 것보다 더 다재다능합니다. – Adriaan

1

더 좋은 방법은 어떤 종류의 인터럽트 구동 방식을 사용하는 아마. 나는 그것이 당신의 시스템에 달려 있다고 생각하지만, IIRC Arduino는 PWM을 위해 인터럽트를 사용합니다.

+0

사용자 공간에서 작동합니까? – Joe

+0

'sleep()'은 이미 시스템 타이머의 인터럽트를 선점 또는 유휴 상태에서 깨우기 위해 사용하는 작업 스케줄러를 포함합니다. – pmdj

+0

@Joe : 구현 방법에 따라 다르지만 리눅스에서 사용자 공간 인터럽트를 지원하는 것으로 보입니다 (주로 사용자 공간 드라이버에 사용되지만 다른 용도로 사용하는 것이 가능할 수도 있음). – Leo

2

당신은이 궁극적 인 목적을 명확하게 말하지는 않지만이 임베디드 및 pthreads에 태그를 지정 했으므로 리눅스 변형이 실행되는 전용 칩이 있다고 가정합니다.

이 경우에는 PWM이 더 큰 제어 응용 프로그램의 일부라고 가정하므로 PWM 출력을 만드는 가장 좋은 방법은 기본 프로그램 루프를 통해하는 것이 좋습니다. 대부분의 간단한 임베디드 응용 프로그램 (UI 없음)은 주 스레드의 GPIO를 주기적으로 업데이트하여 단일 스레드에서 실행할 수 있습니다. 예를 들어

:

InitIOs(); 

while(1) 
{ 
    // Do stuff 
    UpdatePWM(); 
} 

상기되는 것이하여 칩 사양을 확인 대부분의 임베디드 장치에 전용 PWM 출력 핀 (즉 또한 개의 GPIO로서 작용할 수있다) 및 이들에 의해 하드웨어로 간단히 구성 할 수있다 듀티 사이클을 설정하고 필요에 따라 듀티 사이클을 업데이트합니다. 이 경우 하드웨어가 작업을 수행합니다.

약간의 상황을 명확히 할 수 있다면 좀 더 자세한 답변을 드릴 수 있습니다.

+0

하지만'물건을해라 .'에는 정의 된 기간이 없습니다. 이런 식으로 신뢰할 수있는 듀티 사이클을 생산할 수있는 방법을 모르겠습니다. – Joe

+0

답변 해 주셔서 감사합니다. 전용 PWM 핀에 액세스 할 수 있다고 가정하지 마십시오 (따라서 PWM 드라이버 코드를 직접 작성해야합니다). – Joe

+0

Joe, "Do stuff"에 임의의 시간이 걸릴 수 있으며, "Do stuff"가 얼마나 복잡한 지에 따라 다릅니다. 일반적으로 말해서, 현대 칩은 대부분의 듀티 사이클이 KHz 범위에 있고, 칩은 수 MHz에서 실행되는 반면, 듀티 사이클보다 훨씬 빠릅니다. 즉, 듀티 사이클 (듀티 사이클이 아날로그 신호를 개략적으로 시뮬레이션 할 때 완벽 할 필요는 없음)이 염려되는 경우 사전 정의 된 Tick에 도달 할 때마다 "UpdatePWM()"을 호출하는 하드웨어 타이머 인터럽트를 설정할 수 있습니다 카운트. 이렇게하려면 타이머를 묶어야합니다. – sberube

1

100Hz는 사용자 공간과 거의 비슷한 것처럼 보입니다. 일반적인 OS 작업 스케줄러 타임 슬라이스는 약 10ms이므로 CPU가 이미 해당 간격으로 멀티 태스킹을 수행합니다. 수면이 오버런하지 않도록 (많은 신경을 써야 함) 높은 드리 우기 우선 순위 (낮은 니스)를 사용하고 드리프트를 피하기 위해 실제 벽 시간을 추적하고 잠재적으로 수면 값을 조정하십시오. 또한 커널이 하드웨어에서 사용하는 타이머가 충분히 높은 해상도를 가지고 있는지 확인해야합니다.

RAM이 매우 부족하고 스와핑이 심한 경우 프로그램을 디스크로 페이징하는 문제가 발생할 수 있습니다. 또한 커널이 다른 CPU 집약적 인 작업을 수행하는 경우 이는 허용 할 수없는 지연을 가져옵니다. (다른 우선 순위가 낮은 사용자 공간 작업은 괜찮습니다.) 주파수를 일정하게 유지하는 것이 중요하다면, 커널에서 이것을 해결하는 것이 더 나을 것입니다.

+0

100Hz PWM 주파수는 약간의 큰 배수 (약 8 비트 동등한 PWM을 얻기 위해 256x)에서 가장자리를 이동해야한다는 것을 의미합니다. 10ms 스케쥴러 틱 (ticker tick)에서이를 수행 할 수 없습니다 - 8 비트에 해당하는 에지 해상도는 ~ 40us 일 필요가 있습니다! –

0

인터럽트가 비활성화되었을 때 PWM 인터럽트가 발생하거나 프로세서가 긴 중단없이 서비스를 제공하는 등의 인터럽트 서비스 및 소프트웨어 상호 작용이 도입 할 고유의 타이밍 지터가 모두있는 소프트웨어에서 PWM을 수행하려는 이유를 이해하지 못합니다. 명령 또는 다른 서비스 루틴이 활성화 된 경우). 최신의 마이크로 컨트롤러 (ARM-7, ARM Cortex-M, AVR32, MSP 등)는 PWM 생성기로 생성되거나 전용으로 구성 될 수있는 타이머를 가지고 있습니다. 이것들은 한 번 설정되면 실행을 계속하기 위해 제로 프로세서 입력을 필요로하는 여러 암 안정 PWM 신호를 생성합니다. 이 PWM 출력은 애플리케이션에서 요구하는대로 두 신호가 겹치지 않거나 동시에 에지를 갖도록 구성 할 수 있습니다.

OS 에지 기능을 사용하여 PWM 에지 사이의 시간을 설정하는 경우 느리게 실행됩니다. 절전 기능은 작업 활성화 사이의 최소 시간을 설정하며 작업 전환, 더 높은 우선 순위의 스레드 또는 다른 커널 기능 실행 중 지연 될 때까지의 시간을 설정합니다.

+0

제가 말씀 드렸듯이, 범용 하드웨어에서 PWM을 수행하는 것에 대한 학문적 인 시도였습니다. 실제로 특정 작업을 수행하려고 시도하지 않았습니다. 내 대답은 "나쁘지는 않지만 전문가 하드웨어를 사용해야합니다"라는 것 같습니다. – Joe

1

RTOS가 아닌 OS에서 스레드를 사용하고 잠자는 것은 매우 정확하거나 일관된 결과를 산출하지 못합니다.

더 좋은 방법은 타이머 인터럽트를 사용하고 ISR의 GPIO를 전환하는 것입니다. 하드웨어 타이머에서 하드웨어 PWM 출력을 사용하는 것과는 달리이 방법을 사용하면 여러 신호와 다른 목적을 위해 단일 타이머를 사용할 수 있습니다. 하드웨어 PWM과 실용적인 주파수 범위 및 펄스 해상도가 하드웨어에서 달성 할 수있는 것보다 훨씬 더 낮을 지 모르지만 적어도 지터는 밀리 초보다는 오히려 마이크로 초일 것입니다.

1

타이머가있는 경우 새 PWM 에지가 필요할 때마다 인터럽트를 실행하도록 타이머를 설정할 수 있습니다. 영리한 코딩을 사용하면 인터럽트 핸들러가 많은 PWM 채널 중 어느 것이고 높은 에지 또는 낮은 에지가 필요한지를 알고 있으므로 다음 요구되는 에지를 위해 스케줄링 할 수 있습니다.

타이머가 충분하면 PWM 채널당 하나를 할당하는 것이 훨씬 쉽습니다.

지연 시간이 짧은 인터럽트 응답이있는 임베디드 컨트롤러에서 이것은 놀라운 결과를 가져올 수 있습니다.

관련 문제