PDA

View Full Version : dsPIC Tutorial 5-Module ADC và MCPWM


namqn
04-10-2006, 12:16 AM
Đâ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,

typhn
07-12-2006, 01:05 AM
Em đọc phần PWM của DSPIC30F4011 mà khó hiểu quá,khác xa so với 16F877A.Em đã test thử PWM cho động cơ mà chưa được,ko hiểu tại sao,mong anh giúp đỡ.
Chương trình của em như sau: Bật chức năng PWM của chân PWM1H và PWM2L, với Fpwm=1khz,tỷ lệ D/t=1/2(chạy 50% công suất).Còn chân PWM1L và PWM2H luôn ở mức thấp.PWM cứ hoạt động cho đến khi bit RB1=1(bình thường thì RB1 ở mức 0) thì dừng PWM và các chân PWM lại vào/ra số như các chân khác.
Em dùng thạch anh 8MHZ
Chương trình của em như sau:

#include"p30f4011.h"

_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PBOR_OFF & PWMxL_ACT_HI & PWMxH_ACT_HI);
_FGS(CODE_PROT_OFF);

void init(void)
{
ADPCFG =0xFFFF; //CAC ANX DEU LA DIGITAL
TRISB =0x003F; //Dinh nghia RB0-RB5 la loi vao,cac RBX la loi ra
TRISE =0x0000; //cong E de PWM la loi ra
LATE =0x0000;
PTCON =0x0000; //tat PWM
PTPER =8000; //Fpwm=1KHZ
PWMCON1 =0x0712; // ko su dung mode bù,PWM1H va 2L hoat dong
// cac PWM khác là disable
OVDCON =0x0600 //PWM1H và 2L hoạt động PWM,PWM1L và 2H luôn ở mức 0

}

int main()
{

init();
PDC1=8000;
PDC2 =8000; //chay 50% cong suat
PTCON=0x8000;//bat PWM o che do free running
while(1)
{
if(_RB1==1) break;
}
PTCON=0x0000;//tat PWM
LATE=0x000F;//vao ra so binh thuong
return 0;
}

chương trình của em chỉ đơn giản như vậy.
Mong bác chỉ bảo.
Em đợi tin của bác
thanks

namqn
07-12-2006, 05:05 AM
Nếu bạn chưa đọc tutorial này của tôi thì hãy đọc nó trước đi. Nếu bạn đã thử phần tutorial của tôi rồi thì hãy sửa nó theo cách mà bạn muốn. Như vậy sẽ dễ hơn cho bạn.

Thân,

chukhivuitinh
03-05-2008, 10:46 AM
Báo cáo về UART của tut4 và tut5 của a Nam :

Đây là board test của em ,em xài dsPic 30F4011 :
http://i232.photobucket.com/albums/ee46/khiconrangkhenh/Img0412.jpg
http://i232.photobucket.com/albums/ee46/khiconrangkhenh/Img0413.jpg

Giao tiếp UART của bài 4-1 và 5-2 :
http://i232.photobucket.com/albums/ee46/khiconrangkhenh/tut4-1.jpg
http://i232.photobucket.com/albums/ee46/khiconrangkhenh/tut5.jpg


Bài 4-1 ,với ví dụ là "Xin Chao !" em test thì có rất nhiều đoạn đọc sai ,kí tự " " (khoảng trắng) trong character map là 00A0 ,mà em koi watch thì trong pic đọc ra là 0x0020 ,đây có thể là lỗi do font ko ? cái hình trên là em dùng thời gian tràn của TMR1 là 0.5s ,chứ để 1s ,nó ra tùm lum hết T_T .

Tut 3 và 4-3 ,4-4 vì ko có LCD và DS1307 nên em chưa test thực tế được ,chỉ coi watch chạy thui .Nên chưa nắm rõ lắm .

chukhivuitinh
03-05-2008, 07:00 PM
ở bài 4-1 ,nếu muốn chuỗi kí tự khi đọc về xuống dòng và về đầu dòng thì thêm cái này vào sau chuỗi nha :
\n : xuống dòng
\r : về đầu dòng
ví dụ : .asciz "-=(chukhivuitinh^_^khiconrangkhenh)=-\n\r"

namqn
28-05-2008, 05:26 PM
Báo cáo về UART của tut4 và tut5 của a Nam :
...
Bài 4-1 ,với ví dụ là "Xin Chao !" em test thì có rất nhiều đoạn đọc sai ,kí tự " " (khoảng trắng) trong character map là 00A0 ,mà em koi watch thì trong pic đọc ra là 0x0020 ,đây có thể là lỗi do font ko ? cái hình trên là em dùng thời gian tràn của TMR1 là 0.5s ,chứ để 1s ,nó ra tùm lum hết T_T .

Tut 3 và 4-3 ,4-4 vì ko có LCD và DS1307 nên em chưa test thực tế được ,chỉ coi watch chạy thui .Nên chưa nắm rõ lắm .
Khoảng trắng có mã ASCII là 0x20, còn 0xA0 là mã của 'no-break space' chứ không phải 'space'. Khi dùng Character Map để xem các font thông thường, các mã điều khiển (nằm trong phạm vi 0x00 đến 0x1F) và ký tự 'space' không được thể hiện trong bảng ký tự.

Thân,

tungtuantu
12-11-2008, 10:50 PM
bác namqn cho em hỏi, em có thể dùng chân PWM_L cho chức năng PWM, và chân PWM_H cho chức năng port I/O bình thường ko ah, và làm thế nào.
Nếu em muốn PWM1 là PWM, còn PWM2 hoặc 3 là port I/O thường chỉ việc cho LATx= 0 hoặc 1 là dc hả anh.
Em lấy ví dụ 5.1 của anh sửa đi để chạy với mạch thật, biến trở em nối vào nguồn 5V, diều khiển động cơ dùng L298, dùng PWM1L và PWM2L để điều khiển, em cho luôn chân PWM2L=0, khi điều chỉnh biến trở thì chỉ 1 nửa là động cơ chạy, 1 nửa là dứng yên, tức là ko điều chỉnh dc toàn dải, mắc dù em cho chân PWM2L=0 rồi nhưng khi em đo áp trên chan này thì dc hơn 1 V, em nghĩ đây là nguyên nhân mà ko điều chỉnh dc toàn dải, có phải ko anh, cho em cách khắc phục
_FOSC(CSW_FSCM_OFF & FRC_PLL4); cái này có phải cấu hình dùng dao động nội của chip ?
nếu em dùng thach anh 20Mhz thì em cấu hình như này
_FOSC(CSW_FSCM_OFF & HS); có đúng ko anh.
Nên dùng thạch anh ngoài hay bộ dao động nội, em thấy các ví dụ của anh toàn dùng dao động nội? nếu dùng thạch anh thì fcy (tần số thực thi lệnh) = Fosc/4 đúng ko anh?
Nếu em muốn viết 1 hàm trễ 1ms bằng vòng lặp for thì cách tính toán như nào ( anh cho ví dụ luôn nhé),viết hàm delay nên dùng vòng lặp for hay dùng timer ?

