PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   dsPIC - Bộ điều khiển tín hiệu số 16-bit (http://www.picvietnam.com/forum/forumdisplay.php?f=29)
-   -   dsPIC Tutorial 5-Module ADC và MCPWM (http://www.picvietnam.com/forum/showthread.php?t=650)

namqn 19-03-2009 02:57 AM

Trích:

Nguyên văn bởi conglong (Post 23701)
Ở ví dụ 5.1 thầy có viết trong hàm : void Init_MCPWM(void) là

" PWMCON2 = 0x0F00; //Postscale = 1:16 "

em đọc trong farmily reference ... về PWMCON2 register mà không hiểu ý nghĩa của postscale ? và trong TUTO này thầy thiết lập Postscale ảnh hưởng như thế nào ?

Khi dùng pin PWML mà không dùng PWMH thi Duty cycle đó chính là khoảng thời gian LOW hay là HIGHT trong 1 cycle hả thầy. Tại em không có dao động kí nên trả lờ câu hỏi này được>
Em cảm ơn.
Trân trong !.

Postscale ở đây là bộ chia sau để thay đổi tần suất tạo ra PWM Special Event Trigger: nếu postscale là 1:1, mỗi chu kỳ PWM sẽ tạo ra 1 PWM Special Event Trigger, còn nếu postscale là 1:16 thì sau 16 chu kỳ PWM mới tạo ra 1 PWM Special Event Trigger. PWM Special Event Trigger là sự kiện cho phép đồng bộ việc chuyển đổi A/D với tín hiệu PWM. Bạn đọc thêm mục 15.12 của tài liệu "dsPIC30F Family Reference Manual" (mã tài liệu là DS70046).

Trong ví dụ 5-1 của tôi, việc thiết lập postscale khiến cho 1 PWM Special Event Trigger được tạo ra sau mỗi 16 chu kỳ PWM, để kích hoạt việc chuyển đổi A/D.

Về câu hỏi liên quan đến duty cycle, bạn xem hình 14-4 trong datasheet của dsPIC30F2010.

Thân,

conglong 20-03-2009 06:48 PM

Trích:

Nguyên văn bởi namqn (Post 23704)
Về câu hỏi liên quan đến duty cycle, bạn xem hình 14-4 trong datasheet của dsPIC30F2010.

Thân,

Em đã đọc datasheet dsPIC30f2010 phần PWM rồi , em hiểu là dutycycle là khoảng phần trăm thời gian HIGHT trong một chu kỳ phần đối với chân PWMxH , còn đối với PWMxL thì dutycycle lại là khoảng phần trăm thời gian LOW (với giả sử deadtime = 0), nhưng khi vào làm thực tế , cụ thể là ví dụ 5.1 của thấy :
Em dùng biến trở chỉnh điện áp tại chân RB0(AN0) là 1V thì theo lí thuyết , khi đó giá trị mình thu được tại thanh ghi ADCBUF0 là: 1x(2^10 - 1) / 5 = 204.6 hay là 11001101B sau lệnh dịch bit qua phải và gắn vào giá trị này vào PDC1 thì PDC1 = 102, mà duty_cycle = 2 * PDC1 / PTPER, mà ở đây PTPER = Fcy/Fpwm - 1 , với Fcy= 10Mhz ( do em dung thạch anh ngoài 10Mhz với PLL_4), Fpwm = 40Khz => PTPER = 249
Vậy duty_cycle = 2 * 102 / 249 = 0.8193 = 81.93 %, do đó khi dùng VOM để đo trên chân PWML ( RE0 ) thì điện áp DC phải là : (1 - 0.8193 ) * 5V = 0.9035 V.
Mà em đo thực tế lại là : 3.1 V !!!!
Em hiểu như vậy có đúng không Thầy , hay lỗi do đâu thầy ?
Em cảm ơn .
Trân trọng !.

namqn 20-03-2009 08:06 PM

Trích:

Nguyên văn bởi conglong (Post 23783)
Em đã đọc datasheet dsPIC30f2010 phần PWM rồi , em hiểu là dutycycle là khoảng phần trăm thời gian HIGHT trong một chu kỳ phần đối với chân PWMxH , còn đối với PWMxL thì dutycycle lại là khoảng phần trăm thời gian LOW (với giả sử deadtime = 0), nhưng khi vào làm thực tế , cụ thể là ví dụ 5.1 của thấy :
Em dùng biến trở chỉnh điện áp tại chân RB0(AN0) là 1V thì theo lí thuyết , khi đó giá trị mình thu được tại thanh ghi ADCBUF0 là: 1x(2^10 - 1) / 5 = 204.6 hay là 11001101B sau lệnh dịch bit qua phải và gắn vào giá trị này vào PDC1 thì PDC1 = 102, mà duty_cycle = 2 * PDC1 / PTPER, mà ở đây PTPER = Fcy/Fpwm - 1 , với Fcy= 10Mhz ( do em dung thạch anh ngoài 10Mhz với PLL_4), Fpwm = 40Khz => PTPER = 249
Vậy duty_cycle = 2 * 102 / 249 = 0.8193 = 81.93 %, do đó khi dùng VOM để đo trên chân PWML ( RE0 ) thì điện áp DC phải là : (1 - 0.8193 ) * 5V = 0.9035 V.
Mà em đo thực tế lại là : 3.1 V !!!!
Em hiểu như vậy có đúng không Thầy , hay lỗi do đâu thầy ?
Em cảm ơn .
Trân trọng !.

Bạn hiểu nhầm về công thức tính duty cycle. Xét ví dụ 5-1 trong tutorial của tôi, tôi đã chú thích giá trị duty cycle ứng với giá trị PTPER = 199 (Fcy/Fpwm - 1 = 8000000/40000 - 1). Với chu kỳ đếm 200, giá trị 0x64 = 100 mà tôi đặt vào các thanh ghi PDCx lại chỉ cho duty cycle = 25%, không rõ bạn có chú ý điểm này hay không.

Với PWM timer chạy ở chế độ free-running (như trong ví dụ của tôi đã thiết lập), công thức tính duty cycle như sau:

duty_cycle = PDCx/((PTPER + 1)*2)

Do đó, với các thông số mà bạn đã thiết lập, bạn sẽ có duty cycle của chân PWM1H là 102/((249 + 1)*2) = 20.4 %, và duty cycle của chân PWM1L sẽ là 100 - 20.4 = 79.6 %, tương ứng với khoảng 4 V, nếu hoàn toàn không có dead time. Có lẽ kết quả chuyển đổi A/D là khác với giá trị 204 hay 205 đang dùng để tính toán ở đây.

Thân,

conglong 21-03-2009 05:18 PM

Trong dsPic30 farmily reference ... ở phần PWM có nói cách thiết lập chế độ hoạt động của PWM thông qua các bits PTMOD<1:0> ở thanh ghi PTCON là:

"
PTMOD<1:0>: PWM Time Base Mode Select bits

11 = PWM time base operates in a continuous up/down mode with interrupts for double PWM updates

10 = PWM time base operates in a continuous up/down counting mode

01 = PWM time base operates in single event mode

00 = PWM time base operates in a free running mode "

Thầy Nam hoặc anh em nào trong diễn đàn hiểu rõ về các MOD hoạt động này ảnh hưởng như thế nào tơi PWM như công thức tính duty_cycle .... chỉ cho mình với ?
Cảm ơn nhiều !
Trân trọng !.

conglong 21-03-2009 06:03 PM

Trích:

Nguyên văn bởi namqn (Post 23704)
Về câu hỏi liên quan đến duty cycle, bạn xem hình 14-4 trong datasheet của dsPIC30F2010.

Thân,

Thầy Nam ơi mọi hôm em nói sai về Duty_cycle rồi thầy ơi đúng ra phải là :
Duty_cycle là khoảng phần trăm thời gian HIGHT trong một chu kỳ đối với chân PWMxH , còn đối với PWMxL thì dutycycle lại là khoảng phần trăm thời gian LOW (với giả sử deadtime = 0) KHI TA ĐANG DÙNG pwm Ở MODE complementary , còn PWM ở MODE independence thì duty_cycle cũng là khoảng phần trăm thời gian HIGHT trong một chu kỳ đối với chân PWMxL hay chân PWMxH (tùy vào chân nào được set). Tại em đo thực tế thấy như vậy,
Trân trọng !.

conglong 21-03-2009 11:36 PM

Display Duty_cycle of PWM on PC by using UART and ADC comunication
 
1 Attachment(s)
Đây là project mình làm sau khi đọc 2 TUTO của Thầy Nam (namnq) là UART và PWM - ADC , ở đây mình kết hợp 3 module này lại với nhau để hiện thị thông số của PWM (duty_cycle) lên PC sau khoảng thời gian 1ms , và duty_cycle được điều khiển bởi điện áp tại chân RB0 thông qua biến trở, các bạn tham khảo nha, có gì thì cùng trao đổi, Project này đã chạy thực tế rồi (mình dùng dsPic30f2010 nhưng con này không khác con 30f4012 gì cả).
Trân trọng !.

silvadk2 23-03-2009 01:23 PM

anh Nam ơi, xem hộ em lỗi này là sao ạ :
c:\program files\microchip\mplab c30\bin\pic30-coff-ld.exe Error: A heap is required, but has not been specified
Link step failed.
em đã có đủ những tập tin cần thiết rồi mà nó vẫn báo vậy.

namqn 23-03-2009 03:05 PM

Trích:

Nguyên văn bởi silvadk2 (Post 23898)
anh Nam ơi, xem hộ em lỗi này là sao ạ :
c:\program files\microchip\mplab c30\bin\pic30-coff-ld.exe Error: A heap is required, but has not been specified
Link step failed.
em đã có đủ những tập tin cần thiết rồi mà nó vẫn báo vậy.

Bạn xem post #18 của luồng sau:
http://www.picvietnam.com/forum/showthread.php?p=2663

Thân,

silvadk2 23-03-2009 04:29 PM

Em đang làm việc với con dspic30f4011. Em đang làm 1 bài toán là đo nhiệt độ rồi hiển thị lên lcd. anh có thể nói cho em về phần xử lí số liệu lấy ra từ module ADC để đưa lên LCD để hiển thị nhiệt độ ko anh ? Em dùng lm35 đó.

namqn 24-03-2009 12:37 AM

Trích:

Nguyên văn bởi silvadk2 (Post 23908)
Em đang làm việc với con dspic30f4011. Em đang làm 1 bài toán là đo nhiệt độ rồi hiển thị lên lcd. anh có thể nói cho em về phần xử lí số liệu lấy ra từ module ADC để đưa lên LCD để hiển thị nhiệt độ ko anh ? Em dùng lm35 đó.

Bạn còn dùng dsPIC30F4011 vào việc gì khác không? Nếu chỉ với mục đích trên thì đâu cần dùng đến dsPIC.

Nguyên tắc chung: bạn xác định dải nhiệt độ cần đo, xác định dải điện áp ra tương ứng và xử lý để nó tận dụng dải điện áp analog mà PIC/dsPIC có thể đọc. Từ đó, xác định công thức chuyển đổi từ kết quả A/D và nhiệt độ thực. Việc còn lại chỉ là đưa chuỗi ký tự ra LCD.

Thân,

silvadk2 24-03-2009 01:28 AM

Đây chỉ là 1 phần trong đề tài của em. Dải nhiệt độ của em cần đo là từ 0-100 độ C.Em xem trên datasheet của lm35 thấy khoảng điện áp ra tương ứng la-1000mV cho khoảng nhiệt độ từ 0-100 độ C.Phần hiển thị lên LCD thì em làm rồi, nhờ anh xem phần xử lý số liệu hộ em mới. Thank anh nhiều nhiều

conglong 24-03-2009 11:18 AM

Trích:

Nguyên văn bởi silvadk2 (Post 23937)
nhờ anh xem phần xử lý số liệu hộ em mới. Thank anh nhiều nhiều

số liệu gì bạn, bạn phải nói rõ chứ, LM35 có tầm điện áp như vậy trong khoảng nhiệt độ như bạn đã nêu thì bạn đọc giá trị điện áp thông qua thanh ghi ADCBUF0 rồi chyển thầnh nhiệt độ và hiển thị lên LCD , (dùng hàm sprintf() để chuyển số DECIMAL ra chuỗi ASCII ),
Trân trọng !.

silvadk2 27-03-2009 04:25 PM

Đây là code của em, đo nhiệt độ đưa vào RB8 rồi hiển thị ra LCD, nhưng sao dòng 2 chỉ hiện ra là 0. Em không biết là sai chỗ nào, hic

Code:

#include        <p30f4011.h>
#include        <string.h>
#include        <stdio.h>

_FOSC(CSW_FSCM_OFF & HS);       
_FWDT(WDT_OFF);                               
_FBORPOR(MCLR_EN & PBOR_ON & BORV_27);
_FGS(CODE_PROT_OFF);               

#define                LCD_EN                LATFbits.LATF2                //Tin hieu Enable cho LCD, chan RF2
#define                LCD_RS                LATFbits.LATF6                //Tin hieu Reset cho LCD, chan RF6
#define                LCD_RW                LATFbits.LATF3                //Tin hieu doc ghi cho LCD, chan RF3
#define                RW_TRIS          TRISFbits.TRISF3
#define                RS_TRIS                TRISFbits.TRISF6
#define                E_TRIS                TRISFbits.TRISF2
#define                LCD_PORTB        PORTB
#define                LCD_DATA        LATB                                //Cac tin hieu Data cho LCD
#define                LCD_TRIS        TRISB                                //Tristate cua cac tin hieu Data cho LCD

#define                LCD_CLEAR                0x01                //Xoa man hinh LCD
#define                LCD_HOME                0x02                //Tro ve dau dong
#define                LCD_NORMAL                0x06                //Che do nhap du lieu binh thuong
#define                LCD_NORMAL_S        0x07                //Che do nhap du lieu binh thuong, dich man hinh
#define                LCD_OFF                0x08                //Tat man hinh
#define                LCD_ON                        0x0C                //Bat man hinh
#define                LCD_ON_CRSR        0x0E                //Bat man hinh va con tro
#define                LCD_ON_BLINK        0x0F                //Bat man hinh va con tro (nhap nhay)
#define                LCD_8B2L                0x38                //Che do 2 dong, giao tiep 8 bit du lieu
#define                LCD_HOMEL1                0x80                //Ve dau dong 1
#define                LCD_HOMEL2                0xC0                //Ve dau dong 2

#define                ShortDelay()        {Nop() Nop() Nop() Nop() Nop() Nop() Nop() Nop() Nop()}
//***************************************************************************//
unsigned int ADCValue;


//***************************************************************************//
//
//        Function:                LCDdelayms
//        Description:        LCDdelayms for LCD               
//        Input:                        Number of ms
//        Output:                        None
//
//***************************************************************************//
void LCDdelayms(unsigned int ms)
{
        #define                FCY                                2500*4
        unsigned int i=0;
        while(ms--){while(++i<FCY/7);        i=0;}
}
//*************************** END OF LCDDELAYMS ****************************//

void LCD_CMD(unsigned char CMD)
{

        LCD_RW=0;
        LCD_RS = 0;       
    LCD_DATA = CMD;                                               
        LCD_EN = 1;        ShortDelay();        LCD_EN = 0;
               
}
//************************* End of LCD_CMD *********************************//

void LCD_DAT(unsigned char DATA)
{
        LCD_RW=0;
        LCD_RS = 1;       
    LCD_DATA = DATA;                                               
        LCD_EN = 1;        ShortDelay();        LCD_EN = 0;        //Xung Enable
       
}
//****************************** END OF LCD_DATA ****************************//



void InitLCD(void)
{
        LCD_CMD(LCD_8B2L);                        //Dat che do giao tiep 8-bit, man hinh 2 dong
        LCDdelayms(1);
        LCD_CMD(LCD_8B2L);                        //Dat che do giao tiep 8-bit, man hinh 2 dong
        LCDdelayms(1);
        LCD_CMD(LCD_8B2L);                        //Dat che do giao tiep 8-bit, man hinh 2 dong
        LCDdelayms(1);
        LCD_CMD(LCD_OFF);                        //Tat man hinh
        LCDdelayms(1);
        LCD_CMD(LCD_CLEAR);                        //Xoa man hinh
        LCDdelayms(1);
        LCD_CMD(LCD_ON);                        //Bat man hinh
        LCDdelayms(1);
        LCD_CMD(LCD_NORMAL);                //Che do nhap lieu binh thuong
                                                                //Cursor move Increment, Not to shift the display
        LCDdelayms(1);
        LCD_CMD(LCD_CLEAR);                        //Xoa man hinh
        LCDdelayms(5);
}
//************************** END OF InitLCD *********************************//

void LCD_PutChar(unsigned char character)
{
                LCD_DAT(character);
        LCDdelayms(1);
}
//************************** END of LCD_PutChar *****************************//

void LCD_WriteString(const char *str)
{
//        LCDdelayms(1);
        char ps;
        ps = *str;               
        while(ps>0)               
        {
                str++;                       
                if (ps==0) break;
                LCDdelayms(1);
                LCD_DAT(ps);               
            ps = *str;               
        }       
}
//*********************** END OF LCD_Writestring ****************************//



void LCD_Gotoxy(char x, char y)
{
        char tg;
        LCDdelayms(5);
    switch (y)
        {
                case 1:tg = 0x80+x;
                        break;
                case 2:tg = 0xC0+x;
                        break;
    }
        LCD_CMD(tg);
}
//************************* END OF LCD_Gotoxy *******************************//

void LCD_Clear(void)
{
        LCD_CMD(LCD_CLEAR);
}

void SystemInit(void)
{
        //Init IO
        TRISB = TRISB & 0xFF00;                //RB0..RB7 Output.
        TRISBbits.TRISB8 = 1;
        TRISFbits.TRISF6 = 0;               
        TRISFbits.TRISF2 = 0;               
        TRISFbits.TRISF3 = 0;               
        LATB = 0xFF00;
        LATFbits.LATF6 = 0;               
        LATFbits.LATF2 = 0;
        LATFbits.LATF3 = 0;               
                //InitLCD
        InitLCD();
}
//******************************* End of SystemInit *************************//
void Init_ADC10(void) {
        ADPCFG = 0xFEFF;                //Cac chan khac la digital, chan AN8/RB8 la analog

        ADCON1 = 0x0040;                //Timer 3 cham dut lay mau va kich hoat
                                                        //viec chuyen doi A/D
        ADCON2 = 0;
        ADCHS =  0x0008 ;                                //Kenh 0 doc tin hieu giua AN8 va AVss
        ADCSSL = 0;                                //Khong quet cac ngo vao
        ADCON3 = 0x0103;                //Dung 1 TAD cho lay mau, dung clock he thong,
        TMR3 = 0;                                //Xoa thanh ghi dem cua Timer 3
        PR3 = 0x03E8;                        //Nguong delay cho TMR3 la khoang 1 ms
        T2CON = 0x8010;                        //Prescale = 1:8, bat cho TMR3 chay

        _ADIF = 0;                                //Xoa co ngat ADC
        _ADIE = 1;                                //Cho phep ngat ADC
        _ADON = 1;                                //Bat module ADC
        _ASAM = 1;                                //Khoi dong che do tu dong lay mau
}
void _ISR _ADCInterrupt(void)
{
        ADCValue = ADCBUF0 ;               
        _ADIF = 0;
}
int main(void)
{
        int ADCVoltage;
        char Nhietdo[40];
        ADPCFG = 0xFEFF;
        SystemInit();
        Init_ADC10();
        LCD_Gotoxy(1,1);       
        LCD_WriteString("nhiet do la");       
        LCDdelayms(10);
        LCD_Gotoxy(3,2);
        ADCVoltage=ADCValue/2;
        sprintf(Nhietdo, "%d",ADCVoltage );
        LCD_WriteString(Nhietdo);
       
        while(1);                //Dung chuong trinh.
}
//********************************* End of Main *****************************//


namqn 27-03-2009 05:20 PM

Trước khi dùng kết quả chuyển đổi A/D, bạn đặt một giá trị đã biết vào biến ADCVoltage để xem lệnh gọi hàm LCD_WriteString() thứ hai của bạn chạy có ổn không. Nếu ổn thì bạn xem lại phần đọc tín hiệu analog, vì bạn chưa có kết quả chuyển đổi A/D hợp lý.

Thân,

silvadk2 27-03-2009 05:54 PM

Em đã đặt 1 biến vào ADCVoltage để thử rồi, chạy tốt anh ạ.


Múi giờ GMT. Hiện tại là 10:50 AM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam