Arduino가 특정 (예 : 56kHz) 반송파 주파수를 어떻게 출력 할 수 있습니까?


9

두 지점 사이에 무선으로 데이터를 보내기 위해 자유 공간 광학 프로젝트를 진행하고 있습니다. 이 작업을 수행하기 위해 송신기의 56 kHz 캐리어 주파수로 펄스하는 Arduino Uno에 연결된 IR LED와 수신기의 56 kHz IR 검출기 모듈이있는 두 번째 Arduino를 사용하고 있습니다.

반송파 주파수를 생성하기 위해 핀 하이와 핀 로우 명령 사이에 delayMicroseconds ()를 사용하려고했습니다. 이런 종류의 작동하지만 주파수가 항상 동일하지는 않으며 신호를 펄스하기위한 추가 지연 (즉, 함수를 호출하고 감소시키는 데 필요한 시간)이이를 변경할 수 있습니다.

ATmega328의 데이터 시트를 읽으면 칩 타이머를 사용하여보다 정확한 펄스를 설정하는 방법이있는 것 같습니다. 가능합니까? 그렇다면 타이머를 사용하여 어떻게 56kHz 펄스를 생성합니까?


56KHz 주파수에 필요한 정확도는 무엇입니까? 즉, 프로젝트에서 어떤 주파수 범위가 허용됩니까? Arduino 타이머 만 사용하면 정밀도에 한계가 있기 때문에 묻습니다.
jfpoilpret

검출기에서 높은 수준의 응답 성을 유지하려면 55.5khz ~ 56.5khz가 이상적입니다.
jlbnjmn

답변:


10

Arduino 타이머로 56kHz 신호를 생성 할 수 있습니다 .

실제로 타이머는 MCU에서 특수 레지스터로 볼 수 있는데, MCU 클록 주파수 (Arduino Uno의 16MHz)에서 주파수로 증가하는 값 (0부터 시작)을 보유한 특수 레지스터로 볼 수 있습니다. 프리스케일러 . 해당 값이 지정한 Match Match 라는 한계에 도달하면 다음 두 가지가 발생합니다.

  • 타이머 레지스터 값이 0으로 재설정됩니다.
  • 하나의 ISR (인터럽트 서비스 루틴) 콜백 함수가 호출됩니다 (자신의 코드를 가리 키도록 정의 할 수 있음).

아이디어는 ISR을 사용하여 호출 될 때마다 ( HIGH, 다음 LOW, HIGH...) 논리 핀의 출력을 변경하는 것입니다 .

이제 56kHz 구형파를 생성하려면 ISR을 56000 * 2초당 시간 으로 호출해야합니다 ( * 2주기 당 두 번 출력 값을 변경해야하기 때문에).

다음 목록에서 타이머에 원하는 프리스케일러 값을 선택할 수 있습니다.

  • 1 (클럭 주파수는 분할되지 않으므로 16MHz)
  • 8 (클럭 주파수는 8로 나뉘므로 2MHz)
  • 64
  • 256
  • 1024

Arduino Uno에는 두 가지 크기의 타이머 / 카운터가 있습니다 ( 실제로 는 타이머 / 카운터 라고 합니다 ) : 8 비트 및 16 비트.

Arduino Uno (ATmega328P)에는 전체적으로 3 개의 타이머가 있지만 일부는 Arduino 코어 라이브러리 또는 스케치에 사용 된 다른 라이브러리에서 사용될 수 있습니다 (직접 확인해야합니다).

  • timer0 (8 비트)
  • timer1 (16 비트)
  • timer2 (8 비트) :이 옵션에는 프리 스케일링 옵션이 더 있습니다 (1, 8, 32, 64, 128, 256 및 1024).

이제 16MHz에서 56kHz 웨이브를 생성해야하므로 프리 스케일링없이 다음을 계산해야합니다.

16000000 / (56000 * 2) - 1 = 141.857( - 1타이머는 0부터이 값까지 카운트하고 도달 한 후에 만 재설정되기 때문에 )

이 계산에서 두 가지 관측 값을 그릴 수 있습니다.

  1. 141.857 는 정수가 아니므로 정확히 56kHz의 웨이브를 생성 할 수 없습니다.
  2. 프리 스케일링이 없으면 285는 8 비트 부호없는 정수로 표현할 수 없으므로 16 비트 타이머가 필요합니다.

지금부터 두 가지 옵션이 있습니다.

  1. 16 비트 타이머 ( timer1 )를 사용하고 프리스케일러 = 1을 사용 142하고 비교 일치로 선택 하십시오. 그것은 당신에게 다음과 같은 빈도를 줄 것입니다 :16000000 / (2 * (142 + 1)) = 55944 Hz
  2. 8 비트 타이머 ( timer0 )를 사용하고 프리스케일러 = 8을 사용 17하고 비교 일치로 선택 하십시오. 다음 주파수에서는 정확도가 떨어 16000000 / (8 * 2 * (17 + 1)) = 55555 Hz집니다. 여전히 필요한 범위 내에 있습니다.