namqn
13-11-2008, 02:19 AM
bác namqn cho em hỏi, em có thể dùng chân PWM_L cho chức năng PWM, và chân PWM_H cho chức năng port I/O bình thường ko ah, và làm thế nào.
Nếu em muốn PWM1 là PWM, còn PWM2 hoặc 3 là port I/O thường chỉ việc cho LATx= 0 hoặc 1 là dc hả anh.
Em lấy ví dụ 5.1 của anh sửa đi để chạy với mạch thật, biến trở em nối vào nguồn 5V, diều khiển động cơ dùng L298, dùng PWM1L và PWM2L để điều khiển, em cho luôn chân PWM2L=0, khi điều chỉnh biến trở thì chỉ 1 nửa là động cơ chạy, 1 nửa là dứng yên, tức là ko điều chỉnh dc toàn dải, mắc dù em cho chân PWM2L=0 rồi nhưng khi em đo áp trên chan này thì dc hơn 1 V, em nghĩ đây là nguyên nhân mà ko điều chỉnh dc toàn dải, có phải ko anh, cho em cách khắc phục
_FOSC(CSW_FSCM_OFF & FRC_PLL4); cái này có phải cấu hình dùng dao động nội của chip ?
nếu em dùng thach anh 20Mhz thì em cấu hình như này
_FOSC(CSW_FSCM_OFF & HS); có đúng ko anh.
Nên dùng thạch anh ngoài hay bộ dao động nội, em thấy các ví dụ của anh toàn dùng dao động nội? nếu dùng thạch anh thì fcy (tần số thực thi lệnh) = Fosc/4 đúng ko anh?
Nếu em muốn viết 1 hàm trễ 1ms bằng vòng lặp for thì cách tính toán như nào ( anh cho ví dụ luôn nhé),viết hàm delay nên dùng vòng lặp for hay dùng timer ?
Chân PWMxH có thể dùng làm chân I/O một cách độc lập với chân PWMxL tương ứng, nếu thiết lập cho cặp chân đó làm việc ở chế độ độc lập (bit PMODx tương ứng trong thanh ghi PWMCON1 mang giá trị '1').
Nếu muốn các chân của một kênh PWM nào đó là ngõ vào/ra thông thường thì thiết lập các bit PENxH và PENxL mang giá trị '0'.

Nếu bạn dùng L298 thì cần cho biết sơ đồ kết nối giữa dsPIC và L298. Một phần cứng cụ thể sẽ tương ứng với một thuật toán điều khiển cụ thể. Bạn không thể áp ví dụ của tôi vào mạch cầu H, vì tôi không viết phần mềm để điều khiển mạch cầu H. Tôi chỉ xuất ngõ ra PWM với duty cycle được thay đổi theo tín hiệu ADC vào thôi. Bạn tham khảo thêm cách điều khiển được đề xuất cho cầu H ở post #49 của luồng sau:
http://www.picvietnam.com/forum/showthread.php?t=1186

_FOSC(CSW_FSCM_OFF & FRC_PLL4); chọn bộ dao động nội với x4 PLL được kích hoạt.

Thạch anh ngoài 20 MHz có thể dùng với các cấu hình:
_FOSC(CSW_FSCM_OFF & HS);
hoặc
_FOSC(CSW_FSCM_OFF & XT_PLL4);

XT_PLL4 có thể gặp khó khăn trong việc ổn định dao động cho thạch anh.

Tôi dùng bộ dao động nội trong các tutorial chỉ để đơn giản hóa phần cứng. Với các bài toán yêu cầu độ chính xác cao đối với xung clock thì nên dùng thạch anh ngoài, hoặc tốt hơn là bộ dao động ngoài.

Việc một vòng for nào đó chạy mất bao nhiêu thời gian còn tùy thuộc vào chế độ tối ưu khi biên dịch code. Tôi thường dùng MPLAB SIM để xác định thời gian (hay số chu kỳ máy) cần thiết để thực thi một vòng for.

Theo tôi, không nên dùng vòng lặp đếm chu kỳ máy cho các thời gian trễ tương đối dài (cỡ ms).

Thân,

tungtuantu
13-11-2008, 09:57 AM
Em post mạch của lên bác xem, em cho luôn PWM2L =0 (_LATE2=0), còn PWML1 là chân PWM, nhưng em đo áp trên chân E2 vẫn được hơn 1V, em set = 0 rồi, sao nó ko về 0V, bác xem với mạch của em thì điều khiển với tần số tối đa là bao nhiêu, em đã thay 1N4007 bằng diode schotky 1N5819, chương trình em sửa của bác

#include <p30f4011.h>

_FOSC(CSW_FSCM_OFF & FRC_PLL4);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_EN);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
#define PWM_PORT PORTE //Cac tin hieu PWM nam o cong E
#define PWM_TRIS TRISE //Thanh ghi 3 trang thai cho cac tin hieu PWM
#define PWM_LAT LATE //Thanh ghi chot cac tin hieu PWM
#define Fcy 20000000 //Tan so thuc thi lenh
#define Fpwm 40000 //Tan so PWM = 40 kHz

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void);
void Init_MCPWM(void);
void Init_ADC10(void);

//Cac bien toan cuc
unsigned int ADCValue;

//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
Init_PORTS(); //Khoi tao cac cong I/O
Init_MCPWM(); //Khoi tao module PWM
Init_ADC10(); //Khoi tao module ADC
while (1) Nop();
}

//Chuong trinh con khoi tao cac cong I/O, de xuat cac tin hieu PWM, va doc tin
//hieu dieu chinh cua bien tro tai AN0
void Init_PORTS(void) {
PWM_LAT = 0; //Xoa thanh ghi chot cac tin hieu PWM
PWM_TRIS = 0xFFC0; //Cac tin hieu PWM nam tai RE0..RE5
TRISB = 0x0070; //Chan RB0 la ngo vao analog AN0, cac chan khac
//la ngo ra
_LATE2 = 0;
}

