Làm thế nào một Arduino có thể tạo ra tần số sóng mang cụ thể (tức là 56 kHz)?


9

Tôi đang làm việc trong một dự án quang học không gian miễn phí để gửi dữ liệu không dây giữa hai điểm. Để thực hiện điều này, tôi đang sử dụng một đèn LED hồng ngoại được kết nối với Arduino Uno phát xung với tần số sóng mang 56 kHz cho máy phát và Arduino thứ hai với mô-đun dò hồng ngoại 56 kHz cho máy thu.

Tôi đã thử sử dụng delayMicroseconds () giữa các lệnh pin cao và pin thấp để tạo tần số sóng mang. Đây là loại công việc, nhưng tần số không phải lúc nào cũng giống nhau và bất kỳ độ trễ bổ sung nào cho xung tín hiệu (tức là thời gian cần thiết để gọi chức năng và giảm dần) có thể thay đổi nó.

Đọc biểu dữ liệu cho ATmega328, có vẻ như có một cách để đặt xung chính xác hơn bằng cách sử dụng bộ định thời của chip. Điều đó có thể không, và nếu vậy, làm thế nào để bạn tạo ra xung 56 kHz bằng bộ định thời?


Độ chính xác bạn cần cho tần số 56KHz của bạn là bao nhiêu? Tức là dải tần số nào được chấp nhận trong dự án của bạn? Tôi hỏi bởi vì chỉ sử dụng bộ định thời Arduino, độ chính xác có những hạn chế.
jfpoilpret

55,5khz đến 56,5khz sẽ là lý tưởng để duy trì mức độ đáp ứng cao trong máy dò.
jlbnjmn

Câu trả lời:


10

Thực sự có thể tạo ra tín hiệu 56 kHz với bộ định thời Arduino .

Một bộ định thời thực sự có thể được xem như là một thanh ghi đặc biệt, trong MCU, chứa một giá trị (bắt đầu từ 0) được tăng lên ở tần số là tần số xung nhịp MCU (16 MHz trên Arduino Uno), khả năng chia cho một yếu tố được gọi là bộ đếm trước . Khi giá trị đó đạt đến giới hạn, được gọi là So sánh so sánh , mà bạn chỉ định, thì có hai điều xảy ra:

  • Giá trị thanh ghi hẹn giờ được đặt lại về 0.
  • Một hàm gọi lại ISR (dịch vụ ngắt thường xuyên) được gọi (bạn có thể xác định nó để trỏ đến mã của riêng bạn).

Ý tưởng là sử dụng ISR đó để thay đổi đầu ra của pin logic mỗi khi nó được gọi ( HIGHsau đó LOW, sau đó HIGH...).

Bây giờ, để tạo ra sóng vuông 56 kHz, bạn sẽ cần ISR của mình được gọi là 56000 * 2thời gian mỗi giây ( * 2vì bạn cần thay đổi giá trị đầu ra hai lần mỗi chu kỳ).

Bạn có thể chọn giá trị bộ đếm gộp mà bạn muốn cho bộ đếm thời gian trong danh sách sau:

  • 1 (tần số xung nhịp không được chia, do đó 16 MHz)
  • 8 (tần số xung nhịp được chia cho 8, do đó 2 MHz)
  • 64
  • 256
  • 1024

Có hai kích thước bộ định thời / bộ đếm trên Arduino Uno (chúng thực sự được gọi là bộ đếm thời gian / bộ đếm ): 8 bit và 16 bit.

Trên Arduino Uno (ATmega328P), bạn có ba bộ định thời tổng thể, nhưng một số có thể được sử dụng bởi thư viện lõi Arduino hoặc các thư viện khác được sử dụng trong bản phác thảo của bạn (bạn sẽ phải tự kiểm tra)

  • hẹn giờ0 (8 bit)
  • hẹn giờ1 (16-bit)
  • timer2 (8 bit): cái này có nhiều tùy chọn đặt trước hơn (1, 8, 32, 64, 128, 256 và 1024)

Bây giờ bạn cần tạo ra sóng 56 kHz từ 16 MHz, do đó, không cần đặt trước, bạn sẽ cần phải tính đến:

16000000 / (56000 * 2) - 1 = 141.857( - 1vì bộ đếm thời gian đếm từ 0 đến giá trị này và chỉ đặt lại sau khi đạt được)