이를 위해 스케치를 작성하는 방법에 관해, 나는 매우 완벽하고 읽기에 흥미있는 이 지침 을 확인 하는 것이 좋습니다.

물론, ATmega328P 데이터 시트 는 당신이하는 일을 아주 조금이라도 이해하려면 중요합니다.

몇 가지 중요한 참고 사항 :

  • ISR은 인터럽트가 비활성화 된 상태에서 실행되므로 최대한 짧아야합니다. 특히, Arduino 라이브러리에는 ISR에서 호출되지 않는 몇 가지 기능이 있습니다.
  • Arduino Uno 클럭은 매우 정확하지 않습니다 (쿼츠 대신 세라믹 공진기를 사용하므로 훨씬 더 정확했을 것입니다). 그러면 출력 주파수가 더 이동합니다.

2
또한 지정된 제한에 도달하면 하드웨어 가 핀을 토글 할 수 있습니다. 따라서 ISR을 전혀 사용할 필요가 없습니다. 명령이 시작되면 중단 될 수 없으므로 항상 ISR에 지터 가 발생합니다. 그러나 하드웨어는 항상 원하는 속도로 핀을 토글합니다.
Nick Gammon

Arduino Uno가 세라믹 공진기를 사용한다는 것은 다소 놀라운 일이지만, 그 소스는 Arduino UNO FAQ입니다 ( "Uno는 프로세서 클럭에 공진기 나 크리스털을 사용합니까?" ).
피터 Mortensen

3

tone()모든 핀에서 고주파 펄스를 생성하는 데 유용한 것으로 나타났습니다 . 56KHz를 처리 할 수 ​​있어야합니다. (편집 : jfpoilpret가 지적한 것처럼 실제로 16MHz Arduino에서 얻을 수있는 가장 가까운 것은 약 55.944KHz입니다)

어려움은 분명히 데이터 신호와 결합하는 것입니다. 저수준 코드에 의지하지 않고 소프트웨어에서 그렇게 할 수 있다고 생각하지 않습니다. 그것은 디지털이기 때문에 하드웨어에서 꽤 쉬워야합니다.

데이터 신호를 다른 핀으로 출력 한 다음 AND 게이트를 사용하여 데이터를 캐리어와 결합하기 만하면됩니다. 결합 된 신호는 IR 송신기로 바로 이동할 수 있습니다.

AND 게이트가없는 경우 한 쌍의 트랜지스터를 사용하여 직접 만들 수 있습니다. "트랜지스터 및 게이트"를 온라인으로 검색하십시오.


수신자는 일반적으로 일반적으로 낮은 출력을 활성화합니다. LED의 상단을 56khz에 연결하고 하단을 데이터 핀에 연결하면 데이터 핀이 낮아지면 IR 출력이 발생하여 리시버가 낮아집니다. LED와 저항 만 있으면 게이트가 필요하지 않습니다. 현재의 io 핀이 구동 할 수있는 것에 만 문제가 있습니다.
EternityForest

2

jfpoilpret의 대답은 매우 잘 작성되어 있으며 완벽하게 유효하며 99 %의 경우 나는 그가 설명하는 것을 정확하게 할 것입니다. 그의 솔루션은 정의 된 매개 변수 내에 있으므로 매우 잘 작동합니다. 그러나 " 아주 잘 " 보다 나은 것이 무엇 입니까? 완전! 결국 문제는 정확한 값을 생성하는 것입니다. 대부분의 경우 (충분히 모두) 충분하다고 말했듯이 1 초가 1 초가되어야 할 때 시계로 무언가를 처리 할 때조차도 상속 된 부품 결함을 겪어야합니다.

내가 제안하는 것이 항상 가능한 것은 아닙니다. 어떤 경우에는 가능하지만이 경우보다 훨씬 많은 노력과 노력이 필요합니다. 가치는 사례별로 의존 하는가? 저의 목표는 대체로 다소 까다로운 경우에 더 나은 미래의 참조에 대한 대안을 제시하는 것입니다. 이것은 Arduino의 초보 사용자를 대상으로 작성되었으며 전자 제품에 대한 광범위한 경험이 없습니다.

상급자에게는 아마도 너무 장황하고 멍청하게 보일 것입니다. 그러나 나는 똑같은 사람들이 이미 그것을 알고 있으며이 답변이 필요하지 않다고 생각합니다. 이는 모든 마이크로 컨트롤러 및 모든 제조업체 및 아키텍처에도 적용됩니다. 그러나 다른 마이크로 컨트롤러의 경우 올바른 레지스터와 프리 스케일 이름 및 값을 찾으려면 올바른 데이터 시트를 참조해야합니다.