//Chuong trinh con khoi tao module chuyen doi A/D, doc ngo vao AN0
void Init_ADC10(void) {
ADPCFG = 0xFFBF; //Cac chan khac la digital, chan AN0/RB0 la analog
ADCON1 = 0x0060; //Module PWM cham dut lay mau va kich hoat
//viec chuyen doi A/D
// ADCON1 = 0x0040; //Timer 3 cham dut lay mau va kich hoat
//viec chuyen doi A/D
ADCON2 = 0;
ADCHS = 0x06; //Kenh 0 doc tin hieu giua AN0 va AVss
ADCSSL = 0; //Khong quet cac ngo vao
ADCON3 = 0x0103; //Dung 1 TAD cho lay mau, dung clock he thong,
//TAD = 2xTcy = 250 ns
/* 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
}

//Chuong trinh con khoi tao module PWM
void Init_MCPWM(void) {
PTPER = Fcy/Fpwm - 1; //Dat thanh ghi chu ky voi tan so PWM = 40 kHz
SEVTCMP = PTPER;
PWMCON1 = 0x070F; //Chi dung cac chan PxL, mot cach doc lap
OVDCON = 0xFF00; //Khong dung overdrive
PDC1 = 0x0064; //Khoi tao PWM1, 2, va 3 la 25%
PDC2 = 0x0064;
PDC3 = 0x0064;
PWMCON2 = 0x0F00; //Postscale = 1:16
PTCON = 0x8000; //Kich hoat module PWM
}

//Trinh phuc vu ngat cho ADC
void _ISR _ADCInterrupt(void)
{
ADCValue = ADCBUF0 >> 1; //Chi lay 9-bit cao nhat cua ket qua ADC
PDC1 = ADCValue; //Cap nhat cac thanh ghi dem chu ky nhiem vu

_ADIF = 0;
}

namqn
14-11-2008, 08:15 PM
Em post mạch của lên bác xem, em cho luôn PWM2L =0 (_LATE2=0), còn PWML1 là chân PWM, nhưng em đo áp trên chân E2 vẫn được hơn 1V, em set = 0 rồi, sao nó ko về 0V, bác xem với mạch của em thì điều khiển với tần số tối đa là bao nhiêu, em đã thay 1N4007 bằng diode schotky 1N5819, chương trình em sửa của bác

#include <p30f4011.h>

_FOSC(CSW_FSCM_OFF & FRC_PLL4);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_EN);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
#define PWM_PORT PORTE //Cac tin hieu PWM nam o cong E
#define PWM_TRIS TRISE //Thanh ghi 3 trang thai cho cac tin hieu PWM
#define PWM_LAT LATE //Thanh ghi chot cac tin hieu PWM
#define Fcy 20000000 //Tan so thuc thi lenh
#define Fpwm 40000 //Tan so PWM = 40 kHz

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void);
void Init_MCPWM(void);
void Init_ADC10(void);

//Cac bien toan cuc
unsigned int ADCValue;

//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
Init_PORTS(); //Khoi tao cac cong I/O
Init_MCPWM(); //Khoi tao module PWM
Init_ADC10(); //Khoi tao module ADC
while (1) Nop();
}

//Chuong trinh con khoi tao cac cong I/O, de xuat cac tin hieu PWM, va doc tin
//hieu dieu chinh cua bien tro tai AN0
void Init_PORTS(void) {
PWM_LAT = 0; //Xoa thanh ghi chot cac tin hieu PWM
PWM_TRIS = 0xFFC0; //Cac tin hieu PWM nam tai RE0..RE5
TRISB = 0x0070; //Chan RB0 la ngo vao analog AN0, cac chan khac
//la ngo ra
_LATE2 = 0;
}

//Chuong trinh con khoi tao module chuyen doi A/D, doc ngo vao AN0
void Init_ADC10(void) {
ADPCFG = 0xFFBF; //Cac chan khac la digital, chan AN0/RB0 la analog
ADCON1 = 0x0060; //Module PWM cham dut lay mau va kich hoat
//viec chuyen doi A/D
// ADCON1 = 0x0040; //Timer 3 cham dut lay mau va kich hoat
//viec chuyen doi A/D
ADCON2 = 0;
ADCHS = 0x06; //Kenh 0 doc tin hieu giua AN0 va AVss
ADCSSL = 0; //Khong quet cac ngo vao
ADCON3 = 0x0103; //Dung 1 TAD cho lay mau, dung clock he thong,
//TAD = 2xTcy = 250 ns
/* 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
}

//Chuong trinh con khoi tao module PWM
void Init_MCPWM(void) {
PTPER = Fcy/Fpwm - 1; //Dat thanh ghi chu ky voi tan so PWM = 40 kHz
SEVTCMP = PTPER;
PWMCON1 = 0x070F; //Chi dung cac chan PxL, mot cach doc lap
OVDCON = 0xFF00; //Khong dung overdrive
PDC1 = 0x0064; //Khoi tao PWM1, 2, va 3 la 25%
PDC2 = 0x0064;
PDC3 = 0x0064;
PWMCON2 = 0x0F00; //Postscale = 1:16
PTCON = 0x8000; //Kich hoat module PWM
}

//Trinh phuc vu ngat cho ADC
void _ISR _ADCInterrupt(void)
{
ADCValue = ADCBUF0 >> 1; //Chi lay 9-bit cao nhat cua ket qua ADC
PDC1 = ADCValue; //Cap nhat cac thanh ghi dem chu ky nhiem vu

_ADIF = 0;
}


L298 coi điện áp ngõ vào 1 V là mức '0', do đó không có vấn đề gì về logic. Bạn đã thử chạy dsPIC riêng (không nối vào L298) và đo điện áp của chân RE2 chưa?

Bạn sửa code mà không chú thích lại. Với FRC_PLL4, Fcy không thể là 20 MHz, mà chỉ có thể là 7.37 MHz (với các dsPIC30F4011 sau này, theo các phiên bản datasheet mới nhất).

Để có thể dùng phần lớn phạm vi điều chỉnh của biến trở ngõ vào ADC, bạn cần tính toán đôi chút, và có thể cần phải điều chỉnh thiết kế ở phần ngõ vào ADC dùng để đặt duty cycle. Với ví dụ của tôi, tôi đã dùng Fcy = 8 MHz, với tần số ngõ ra là 40 kHz, do đó PTPER của tôi sẽ là 200. Độ phân giải của duty cycle gấp đôi độ phân giải của timer tạo chu kỳ. Do đó, số đếm tương ứng với duty cycle 100% sẽ là 400. Từ đó, tôi mới lấy 9 bit của kết quả ADC để đặt duty cycle, với phạm vi thay đổi là 0 .. 511. Như vậy, biến trở của tôi chạy đến khoảng 80% phạm vi của nó thì duty cycle của tôi sẽ đạt 100%. Bạn cần tính toán lại cho trường hợp của bạn.

Bạn cũng chưa cho biết đã nối biến trở đến ngõ vào ADC như thế nào.

Theo datasheet của L298 thì tần số điển hình của mạch là 25 kHz, tối đa là 40 kHz. Bạn có thể dùng 20 kHz với các thử nghiệm ban đầu.

Mỗi bài viết của một thành viên nào đó đều có nút 'Cảm ơn' để những thành viên khác sử dụng. Nếu bạn thấy bài viết nào có ích cho bạn thì bạn có thể nhấn nút đó, và không cần viết bài cảm ơn.

Thân,

tungtuantu
16-11-2008, 12:08 PM
Em đã sửa lại chương trình của em và đã điều chỉnh trên toàn dải, bác cho em hỏi là nếu mình dùng nhiều hơn 1 chân kiểu analog thì mình dùng kiểu quét để đọc giá trị về ah, và các ngắt của nó xảy ra như nào ah. con 30F4011 có 8 chân Analog thì có 16 bộ đệm ADCBUF là như nào hả bác, ví dụ như là đọc giá trị từ chân AN0, AN6 thì mình dùng bộ đếm mấy ah, em chư hiểu kiểu lấy mẫu A hoặc B như nào.
Một vấn đề nưa em muốn hỏi bác luôn là, em dùng QEI và đã được đọc số chính xác, nhưng em đọc datasheet con 30F4011 ko có chế độ VELOCITY MEASUREMENT như con 18F4331, như thế em để suy ra vận tốc, thì em dùng 1 ngắt timer trong 1s để đọc số xung rồi suy ra vận tốc, ví dụ trong 1s đó mà quay dc 5,5 vòng thì em phải dùng thêm ngắt của QEI đẻ xác định số vòng rồi cộng thêm với số vòng dư. Hoặc em chỉ dùng ngắt của QEI ví dụ số vòng đến 5 thì đọc giá trị của 1 timer chạy free run, bác xem 2 cách trên của em có khả thi ko.
Nếu em gộp ctr là điều chỉnh và hiện thị tốc độ, hiện thị cả dòng điện phản hồi nữa, như thế em phải dùng nhiều ngắt,em đang rối phần ưu tiên ngắt, bác mách nước cho em đuọc ko ah.
Thanks

namqn
17-11-2008, 04:14 AM
Em đã sửa lại chương trình của em và đã điều chỉnh trên toàn dải, bác cho em hỏi là nếu mình dùng nhiều hơn 1 chân kiểu analog thì mình dùng kiểu quét để đọc giá trị về ah, và các ngắt của nó xảy ra như nào ah. con 30F4011 có 8 chân Analog thì có 16 bộ đệm ADCBUF là như nào hả bác, ví dụ như là đọc giá trị từ chân AN0, AN6 thì mình dùng bộ đếm mấy ah, em chư hiểu kiểu lấy mẫu A hoặc B như nào.
Một vấn đề nưa em muốn hỏi bác luôn là, em dùng QEI và đã được đọc số chính xác, nhưng em đọc datasheet con 30F4011 ko có chế độ VELOCITY MEASUREMENT như con 18F4331, như thế em để suy ra vận tốc, thì em dùng 1 ngắt timer trong 1s để đọc số xung rồi suy ra vận tốc, ví dụ trong 1s đó mà quay dc 5,5 vòng thì em phải dùng thêm ngắt của QEI đẻ xác định số vòng rồi cộng thêm với số vòng dư. Hoặc em chỉ dùng ngắt của QEI ví dụ số vòng đến 5 thì đọc giá trị của 1 timer chạy free run, bác xem 2 cách trên của em có khả thi ko.
Nếu em gộp ctr là điều chỉnh và hiện thị tốc độ, hiện thị cả dòng điện phản hồi nữa, như thế em phải dùng nhiều ngắt,em đang rối phần ưu tiên ngắt, bác mách nước cho em đuọc ko ah.
Thanks
Chỉ có ngắt khi hoàn thành việc chuyển đổi A/D (A/D conversion), còn việc lấy mẫu điện áp ngõ vào thì không có ngắt. Module ADC của dsPIC chỉ có 1 bộ chuyển đổi, và ngắt có thể được thiết lập để xuất hiện sau mỗi phép chuyển đổi, hoặc sau một số lần chuyển đổi (các kết quả chuyển đổi được tạm thời lưu vào các thanh ghi đệm ADCBUF0 .. ADCBUFF). Bạn có thể lấy mẫu đồng loạt rồi chuyển đổi, hoặc lấy mẫu đến đâu thì chuyển đổi đến đó. Thông tin chi tiết có ở section 17 của tài liệu "dsPIC30F Family Reference Manual" (DS70046E), rất dài dòng để nói hết ở đây.

Đọc số xung encoder trong 1 giây để tính vận tốc chỉ thích hợp cho hiển thị, thường không đủ cho điều khiển (tốc độ cập nhật quá chậm). Cả hai cách bạn nêu đều thích hợp, nhưng áp dụng ở các dải tốc độ khác nhau.

Các ngắt thông thường có thể được thiết lập ở một trong bảy mức ưu tiên ngắt. Tôi tin rằng bạn có thể dễ dàng thiết lập mức độ ưu tiên cho vài ngắt mà bạn đang dùng. Việc bố trí các ngắt như thế nào còn tùy vào mức độ quan trọng của ngắt đang được xử lý, thời gian xử lý của một ngắt được dự định gán mức ưu tiên cao hơn ngắt đó, ... Hy vọng bạn có thể dựa vào một vài gợi ý trên để thiết lập việc ưu tiên ngắt cho hiệu quả.

Thân,

han_nang_008
16-12-2008, 04:26 PM
bác namqn có thể nói rõ hơn khi mình dùng nhiều hơn 1 chân ADC, bác có thể viết 1 đoặn ví dụ cụ thể dc ko ah.
Ví dụ dùng AN0 và AN6, chân AN0 lấy tín hiệu từ triết áp để điều khiển tốc độ động cơ, còn chân AN6 lấy tín hiệu dòng phản hồi của động cơ, rồi hiện thì lên LCD chẳng han,thì cấu hình như nào, tốc độ lấy mẫu như nào thì phù hợp ah, với AN0 thì dùng PWM chấm dứt lấy mẫu, còn với AN6 mình dùng TIMER3 chấm dứt lấy mẫu có hợp lý ko anh, ADCHS mình khai báo như nào ah kết quả chuyển đổi từ 2 chân trên mình lấy ở đâu ra ah, có phải từ ADCBUF0 và ADCBUF6 ko bác
EM hỏi thêm bác đoặn này
bit 5-2 SMPI<3:0>: Sample/Convert Sequences Per Interrupt Selection bits
1111 = Interrupts at the completion of conversion for each 16th sample/convert sequence
1110 = Interrupts at the completion of conversion for each 15th sample/convert sequence
.....
0001 = Interrupts at the completion of conversion for each 2nd sample/convert sequence
0000 = Interrupts at the completion of conversion for each sample/convert sequence
cái này có phải lựa chon ngắt xảy ra sau 1 đến 16 lần chuyển đổi xong, hay ngắt khi lấy mẫu 1 đến 16 lần rồi chuyển đôi.
Em thấy cái thứ nhất có vẻ đúng hơn, có phải ko hả bác
Mong bác giúp đỡ em

han_nang_008
17-12-2008, 12:03 PM
bác namqn giúp em thêm cái này nữa, em viết đoặn chtr điều khiển tốc độ động cơ dùng triết áp, điểm đầu và chuối mắc vào 0 và 5V, điểm giữa đưa vào AN0 của 30F4011, dùng L298,
với động cơ chưa có tải, và em để PWM là kich chuyển đổi ADC thì em chỉnh chiết áp thì tốc độ thay đổi rất trươn ko có vấn đề j cả, nhung em cho thêm cái tải là em dùng dây cô doa nối sang 1 động cơ khác thôi, là tụ nhiên 2 chạy rất giật, điều chỉnh tốc độ cũng bị giật mà để em 1 vị trí tốc độ thì nó chạy dc vài vông lại giật 1 cái, ở dải tốc độ thấp cả 2 con đều ko chay, em có chuyển sang dùng timer3 kích chuyển đổi thì có vẻ chạy ko bị giật hơn và ở giải tốc đọ thấp vẫn điều khiển dc, nhung chỉ cần hơi vặn nhanh triết áp 1 tí là vdk bị đơ và dc đứng yên. anh xem hộ em vơi
đây là code của em

------------------------------------------------------------------------------*/
#include <p30f4011.h>
#include <pwm.h>
#include <adc10.h>

_FOSC(CSW_FSCM_OFF & FRC_PLL4);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_EN);
_FGS(CODE_PROT_OFF);

