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)

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 ạ.

namqn 27-03-2009 06:55 PM

Trích:

Nguyên văn bởi silvadk2 (Post 24082)
Em đã đặt 1 biến vào ADCVoltage để thử rồi, chạy tốt anh ạ.

Như tôi đã nói, bạn xem lại phần đọc tín hiệu analog. Bạn đã thử một trong hai tutorial của tôi chưa? Nếu đã thử thì bạn có thể chỉnh code lại để đọc từ RB8 thay vì RB0 xem có thành công hay không.

Thân,

conglong 27-03-2009 07:04 PM

Sai ở hàm main đó bạn,
 
Trích:

Nguyên văn bởi silvadk2 (Post 24082)
Em đã đặt 1 biến vào ADCVoltage để thử rồi, chạy tốt anh ạ.


Vong lặp while(1) của bạn đặt ở cuối chương trình nên không hiện thị nhiệy độ đúng, bạn sửa lại như sau:

Code:

void main(void)
{
        int ADCVoltage;
        char Nhietdo[40];
        ADPCFG = 0xFEFF;
        SystemInit();
        Init_ADC10();
        LCD_Gotoxy(1,1);       
        LCD_WriteString("nhiet do la");       
        LCDdelayms(10);
  while(1){
        LCD_Gotoxy(3,2);
        ADCVoltage=ADCValue/2;
        sprintf(Nhietdo, "%d",ADCVoltage );
        LCD_WriteString(Nhietdo);
          };
}

Nó sẽ chạy nhưng code này vẫn chưa tối ưu.

namqn 27-03-2009 07:16 PM

Trích:

Nguyên văn bởi conglong (Post 24086)
Vong lặp while(1) của bạn đặt ở cuối chương trình nên không hiện thị nhiệy độ đúng, bạn sửa lại như sau:

Code:

void main(void)
{
        int ADCVoltage;
        char Nhietdo[40];
        ADPCFG = 0xFEFF;
        SystemInit();
        Init_ADC10();
        LCD_Gotoxy(1,1);       
        LCD_WriteString("nhiet do la");       
        LCDdelayms(10);
  while(1){
        LCD_Gotoxy(3,2);
        ADCVoltage=ADCValue/2;
        sprintf(Nhietdo, "%d",ADCVoltage );
        LCD_WriteString(Nhietdo);
          };
}

Nó sẽ chạy nhưng code này vẫn chưa tối ưu.

Bạn silvadk2 chỉ muốn thử hiển thị một giá trị nhiệt độ rồi cho dừng chương trình, do đó không hẳn là sai. Vấn đề là biến ADCValue chưa có được giá trị digital tương ứng với tín hiệu analog ở ngõ vào, theo ý của bạn silvadk2. Nguyên nhân có thể do phần cứng, cũng có thể do cách thiết lập cho module ADC của bạn ấy chưa đúng.

Thân,

silvadk2 27-03-2009 09:24 PM

Ha ha, được rồi bác ạ . Em bị lỗi tý phần cứng, giờ ngon rồi, ha ha! Thank cả nhà rất rất là nhiều.

conglong 27-03-2009 11:26 PM

Thầy Nam cho em hỏi (hơi ngoài luồng) : em đang làm đồ án muôn học là dùng vi điều khiển (dsPIC) để PID tốc độ và vị trí động cơ, em dung động cơ DC secvo 24v/60w, và encoder 504xung/vòng; về thuật toán PID thì em được học rồi nhưng khi vào làm thực tế thì em không biết cách nào để xác định được Kpgh, Ki , Kd, ?!
Trên lí thuyết : xác định Kpgh bằng cách cho ki = 0,Kd = 0, sau đó tăng từ từ Kp cho tới khi có dao động (với chu kì là Tgh) ở ngõ ra, thì đây là Kpgh, và lúc này ta có Kp = 0.6*Kpgh
còn Ki = kp / Ti , Kd = Kp*Td, với Ti = 0.5*Tgh, Td = 0.125*Tgh

Thầy nói rõ cho em hơn chố này được không thầy , ý em là viết phần mềm như thế nào để tăng Kp mà ta có thể tìm được Kgh và Tgh?
Em cảm ơn thầy nhiều lắm !.
Trân trọng !.

namqn 28-03-2009 12:11 AM

Trích:

Nguyên văn bởi conglong (Post 24096)
Thầy Nam cho em hỏi (hơi ngoài luồng) : em đang làm đồ án muôn học là dùng vi điều khiển (dsPIC) để PID tốc độ và vị trí động cơ, em dung động cơ DC secvo 24v/60w, và encoder 504xung/vòng; về thuật toán PID thì em được học rồi nhưng khi vào làm thực tế thì em không biết cách nào để xác định được Kpgh, Ki , Kd, ?!
Trên lí thuyết : xác định Kpgh bằng cách cho ki = 0,Kd = 0, sau đó tăng từ từ Kp cho tới khi có dao động (với chu kì là Tgh) ở ngõ ra, thì đây là Kpgh, và lúc này ta có Kp = 0.6*Kpgh
còn Ki = kp / Ti , Kd = Kp*Td, với Ti = 0.5*Tgh, Td = 0.125*Tgh