귀하의 경우 특정 주파수가 필요하며 그에 대한 좋은 점은 실제로 56 kHz가 실제로 매우 쉽게 달성 될 수 있다는 것입니다 (부품의 실제 결함을 계산하지 않음). 따라서 이것은 완벽한 사례입니다.

신호 생성은 jfpoilpret의 설명에 따라 마이크로 컨트롤러의 타이머 및 클럭 소스에 따라 다릅니다. 그의 대답은 한 가지 관점의 문제만을 다루며 타이머를 다루고 있습니다. 그러나 클럭 소스로 바이올린을 피우거나 시너지 효과와 멋진 결과를 모두 얻을 수 있습니다. 환경의 매개 변수를 변경 하여이 경우 시스템을 해킹하고 클럭 소스를 교체하면 훨씬 쉽고 편리하게 특정 문제를 해결할 수 있습니다.

먼저 핀 상태를 토글하기 때문에 신호 주파수보다 2 배 더 높은 ISR을 실행해야합니다. 초당 112,000 회입니다. 56,000과 16,000,000은 이미 지적한 것처럼 훌륭하게 합치 지 않습니다. 신호 주파수 또는 택트 주파수를 변경해야합니다. 불변 신호 주파수를 다루고 더 나은 클럭 속도를 찾아 보자.

0을 추가하기 때문에 56kHz (또는 112kHz)보다 큰 차수의 클럭을 선택하는 것이 가장 간단합니다.이 종류의 수학은 대부분의 사람들에게 가장 간단합니다. 불행히도이 세상의 모든 것은 무언가와 타협합니다. 모든 가치가 효과가있는 것은 아닙니다.

첫 번째 예는 택트 제너레이터 속도가 너무 낮은 경우입니다.

56,000Hz 클록을 선택하면주기마다 ISR을 호출해야하며 다른 작업을 수행 할 수 없으므로 아무 것도 수행 할 수 없습니다. 전혀 쓸모가 없습니다. 10 배 빠른 속도 (560 kHz)를 선택하면 9 (타이머가 최대 값에 도달하기 위해 10 사이클-ISR 기능을 호출하기위한 1 사이클)의 마이크로 컨트롤러 사이클로 작업을 수행 할 수 있으며 이는 충분하지 않을 수 있습니다. 종종 더 많은 계산 능력이 필요합니다.

반면에 너무 큰 값을 선택하면 56MHz로 마이크로 컨트롤러가 작동하지 않습니다. 너무 빠릅니다. 따라서 상점에서 가장 큰 가치를 선택하는 것만으로는 가치가 떨어질 수 없습니다.

오리지널 아두 이노 우노 R3는 16 MHz의 스톡 클록을 가지고 있으므로 동작이 느려질 수 있습니다. 다음으로 56보다 크고 16MHz보다 작은 다음 값은 5.6MHz입니다. 이를 통해 50 사이클마다 ISR을 호출 할 수 있으며 112,000Hz 타이머 주파수를 완벽하게 만들 수 있습니다. 신호는 정확히 56kHz입니다. ISR 호출간에 프로그램을 실행하기 위해 49 개의 MCU주기가 있지만 여전히 원래 클럭 속도의 1/3 정도입니다. 112를 기본으로 사용하고 11.2 MHz 클럭을 사용할 수 있으며 이것은 16 MHz 공진기의 약 2/3를 제공합니다. ISR 기능은 100 사이클마다 호출되며 여전히 완벽한 56 kHz 신호를 생성합니다.

그러나이 값에는 두 가지 주요 문제가 있습니다.

  • 첫 번째 문제는 사용자의 요구에 따라 크게 다릅니다. 찾기 쉬운 레지스터 값 (OCR iirc ) 을 사용하는 정확한 신호 주파수를 얻기 위해 최대 계산 전력의 약 1/3 (11.2MHz)을 희생합니다 . 당신은 그것에 괜찮을 수도 있고 그렇지 않을 수도 있습니다.

  • 두 번째 문제는 어려운 쇼 토퍼입니다 . 값을 찾는 것은 매우 쉽지만 종종 제조 된 클럭 소스로는 존재하지 않습니다. 이것은 단지 5.6 MHz와 11.2 MHz가 모두없는 Farnell의 공진기 웹 페이지 입니다.

이를 피하기 위해 사용 가능한 공진기 값을보고 정확히 원하는 값을 생성하는 데 사용할 수있는 다른 것을 찾을 수 있습니다. 56을 4로 나누면 14가되고 운 좋게도 14 MHz 공진기가 있습니다. 이것은 우리에게 훨씬 더 빠른 속도와 더 많은 파워를 제공하며 레지스터 값을 찾기가 쉽습니다. ISR을 초당 112,000 회 호출하려면 OCR 레지스터에 10 진수 124 또는 16 진 0x7C 값을 넣어야하므로 ISR 호출을 위해 124 사이클 + 1을 세면 원하는 완벽한 값을 얻을 수 있습니다.