//------------------------------------------------------------------------------
//Cac hang so cua chuong trinh (gia tri tuc thoi dung trong chuong trinh)
#define PWM_PORT PORTE //Cac tin hieu PWM nam o cong E
#define PWM_TRIS TRISE //Thanh ghi 3 trang thai cho cac tin hieu PWM
#define PWM_LAT LATE //Thanh ghi chot cac tin hieu PWM

//Cac prototype cho cac chuong trinh con
void Init_PORTS(void);
void INT_MCPWM(void);
void INT_ADC10BIT(void);

//Chuong trinh Khoi tao Module MCPWM
//------------------------------------------------------------------------------
void INT_MCPWM(void)
{
unsigned int config1, config2, config3;
unsigned int period, sptime;


period = 368; // Oche do Free run PTPER = fcy/fpwm/PTMRprescaler - 1
// fcy = 7.37 Mhz, Fpwm = 20 KHz, PTMRprescaler = 1 ==> PTPER =
sptime = 0; //Thiet lap thanh ghi SEVTCMP cho viec tao ngat su kien dac biet(neu can)

config1 = PWM_EN & //PWM Module Enable
PWM_IDLE_STOP& //Idle Mode Operation
PWM_OP_SCALE1& //Output post scaler 1:1
PWM_IPCLK_SCALE1& //input prescaler 1:1
PWM_MOD_FREE; //mode of free run

config2 = PWM_MOD1_IND& //Dung cac chan PWM L&H 1 cach doc lap
PWM_MOD2_IND&
PWM_MOD3_IND&
PWM_PDIS1H& //Chi dung chuc nang PWM voi chan PWM1L
PWM_PDIS2H&
PWM_PDIS3H&
PWM_PEN1L&
PWM_PDIS2L&
PWM_PDIS3L ;

config3 = PWM_SEVOPS16& //Special event post scaler
PWM_OSYNC_TCY& //output Override synchronization
PWM_UEN; //PWM update enable/disable

OpenMCPWM(period, sptime, config1, config2, config3);

PDC1=0;
}