Từ tính toán này, chúng ta có thể rút ra hai quan sát:

  1. 141.857 không phải là số nguyên và do đó bạn sẽ không thể tạo ra sóng chính xác 56 kHz.
  2. Nếu không đặt trước, bạn cần một bộ định thời 16 bit vì 285 không thể biểu diễn dưới dạng số nguyên không dấu 8 bit.

Từ bây giờ bạn có hai lựa chọn:

  1. Sử dụng bộ định thời 16 bit ( timer1 ), sử dụng prescaler = 1 và chọn 142làm So sánh so sánh; Điều đó sẽ cung cấp cho bạn tần số sau:16000000 / (2 * (142 + 1)) = 55944 Hz
  2. Sử dụng bộ định thời 8 bit ( timer0 ), sử dụng prescaler = 8 và chọn 17làm So sánh so sánh; điều đó sẽ cho độ chính xác thấp hơn với tần số sau: 16000000 / (8 * 2 * (17 + 1)) = 55555 Hzvẫn nằm trong phạm vi yêu cầu.

Bây giờ, liên quan đến cách viết bản phác thảo của bạn cho điều đó, tôi khuyên bạn nên xem hướng dẫn này rất đầy đủ và rất thú vị để đọc.

Tất nhiên, bảng dữ liệu hoàn chỉnh ATmega328P cũng rất quan trọng nếu bạn muốn hiểu, trong những chi tiết nhỏ nhất, những gì bạn đang làm.

Một số lưu ý quan trọng:

  • Một ISR được thực thi với các ngắt bị vô hiệu hóa và do đó phải càng ngắn càng tốt. Cụ thể, có một số chức năng từ thư viện Arduino sẽ không được gọi từ ISR.
  • Đồng hồ Arduino Uno không chính xác lắm (nó sử dụng bộ cộng hưởng gốm thay vì thạch anh, điều này sẽ chính xác hơn nhiều), vì vậy điều này có nghĩa là tần số đầu ra sẽ thay đổi hơn nữa.

2
Ngoài ra khi đạt đến giới hạn quy định, phần cứng có thể chuyển đổi mã pin. Do đó, không cần sử dụng ISR. Sẽ luôn có jitter với ISR ​​vì một lệnh không thể bị gián đoạn khi nó bắt đầu. Tuy nhiên, phần cứng sẽ luôn chuyển đổi pin ở tốc độ mong muốn.
Nick Gammon

Điều hơi ngạc nhiên là Arduino Uno sử dụng bộ cộng hưởng gốm, nhưng nguồn cho nó là Câu hỏi thường gặp về Arduino UNO (gần "Uno có sử dụng bộ cộng hưởng hoặc tinh thể cho đồng hồ bộ xử lý không?" ).
Peter Mortensen

3

Tôi đã thấy tone()hữu ích để tạo xung tần số cao trên bất kỳ pin nào. Nó sẽ có thể xử lý 56 KHz. (Chỉnh sửa: Theo ghi nhận của jfpoilpret, gần nhất bạn có thể nhận được trên Arduino 16 MHz là khoảng 55.944 KHz)

Khó khăn rõ ràng sẽ được kết hợp nó với tín hiệu dữ liệu của bạn. Tôi không nghĩ bạn có thể làm điều đó trong phần mềm mà không cần dùng đến mã cấp thấp. Nó sẽ khá dễ dàng trong phần cứng, vì nó là kỹ thuật số.

Tất cả những gì bạn cần làm là xuất tín hiệu dữ liệu của mình trên một pin khác, sau đó kết hợp nó với sóng mang bằng cổng AND. Tín hiệu kết hợp có thể đi thẳng đến bộ phát IR của bạn.

Nếu bạn không có cổng AND thì thật đơn giản để tự tạo một cặp bóng bán dẫn. Chỉ cần tìm kiếm trực tuyến cho "bóng bán dẫn và cổng".


Người nhận thường có đầu ra hoạt động thấp nói chung. Nếu bạn kết nối đỉnh của đèn LED với 56khz và dưới cùng với chân dữ liệu của bạn, khi chân dữ liệu xuống thấp, bạn sẽ nhận được đầu ra IR, điều này sẽ làm cho bộ thu phát xuống thấp. Không và cổng cần thiết, chỉ cần một đèn led và điện trở. Chỉ có vấn đề là bị giới hạn ở bất cứ chân nào io hiện tại có thể lái.
EternityForest