Thầy nói rõ cho em hơn chố này được không thầy , ý em là viết phần mềm như thế nào để tăng Kp mà ta có thể tìm được Kgh và Tgh?
Em cảm ơn thầy nhiều lắm !.
Trân trọng !.

Với câu hỏi này, xin bạn hỏi thầy hướng dẫn của bạn.

Thân,

conglong 29-03-2009 12:06 AM

Trích:

Nguyên văn bởi namqn (Post 24099)
Với câu hỏi này, xin bạn hỏi thầy hướng dẫn của bạn.

Thân,

Tại vì Thầy em đang đi công tác , trước khi đi thầy có cho em địa chỉ mail để liên lạc nhưng em mail cho thầy mà chưa thấy Thầy reply nên em suốt ruột quá ! Đành lên diễn đàn để hỏi, đây là Tutorial liên quan tới PWM mà PID lại liên quan tới PWM, nên mong Thầy Nam giúp em với ,hoặc bạn nào trong diễn đàn đã tứng làm PID thì chỉ cho mình cái nhé, hết nửa học kì rồi mà chưa làm được gì cả ! SOS!
Cảm ơn tất cả !.
Trân trọng !.

anhtuan133 12-04-2009 02:22 PM

Trích:

Nguyên văn bởi han_nang_008 (Post 21563)
vấn đề nhiếu ở trên em đã giải quyết dc rồi, do em dùng bộ dao động nội của chíp, em chuyển sang dùng thạch anh thì ko còn hiện tượng đó,
Còn về vấn đê đọc 2 đầu vào analog em em làm được rồi nhưng có 1 vấn đề thế này, em set các thanh ghi giống như bác ở trên, và bit SIMSAM = 1 để chuyển đôi dồng thời, em chon chế độ tự động chuyển đổi, và ngắt sau 1 chu kid lấy mẫu/chuyển đổi, kết quả ở chân AN6 là CH0 thì ở ADCBUF0, con AN1 là CH1 thì ở ADCBUF1, em vặn biến trở thì cũng điều chỉnh tốc độ động cơ đc, em dùng hàm ngắt timer2 mỗi 100ms để xuất ra trị của đầu vào AN6 là giá trị dòng điện ra LCD, thì em quan sát thấy giá trị này cứ dao động liên tục, ngay cả khi em chưa cho động cơ chạy và lúc động cơ chạy ở tốc độ ổn định, em dùng đồng hồ đo thì thấy giá trị ở chân này ko thay đổi, bác xem hộ em nguyên nhân tại sao nó giao động thế

Mình đã bị thế rồi. Do con L298 đểu, khi có tải nó hay bị rồ lên. Sau 1 thời gian nữa thì lúc chạy lúc kô.

anhtuan133 13-04-2009 11:40 AM

Một chú ý khi sử dụng ADC auto input scanning là buffer kết quả kô phải là tương ứng 1-1 với kênh ADC. Ví dụ bạn scan AN3,4,5 ở chế độ auto scanning
ADCON2bits.CSCNA = 1;
ADPCFGbits.PCFG3 = 0;
ADPCFGbits.PCFG4 = 0;
ADPCFGbits.PCFG5 = 0;

ADCSSLbits.CSSL3 = 1;
ADCSSLbits.CSSL4 = 1;
ADCSSLbits.CSSL5 = 1;
thì kết quả ADCBUF0 sẽ là của AN3, ADCBUF1 là của AN4....

khuenguyen 13-04-2009 04:41 PM

Help me!
 
Trích:

Nguyên văn bởi namqn (Post 5244)
Đây là tutorial 5 cho dsPIC, giới thiệu các module ADC và MCPWM. Mã nguồn được viết trong ASM30 (tập tin "Vidu5.zip") và C30 (tập tin "Vidu5C30.zip"). Các tập tin .hex đã được đính kèm.

Một ví dụ đọc ngõ vào ADC và điều chỉnh độ rộng xung một cách tương ứng, ví dụ còn lại đọc ngõ vào analog và gửi các ký tự biểu diễn giá trị đọc được(hexadecimal) ra cổng RS-232.

Chúc các bạn thành công!

Thân,

Mình muốn phát xung PWM có tần số từ 200kHz trở lên thì mình cần cấu hình mạch như thế nào? Code của chương trình thay đổi như thế nào trong tutorial 5 của anh Nam? thanks!

conglong 18-04-2009 02:13 AM

Trích:

Nguyên văn bởi khuenguyen (Post 24729)
Mình muốn phát xung PWM có tần số từ 200kHz trở lên thì mình cần cấu hình mạch như thế nào? Code của chương trình thay đổi như thế nào trong tutorial 5 của anh Nam? thanks!

Vẫn vậy thôi, bạn thay đổi dòng :
#define Fpwm 40000 //Tan so PWM = 40 kHz
Thành :
#define Fpwm 200000 //Tan so PWM = 200 kHz

Trân trọng !.

conglong 03-09-2009 11:01 AM