//Chuong trinh Khoi tao Module ADC 10bit
//------------------------------------------------------------------------------
void INT_ADC10BIT(void)
{
unsigned int config1, config2, config3, configport, configscan;
unsigned int channel;


channel = ADC_CH0_POS_SAMPLEA_AN0 ; // A/D Chan 0 pos i/p sel for SAMPLE A is AN0
SetChanADC10(channel);

config1 = ADC_MODULE_ON&
ADC_IDLE_STOP&
ADC_FORMAT_INTG& //dinh dang ket qua là canh phai (right justify)
ADC_CLK_MPWM& //Module PWM cham dut lay mau va kich hoat
ADC_SAMPLE_INDIVIDUAL &
ADC_AUTO_SAMPLING_OFF& //bat dau lay mau khi SAMP =1
ADC_SAMP_ON; //Khoi dong che do tu dong lay mau

config2 = ADC_VREF_AVDD_AVSS& //lay Vdd va Vss lam dien ap tham chieu
ADC_SCAN_OFF&
ADC_CONVERT_CH0&
ADC_SAMPLES_PER_INT_1& //co bao AIDF va bit DONE duoc set sau 1 lan lay mau (so lan lay mau tu 1 den 16 do bit SMPI <3:0>
ADC_ALT_BUF_OFF&
ADC_ALT_INPUT_OFF;

config3 = ADC_SAMPLE_TIME_1& //Thoi gian lay mau bang 1 Tad
ADC_CONV_CLK_SYSTEM&
ADC_CONV_CLK_2Tcy;

configport = ENABLE_AN0_ANA; //Enable chân AN0 la chan analog

configscan = SCAN_NONE;

OpenADC10(config1, config2, config3, configport, configscan);
_ADIF = 0; //Xoa co ngat ADC
_ADIE = 1; //Cho phep ngat ADC
_ADON = 1; //Bat module ADC

}
//Trinh phuc vu ngat cho ADC
//------------------------------------------------------------------------------
void _ISR _ADCInterrupt(void)
{
PDC1 = ADCBUF0; //Cap nhat cac thanh ghi dem chu ky nhiem vu
_ADIF = 0;
}

//------------------------------------------------------------------------------
//Chuong trinh chinh
int main(void) {
Init_PORTS(); //Khoi tao cac cong I/O
INT_MCPWM(); //Khoi tao module PWM
INT_ADC10BIT(); //Khoi tao module ADC
while (1) Nop();
}

//Chuong trinh con khoi tao cac cong I/O, de xuat cac tin hieu PWM, va doc tin
//hieu dieu chinh cua bien tro tai AN0
void Init_PORTS(void) {
PWM_LAT = 0; //Xoa thanh ghi chot cac tin hieu PWM
PWM_TRIS = 0xFFC0; //Cac tin hieu PWM nam tai RE0..RE5
TRISB = 0x0071; //Chan RB6 la ngo vao analog AN6, cac chan khac
//la ngo ra
_LATE2 = 0;
}



và em đang mong anh chỉ bảo cho em cách dùng nhiều hơn 1 chân analog như ở bài trc em đã hỏi.