2

Câu trả lời được chấp nhận của jfpoilpret được viết rất tốt, hoàn toàn hợp lệ và trong 99% trường hợp tôi sẽ làm chính xác những gì anh ấy giải thích. Các giải pháp của anh ấy nằm trong các tham số đã xác định của bạn, vì vậy chúng sẽ hoạt động rất tốt. Nhưng cái gì tốt hơn " rất tốt "? Sự hoàn hảo! Rốt cuộc, câu hỏi là về việc tạo ra một giá trị chính xác. Như đã nói đủ gần là tốt trong hầu hết các trường hợp (có thể nói là tất cả), và ngay cả khi xử lý một cái gì đó như đồng hồ khi 1 giây cần 1 giây, bạn vẫn phải chịu những khiếm khuyết bộ phận được thừa hưởng.

Những gì tôi sẽ đề nghị không phải lúc nào cũng có thể. Trong một số trường hợp, điều đó là có thể, nhưng với nhiều rắc rối và nỗ lực hơn trường hợp này. Là nó xứng đáng phụ thuộc vào từng trường hợp. Mục tiêu của tôi chủ yếu là hiển thị một sự thay thế cho các tài liệu tham khảo trong tương lai tốt hơn trong các trường hợp hơi khác. Điều này được viết với người dùng Arduino mới làm quen với việc không có nhiều kinh nghiệm về điện tử.

Đối với những người cao cấp hơn, điều này có lẽ sẽ trông quá dài dòng và chết lặng. Nhưng tôi tin rằng, những người đó có lẽ đã biết và không cần câu trả lời này. Điều này cũng có thể áp dụng cho mọi vi điều khiển và mọi nhà sản xuất và kiến ​​trúc. Nhưng đối với các bộ vi điều khiển khác, bạn sẽ cần tham khảo bảng dữ liệu chính xác để tìm ra các thanh ghi thích hợp và tên và giá trị đặt trước.

Trong trường hợp của bạn, bạn cần một tần số cụ thể và điều tuyệt vời về nó, đó là chính xác 56 kHz thực sự có thể đạt được rất dễ dàng (không tính các khiếm khuyết thực tế của các bộ phận). Vì vậy, đây cũng là một ví dụ hoàn hảo.

Việc tạo tín hiệu phụ thuộc vào bộ định thời và nguồn xung nhịp của vi điều khiển, như được giải thích tốt bởi jfpoilpret. Câu trả lời của anh ấy liên quan đến vấn đề chỉ có một quan điểm và đó là vấn đề với bộ tính giờ. Nhưng bạn cũng có thể sử dụng nguồn đồng hồ, hoặc thậm chí tốt hơn với cả hai cho kết quả tuyệt vời và tuyệt vời. Bằng cách thay đổi các tham số của môi trường, trong trường hợp này là hack hệ thống và thay thế nguồn đồng hồ, chúng ta có thể xử lý một vấn đề cụ thể với nhiều, đơn giản và dễ dàng hơn nhiều.

Trước tiên, để nhắc nhở, vì chuyển đổi trạng thái pin, bạn cần thực thi ISR ​​nhiều hơn hai lần so với tần số tín hiệu. Đây là 112.000 lần mỗi giây. 56.000 và 16.000.000 không cộng dồn rất độc đáo như đã chỉ ra. Chúng ta cần thay đổi tần số tín hiệu hoặc tần số xúc giác. Bây giờ chúng ta hãy giải quyết với tần số tín hiệu bất biến và tìm tốc độ xung nhịp tốt hơn.

Sẽ đơn giản nhất khi chọn một chiếc đồng hồ có độ lớn lớn hơn 56 kHz (hoặc 112 kHz, nhưng thực tế là như vậy), vì bạn chỉ thêm số không và loại toán này là đơn giản nhất đối với hầu hết mọi người. Thật không may, tất cả mọi thứ trên thế giới này là một loại thỏa hiệp với một cái gì đó. Không phải mọi giá trị sẽ làm việc.

Ví dụ đầu tiên là với tốc độ máy phát chiến thuật quá thấp.

