Lái xe tần số đầu ra PWM


8

Sau nhiều giờ tìm kiếm và đọc không có kết quả, tôi vẫn chưa hiểu đầy đủ về cách thức và lý do để xuất tần số cụ thể từ chân PWM phần cứng trên RPi mà không sử dụng 'hộp đen' của người khác.

Dường như có khá nhiều thông tin không chính xác hoặc không đầy đủ về các chi tiết cụ thể, cũng như các thuật ngữ khác nhau được sử dụng - 'bộ chia xung nhịp', 'chu kỳ nhiệm vụ', 'phạm vi PWM' và chính dữ liệu của chúng, và tất cả chúng có liên quan như thế nào cùng nhau để tạo ra một tần số cụ thể - trong trường hợp của tôi để điều khiển các tần số âm thanh cụ thể ra khỏi một âm thanh piezo.

Câu trả lời:


14

Cuối cùng tôi đã có một sự hiểu biết (ish) đầy đủ từ tệp tiêu đề trình điều khiển bcm2835.h, vì vậy tôi nghĩ rằng tôi sẽ đăng và trả lời câu hỏi của riêng mình cho người khác.

Các bit có liên quan từ tiêu đề:

PWM

BCM2835 hỗ trợ PWM phần cứng trên một tập hợp con giới hạn của các chân GPIO. Thư viện bcm2835 này cung cấp các chức năng để cấu hình và kiểm soát đầu ra PWM trên các chân này.

BCM2835 chứa 2 kênh PWM độc lập (0 và 1), mỗi kênh được kết nối với một tập hợp con giới hạn của các chân GPIO. Các chân GPIO sau có thể được kết nối với các kênh PWM sau:

  GPIO PIN    RPi pin  PWM Channel    ALT FUN
  12                    0             0
  13                    1             0
  18          1-12      0             5
  19                    1             5
  40                    0             0
  41                    1             0
  45                    1             0
  52                    0             1
  53                    1             1

Để chân GPIO phát ra đầu ra từ kênh PWM của nó, nó phải được đặt thành Chức năng Alt được đưa ra ở trên. Lưu ý cẩn thận rằng các phiên bản hiện tại của Raspberry Pi chỉ hiển thị một trong các chân này (GPIO 18 = RPi Pin 1-12) trên các tiêu đề IO, và do đó đây là chân IO duy nhất trên RPi có thể được sử dụng cho PWM. Hơn nữa, nó phải được đặt thành ALT FUN 5 để có đầu ra PWM.

Cả hai kênh PWM được điều khiển bởi cùng một đồng hồ PWM, có dvider đồng hồ có thể được thay đổi bằng cách sử dụng bcm2835_pwm_set_clock(). Mỗi kênh có thể được kích hoạt riêng với bcm2835_pwm_set_mode(). Đầu ra trung bình của kênh PWM được xác định bởi tỷ lệ DATA / RANGE cho kênh đó. Sử dụng bcm2835_pwm_set_range()để đặt phạm vi và bcm2835_pwm_set_data()để đặt dữ liệu theo tỷ lệ đó

Mỗi kênh PWM có thể chạy ở chế độ Cân bằng hoặc Dấu không gian. Trong chế độ Cân bằng, phần cứng sẽ gửi một tổ hợp các xung đồng hồ dẫn đến các xung DATA tổng thể trên mỗi xung RANGE. Trong chế độ Mark-Space, phần cứng đặt mức đầu ra CAO cho xung đồng hồ DATA rộng, theo sau là xung cho đồng hồ RANGE-DATA.

Đồng hồ PWM có thể được thiết lập để kiểm soát độ rộng xung PWM. Đồng hồ PWM có nguồn gốc từ đồng hồ 19,2 MHz. Bạn có thể đặt bất kỳ bộ chia nào, nhưng một số bộ chia chung được cung cấp bởibcm2835PWMClockDivider

Ví dụ: giả sử bạn muốn lái động cơ DC với PWM ở tốc độ khoảng 1kHz và kiểm soát tốc độ theo gia số 1/1024 từ 0/1024 (dừng) đến 1024/1024 (bật đầy đủ). Trong trường hợp đó, bạn có thể đặt bộ chia xung nhịp thành 16 và RANGE thành 1024. Tần số lặp lại xung sẽ là 1,2 MHz / 1024 = 1171.875Hz.

bcm2835PWMClockDividerChỉ định bộ chia được sử dụng để tạo đồng hồ PWM từ đồng hồ hệ thống. Hình dưới đây cho bộ chia, thời gian đồng hồ và tần số đồng hồ. Đồng hồ được chia dựa trên tốc độ xung nhịp cơ sở danh nghĩa là 19,2 MHz. Các tần số hiển thị cho mỗi bộ chia đã được xác nhận bằng phép đo

typedef enum
{
    BCM2835_PWM_CLOCK_DIVIDER_2048  = 2048,    /*!< 2048 = 9.375kHz */
    BCM2835_PWM_CLOCK_DIVIDER_1024  = 1024,    /*!< 1024 = 18.75kHz */
    BCM2835_PWM_CLOCK_DIVIDER_512   = 512,     /*!< 512 = 37.5kHz */
    BCM2835_PWM_CLOCK_DIVIDER_256   = 256,     /*!< 256 = 75kHz */
    BCM2835_PWM_CLOCK_DIVIDER_128   = 128,     /*!< 128 = 150kHz */
    BCM2835_PWM_CLOCK_DIVIDER_64    = 64,      /*!< 64 = 300kHz */
    BCM2835_PWM_CLOCK_DIVIDER_32    = 32,      /*!< 32 = 600.0kHz */
    BCM2835_PWM_CLOCK_DIVIDER_16    = 16,      /*!< 16 = 1.2MHz */
    BCM2835_PWM_CLOCK_DIVIDER_8     = 8,       /*!< 8 = 2.4MHz */
    BCM2835_PWM_CLOCK_DIVIDER_4     = 4,       /*!< 4 = 4.8MHz */
    BCM2835_PWM_CLOCK_DIVIDER_2     = 2,       /*!< 2 = 9.6MHz, fastest you can get */
    BCM2835_PWM_CLOCK_DIVIDER_1     = 1        /*!< 1 = 4.6875kHz, same as divider 4096 */
} bcm2835PWMClockDivider;