namqn
17-12-2008, 09:23 PM
bác namqn có thể nói rõ hơn khi mình dùng nhiều hơn 1 chân ADC, bác có thể viết 1 đoặn ví dụ cụ thể dc ko ah.
Ví dụ dùng AN0 và AN6, chân AN0 lấy tín hiệu từ triết áp để điều khiển tốc độ động cơ, còn chân AN6 lấy tín hiệu dòng phản hồi của động cơ, rồi hiện thì lên LCD chẳng han,thì cấu hình như nào, tốc độ lấy mẫu như nào thì phù hợp ah, với AN0 thì dùng PWM chấm dứt lấy mẫu, còn với AN6 mình dùng TIMER3 chấm dứt lấy mẫu có hợp lý ko anh, ADCHS mình khai báo như nào ah kết quả chuyển đổi từ 2 chân trên mình lấy ở đâu ra ah, có phải từ ADCBUF0 và ADCBUF6 ko bác
EM hỏi thêm bác đoặn này
bit 5-2 SMPI<3:0>: Sample/Convert Sequences Per Interrupt Selection bits
1111 = Interrupts at the completion of conversion for each 16th sample/convert sequence
1110 = Interrupts at the completion of conversion for each 15th sample/convert sequence
.....
0001 = Interrupts at the completion of conversion for each 2nd sample/convert sequence
0000 = Interrupts at the completion of conversion for each sample/convert sequence
cái này có phải lựa chon ngắt xảy ra sau 1 đến 16 lần chuyển đổi xong, hay ngắt khi lấy mẫu 1 đến 16 lần rồi chuyển đôi.
Em thấy cái thứ nhất có vẻ đúng hơn, có phải ko hả bác
Mong bác giúp đỡ em
Bạn cần tham khảo hình 20-1 trong datasheet (hay hình 17-1 trong tài liệu "dsPIC30F Family Reference Manual") về cách thức kết nối các ngõ vào đến các bộ sample-and-hold (S/H), và xem thêm các khả năng sử dụng các bộ multiplexer A và B.

Tôi không có thói quen dùng hàm thư viện của MPLAB C Compiler for dsPIC, do đó tôi chỉ nêu những thay đổi đối với các thanh ghi liên quan đến module ADC, cho trường hợp ví dụ của bạn, sử dụng AN0 và AN6.

Dựa vào hình vẽ 20-1 trong datasheet, có thể thấy để lấy mẫu các ngõ vào AN0 và AN6, cần thiết lập để kênh S/H số 0 (CH0) sử dụng AN6, và kênh S/H số 1 (CH1) sử dụng AN0. Để làm việc này, thanh ghi ADCHS sẽ được thiết lập là 0x0006 (bạn xem "dsPIC30F Family Reference Manual" về ý nghĩa của các trường trong thanh ghi này). Đồng thời, các bit CHPS<1:0> trong thanh ghi ADCON2 cần được thiết lập là '01' để việc chuyển đổi được thực hiện cho CH0 và CH1. Tất nhiên, thanh ghi ADPCFG cũng cần cập nhật để các bit 6 và 0 là '0' (do đó các chân AN6 và AN0 sẽ là các chân analog).

Bạn có thể dùng chế độ tự động lấy mẫu, thay vì chọn một trong các nguồn tín hiệu chấm dứt lấy mẫu.

ADCBUF chỉ là một bộ đệm được lần lượt điền các kết quả vào, không có chuyện ánh xạ kết quả của AN0 vào ADCBUF0, và của AN6 vào ADCBUF6. Tôi chân thành đề nghị bạn đọc mục 17 của tài liệu "dsPIC30F Family Reference Manual", có rất nhiều ví dụ với hình minh họa về cách sử dụng bộ đệm ADCBUF. Câu hỏi của bạn về field SMPI<3:0> cũng được trả lời rõ trong phần này, theo như ý đầu tiên của bạn: ngắt sau 1 đến 16 chu kỳ lấy mẫu/chuyển đổi.

Thân,

namqn
17-12-2008, 09:25 PM
bác namqn giúp em thêm cái này nữa, em viết đoặn chtr điều khiển tốc độ động cơ dùng triết áp, điểm đầu và chuối mắc vào 0 và 5V, điểm giữa đưa vào AN0 của 30F4011, dùng L298,
với động cơ chưa có tải, và em để PWM là kich chuyển đổi ADC thì em chỉnh chiết áp thì tốc độ thay đổi rất trươn ko có vấn đề j cả, nhung em cho thêm cái tải là em dùng dây cô doa nối sang 1 động cơ khác thôi, là tụ nhiên 2 chạy rất giật, điều chỉnh tốc độ cũng bị giật mà để em 1 vị trí tốc độ thì nó chạy dc vài vông lại giật 1 cái, ở dải tốc độ thấp cả 2 con đều ko chay, em có chuyển sang dùng timer3 kích chuyển đổi thì có vẻ chạy ko bị giật hơn và ở giải tốc đọ thấp vẫn điều khiển dc, nhung chỉ cần hơi vặn nhanh triết áp 1 tí là vdk bị đơ và dc đứng yên. anh xem hộ em vơi
đây là code của em
...
Bạn cho biết sơ đồ nguyên lý của mạch động lực sử dụng L298 mà bạn đang dùng. Đôi khi mạch nguyên lý không có vấn đề nhưng mạch thực của bạn có thể dẫn đến nhiễu mạnh đối với vi điều khiển.

Thân,

han_nang_008
19-12-2008, 08:44 AM
mạch của em mắc như này, bỏ cái phần mắc cho vui, ko dùng con uc3611 mà dùng 4 con diode schotky, vấn đề củ em là ở phần mềm hay ở phần cứng hả anh

namqn
19-12-2008, 08:16 PM
mạch của em mắc như này, bỏ cái phần mắc cho vui, ko dùng con uc3611 mà dùng 4 con diode schotky, vấn đề củ em là ở phần mềm hay ở phần cứng hả anh
Đề nghị bạn dùng sơ đồ ứng dụng đã giới thiệu trong datasheet của L298.

Thân,

han_nang_008
20-12-2008, 10:23 PM
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ế

honinh_spkt
13-01-2009, 05:02 PM
''Chú ý là độ phân giải của chu kỳ nhiệm vụ là TCY/2, còn độ phân giải của chu kỳ xung là TCY. Do đó, chẳng hạn PTPER = 0x7F thì PDCx = 0xFF mới là chu kỳ nhiệm vụ = 100%.''
Anh namqn cho em hỏi là chu kỳ nhiệm vụ là như thế nào? thank's

namqn
13-01-2009, 06:25 PM
''Chú ý là độ phân giải của chu kỳ nhiệm vụ là TCY/2, còn độ phân giải của chu kỳ xung là TCY. Do đó, chẳng hạn PTPER = 0x7F thì PDCx = 0xFF mới là chu kỳ nhiệm vụ = 100%.''
Anh namqn cho em hỏi là chu kỳ nhiệm vụ là như thế nào? thank's
Bạn nên đọc các tài liệu cơ bản về PWM (Pulse Width Modulation). Chu kỳ nhiệm vụ (duty cycle) là một khái niệm cơ bản trong PWM. Ví dụ, bạn có một tín hiệu điều khiển với chu kỳ là 10 ms. Trong khoảng thời gian 10 ms đó, có 4 ms tín hiệu ở trạng thái tích cực, còn 6 ms tín hiệu ở trạng thái không tích cực, chúng ta nói tín hiệu có duty cycle = 40% (tức là bằng thời gian tích cực/thời gian chu kỳ).

