Lập trình ATtiny13 như một bộ tạo dao động âm thanh với tần số và độ rộng xung thay đổi


8

Tôi muốn tạo ra một bộ dao động sóng vuông đơn giản tương tự như những gì người ta sẽ làm với một chiếc 555, nhưng tôi muốn sử dụng hỗ trợ PWM dựa trên ngắt để kiểm soát độ rộng và tần số xung.

Tôi đã nghiên cứu bảng dữ liệu, API AVR và bất kỳ ví dụ nào tôi có thể tìm thấy, nhưng tôi hoàn toàn không thể kết hợp tất cả lại với nhau.

Có thể tạo ra một bộ tạo dao động như vậy với chức năng AVR PWM tích hợp và, nếu vậy, làm thế nào? Người bạn của tôi đã làm một cái gì đó tương tự với PIC 8 pin.

Lý do của tôi là tôi sẽ có được âm thanh thú vị bằng cách thay đổi độ rộng xung và do đó dạng sóng ở một tần số nhất định. Tương tự như cách Atari Punk Console hoạt động nhưng hy vọng theo cách ổn định hơn, tức là thay đổi độ rộng xung, nhưng để lại tần số không đổi hoặc ngược lại.


2
bạn có thể vui lòng làm rõ câu hỏi của bạn là gì?
Jason S

Tôi không chắc chúng sẽ thú vị như thế nào nhưng nó rất dễ để thử và bạn có thể phán xét. Khi xung thu hẹp biên độ của sóng hài tăng. Tiếp tục thu hẹp xung và bạn có được tiếng ồn trắng. Tôi nghĩ bạn sẽ có nhiều lựa chọn thú vị hơn khi thực hiện bộ dao động điều khiển số. Bạn có thể thay đổi các dạng sóng được tải vào wavetable.
jluciani

Câu trả lời:


5

Chúng sẽ giúp bạn đi khá xa và phần còn lại bạn có thể làm với biểu dữ liệu. Bắt đầu xây dựng từng mảnh, từ mờ đến dạng sóng đến dạng sóng thay đổi theo thời gian sang tông màu. Một số nguồn có thể giúp lọc và điều khiển đầu ra âm thanh (LPF hoạt động có thể thực hiện cả hai cách gọn gàng).

Tôi đề nghị quay lại với những câu hỏi cụ thể hơn.


4

Thời gian của PWM được xác định bởi tốc độ tràn bộ đếm thời gian của bạn. Có rất nhiều cài đặt trên phần Chế độ hoạt động để suy nghĩ. Nếu tất cả những gì bạn muốn làm là tạo ra một sóng vuông có chu kỳ không đổi, với chu kỳ nhiệm vụ thay đổi, tôi nghĩ bạn sẽ muốn sử dụng chế độ CTC (Xóa bộ đếm thời gian trên So sánh so sánh). Ý tưởng cơ bản là đặt OCR0A thành số lần bấm giờ cho đến khi bạn muốn ghim chuyển đổi tiếp theo và sử dụng ngắt So sánh đối sánh để thay đổi giá trị đó cho lần tiếp theo. Vì vậy, trong avr-gcc, nó sẽ trông giống như:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

// global variables defining number of ticks on and off
uint8_t on_time_ticks, off_time_ticks, csxx_bits=0; 


void setup_timer(double p_ms, double duty){
  TCCR0A = _BV(COM0A0) // toggle OC0A on Compare Match
  TCCR0B = _BV(WGM02); // set CTC mode WGM0[2,1,0] = 0b100

  // ... do some stuff based on your CPU frequency
  // to define the csxx_bits of TCCR0B when the timer is running
  // and consequently, to set on_time_ticks and off_time_ticks
  OCR0A = on_time_ticks;
  TCCR0B |= your_settings_here;
}


void start_timer(){
  //start the timer running at the desired rate
  TCCR0B |= csxx_bits; 
}


int main(int argc, char **argv){
  double period_ms, duty_cycle;
  setup_timer(period_ms, duty cycle);
  start_timer();  
  for(;;){
    //spin or sleep or whatever
  }
}


ISR(TIM0_COMPA_vect){
  if(OCR0A == on_time_ticks){
    OCR0A = off_time_ticks;
  }
  else{
    OCR0A = on_time_ticks;
  }
}