Giúp em về dead time của dsPIC.
 
Thầy Nam và các anh chị trong diễn đàn cho em hỏi về dead time của dsPIC cái ah.
Ở hình 15-16 trang 360 mục Motor control PWM của tài liêu dsPIC Family Reference , họ có nói là trong lúc dead time thì mức tín hiệu ở hai chân PWMxH và PWMxL đều ở mức thấp (LOW), do mạch công suất của em (đã đặt và thi công mất rồi) nếu cả hai chân này đều ở mức thấp thì sẽ kích cả 2 nửa cầu H cùng lúc và xảy ra trùng dẫn, vậy trong dsPIC có cung cấp cho mình lựa chọn mức tín hiệu của 2 chân PWMxH và PWMxL trong lúc dead time không ah ?. cụ thể là em muốn mức tín hiệu của 2 chân PWM lúc dead time là mức cao (High).

Do sự cố trên nên trước mắt , em đang điều khiển động cơ mà không set dead time (dead time = 0 ) , nó vẫn chạy được nhưng FET rất nóng (do quá trình chuyển trạng thái của 2 mức tín hiệu trên cặp chân PWM không lý tưởng) nên sau đó một lúc (hơn 3 phút) bị chết FET.

Thầy và anh chị cho em hỏi câu nữa là trong thanh ghi FBORPOR ( BOR and POR Configuration Register) mục Device Configuration trang 710 của tài liêu dsPIC Family Reference có 2 bit là HPOL và LPOL, họ có giải thích nhưng em chưa hiểu rõ lắm về mục đích của 2 bit này, liệu có phải 2 bit này dùng để set trạng thái của chân PWM khi dead time không ah ?

Em xin chân thành cảm ơn !.
Trân trọng !.

JohnnyNguyen 03-09-2009 08:52 PM

hỏi về tutorial của thầy Nam.thầy cho em hỏi,cái câu lệnh:
ADCValue = ADCBUF0 >>1 //chi lay 9 bit cao nhat
tại sao chỉ lấy 9 bit cao nhất.em chưa hiểu rõ chỗ này.em mới đang tiếp cận ADC,mong thầy chỉ rõ cho.
cho em hỏi thêm về sơ đồ mạch,cái con MAX232 có tác dụng gì a.

conglong 03-09-2009 11:12 PM

Trích:

Nguyên văn bởi JohnnyNguyen (Post 29275)
hỏi về tutorial của thầy Nam.thầy cho em hỏi,cái câu lệnh:
ADCValue = ADCBUF0 >>1 //chi lay 9 bit cao nhat
tại sao chỉ lấy 9 bit cao nhất.em chưa hiểu rõ chỗ này.em mới đang tiếp cận ADC,mong thầy chỉ rõ cho.
cho em hỏi thêm về sơ đồ mạch,cái con MAX232 có tác dụng gì a.

Để loại bỏ sai số do nhiễu thôi bạn ah.

namqn 04-09-2009 12:00 AM

Trích:

Nguyên văn bởi conglong (Post 29256)
Thầy Nam và các anh chị trong diễn đàn cho em hỏi về dead time của dsPIC cái ah.
Ở hình 15-16 trang 360 mục Motor control PWM của tài liêu dsPIC Family Reference , họ có nói là trong lúc dead time thì mức tín hiệu ở hai chân PWMxH và PWMxL đều ở mức thấp (LOW), do mạch công suất của em (đã đặt và thi công mất rồi) nếu cả hai chân này đều ở mức thấp thì sẽ kích cả 2 nửa cầu H cùng lúc và xảy ra trùng dẫn, vậy trong dsPIC có cung cấp cho mình lựa chọn mức tín hiệu của 2 chân PWMxH và PWMxL trong lúc dead time không ah ?. cụ thể là em muốn mức tín hiệu của 2 chân PWM lúc dead time là mức cao (High).

Do sự cố trên nên trước mắt , em đang điều khiển động cơ mà không set dead time (dead time = 0 ) , nó vẫn chạy được nhưng FET rất nóng (do quá trình chuyển trạng thái của 2 mức tín hiệu trên cặp chân PWM không lý tưởng) nên sau đó một lúc (hơn 3 phút) bị chết FET.

Thầy và anh chị cho em hỏi câu nữa là trong thanh ghi FBORPOR ( BOR and POR Configuration Register) mục Device Configuration trang 710 của tài liêu dsPIC Family Reference có 2 bit là HPOL và LPOL, họ có giải thích nhưng em chưa hiểu rõ lắm về mục đích của 2 bit này, liệu có phải 2 bit này dùng để set trạng thái của chân PWM khi dead time không ah ?

Em xin chân thành cảm ơn !.
Trân trọng !.

Tài liệu vẽ minh họa cho trường hợp cả hai chân PWMxH và PWMxL là active-high (tích cực mức cao), do đó trong thời gian dead-time, cả hai chân này sẽ ở mức low (tức là ở trạng thái inactive).