Thân,

ham_hoc_hoi
22-01-2009, 11:24 PM
bác nam ơi, em đọc 1 lúc 5 chân ADC là AN0,1,2,3,6
các chân này em nối với chân giữa của biến trở 100k, 2 chân còn lại của btr dc nối vào nguồn 5V, em đã đọc dc 5 giá tri ADC và hiển thị len LCD, nhưng mà các giá trị này toàn bị dao động thôi bác ah, ngoại trừ em vặn về 0 và 5V thì giá trị ADC đứng yên, em vặn 1 giá trị bất kì chẳng hạn thì nó dao đọng ví dụ từ 231 đến 243, nó cứ chạy lên chạy xuống.
Làm sao để đọc dc giá trị ko bị dao động hả bác

Mr.Bi
22-01-2009, 11:56 PM
bác nam ơi, em đọc 1 lúc 5 chân ADC là AN0,1,2,3,6
các chân này em nối với chân giữa của biến trở 100k, 2 chân còn lại của btr dc nối vào nguồn 5V, em đã đọc dc 5 giá tri ADC và hiển thị len LCD, nhưng mà các giá trị này toàn bị dao động thôi bác ah, ngoại trừ em vặn về 0 và 5V thì giá trị ADC đứng yên, em vặn 1 giá trị bất kì chẳng hạn thì nó dao đọng ví dụ từ 231 đến 243, nó cứ chạy lên chạy xuống.
Làm sao để đọc dc giá trị ko bị dao động hả bác

làm sao ko dao động đc u ?!! nguyên nhân í là do biến trở than của chúng ta . Cách khắc phục : adc = read_adc(AN0) , nếu (231<= adc <=243) thì ta làm công việc j đóa . Dễ ẹt thui mà ! động não chút là ta có thể dùng software khắc phục nhược điểm của hareware.

namqn
23-01-2009, 12:15 AM
bác nam ơi, em đọc 1 lúc 5 chân ADC là AN0,1,2,3,6
các chân này em nối với chân giữa của biến trở 100k, 2 chân còn lại của btr dc nối vào nguồn 5V, em đã đọc dc 5 giá tri ADC và hiển thị len LCD, nhưng mà các giá trị này toàn bị dao động thôi bác ah, ngoại trừ em vặn về 0 và 5V thì giá trị ADC đứng yên, em vặn 1 giá trị bất kì chẳng hạn thì nó dao đọng ví dụ từ 231 đến 243, nó cứ chạy lên chạy xuống.
Làm sao để đọc dc giá trị ko bị dao động hả bác
Biến trở của bạn có giá trị lớn quá, làm cho nội trở tương đương của nguồn tín hiệu cũng lớn. Bạn thử dùng biến trở 5 k hay 1 k xem.

Với ADC 10-bit, hai bit cuối cùng thường dao động với mạch thử nghiệm thông thường của bạn. Cần thiết kế phù hợp để đạt được đầy đủ độ phân giải 10-bit.

Thân,

ham_hoc_hoi
24-01-2009, 11:20 AM
Biến trở của bạn có giá trị lớn quá, làm cho nội trở tương đương của nguồn tín hiệu cũng lớn. Bạn thử dùng biến trở 5 k hay 1 k xem.

Với ADC 10-bit, hai bit cuối cùng thường dao động với mạch thử nghiệm thông thường của bạn. Cần thiết kế phù hợp để đạt được đầy đủ độ phân giải 10-bit.

Thân,
em đã thử thay biến trở nhỏ trở nhỏ, thậm chí dịch phải 2 bit thì tình hình cũng không khá nê lên là máy, nóc vẫn dao động lên xuống bác ah, Thiết kế phù hợp như nào hả bác, bác chỉ cho em dc ko, em dùng biến trở thay đổi tốc đọ mà nó cứ dao đọng thế này thì tốc đọ cũng dao động theo

namqn
24-01-2009, 05:02 PM
em đã thử thay biến trở nhỏ trở nhỏ, thậm chí dịch phải 2 bit thì tình hình cũng không khá nê lên là máy, nóc vẫn dao động lên xuống bác ah, Thiết kế phù hợp như nào hả bác, bác chỉ cho em dc ko, em dùng biến trở thay đổi tốc đọ mà nó cứ dao đọng thế này thì tốc đọ cũng dao động theo
Bạn đọc app. note sau của Microchip để hình dung những vấn đề gặp phải khi thiết kế với các bộ ADC có độ phân giải từ 10-bit trở lên: http://ww1.microchip.com/downloads/en/AppNotes/00688b.pdf.

Ngay cả những hướng dẫn của họ cũng vẫn mang tính lý thuyết, và bạn vẫn cần kinh nghiệm thực tế để thực hiện tốt những dẫn hướng đó.

Các nhà sản xuất ADC hàng đầu như Maxim, Analog Devices, hay Linear Technology đều có các app. note hướng dẫn thiết kế mạch giao tiếp với ADC để đạt độ phân giải danh định của vi mạch. Chẳng hạn:
http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1155,C1001,C1158, P1037,D4160
http://pdfserv.maxim-ic.com/en/an/AN1948.pdf

Rất tiếc là tôi không có điều kiện để tìm hết các tài liệu này cho bạn, hơn nữa, kinh nghiệm thiết kế kiểu này khó có thể truyền đạt qua diễn đàn.

Thân,

ham_hoc_hoi
07-02-2009, 08:37 PM
Bác namqn ơi cho em hỏi, có lẽ nào bộ ADC của con 30F4011 chết được ko hả bác, bo mạch em vân dùng bình thg ko đọng j đến cả, tự nhiên em bật nên thì tất cả các bộ đệm của ADC đều ở giá trị max là 1023, em đã kiểm tra hết tất cả đầu vào xoay biến trở thì vẫn chạy từ 0 đến 5V, em thử nạp lại mấy ch trình ADC đã chạy ngon thì vẫn thế, con chip này làm việc với LCD, PWM, UART vẫn ngon bác ah. Không nhẽ nó chỉ hỏng mỗi bộ ADC10 bit

conglong
19-03-2009, 12:43 AM
Thầy Nam cho em hỏi là trong file p30f2010.h của phần mềm mplap C30 có đoạn họ định nghĩa về 16 buffer chứa kết quả tạm thời của ADC là :
" extern volatile unsigned int ADCBUF0 __attribute__((__sfr__));
extern volatile unsigned int ADCBUF1 __attribute__((__sfr__));
extern volatile unsigned int ADCBUF2 __attribute__((__sfr__));
extern volatile unsigned int ADCBUF3 __attribute__((__sfr__));
.........."
vậy ở đây __attribute__((__sfr__)) có nghĩa là gì hả thầy?

