![]() |
|
Tài trợ cho PIC Vietnam |
||||||||
| Thực hành Bắt đầu làm một robot như thế nào? Mẹo vặt? Kỹ thuật? Công nghệ?... Hãy bắt tay vào việc... |
![]() |
|
|
Ðiều Chỉnh | Xếp Bài |
|
|
|
|
#1 |
|
Đệ tử 1 túi
Tham gia ngày: Mar 2007
Bài gửi: 25
: |
cảm ơn bạn!!
mạch của mình ,do chân encoder mình đưa chân timer 1! nên mình tính dùng timer 1 để đọc encoder, động cơ mình dùng có công suất thấp với lại encoder 100 xung/1 vòng nên timer 1 ko sợ bị tràn mình có sửa lại đoạn code của cậu cho phù hợp với mạch của mình! khi chạy thử thì no báo lỗi mong bạn giúp đỡ Code:
#include <16f877a.h>
#fuses HS,NOPROTECT,NOWDT,NOBROWNOUT
#use delay (clock = 20000000)
// Giao tiep vi dieu khien
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8) // Giao tiep RS232
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include<ctype.h>
#byte PR2 = 0x92
int16 e2;
int16 e1;
///////////////////////////////////////////////////////
int16 v_set = 250;
/////////////////////////////////////////////////////////
int16 v_cur;
int16 e_sum;
int16 e_del;
int16 flag_timer1;
///////////////////////////////////////////////////////////
unsigned long kp =5;
unsigned long ki = 0.62;
unsigned long kd = 10;
////////////////////////////////////////////////////////////
int16 i = 1 ;
int16 pw_duty;
int16 counted_round_value;
int16 temp_timer0;
int16 temp_timer1;
int16 update_counted_round_value;
#byte TMR0 = 0x01 //timer0 REGISTER
#byte TMR1_L = 0X0E
#byte TMR1_H = 0X0F
#define START_VALUE_TIMER0 5 //tri khoi tao ban dau cua timer0 5, so xung dem duoc moi khi ngat la 255 - 5
#define START_VALUE_TIMER1 5535 //tri khoi tao ban dau cua timer1 65536-5536=60000
#INT_TIMER0 // ngat timer0 tang bien len 1
void TIMER0_int()
{
set_timer0(START_VALUE_TIMER0);
i++;
}
void doc_xung()
{
if ( i==50 )
temp_timer1 = get_timer1();
set_timer1(START_VALUE_TIMER1);//lan tran thu 50 cua timer0 se set timer1
i=0;
if (temp_timer0 == 0){
temp_timer0= 255;
}
v_cur = 2*(temp_timer1 - START_VALUE_TIMER1);
set_timer1(START_VALUE_TIMER1);
i = 1;
//printf("%ld\t",pw_duty);
flag_timer1 = 1;
}
void init_timer0()
{
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16); // moi lan tran timer0 tuong ung 250*16*1/5 us = 0.8ms,chu ky lay mau=0.8*50=40ms
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1); // moi lan tran timer0 , khoi tao lai luon gia tri dem xung timer1
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
}
void init_PWM(int16 frequency){
setup_ccp1(CCP_PWM); // initiate PWM
PR2 = 20000000/4/frequency - 1; // set PWM period
setup_timer_2(T2_DIV_BY_1,255,1); // initiate time 2 The cycle time will be (1/clock)*4*t2div*(period+1)
// (1/20000000)*4*1*(255+1) = 51.2 us( will over flow every 51.2 us, will intrup every 51.2 uS or 19.5 khz;
}
void cal_pid(){
long temp_kp;
long temp_ki;
long temp_kd;
e2 = v_set - v_cur;
e_sum += e2;
e_del = e2 - e1;
e1 = e2;
temp_kp = kp*e2;
temp_ki = ki*e_sum;
temp_kd = kd*e_del;
pw_duty +=temp_kp;
if (pw_duty <800)
pw_duty += temp_ki;
if (pw_duty <800)
pw_duty += temp_kd;
if (pw_duty <256) // vi khi pw_duty <256 thi PWM chi dieu rong xung 8 bit / //chu khong phai 10 bit,
pw_duty = 256;
if (pw_duty >800) // bao hoa
pw_duty = 800;
printf(" \t%ld", v_cur); // truyen toc do xung ve may tinh hien thi tren Hyperterminal
}
void main()
{
int8 timer0_value;
init_timer0();
init_PWM(19500);
while(true){
if (flag_timer1 ==1){
flag_timer1 = 0;
cal_pid();
set_pwm1_duty(pw_duty);
}
}
}
thay đổi nội dung bởi: namqn, 12-05-2007 lúc 06:50 PM. |
|
|
|
|
|
#2 |
|
Đệ tử 3 túi
Tham gia ngày: Jun 2006
Bài gửi: 53
: |
tôi đã sửa một số chỗ sai trong đoạn code của bạn rồi, xem lại đi nhe
Code:
#include <16f877a.h>
#fuses HS,NOPROTECT,NOWDT,NOBROWNOUT
#use delay (clock = 20000000)
// Giao tiep vi dieu khien
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8) // Giao tiep RS232
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include<ctype.h>
#byte PR2 = 0x92
int16 e2;
int16 e1;
///////////////////////////////////////////////////////
int16 v_set = 350;
/////////////////////////////////////////////////////////
int16 v_cur;
int16 e_sum;
int16 e_del;
int16 flag_timer0;
//////////////////// cac thong so pid ban co the thay doi cho
//////////////////// phu hop voi dong co cua ban
unsigned long kp =2.5;
unsigned long ki = 0.0092;
unsigned long kd = 0;
////////////////////////////////////////////////////////////
int16 i = 1 ;
int16 pw_duty;
int16 counted_round_value;
int16 temp_timer0;
int16 temp_timer1;
int16 update_counted_round_value;
//#byte TMR0 = 0x01 //timer0 REGISTER
//#byte TMR1_L = 0X0E
//#byte TMR1_H = 0X0F
#define START_VALUE_TIMER0 5 //tri khoi tao ban dau cua timer0 5, so xung dem duoc moi khi ngat la 255 - 5
#define START_VALUE_TIMER1 5535 //tri khoi tao ban dau cua timer1 65536-5536=60000
#INT_TIMER0 // ngat timer0 tang bien len 1
void TIMER0_int()
{
set_timer0(START_VALUE_TIMER0);
i++;
///////////// ban sai cho nay
if(i==60 ){
temp_timer1 = get_timer1();
set_timer1(START_VALUE_TIMER1);
i=0;
v_cur = 2*(temp_timer1 - START_VALUE_TIMER1);
flag_timer0 = 1;
}
}
#INT_TIMER1 /// thuc hien khi ngat timer 1
void timer1_int(){
set_timer1(START_VALUE_TIMER1);
}
void init_timer0()
{
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16); // moi lan tran timer0 tuong ung 250*16*1/5 us = 0.8ms,chu ky lay mau=0.8*60=48ms
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_2); // he so chia la 2 moi lan tran timer0 , khoi tao lai luon gia tri dem xung timer1
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER1);
}
void init_PWM(int16 frequency){
setup_ccp1(CCP_PWM); // initiate PWM
PR2 = 20000000/4/frequency - 1; // set PWM period
setup_timer_2(T2_DIV_BY_1,255,1); // initiate time 2 The cycle time will be (1/clock)*4*t2div*(period+1)
// (1/20000000)*4*1*(255+1) = 51.2 us( will over flow every 51.2 us, will intrup every 51.2 uS or 19.5 khz;
}
void cal_pid(){
long temp_kp;
long temp_ki;
long temp_kd;
e2 = v_set - v_cur;
e_sum += e2;
e_del = e2 - e1;
e1 = e2;
temp_kp = kp*e2;
temp_ki = ki*e_sum;
temp_kd = kd*e_del;
pw_duty +=temp_kp;
if (pw_duty <1000)
pw_duty += temp_ki;
if (pw_duty <1000)
pw_duty += temp_kd;
if (pw_duty <256) // vi khi pw_duty <256 thi PWM chi dieu rong xung 8 bit / //chu khong phai 10 bit,
pw_duty = 256;
if (pw_duty >1000) // bao hoa
pw_duty = 1000;
printf(" \t%ld", v_cur); // truyen toc do xung ve may tinh hien thi tren Hyperterminal
}
void main()
{
int8 timer0_value;
init_timer0();
init_PWM(19500);
//set_pwm1_duty(500);
while(true){
if (flag_timer0 ==1){
flag_timer0 = 0;
cal_pid();
set_pwm1_duty(pw_duty);
}
}
}
thân, thay đổi nội dung bởi: namqn, 14-05-2007 lúc 07:23 PM. |
|
|
|
|
|
#3 |
|
Nhập môn đệ tử
Tham gia ngày: May 2007
Bài gửi: 10
: |
Help Me !
minh co tham khao doan code cua bluepine va lam nhu sau : minh da tao 4 nut nhan tren Vb : opencom , closecom , start , stop . Nut start se gui gia tri "a" , stop goi gia tri "b" .
Phan pic minh viet voi muc dich nhu sau : dung ngat RDA de khi co 1 bye du lieu truyen tu may tinh ( ki tu "a" hay "b" ) , thi con pic dung hoat dong , nhay den gan gia tri do ( khong biet gia tri luc do la ma hay la ki tu nhi ) vao bien tam va kiem tra ! Dung ngat timer0 lam chu ki lay mau , va doc gia tri timer1 ( doc encoder ; chan ccp2 : gan voi tin hieu encoder ) chuong trinh nhu sau : Code:
#include <16f877a.h>
#device *=16 ADC=10
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay (clock = 20000000)
// Giao tiep vi dieu khien
#use rs232(baud=9600, parity=N,xmit=PIN_C6, rcv=PIN_C7 ) // Giao tiep RS232
#use i2c(master,fast,sda=PIN_C4,scl=PIN_C3,FORCE_HW)
#use fast_io(A)
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include<ctype.h>
#byte PR2 = 0x92
int16 e2;
int16 e1;
///////////////////////////////////////////////////////
int16 v_set = 200;
/////////////////////////////////////////////////////////
int16 v_cur;
int16 e_sum;
int16 e_del;
int16 flag_timer1;
int16 i=1 ;
///////////////////////////////////////////////////////////
unsigned long kp =5;
unsigned long ki = 0.62;
unsigned long kd = 10;
////////////////////////////////////////////////////////////
int16 pw_duty;
int16 temp_timer1;
char tam ;
#byte TMR0 = 0x01 //timer0 REGISTER
#byte TMR1_L = 0X0E
#byte TMR1_H = 0X0F
#define START_VALUE_TIMER0 5 //tri khoi tao ban dau cua timer0 55, so xung dem duoc moi khi ngat la 255 - 5
#define START_VALUE_TIMER1 15535 //tri khoi tao ban dau cua timer1 65536-15536
#define dir PIN_B3 //or #bit dir = 0x6.3
#define brk PIN_B4
#define pwm PIN_C2
#priority RDA , timer0
#INT_RDA// ngat khi nhan 1 bye
RDA_isr()
{
tam=getc(); // lay gia tri tu cong
}
#INT_TIMER0 // ngat timer0 tang bien len 1
void timer0_int()
{
set_timer0(START_VALUE_TIMER0);
i++ ;
if ( i==50 )//neu nhu sau 50 lan tran cua timer0 (40ms:chu ki lay mau ) thi :
temp_timer1 = get_timer1();
set_timer1(START_VALUE_TIMER1);//lan tran thu 50 cua timer0 se set timer1
v_cur = 8*(temp_timer1 - START_VALUE_TIMER1);
i = 0;
printf("%ld\t",pw_duty);
flag_timer1 = 1;
}
void init_timer0()
{
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16); // timer0 dung xung ngoai va chia xung vao
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_8); //
set_timer0(START_VALUE_TIMER0);
set_timer1(START_VALUE_TIMER1);
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
}
void init_PWM(int16 frequency){
setup_ccp1(CCP_PWM); // initiate PWM
PR2 = 20000000/4/frequency - 1; // set PWM period
setup_timer_2(T2_DIV_BY_1,255,1); // initiate time 2 The cycle time will be (1/clock)*4*t2div*(period+1)
// (1/20000000)*4*1*(255+1) = 51.2 us( will over flow every 51.2 us, will intrup every 51.2 uS or 19.5 khz;
}
void cal_pid(){
long temp_kp;
long temp_ki;
long temp_kd;
e2 = v_set - v_cur;
e_sum += e2;
e_del = e2 - e1;
e1 = e2;
temp_kp = kp*e2;
temp_ki = ki*e_sum;
temp_kd = kd*e_del;
pw_duty +=temp_kp;
if (pw_duty <1000)
pw_duty += temp_ki;
if (pw_duty <1000)
pw_duty += temp_kd;
if (pw_duty <1000) // vi khi pw_duty <256 thi PWM chi dieu rong xung 8 bit / //chu khong phai 10 bit,
pw_duty = 256;
if (pw_duty >1000) // bao hoa
pw_duty = 1000;
printf(" \t%ld", v_cur); // truyen toc do xung ve may tinh hien thi tren Hyperterminal
}
void main()
{
int8 timer0_value;
init_timer0();
init_PWM(19500);
while(tam=='a') //vd 'a' ung voi nut quay thuan // khac a , khac (b) la stop
{
if (flag_timer1 ==1)
{
flag_timer1 = 0;
cal_pid();
output_low(pwm);// tat 4 con fet tuc thoi
delay_us(20);
output_low(brk);
output_low(dir);
delay_us(50);
set_pwm1_duty(pw_duty);
}
}
}
thay đổi nội dung bởi: falleaf, 16-05-2007 lúc 05:12 PM. |
|
|
|
|
|
#4 |
|
Nhập môn đệ tử
Tham gia ngày: May 2007
Bài gửi: 10
: |
code chuong trinh VB cua minh ne !
va day la code vb cua minh :
Code:
Private Sub cmdClosecom_Click()
MSComm.PortOpen = False
Cmdopencom.Enabled = True
Cmdstart.Enabled = False
cmdClosecom.Enabled = False
End Sub
Private Sub cmdexit_Click()
Unload Me
End Sub
Private Sub Cmdopencom_Click()
If MSComm.PortOpen = True Then
MSComm.PortOpen = False
End If
MSComm.CommPort = 1
MSComm.Settings = "9600,N,8,1"
MSComm.InBufferCount = 0
MSComm.InputLen = 0
MSComm.PortOpen = True
cmdStop.Enabled = False
Cmdstart.Enabled = True
Cmdopencom.Enabled = False
cmdClosecom.Enabled = True
End Sub
Private Sub Cmdstart_Click()
MSComm.Output = "a"
cmdStop.Enabled = True
Cmdstart.Enabled = False
End Sub
Private Sub cmdStop_Click()
MSComm.Output = "b"
cmdStop.Enabled = False
Cmdstart.Enabled = True
End Sub
Private Sub Form_Load()
Cmdstart.Enabled = False
cmdStop.Enabled = False
cmdClosecom.Enabled = False
End Sub
thay đổi nội dung bởi: falleaf, 16-05-2007 lúc 05:13 PM. |
|
|
|
|
|
#5 |
|
PIC Bang chủ
|
Gửi thêm cái tutorial PID, cái này cực đơn giản, làm với Matlab, lại rất hay.
Chúc vui
__________________
Công ty TNHH Thương mại và Giao nhận R&P store.hn@rpc.vn - store.hcm@rpc.vn Học PIC như thế nào? thay đổi nội dung bởi: falleaf, 23-05-2007 lúc 02:26 AM. |
|
|
|
|
|
#6 |
|
Đệ tử 2 túi
Tham gia ngày: Jan 2007
Bài gửi: 34
: |
Help me!Help me!
Mình muốn làm một bộ điều khiển PID như của bạn. Mình kiếm mãi mới tìm được một em động cơ Encorder 100x/v. Mình đã đọc hết tất cả những bài bạn viết trong luồng "Tìm người làm bài thực hành PID..." và muốn bạn giúp đỡ trong quá trình làm. Không biết luồng trên còn làm việc không hay xong rồi mà mình hỏi mãi không thấy ai trả lời cả. Mình down sơ đồ nguyên lý của bạn bằng Orcard về rồi nhưng không sao mở được,bạn vẽ trên orcard 9.0,9.1,hay 10.0 vậy. Nếu có thể bạn gửi cho mình cả sơ đồ và chương trình bạn viết cho PID giao tiếp với máy tính được không?Cảm ơn bạn nhiều! Mình thực sự rất muốn thử làm cái bạn đã làm này. Cám ơn bạn rất nhiều!Happy New Year 2008! Nếu có thể gửi cho mình qua mail nguyenvan_lanh3@yahoo.com.Mong học hỏi ở bạn nhiều điều bổ ích nhờ các bạn và PICVN!
|
|
|
|
|
|
#7 | |
|
Đệ tử 1 túi
Tham gia ngày: Jan 2007
Bài gửi: 21
: |
Trích:
unsigned long ki = 0.0092. nếu khai báo như thế này thì ki là số nguyên phải không? Nếu vậy thì ki ở đây sẽ bằng 0. Không biết tôi có sai chỗ nào không. Các bạn góp ý nhé ![]() |
|
|
|
|
|
|
#8 |
|
Trưởng lão PIC bang
|
Hai vấn đề bạn jean thảo luận đều đúng.
Nếu không dùng directive #TYPE signed để định nghĩa lại kiểu mặc định là signed thì các khai báo int16 đều được CCS C hiểu ngầm là số không dấu => có vấn đề, vì sai số nên được biểu diễn bằng số có dấu. kd, ki đều dùng kiểu số thực khi đặt giá trị, nhưng lại khai báo là unsigned long. Có 2 khả năng xảy ra, CCS C sẽ chuyển kiểu biểu thức thành kiểu của biến (có vấn đề) hay chuyển kiểu của biến thành float để có thể chứa giá trị của biểu thức (không có vấn đề). Tôi không dùng CCS C nên không thể đánh giá được. Nhờ các bạn khác có sử dụng CCS C đánh giá vấn đề này. Nói chung, không nên để trình biên dịch làm chủ chúng ta, mà chúng ta nên làm chủ trình biên dịch, tức là hiểu rõ phải viết code C ra sao để có được kết quả mong muốn. Nếu chưa hiểu được trình biên dịch sẽ dịch code đang đặt nghi vấn ra sao, tại sao chúng ta không viết code thử nghiệm, biên dịch nó, và đánh giá kết quả bằng việc mô phỏng/thử nghiệm. Thân,
__________________
Biển học mênh mông, sức người có hạn. Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau: http://www.picvietnam.com/forum/showthread.php?t=1263 |
|
|
|
![]() |
| Ðiều Chỉnh | |
| Xếp Bài | |
|
|