Các bit HPOL và LPOL trong thanh ghi cấu hình FBORPOR cho phép chọn trạng thái tích cực của các chân PWMxH và PWMxL một cách tương ứng (nếu bạn không mô tả chúng thì mặc định là các bit này ở mức cao, tương ứng với các chân PWMxH và PWMxL là active-high). Bạn có thể thiết lập xóa các bit cấu hình này để các chân PWMxH và PWMxL là tích cực mức thấp (active-low), khi đó trong khoảng deadtime các chân PWMxH và PWMxL sẽ ở mức cao. Và kiểu logic này mới tương thích với mạch công suất của bạn.

Thân,

namqn 04-09-2009 12:07 AM

Trích:

Nguyên văn bởi JohnnyNguyen (Post 29275)
hỏi về tutorial của thầy Nam.thầy cho em hỏi,cái câu lệnh:
ADCValue = ADCBUF0 >>1 //chi lay 9 bit cao nhat
tại sao chỉ lấy 9 bit cao nhất.em chưa hiểu rõ chỗ này.em mới đang tiếp cận ADC,mong thầy chỉ rõ cho.
cho em hỏi thêm về sơ đồ mạch,cái con MAX232 có tác dụng gì a.

Vì trong ví dụ đó tôi thiết lập tần số PWM là 40 kHz, ứng với tần số thực thi lệnh là 8 MHz, nên phạm vi duty cycle chỉ là 0 .. 400, tức là có thể mã hóa bằng 9 bit. Để tận dụng gần như toàn bộ dải điện áp ở ngõ vào ADC (phạm vi điều chỉnh biến trở rộng nhất có thể có), chỉ có 9 bit cao nhất của kết quả chuyển đổi A/D được sử dụng để thiết lập duty cycle. Điều này tương ứng với việc bạn vặn biến trở từ 0 đến khoảng 80% để chỉnh duty cycle từ 0 đến 100%.

MAX232 là vi mạch dịch mức, để chuyển logic TTL/CMOS 5 V sang dạng tương thích với chuẩn RS-232 (mức điện áp thể hiện logic là khoảng +/- 12 V).

Thân,

conglong 04-09-2009 08:27 PM

Trích:

Nguyên văn bởi namqn (Post 29284)
Tài liệu vẽ minh họa cho trường hợp cả hai chân PWMxH và PWMxL là active-high (tích cực mức cao), do đó trong thời gian dead-time, cả hai chân này sẽ ở mức low (tức là ở trạng thái inactive).

Các bit HPOL và LPOL trong thanh ghi cấu hình FBORPOR cho phép chọn trạng thái tích cực của các chân PWMxH và PWMxL một cách tương ứng (nếu bạn không mô tả chúng thì mặc định là các bit này ở mức cao, tương ứng với các chân PWMxH và PWMxL là active-high). Bạn có thể thiết lập xóa các bit cấu hình này để các chân PWMxH và PWMxL là tích cực mức thấp (active-low), khi đó trong khoảng deadtime các chân PWMxH và PWMxL sẽ ở mức cao. Và kiểu logic này mới tương thích với mạch công suất của bạn.

Thân,

Em Xin chân thành cảm ơn thầy về câu trả lời này,
Đáng lẽ em phải thử để khỏi làm phiền thầy , nhưng em không có ossilo nên không quan sát được tín hiệu ở 2 chân PWMxH , PWMxL. em định thử set up 2 bit HPOL và LPOL để biết trước khi hỏi thầy nhưng em không chắc nên quyết định hỏi cho chắc !, làm việc với phần công suất (PWM) mà không chắc là em sợ lắm rùi, vì nó chết FET (Đôi khi nổ cái "đùng") hoặc chết IR2102 (mỗi con 17 ngàn) !
Nên em xin chân thành cảm ơn thầy !.
Trân trọng !.

Hiepnv101 11-09-2009 10:39 AM

Anh Nam cho em hỏi, trong chế độ quét nhiều kênh ADC, dùng Timer3 kết thúc lấy mẫu và bắt đầu chuyển đổi thì việc xác định giá trị PR3 có giông như trong chế độ quét 1kênh ADC không? Em thấy khi quét nhiều kênh thì khi đó thời gian ngắt của Timer3 là không đều và không như ý của mình, giá trị hiển thị về thỉnh thoảng lại là 0, em hiển thị lên led 7 thanh.

Thanks,

diepvu1805 10-10-2009 05:42 PM

Em đang dung DSpic30f4013. Nhưng em không biết là ADC của nó có đo được điện áp +/- không. Bác nào biết chỉ dùm em.
Thank các bac

nvcong 19-11-2009 09:18 AM

dieu khien dc dung pic16
 
cho em hoi neu mach cau H co phan hoi dong dien qua Rshun thi tin hieu ve noi vao chan nao cua pic vay?

npbaoduy 19-11-2009 10:53 PM

Trích:

Nguyên văn bởi nvcong (Post 31400)
cho em hoi neu mach cau H co phan hoi dong dien qua Rshun thi tin hieu ve noi vao chan nao cua pic vay?

Đọc áp trên Rshun bằng bộ ADC của PIC, có áp -> dòng -> điều khiển.