Cho em hỏi câu nữa là em muốn cùng một lúc 6 ngõ vào AD là AN0 ... AN5 , thì em phải làm thiết lập sao? bởi vì em thấy trong Farmily rerence .... chỉ thấy có 4 chanels chuyển đổi nên khi dung 6 ngõ vào AD có vấn đề ? chắc em hiểu chưa cặn kẽ về AD module mong thầy chỉ rõ dùm em.
Em cảm ơn.
Trân trọng !.

conglong
19-03-2009, 01:53 AM
Ở 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 không trả lờ câu hỏi này được>
Em cảm ơn.
Trân trong !.

namqn
19-03-2009, 02:50 AM
Thầy Nam cho em hỏi là trong file p30f2010.h của phần mềm mplap C30 có đoạn họ định nghĩa về 16 buffer chứa kết quả tạm thời của ADC là :
" extern volatile unsigned int ADCBUF0 __attribute__((__sfr__));
extern volatile unsigned int ADCBUF1 __attribute__((__sfr__));
extern volatile unsigned int ADCBUF2 __attribute__((__sfr__));
extern volatile unsigned int ADCBUF3 __attribute__((__sfr__));
.........."
vậy ở đây __attribute__((__sfr__)) có nghĩa là gì hả thầy?

Cho em hỏi câu nữa là em muốn cùng một lúc 6 ngõ vào AD là AN0 ... AN5 , thì em phải làm thiết lập sao? bởi vì em thấy trong Farmily rerence .... chỉ thấy có 4 chanels chuyển đổi nên khi dung 6 ngõ vào AD có vấn đề ? chắc em hiểu chưa cặn kẽ về AD module mong thầy chỉ rõ dùm em.
Em cảm ơn.
Trân trọng !.
__attribute__((__sfr__)) thể hiện rằng các thanh ghi này là các thanh ghi SFR (Special File Register) của dsPIC.

dsPIC30F2010 chỉ có một bộ chuyển đổi A/D (là phần tử ADC trong sơ đồ ở hình 18-1 của datasheet). dsPIC30F2010 có thể lấy mẫu (sample) mỗi lần 1 ngõ vào, 2 ngõ vào, hay 4 ngõ vào, tùy theo sự thiết lập của các bit CHPS trong thanh ghi ADCON2. dsPIC30F2010 có thể lấy mẫu cả 4 kênh một lần nhờ vào sự hiện diện của 4 bộ S/H (Sample and Hold), được ký hiệu là CH0 đến CH3 trong sơ đồ nêu trên. Dù bạn lấy mẫu kiểu nào đi nữa, mỗi tín hiệu được lấy mẫu đều được xử lý bởi cùng một bộ chuyển đổi A/D.

Để chuyển đổi 6 ngõ vào AN0 đến AN5, bạn sẽ phải lấy mẫu 6 ngõ vào đó theo một thứ tự nào đó (phù hợp với sự bố trí các chân analog đến các bộ S/H), và lần lượt chuyển đổi các tín hiệu đã được lấy mẫu đó. Ví dụ, bạn có thể chỉ dùng một bộ S/H CH0 và lần lượt lấy mẫu, sau đó chuyển đổi các ngõ vào AN0 đến AN5. Hoặc bạn có thể dùng 2 bộ S/H CH0 và CH1, để cùng lúc lẫy mẫu AN0 và AN1, sau đó lần lượt chuyển đổi các ngõ vào này, rồi sau đó thiết lập để dùng 4 bộ S/H từ CH0 đến CH3, để cùng lúc lấy mẫu AN2 đến AN5, và sau đó lần lượt chuyển đổi các ngõ vào này.

Với mỗi cách thực hiện, code để hiện thực sẽ có sự thay đổi tương ứng. Đề nghị bạn đọc thêm về bộ ADC 10-bit trong tài liệu "dsPIC30F Family Reference Manual" (mã của tài liệu là DS70046) trước khi đặt tiếp câu hỏi (điều này sẽ giúp bạn hiểu được những câu trả lời).

Thân,

namqn
19-03-2009, 02:57 AM
Ở 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
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
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
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
Đâ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
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
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
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

#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
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
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:

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
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:

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
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
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
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
Đâ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
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
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
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
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
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
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
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
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
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
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
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

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:

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

dinhvanloc
30-10-2012, 10:28 AM
Đâ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,

em chào anh. anh cho em hỏi cách nào để dừng động cơ đang chạy trong thời gian nhỏ nhất. em dùng IC l298 để điều khiển.
em cảm ơn anh!

nguyenvietcuong
11-12-2012, 05:58 PM
em chào anh. anh cho em hỏi cách nào để dừng động cơ đang chạy trong thời gian nhỏ nhất. em dùng IC l298 để điều khiển.
em cảm ơn anh!

Mình nghĩ dừng động cơ đang chạy trong thời gian nhỏ nhất thì chỉ cần cho xung điều khiển động cơ đó về 0, hoặc dùng chương trình đảo chiều quay của động cơ rồi cấp xung hãm cho nó, hoặc dùng thuật toán điều khiển vận tốc động cơ kết hợp encoder. Nhưng câu hỏi của bạn chung chung quá, không biết ý của bạn chỉ là tắt động cơ đang chạy hay còn có ý nào khác không nhỉ?

nguyenvietcuong
11-12-2012, 06:17 PM
Mọi người có kinh nhiệm lập trình ADC cho dsPic33F cho em hỏi một chút xíu... Em đang lập trình ADC cho con dsPic33FJ32GS608. Nhưng em đọc trên datasheet của con này thì các thanh ghi ADC của nó khác hoàn toàn so với những con dsPic mà mọi người đang đang lấy ví dụ ở đây. Cụ thể là nó chỉ có thanh ghi ADCON mà không có các thanh ghi ADCON1, ADCON2, ADCON3. Em nghĩ là có thể datasheet không ghi hết nhưng khi em sử dụng các thanh ghi này trong MpLab IDE thì nó báo lỗi không hiểu các thanh ghi trên là gì. Em lên trên trang microchip để tìm code mẫu thì chỉ được các code dùng cho các con dsPic có các thanh ghi ADCON1, ADCON2, ADCON3 mà thôi. Trên datasheet của con chip này cũng có code mẫu nhưng em đã thử, nó biên dịch được nhưng chương trình không hoạt động. Em muốn hỏi mọi người có phải con dsPic33FJ32GS608 này có phải là dòng đặc biệt của microchip hay không mà thanh ghi ADC của nó lại khác học dsPic33F như vậy ạ? Mọi người đã từng làm với con này rồi có thể cho em một vài cao kiến hoặc chương trình khai báo sử sụng ADC của nó được không ạ? Em muốn sử dụng 8 chân ADC của nó để đọc tín hiệu sensor nhận vạch trắng.

manhquy1992
12-09-2013, 10:33 PM
Ai có thư viện DSP30F trong protues không cho mình với!