Cảnh báo, đây là mã chưa được kiểm tra nhưng tôi nghĩ ý tưởng này là đúng. Đây không phải là cách duy nhất để làm điều đó.

Nhân tiện, có một điều bạn nên biết về ATTiny13. Bộ tạo dao động RC nội bộ chỉ được đảm bảo chính xác trong vòng 10% so với sàn nhà máy. Có một quá trình sử dụng hiệu chuẩn bạn có thể đi qua (được mô tả bởi một Atmel appnote ) sẽ giúp bạn có được 2% độ chính xác cho ATtiny13. Nếu bạn muốn làm tốt hơn thế, có lẽ bạn sẽ cần sử dụng một con chip chứa một tinh thể bên ngoài ...


1
Câu trả lời của bạn đã giúp làm rõ điều gì đó tương tự mà tôi đang gặp vấn đề - cảm ơn. Chỉ là một điểm (đối với bất kỳ ai đọc lâu sau chuỗi gốc): Lựa chọn 0b100 của bạn cho WGM0 [2,1,0] sẽ không đặt chế độ CTC. (Trên thực tế, nó sẽ đặt chế độ dành riêng cho Atmel.) Bảng dữ liệu ATtiny13 cho biết chế độ CTC cần giá trị 2; thay vào đó, bạn đã vô tình đưa cho nó bit_number 2 (tức là giá trị 4). Do đó, không chỉ cần thay đổi (nghĩa là xóa) WGM02 trong TCCR0B mà còn phải đặt các bit WGM01 và WGM00 thành 1 và 0 tương ứng. Các bit đó nằm trong TCCR0A, vì vậy không đủ để đặt TCCR

3

Không phải là một câu trả lời trực tiếp cho câu hỏi của bạn nhưng đây có thể là apropos và cung cấp một số gợi ý -

Tôi vừa tạo một bộ tạo dao động điều khiển số (NCO) bằng cách sử dụng ATmega uC và một bộ xử lý. Một mảng các số nguyên được sử dụng để lưu trữ một chu kỳ của dạng sóng (có thể bỏ qua). Bộ tích lũy pha (long int) được sử dụng để xác định địa chỉ của dữ liệu đầu ra trong phần có thể quét được. Mỗi bộ định thời ngắt làm tăng bộ tích lũy pha theo một giá trị cố định. Độ tăng pha xác định tần số.

Trong ứng dụng của mình, tôi đã sử dụng một wavetable 64 byte có chứa một chu kỳ của hình sin. Thật dễ dàng để mở rộng wavetable và thêm độ phân giải cho các mẫu. Ghi chú ứng dụng của tôi có tại http://wiblocks.com/docs/app-notes/nb1a-nco.html


1

Về cơ bản, một PWM không thay đổi tần số. PWM chủ yếu được sử dụng để kiểm soát "cường độ" của tín hiệu.

Để tạo ra một ngắt cho các tần số khác nhau, tôi khuyên bạn nên sử dụng bộ hẹn giờ ở chế độ CTC.

Nó sẽ chạy đến giá trị so sánh của bạn, chuyển một ngắt, xóa và tự khởi động lại - cho đến khi nó chạy lại giá trị so sánh của bạn ...

Sau mỗi lần ngắt, bạn có thể chuyển đổi một hoặc nhiều cổng và thời gian còn lại (bộ hẹn giờ vẫn tự động chạy), bạn có thể xem bất kỳ đầu vào nào của mình ...

Bạn vẫn có thể "điều chỉnh" sóng vuông của mình bằng một PWM để điều khiển "mức tăng". Nhưng một trong số chúng phải được thực hiện "bằng tay" vì ATtiny13 chỉ có một bộ đếm thời gian phần cứng ...


1
hầu hết các thiết bị ngoại vi PWM phần cứng cho phép bạn chọn tần số; nếu bạn giữ chu kỳ nhiệm vụ không đổi thì PWM vẫn có thể cung cấp cho bạn điều khiển tần số biến
Jason S

1
Thay đổi độ rộng xung không thay đổi tần số cơ bản nhưng nó thay đổi sóng hài.
jluciani
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.