Tạo tín hiệu sin bằng cách sử dụng PWM


16

Chúng tôi không thể tạo tín hiệu sin đúng cách bằng vi điều khiển MC68HC908GP32 . Mô tả về PWM bắt đầu ở trang 349. Tần số xung nhịp là 2,4 MHz, trong khi chúng tôi đã sử dụng PWM 7 kHz bằng cách sử dụng bộ đếm gộp trước và đặt modulo hẹn giờ thành 350 như sau:

T1SC = 0x60;    // Prescaler: Div entre 64
//Counter modulo = 0x015E = 350
T1MODH = 0x01;   // High
T1MODL = 0x5E;   // Low

Đầu ra PWM được lọc bởi bộ lọc RLC sau, và sau đó DC được loại bỏ bằng cách sử dụng nắp 1uF loạt. Tần số cắt là cách dưới 7kHz của PWM.

nhập mô tả hình ảnh ở đây

Đầu tiên, chúng tôi đã thử sử dụng LUT, mẫu nào được tạo bằng trang này (100 mẫu, biên độ = 250). Điều này bao gồm một giai đoạn duy nhất.

 int seno[100]={ 125, 133, 141, 148, 156, 164, 171, 178, 185, 192, 198, 205, 211, 216, 221, 226, 231, 235, 238, 241, 244, 246, 248, 249, 250, 250, 250, 249, 248, 246, 244, 241, 238, 235, 231, 226, 221, 216, 211, 205, 198, 192, 185, 178, 171, 164, 156, 148, 141, 133, 125, 117, 109, 102, 94, 86, 79, 72, 65, 58, 52, 45, 39, 34, 29, 24, 19, 15, 12, 9, 6, 4, 2, 1, 0, 0, 0, 1, 2, 4, 6, 9, 12, 15, 19, 24, 29, 34, 39, 45, 52, 58, 65, 72, 79, 86, 94, 102, 109, 117}; 

Độ rộng của xung sau được tính sau mỗi chu kỳ PWM:

interrupt 4 void rsi_t1ch0 (void)
{
    //-- disable interruption flag
    T1SC0&=(~0x80);
    //-- pwm to '0' 
    PTB&=0xFD;

    //some sensor measures are done here.... 100 out of the 350 cycles are left for this                
}
/************************************************************/
/* TIM1 overflow rutine                                     */
/************************************************************/
interrupt 6 void rsi_ov1 (void)
{

    T1SC&=(~0x80);
    //-- set PWM to 1
    PTB|=0x02;
    T1CH0H = ((seno[fase])>>8);   // high bits
    T1CH0L = (seno[fase])&0xFF;   // low bits
    fase+=1;
    if (fase >= 99)
      fase=0;
}

void main(void)
{
float temp;
    int i;

    CONFIG1|=0x01;  
    DDRB=0xFF;      //-- Port B is set as output
    PTB=0x00;       
    //Timer setup
    T1SC = 0x60;    // Prescaler: Div by 64  
    T1MODH = 0x01;   //Counter modulo
    T1MODL = 0x5E;  
    T1SC0 = 0x50;  //Comparator setup
    //-- Initial width
    T1CH0H = 0x00;
    T1CH0L = 0x53;

    EnableInterrupts;
    T1SC&=~(0x20); //Run timer forever
    for(;;);   
}

Khi cắm nó vào phạm vi, chúng ta nhận được tín hiệu sau. Chúng tôi không thể tránh được đỉnh kỳ lạ đó gần mức tối thiểu.

nhập mô tả hình ảnh ở đây

Khi phóng to xung quanh đỉnh đó, chúng ta có thể thấy đầu ra của PWM (lên) trên thực tế không chính xác.

nhập mô tả hình ảnh ở đây

Vì vậy, sau khi loay hoay một lúc và không thể thoát khỏi nó, chúng tôi đã thử tính toán tín hiệu sin trong MCU, thay vì mã hóa cứng giá trị cho từng mẫu. Chúng tôi đã thêm đoạn mã sau vào chức năng chính, ngay trước khi tất cả các thiết lập bộ đếm:

 for(i=0;i<99;i++) {
     temp=100*(sin(2*3.14159*i/100)+1);
     seno[i]=(int)temp;
 }

Nhưng kết quả thậm chí không giống như một hình sin:

nhập mô tả hình ảnh ở đây

Sau nhiều giờ vật lộn với nó, chúng tôi đã không thể tìm ra sai lầm của mình. Chúng tôi sẽ đánh giá cao một lời khuyên.


Bạn có thể đăng toàn bộ danh sách các giá trị PWM không?
pjc50

@ pjc50 Đây là: pastebin.com/sNyA0Hki . Cảm ơn rât nhiều.
Serge

Hãy thử thay thế tất cả các giá trị "0" ở giữa bằng "1"; Tôi nghi ngờ rằng 0 cung cấp cho bạn tín hiệu cao rộng hơn là tín hiệu thấp mà bạn muốn.
pjc50

@Serge - Vui lòng nội tuyến dữ liệu. Dán có thể biến mất và sẽ là xấu khi mất một phần của câu hỏi. Nhưng vui lòng định dạng nó để nó không sử dụng nhiều dung lượng. Cảm ơn.
Trygve Laugstøl

Đây rõ ràng không phải là bộ lọc - chúc may mắn - có vẻ như bảng của bạn đang bị hỏng hoặc bạn mất con trỏ vào nó.
Andy aka

Câu trả lời:


16

Ở dưới cùng của trang 350 của biểu dữ liệu vi điều khiển, nó đề cập rằng việc ghi một giá trị nhỏ vào thanh ghi giá trị bộ định thời trong khi ngắt tràn có thể khiến ngắt tiếp theo chỉ được kích hoạt trong lần lặp pwm tiếp theo, vì bộ định thời tiếp tục đếm trong khi thói quen ngắt đang được thực hiện.

Việc ghi không đồng bộ vào các thanh ghi kênh TIM để thay đổi giá trị độ rộng xung có thể gây ra hoạt động không chính xác trong tối đa hai chu kỳ PWM. Ví dụ, viết một giá trị mới trước khi bộ đếm đạt đến giá trị cũ nhưng sau khi bộ đếm đạt đến giá trị mới sẽ ngăn chặn mọi so sánh trong khoảng thời gian PWM đó. Ngoài ra, sử dụng thói quen ngắt tràn TIM để ghi giá trị độ rộng xung mới, nhỏ hơn có thể khiến cho phép so sánh bị bỏ qua. TIM có thể vượt qua giá trị mới trước khi nó được viết.

Điều này được xác nhận bởi thực tế là giá trị pwm được giữ ở mức cao trong toàn bộ thời gian đồng hồ pwm + trông giống như thời lượng hẹn giờ (dựa trên độ dài xung quanh). Giá trị được ghi vào thanh ghi thời gian hẹn giờ có thể gần bằng 0 tại thời điểm xảy ra lỗi, do đó, rất có khả năng bộ đếm đã vượt qua giá trị nhỏ hơn trong khi ngắt và sẽ chỉ kích hoạt trong chu kỳ sau.

Điều này có thể được khắc phục bằng cách tăng mức tối thiểu hình sin lên mức cao hơn thời gian cần thiết để thực thi ISR ​​hoặc thay đổi cơ chế theo đó mức mới được đặt. Đầu trang 351 chi tiết làm thế nào điều này có thể được thực hiện.


1
Tôi không biết làm thế nào tôi có thể bỏ qua điều đó khi đọc biểu dữ liệu. Cảm ơn bạn!
Serge
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.