Nếu bạn chọn đồng hồ 56.000 Hz, bạn sẽ không thể làm bất cứ điều gì vì bạn sẽ cần gọi ISR ​​mỗi chu kỳ và không thể làm gì khác. Nó hoàn toàn vô dụng. Nếu bạn chọn tốc độ nhanh hơn 10 lần (560 kHz), bạn sẽ có 9 (10 chu kỳ để bộ định thời đạt giá trị tối đa - một chu kỳ để gọi hàm ISR) chu trình vi điều khiển để thực hiện công việc của bạn và điều này hoàn toàn có thể là không đủ. Bạn chỉ đơn giản là thường cần sức mạnh tính toán nhiều hơn.

Nếu bạn chọn một giá trị quá lớn, mặt khác, vì 56 MHz, vi điều khiển đơn giản là không thể làm việc với nó. Đó là cách quá nhanh. Vì vậy, chỉ cần chọn giá trị lớn nhất trong cửa hàng cũng sẽ không cắt giảm.

Arduino Uno R3 nguyên bản có xung nhịp chứng khoán ở mức 16 MHz, do đó, mọi thứ chậm hơn được đảm bảo để hoạt động. Giá trị tiếp theo là một thứ tự cường độ lớn hơn 56 và thấp hơn 16 MHz là 5,6 MHz. Điều này sẽ dẫn đến việc có thể gọi ISR ​​sau mỗi 50 chu kỳ và sẽ tạo ra tần số hẹn giờ 112.000 Hz hoàn hảo. Và tín hiệu của bạn sẽ chính xác là 56 kHz. Bạn sẽ có 49 chu kỳ MCU để thực hiện chương trình của mình giữa các cuộc gọi ISR, nhưng nó vẫn chỉ bằng khoảng 1/3 tốc độ của đồng hồ gốc. Người ta có thể sử dụng 112 làm cơ sở và sử dụng đồng hồ 11,2 MHz và điều này sẽ cung cấp khoảng 2/3 bộ cộng hưởng 16 MHz. Hàm ISR sẽ được gọi sau mỗi 100 chu kỳ và vẫn tạo ra tín hiệu 56 kHz hoàn hảo.

Tuy nhiên, hai vấn đề chính tồn tại với các giá trị này.

  • Vấn đề đầu tiên phụ thuộc rất nhiều vào nhu cầu của bạn: Bạn hy sinh khoảng 1/3 (với 11,2 MHz) công suất tính toán tối đa của bạn để có được tần số tín hiệu chính xác sử dụng giá trị thanh ghi dễ tìm (OCR iirc ). Bạn có thể ổn với nó hoặc bạn có thể không.

  • Vấn đề thứ hai là một showstopper khó : Rất dễ tìm thấy các giá trị, nhưng rất thường chúng không tồn tại như một nguồn đồng hồ được sản xuất. Đây là trang web cộng hưởng của Farnell chỉ đơn giản là thiếu cả 5,6 MHz và 11,2 MHz.

Để phá vỡ điều này, chúng ta có thể xem xét các giá trị cộng hưởng có sẵn và tìm ra thứ khác có thể được sử dụng để tạo ra các giá trị mong muốn chính xác. Nếu chúng ta chia 56 cho 4, chúng ta sẽ có 14 và may mắn là có bộ cộng hưởng 14 MHz. Điều này cung cấp cho chúng tôi tốc độ cao hơn và nhiều sức mạnh hơn và với giá trị đăng ký dễ dàng như nhau. Để gọi ISR ​​112.000 lần mỗi giây, chúng ta cần đặt giá trị thập phân 124 hoặc thập lục phân 0x7C vào thanh ghi OCR, do đó, với việc đếm 124 chu kỳ + 1 để gọi ISR, chúng ta có được giá trị hoàn hảo mong muốn.