Tóm tắt:

  1. Nếu bạn muốn PWM phần cứng - bạn bị mắc kẹt với chân 12 (BCM18), các chân GPIO khác sẽ sử dụng phần mềm PWM.

  2. Có lẽ bạn sẽ cần phải đặt chế độ PWM thành chế độ 'Mark-Space' cho hầu hết các trường hợp sử dụng và lý do vệ sinh như được mô tả ở trên.

  3. Trong chế độ này, thời lượng mà mỗi 'xung' là CAO so với THẤP được xác định bởi tỷ lệ của dữ liệu PWM với phạm vi PWM - không phụ thuộc vào tốc độ xung nhịp của PWM.

  4. Phạm vi PWM có hiệu quả là 'độ phân giải' hoặc số lượng 'phân chia' có thể có của mỗi xung. Càng nhiều phân chia thì độ phân giải càng cao và do đó càng có nhiều trạng thái mã hóa cho độ rộng xung cho trước.

  5. "Chu kỳ nhiệm vụ" là tỷ lệ của dữ liệu PWM với phạm vi PWM được biểu thị bằng phần trăm. Phạm vi PWM là 10 với dữ liệu PWM là 8 là chu kỳ nhiệm vụ 80%.

  6. Tốc độ xung nhịp PWM là sức mạnh của hai ước. Vì vậy, tốc độ xung nhịp đã chọn của bạn cho PWM phải là divisor & (divisor -1) == 0Mặc dù 12 giá trị hợp lệ được liệt kê ở trên.

  7. Chia tần số xung nhịp PWM theo tần số đầu ra mong muốn sẽ cho giá trị dải xung.

  8. Khi tôi đang mã hóa âm thanh và sử dụng một âm thanh piezo, tôi cần chu kỳ nhiệm vụ 50% để tối đa hóa dao động piezo và do đó âm lượng. Do đó, giá trị dữ liệu PWM luôn bằng một nửa giá trị phạm vi PWM - 50% CAO 50% THẤP.

Để tính tần số yêu cầu của bạn, hãy chọn một ước số đồng hồ có ý nghĩa cho ứng dụng của bạn - Tôi đã chọn 16, tương đương với 1,2Mhz. Vì thế:

Lưu ý của A là 440Hz, F # là 370Hz, C # là 277Hz

PWMClock = 16; // 1.2Mhz

const A4_RANGE = 1.2e6 / 440;  // 1.2Mhz/440Hz
A4Data = A4_RANGE / 2;

const F4S_RANGE = 1.2e6 / 370;  // 1.2Mhz/370Hz
F4SData = F4S_RANGE / 2;

const C4S_RANGE = 1.2e6 / 277;  // 1.2Mhz/277Hz
C4SData = C4S_RANGE / 2;

Bạn có thể dễ dàng thay đổi phạm vi PWM lên và xuống quãng tám theo bội số - phạm vi * 2 sẽ đưa nó xuống quãng tám, phạm vi * 0,5 sẽ đưa nó lên một quãng tám.

Nếu bạn muốn lái một servo ở tốc độ 50Hz, thì phép tính phạm vi tương tự vẫn đúng:

PWM Range = PWM frequency / Desired Output Frequency

(Giá trị phạm vi PWM tối đa theo một số bài viết có giai đoạn là 4096 - theo kinh nghiệm của tôi, điều này không đúng khi chơi C # như trên mang lại phạm vi PWM là 4332 hoạt động như mong đợi.)

Giống như hầu hết mọi thứ - thật dễ dàng khi bạn biết cách.

~ N


3
Lưu ý rằng bit "chỉ 12 pin" áp dụng cho các kiểu 26 chân. Các mô hình 40 pin có thêm ba (13, 18 và 19), nhưng vẫn chỉ có 2 kênh đồng hồ và các chân có liên kết cứng với một hoặc khác (chân 12 và 18 là kênh 0, 13 và 19 là kênh 1); theo các tài liệu được trích dẫn ở trên libbcm2835 sẽ cho phép bạn định cấu hình cả hai kênh và cả bốn chân. Các hàm ALT để làm như vậy khác nhau cho mỗi pin; có một bảng ở đây phần lớn được lấy trực tiếp từ bảng dữ liệu SoC của Broadcom. Các mục bị gạch bỏ chỉ trên các mô hình 40 chân.
goldilocks

7

Trên Pis gần đây (những người có tiêu đề mở rộng 40 pin và mô đun tính toán) GPIO 12/13/18/19 có thể được sử dụng để cung cấp tín hiệu PWM phần cứng.

Nguồn xung nhịp PWM không cần phải là tinh thể 19,2 MHz , pigpio sử dụng PLLD 500 MHz.

Để biết phương pháp dòng lệnh đơn giản để đặt tần số PWM phần cứng, hãy xem http://abyz.me.uk/rpi/pigpio/pigs.html#HP

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.