npbaoduy 27-11-2009 10:37 PM

Áp vào chân ADC của dspic30F6014A
 
2 Attachment(s)
Em thiết kế mạch khuyếch đại từ micro, sao cho áp ra dao động với biên độ +- 2.5V, sau đó qua mạch lọc, xong qua mạch cộng thêm 2.5v để được áp dao động từ 0-5v. Xong phần này tín hiệu do bằng dao động ký rất tốt (em sử dụng mạch khuyếch đại và lọc dụng Opamp OP07).
Sau đó đưa áp này vào chân ADC của dspic30F6014A, quan sát áp trên dao động ký thì thấy nó bị xén mất một phần ,chỉ còn lại phần từ 0- khoảng 1v (em nhấn mạnh là xén mất chứ ko phải sụt áp). Em ko hiểu tại sao lại như vậy, em đã thử thêm một tần đệm trước khi đưa vào ADC, nhưng kết quả vẫn như vậy.
Em xin đính kèm sơ đồ mạch, ai có kinh nghiệm xem xét giúp em với, em cám ơn rất nhiều.
Sơ đồ mạch em đã post thêm file pdf, phần mạch khuyếch đại và lọc em vẽ ở phía dưới cùng, tín hiệu sau xử lý đưa vào chân AN15 (nối bằng jumper giữa J11 và J3).

namqn 27-11-2009 11:05 PM

Trích:

Nguyên văn bởi npbaoduy (Post 31712)
Em thiết kế mạch khuyếch đại từ micro, sao cho áp ra dao động với biên độ +- 2.5V, sau đó qua mạch lọc, xong qua mạch cộng thêm 2.5v để được áp dao động từ 0-5v. Xong phần này tín hiệu do bằng dao động ký rất tốt (em sử dụng mạch khuyếch đại và lọc dụng Opamp OP07).
Sau đó đưa áp này vào chân ADC của dspic30F6014A, quan sát áp trên dao động ký thì thấy nó bị xén mất một phần ,chỉ còn lại phần từ 0- khoảng 1v (em nhấn mạnh là xén mất chứ ko phải sụt áp). Em ko hiểu tại sao lại như vậy, em đã thử thêm một tần đệm trước khi đưa vào ADC, nhưng kết quả vẫn như vậy.
Em xin đính kèm sơ đồ mạch, ai có kinh nghiệm xem xét giúp em với, em cám ơn rất nhiều.

Nên gửi sơ đồ mạch dạng ảnh (đọc luồng có link nằm trong chữ ký của tôi). Không phải ai cũng dùng phần mềm OrCAD, hay một phần mềm nào khác mà bạn đang dùng.

Nếu đưa dạng sóng đã kiểm tra tốt vào PIC/dsPIC mà dạng sóng bị xén mất thì phải xem lại mức đỉnh của tín hiệu có tương thích với áp nguồn của PIC/dsPIC hay không. Các chân vào/ra của PIC/dsPIC thường có 2 diode bảo vệ.

Thân,

npbaoduy 28-11-2009 09:48 PM