Lưu ý

  1. ISR - thói quen dịch vụ ngắt (đây là mã chỉ được thực thi trên các ngắt được tạo)
  2. Chương trình của bạn có thể lớn đến mức nào tùy thuộc vào kích thước bộ nhớ! Nó không liên quan gì đến tốc độ đồng hồ và không liên quan gì đến tần suất bạn gọi ISR.
  3. Khi vi điều khiển bắt đầu với lệnh chương trình, bộ đếm được tăng lên. Nếu một ngắt được tạo, ISR được gọi và giá trị này được lưu trữ trong một thanh ghi đặc biệt. Khi mã ISR hoàn thành, giá trị của bộ đếm chương trình được khôi phục từ thanh ghi đặc biệt này và chương trình tiếp tục từ nơi bị gián đoạn như thể nó chưa từng xảy ra.

    Tôi sẽ đưa ra một ví dụ cực kỳ ngu ngốc. Nếu bạn là người theo chủ nghĩa thuần túy, tôi cảnh báo bạn: chảy máu mũi và mắt có thể xảy ra.

    Hãy tưởng tượng bạn phải đi bộ từ nơi nào đó đến nơi nào đó. Các hướng dẫn lộ trình từng bước là chương trình chính của bạn và các lệnh của nó. Bạn đi bộ hay chạy nhanh như thế nào, tùy thuộc vào "tốc độ đồng hồ" của bạn, nhưng không phụ thuộc vào hướng dẫn lộ trình (30 bước tiến, 1 rẽ 90 độ trái, 10 bước tiến, 45 độ, phải, v.v.) Chúng luôn giống nhau . Bây giờ hãy tưởng tượng một đứa trẻ hoặc một chính trị gia tham nhũng địa phương tham lam cởi giày của bạn bây giờ và sau đó. Đây là sự kiện tạo ra một ngắt. Sau đó, bạn dừng lại sau bước cuối cùng của bạn, quỳ xuống và buộc giày của bạn một lần nữa. Đây là chương trình ISR của bạn.

    Sau đó, bạn tiếp tục từ nơi bạn đã dừng lại; bạn không bắt đầu lại từ đầu Khi bạn đi bộ mà không có sự quan tâm trên thế giới và với tất cả thời gian, bạn không quan tâm ngay cả khi bạn phải buộc giày của mình mỗi bước khác. Tuy nhiên, nếu bạn làm điều đó với thời gian hạn chế, như chạy trong 100 mét trên Thế vận hội (hoặc chạy từ một kẻ săn mồi ăn thịt đói), dừng và buộc giày của bạn có thể gây ra hậu quả nghiêm trọng. Điều tương tự là với vi điều khiển. Ngay cả khi bạn chỉ thực thi một dòng mã, chương trình của bạn sẽ tiếp tục, mặc dù chậm. Nếu bạn không quan tâm đến tốc độ, nó sẽ không thành vấn đề. Nếu bạn phải thực hiện một số thời gian liên quan, như sử dụng các hành động phụ thuộc thời gian khác, nhiễu có thể rất không mong muốn và có vấn đề.

  4. Càng đơn giản càng đẹp! Đồng hồ nhanh hơn không phải lúc nào cũng tốt hơn. Các thiết bị có đồng hồ chậm hơn sử dụng ít năng lượng hơn đáng kể. Đây có thể là một điểm quan trọng trong một thiết bị hoạt động bằng pin.

  5. Các chu trình cần thiết được lấy từ công thức này:
    (tốc độ xung nhịp / (giá trị bộ đếm trước * tần số gọi ISR ​​cần thiết)) - 1


TLDR: Giải mã bộ tạo dao động 16 MHz bằng gốm và thay thế nó bằng bộ dao động khác cho phép chính xác 56 kHz bằng cách chia số nguyên (ví dụ 14 MHz và chia cho 250).
Peter Mortensen

0

Bạn có thể bật và tắt sóng mang đơn giản bằng cách chuyển đổi chế độ chân của sóng mang giữa đầu ra và đầu vào. Tôi đã sử dụng điều này để điều khiển một máy bơm nhiệt thông qua cổng hồng ngoại (điều khiển từ xa) 37KHz.


0

Không cần sử dụng ISR để tạo sóng mang. Chỉ cần thiết lập bộ hẹn giờ để tạo ra đầu ra PWM 50% ở tần số sóng mang yêu cầu. ISR sau đó chỉ chịu trách nhiệm điều chỉnh sóng mang - thường ở các khoảng 0,5 hoặc 1ms - một tỷ lệ thoải mái hơn nhiều. Theo kinh nghiệm của tôi, lỗi 5% trong tần số sóng mang được chấp nhận bởi hầu hết các máy thu IR. Tôi đã sử dụng Freetronics EtherMega 2560 (có nhiều bộ hẹn giờ) nhưng tôi chắc chắn rằng các CPU khác cũng sẽ làm như vậy.


Làm thế nào chính xác là điều chế của tàu sân bay được thực hiện sau đó? Thay đổi chế độ cho pin chụp đầu ra hẹn giờ giữa đầu vào (tắt sóng mang) và đầu ra (bật sóng mang)?
Peter Mortensen
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.