NB

  1. ISR-인터럽트 서비스 루틴 (생성 된 인터럽트에서만 실행되는 코드)
  2. 프로그램 크기는 메모리 크기에 따라 다릅니다! 클럭 속도와 관련이 없으며 ISR을 호출하는 빈도와는 관련이 없습니다.
  3. 마이크로 컨트롤러가 프로그램 명령으로 시작하면 카운터가 증가합니다. 인터럽트가 발생하면 ISR이 호출되고이 값은 특수 레지스터에 저장됩니다. ISR 코드가 완료되면 프로그램 카운터의 값이이 특수 레지스터에서 복원되고 프로그램은 마치 발생한 적이없는 것처럼 중단 된 위치부터 계속됩니다.

    나는 매우 바보 같은 예를 제시 할 것이다. 당신이 순수 주의자라면, 나는 당신에게 경고합니다 : 코와 눈 출혈이 발생할 수 있습니다.

    어딘가에서 다른 곳으로 걸어 가야한다고 상상해보십시오. 단계별 경로 지침은 기본 프로그램 및 해당 명령입니다. 걷거나 달리는 속도는 "클럭 속도"에 따라 다르지만 경로 지침 (30 걸음 앞으로, 1 회전 90도 왼쪽, 10 걸음 앞으로, 45 단계 오른쪽 등)에 따라 다릅니다. . 이제 작은 꼬마 나 욕심이 부패한 지역 정치인이 지금 당신의 신발을 풀고 있다고 상상해보십시오. 인터럽트를 발생시키는 이벤트입니다. 그런 다음 마지막 단계를 마친 후에 무릎을 꿇고 신발을 다시 묶으십시오. 이것은 당신의 ISR 프로그램입니다.

    그런 다음 중단 한 곳에서 계속하십시오. 당신은 처음부터 시작하지 않습니다. 세상을 돌보지 않고 항상 걸을 때는 신발을 매 단계마다 묶어야하더라도 신경 쓰지 않아도됩니다. 그러나 올림픽에서 100 미터를 달리거나 굶주린 살을 먹는 포식자에서 달리는 등 시간 제약이있는 경우 신발을 멈추고 묶는 것은 심각한 결과를 초래할 수 있습니다. 마이크로 컨트롤러도 마찬가지입니다. 한 줄의 코드 만 실행하더라도 프로그램은 느리지 만 계속 진행됩니다. 속도에 전혀 신경 쓰지 않는다면 문제가되지 않습니다. 다른 타이머 종속 작업을 사용하는 것과 같이 시간과 관련하여 시간을 내야하는 경우 간섭이 매우 원치 않으며 문제가 될 수 있습니다.

  4. 더 적은 것입니다! 더 빠른 시계가 항상 좋은 것은 아닙니다. 클럭이 느린 장치는 훨씬 적은 전력을 사용합니다. 이것은 배터리로 작동되는 장치에서 중요한 포인트가 될 수 있습니다.

  5. 필요한 사이클은이 공식에서 파생됩니다.
    (클럭 속도 / (프리스케일러 값 * 필요한 ISR 호출 주파수))-1


TLDR : 세라믹 16MHz 오실레이터를 납땜 해제 하고 정수 나눗셈 (예 : 14MHz, 250으로 나눔)으로 정확히 56kHz 를 허용 하는 다른 것으로 교체하십시오 .
Peter Mortensen

0

캐리어 핀 모드를 출력과 입력간에 전환하여 캐리어를 켜고 끌 수 있습니다. 이것을 사용하여 37KHz 적외선 (원격 제어) 포트를 통해 열 펌프를 제어했습니다.


0

캐리어를 만들기 위해 ISR을 사용할 필요가 없습니다. 필요한 반송파 주파수에서 50 % PWM 출력을 생성하도록 타이머를 설정하기 만하면됩니다. 그런 다음 ISR은 일반적으로 0.5 또는 1ms 간격으로 캐리어를 훨씬 더 편안한 속도로 변조하는 역할을합니다. 내 경험상 반송파 주파수의 5 % 오류는 대부분의 IR 수신기에서 허용됩니다. Freetronics EtherMega 2560 (타이머가 많음)을 사용했지만 다른 CPU도 마찬가지입니다.


그러면 반송파 변조가 정확히 어떻게 구현됩니까? 입력 (캐리어 꺼짐)과 출력 (캐리어 켜짐) 사이에서 타이머 출력 캡처 핀의 모드를 변경 하시겠습니까?
피터 Mortensen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.