Em vẫn ko hiểu được anh à, nếu như ngõ vào ADC nối vô con biến trở rồi vặn biến trở thì áp bình thường ko bị sụt (0-5V), chỉ có tín hiệu từ sau bộ khuyếch đại đưa vào mới bị xén. Giả thiết bị sụt áp do dòng bé cũng ko thuyết phục lắm, vì nếu dòng nhỏ thì bị sụt áp chứ ko phải xén, hơn nữa em đã thêm mạch khuyếch đại đệm vào kết quả vẫn vậy, tín hiệu bị xén hết chỉ còn phần nằm trong khoảng 0-1V thôi :(. Em xem phần nguồn của con dsPIC cũng ko phát hiện gì cả.

namqn 28-11-2009 10:32 PM

Trích:

Nguyên văn bởi npbaoduy (Post 31754)
Em vẫn ko hiểu được anh à, nếu như ngõ vào ADC nối vô con biến trở rồi vặn biến trở thì áp bình thường ko bị sụt (0-5V), chỉ có tín hiệu từ sau bộ khuyếch đại đưa vào mới bị xén. Giả thiết bị sụt áp do dòng bé cũng ko thuyết phục lắm, vì nếu dòng nhỏ thì bị sụt áp chứ ko phải xén, hơn nữa em đã thêm mạch khuyếch đại đệm vào kết quả vẫn vậy, tín hiệu bị xén hết chỉ còn phần nằm trong khoảng 0-1V thôi :(. Em xem phần nguồn của con dsPIC cũng ko phát hiện gì cả.

Một câu hỏi hơi ngớ ngẩn: Lúc đưa tín hiệu từ mạch OP-AMP vào chân AN15 của dsPIC, bạn có cấp nguồn cho dsPIC không? Nếu có thì code của dsPIC ra sao (phần liên quan đến chức năng ADC)?

Thân,

npbaoduy 28-11-2009 10:52 PM

Tất nhiên là em có cấp nguồn :D.
code em làm tương tự như code mẫu trên trang của microchip
Code:

void Init_ADC12(void)
{
  //ADCON1 Register
        //Set up A/D for Automatic Sampling
        //Use Timer3 to provide sampling time
        //Set up A/D conversrion results to be read in fractional
        //number format.
        //All other bits to their default state
        ADCON1bits.FORM = 3; // luu du lieu dinh dang signed fractional 1.15
        ADCON1bits.SSRC = 2; // dung timer3 de kich chuyen doi ADC
        ADCON1bits.ASAM = 1; // cai dat che do tu dong lay mau

    //ADCON2 Register
        //Set up A/D for interrupting after 16 samples get filled in the buffer
        //All other bits to their default state
        ADCON2bits.SMPI = 15; // cai da che do ngat ADC sau khi day 16 mau trong bo dem du lieu
     
  //ADCON3 Register
        //We would like to set up a sampling rate of 8KHz
        //Total Conversion Time= 1/Sampling Rate = 125 microseconds
        //At 29.4 MIPS, Tcy = 33.9 ns = Instruction Cycle Time
        //Tad > 667ns (for -40C to 125C temperature range)
        //We will set up Sampling Time using Timer3 & Tad using ADCS<5:0> bits
        //All other bits to their default state
        //Let's set up ADCS arbitrarily to the maximum possible amount = 63
        //So Tad = Tcy*(ADCS+1)/2 = 1.085 microseconds
        //So, the A/D converter will take 14*Tad periods to convert each sample
        ADCON3bits.ADCS = 63;

        //Next, we will to set up Timer 3 to time-out every 125 microseconds
        //As a result, the module will stop sampling and trigger a conversion
        //on every Timer3 time-out, i.e., 125 microseconds. At that time,
        //the conversion process starts and completes 14*Tad periods later.
        //When the conversion completes, the module starts sampling again
        //However, since Timer3 is already on and counting, about 110
        //microseconds later (=125 microseconds - 14*Tad), Timer3 will expire
        //again. Effectively, the module samples for 110 microseconds and
        //converts for 15 microseconds
        //NOTE: The actual sampling rate realized may be 7998.698 Hz
        //      due to a small round off error. Ensure you provide the
        //      true sampling rate to dsPICworks if you are trying to plot
        //      the sampled or filtered signal.
        TMR3 = 0x0000;
        PR3 = 0X0E65;
        IFS0bits.T3IF = 0; // cho co ngat timer3=0
        IEC0bits.T3IE = 0; // khong cho phep ngat timer3

        //ADCHS Register
        //Set up A/D Channel Select Register to convert AN7 on Mux A input
        ADCHS = 0x000F; // chon AN15 la kenh thu du lieu analog


        //ADCSSL Register
        //Channel Scanning is disabled. All bits left to their default state
        ADCSSL = 0x0000; // tat che do quet cac kenh. Cac n=bit con lai de che do mac dinh

        //ADPCFG Register
        //Set up channels AN15 as analog input and configure rest as digital
        //Recall that we configured all A/D pins as digital when code execution
        //entered main() out of reset
              ADPCFG = 0xFFFF;
        ADPCFGbits.PCFG15 = 0; //ngo AN15 la ngo vao analog

        //Clear the A/D interrupt flag bit
        IFS0bits.ADIF = 0; // xoa co ngat chuyen doi ADC

        //Set the A/D interrupt enable bit
        IEC0bits.ADIE = 1; // cho phep ngat ADC

        //Turn on the A/D converter
        //This is typically done after configuring other registers
        ADCON1bits.ADON = 1; // bat dau cho do ADC hoat dong

        //Start Timer 3
        T3CONbits.TON = 1; // cho timer3 bat dau chay



void __attribute__((interrupt, no_auto_psv)) _ADCInterrupt(void)
{
    IFS0bits.T3IF = 0; //Xoa co ngat timer3
    unsigned int i = 0;
    IFS0bits.ADIF = 0; //Xoa co ngat ADC
    adcPtr=&ADCBUF0; // lay dia chi thanh ghi ADCBUF0 ghi vao thanh ghi adcPtr

  for(i=0;i<=15;i++)
      {
      *iPtr++=*adcPtr++; //lay noi dung cua cac thanh ghi Buffer lan luot ghi vao cac bien
                    // inputsignal[]
      }
  if (iPtr>&inputsignal[159])    doFilterFlag=1;        // thu duoc 160 mau thi vao xu ly                               
}

Trong chương trình chính:
Code:

....
        while(1)
        {
            while(!doFilterFlag){};  //Vong lap cho day 160 mau trong bo dem ADC
        doFilterFlag=0;          //chuan bi vong lap sau
        (.....tính toán xử lý .........................)

Anh xem giúp em nhé!

npbaoduy 30-11-2009 05:00 PM

Luôn tiện a cho em hỏi luôn là nếu đưa áp vào chân ADC mà vuợt ngoài tầm 0-5v (áp âm hoặc lớn hơn 5v) thì có thể làm hư chân ADC đó ko ?

ngoducbinh1987 14-12-2009 09:48 AM

anh Nam ơi cho em hỏi thanh ghi SEVTCMP có tác dụng gì vậy ạ

thuhuong 04-03-2010 09:36 AM

Anh Nam và các bạn cho hỏi ở phần giới thiệu trong tutorial 5 có nói: "Ví dụ 5-1 sẽ giới thiệu cách điều chỉnh độ rộng xung theo một giá trị tương tự được đọc về thông qua một ngõ vào analog". Vậy ở đây giá trị tương tự là tín hiệu gì và tín hiệu xung điều chỉnh theo tham số nào của tín hiệu tương tự đó. Thank!

namqn 04-03-2010 09:57 AM

Trích:

Nguyên văn bởi thuhuong (Post 33820)
Anh Nam và các bạn cho hỏi ở phần giới thiệu trong tutorial 5 có nói: "Ví dụ 5-1 sẽ giới thiệu cách điều chỉnh độ rộng xung theo một giá trị tương tự được đọc về thông qua một ngõ vào analog". Vậy ở đây giá trị tương tự là tín hiệu gì và tín hiệu xung điều chỉnh theo tham số nào của tín hiệu tương tự đó. Thank!

Giá trị tương tự là tín hiệu điện áp đặt vào ngõ vào analog, thay đổi từ 0 V đến VDD.

Với cách thiết lập tham số cho module MCPWM trong ví dụ 5-1, duty cycle = 100% sẽ ứng với giá trị 400 (đọc kỹ tutorial nếu chưa rõ).

Với cách đọc tín hiệu ADC đã dùng trong ví dụ 5-1, khi điện áp ngõ vào analog thay đổi từ 0 V đến VDD thì sẽ có được giá trị 0 - 511 trong biến ADCValue, và giá trị này được ghi thẳng vào các thanh ghi PDCx để thiết lập duty cycle.

Như vậy, khi ngõ vào analog thay đổi từ 0 V đến khoảng 80% giá trị của VDD (chính xác là 400*VDD/512) thì duty cycle của tín hiệu ra sẽ thay đổi từ 0% đến 100%.

Có vẻ như bạn chưa đọc kỹ tutorial và code đi kèm.

Thân,

thuhuong 06-03-2010 12:33 AM

Nhờ Anh Nam hướng dẫn giúp: Em muốn làm một bộ inverter từ DC-AC sử dụng nguyên lý điều biến sin độ rộng xung, trong đó tín hiệu điện áp ra được ổn định.
Nguyên tắc ổn định là dùng mạch hồi tiếp, bám điện áp ra: Khi có điện áp ra thay đổi lệch khỏi điện áp định mức thì mạch sẽ đo và đưa tín hiệu sai lệch để điều chỉnh sai lệch đó.
A cho E hỏi: điều chế sin độ rộng xung trong DS pic muốn điều chỉnh điện áp như thế thì đưa tín hiệu sai lêch (tín hiệu điều khiển) vào chân nào và điều chỉnh như thế nào trong con dspic đó.
E đã hỏi và A đã trả lời là lập một bảng sin khác trong Ram, nhưng như thể chỉ có thể thay đổi được điện áp ra, còn để điều chỉnh (Bám-trơn) thì E khồn biết làm thế nào.

namqn 06-03-2010 06:56 PM

Trích:

Nguyên văn bởi thuhuong (Post 33865)
Nhờ Anh Nam hướng dẫn giúp: Em muốn làm một bộ inverter từ DC-AC sử dụng nguyên lý điều biến sin độ rộng xung, trong đó tín hiệu điện áp ra được ổn định.
Nguyên tắc ổn định là dùng mạch hồi tiếp, bám điện áp ra: Khi có điện áp ra thay đổi lệch khỏi điện áp định mức thì mạch sẽ đo và đưa tín hiệu sai lệch để điều chỉnh sai lệch đó.
A cho E hỏi: điều chế sin độ rộng xung trong DS pic muốn điều chỉnh điện áp như thế thì đưa tín hiệu sai lêch (tín hiệu điều khiển) vào chân nào và điều chỉnh như thế nào trong con dspic đó.
E đã hỏi và A đã trả lời là lập một bảng sin khác trong Ram, nhưng như thể chỉ có thể thay đổi được điện áp ra, còn để điều chỉnh (Bám-trơn) thì E khồn biết làm thế nào.

Bạn xem lại nguyên tắc của SPWM. Bạn chỉ có 1 giá trị trung bình trong mỗi chu kỳ chuyển mạch, và bạn có thể điều chỉnh để giá trị trung bình đó bám theo tín hiệu tham chiếu.

Bảng sin trong RAM cho phép bạn tùy nghi thay đổi giá trị trung bình của chu kỳ chuyển mạch bất kỳ, như vậy thực sự cho phép bạn thực hiện điều trên.

Bạn có thể đưa tín hiệu sai lệch vào một ngõ vào analog và đọc nó vào dsPIC, rồi từ đó tính toán để cập nhật bảng sin trong RAM.

Thân,

chanxi9 03-08-2010 12:46 PM

chào a Nam
E đang đọc đến phần module PWM, có phần độ phân giải PWM (= Tcy/2) e ko hiểu rõ ý nghĩa của nó lắm . Đọc tài liệu có phần trích dẫn là : "Though the clock to the time base timer is Tcy, the duty cycle resolution is Tcy/2; this feature can be utlized to obtain finer PWM resolution at lower device operating speeds, e.g., 11 bits of resolution at 19.5 Khz using a 20 MHz clock."
Mong a cùng các bạn có thể giải thích rõ hơn cho e hiểu được ko ạ.

truongaka 23-12-2010 05:26 PM

Chào mọi người!
Em đang dùng con Dspic 30f2020 để điều khiển đóng mở FET bằng cách điều chỉnh PWM.
Em thay đổi PDC1 để thay đổi Duty nhưng khi thay đổi PDC1 thì Duty đo trên osiloscope luôn không đổi. thầy Nam và mọi người xem giúp em với ạ?



#include <p30F2020.h>
#include <adc10.h>
// cau hinh cho chip
_FOSC(CSW_FSCM_OFF) // tat che do du phong
_FOSCSEL(FRC_PLL) //chon nguon xung trong
_FWDT(FWDTEN_OFF) //tat bo dinh thoi giam sat
_FPOR(PWRT_OFF)
// dinh nghia cac dinh nghia cac nhan cua chuong trinh
#define PWM_PORT PORTE // thanh ghi port E
#define PWM_TRIS TRISE // thanh ghi tris E
#define PWM_LAT LATE // thanh ghi lat E
#define Fcy 925000000 // TAN SO THUC THI LENH
#define Fpwm 50000 //tan so PWM = 50 kHz
// cac prototype
void Init_ADC0(void); // khoi tao adc
void Init_PORT(void); // khoi tao port
void Init_MCPWM(void);
//khoi tao cac module PWM
//int duty = 50;
// CHUONG TRINH CHINH
int main(void)
{ Init_PORT();
Init_ADC0();
Init_MCPWM();
// asm("nop");
// asm("nop");
// asm("nop");
while (1) ; // cho ngat
return 0;
}

// chuong trinh khoitao cong
void Init_PORT(void)
{
PWM_LAT = 0x0000; //Xoa thanh ghi chot tin hieu ra PWM
PWM_TRIS = 0x0000; // port E la output
TRISB = 0xFFFF; // port B la in put
ADPCFG = 0x0000; // port B la dau vao tuong tu
}

//Chuong trinh con khoi tao PWM chung cho cac module
void Init_MCPWM(void)
{
//PTCON = 0x0000;
PTPER = Fcy/Fpwm - 1; //Dat thanh ghi chu ky voi tan so PWM = 40 kHz
SEVTCMP = PTPER; //su kien dac biet duy nhat là khi bo dem bang PTPER
PWMCON1 = 0x0080; // thanh ghi dieu khien pwm1, dung rieng PDCx,lo dead_time
//PWMCON2 = 0x0080; // thanh ghi dieu khien pwm2, dung rieng PDCx,lo dead_time
PHASE1 = 0x0000;
PWMCON1 = 0x0001;
FCLCON1 = 0x0003;
//PHASE2 = Fcy/Fpwm - 1; // khoi tao period cho pwm2
PDC1 = 0.8*(PTPER + 1) ; // dat khoi tao duty cycle cho pwm1
//PDC2 = 0x00A0; // dat khoi tao duty cycle cho pwm2
IOCON1 = 0xC000;
IOCON2 = 0xC000;
PTCON = 0x8000; //Kich hoat module PWM
}

// chuong trinh khoi tao module ADC
void Init_ADC0(void)
{
ADCON = 0x2003; // CHO PHEP ADC HOAT DONG O 4 CHAN B0, B1, B2, B3
ADCPC0 = 0xC3C3; // lien ket voi PWM//
_ADIF = 0; //Xoa co ngat ADC
_ADCP0IF = 0; //--------------
ADSTATbits.P0RDY = 0; //XOA co bao data is ready
_ADCP1IF = 0; //--------------
ADSTATbits.P1RDY = 0; //XOA co bao data is ready
_ADIE = 1; //Cho phep ngat ADC
_ADON = 1; // cho phep ADC hoat dong
}

void _ISR _ADCInterrupt(void) //ham ngat cua adc
{
PDC1 = ADCBUF0*10; // gan ket qua adc ra pw1 (chan E0 va E1)
PDC2 = ADCBUF2*10; // gan ket qua adc ra pw2 (chan E3 va E4)
_ADIF = 0; // xoa co ngat
_ADCP0IF = 0; //xoa co ngat
ADSTATbits.P0RDY=0; //xoa bit bao du lieu
_ADCP1IF = 0; //xoa co ngat
ADSTATbits.P1RDY=0; //xoa bit bao du lieu

provaidan 04-10-2012 07:18 PM

mình đang làm việc với dspic33fj32mc202,ai cho minh hỏi: mình ko thấy chân sử dụng Input Capture là pin nào?ai giúp mình với
thank nhiều!


Múi giờ GMT. Hiện tại là 04:30 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