Thông báo

Collapse
No announcement yet.

tutorial cho HTPIC

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • #46
    Lấy đặc tính h(t) của động cơ.

    Chào các bạn. Tôi đã làm xong bài tập lớn môn lý thuyết điều khiển tự động là thiết kế bộ điều khiển PID trên nền PIC.Bây giờ tôi xin đưa các đoạn code của bài tập lớn của tôi.

    Đầu tiên là công việc là lấy đặc tính đáp ứng h(t) của động cơ để từ đó tính toán các tham số Kp, Ki, Kd. Đây là bước tính toán thô các giá trị của bộ PID sau đó mình mới tinh chỉnh lại sau ở một chương trình khác.

    Vi điều khiển ứng dụng: PIC6F877A

    Ngôn ngữ lập trình: HTPIC

    Trong bài này tôi mục đích làm như sau: khi ấn "P" trên giao diện trên PC hay nói cách khác truyền kí tự P xuống chip thì nó nhận lệnh và cho động cơ hoạt động. Tôi điều chế một xung 15KHZ, ở đây cho độ rộng 100% luôn. Và từ đó liên tục đọc 500 giá trị và truyền lên PC.

    Thời gian trích mẫu của hệ thống là 10ms. Tôi truyền số xung đo được lên PC, từ số liệu này sẽ tính toán ra tốc độ thực và vẽ được hàm h(t) của đối tượng. Tôi dùng chương trình Terminal (do lười nên không viết chương trình trên PC riêng) và lấy dữ liệu và cho vào Matlab để nội suy ra hàm quá độ h(t) . Tôi định viết một chương trình bằng Matlab nhận giao tiếp RS232 tính toán và đưa ra đồ thị luôn. Nhưng phải chờ tí đã, dạo này ôn thi nên hơi lười làm.

    Chương trình Terminal và giao tiếp RS232 các bạn có thể xem tại
    http://www.picvietnam.com/forum/show...p?t=274&page=2

    Code chương trình trên Matlab: dùng nội suy Cubic
    Code:
    hold off;
    x_rough= 0:0.01:5;
    %x_fine= 0:0.05:0.8 ;% chon buoc noi suy tu xmin:0.1:xmax( voi xmin la gia tri nho nhat cua x_rough, xmax tuong tu;
    x_fine = 0:0.001: 5;
    data = [ ]; // Các giá trị số xung đo được 500 giá trị
    data = data * 1000 /(10 * 100 *12);     
    % tính toán ra tốc độ thực và chia cho 12V để suy ra đáp ứng khi U = 1V vì coi động cơ DC là tuyến tính
    % 100 là số lỗ /1 vòng của Encoder
    inter_cubic= interp1(x_rough,data,x_fine,'cubic');
    % noi suy theo phuong phap cubic
    plot(x_fine,inter_cubic,'k','LineWidth',2);
    grid on;
    Code cho PIC6F877A

    Code:
    #include<pic.h>
    # include "stdio.h"
    
    __CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );
    
    const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
    							0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};
    
    # define Ts 	10						// Thoi gian trich mau Ts (ms)
    # define Encoder_resolution 100		// So lo cua Encoder/1 vong
    # define Total_Point			500		// So diem can trich mau
    
    // ham truyen du lieu
    void putch(unsigned char byte) 
    {
    	/* output one byte */
    	while(!TXIF);	/* set when register is empty */
    	//	continue;
    	TXREG = byte;
    }
    
    //=====  Ham khoi tao
    void interrupt MyInt(void){
    	static volatile unsigned int  i, Pulse_Encoder;
    	// i la so diem trich mau
    	// Pulse_Encoder = so xung do duoc tu Encoder
    	static volatile unsigned char  allow,counter_Sampling;
    	// allow la bien cho phep bat dau trich mau
    	// counter_Sampling: bien dem de trich mau
    	unsigned char RC_USART;			// gia tri doc duoc tu thanh ghi nhan du lieu USART
    	if(T0IF & T0IE){	
    		TMR0 = 6;
    		T0IF = 0 ;// xoa co ngat
    		if((++counter_Sampling  == Ts) && allow){				// Ts = 10 ms
    			Pulse_Encoder  = (TMR1H << 8) | TMR1L;
    			// Toc do dong co = Pulse_Encoder * 1000 / (Encoder_resolution * Ts)  (vong/s)
    			printf("%6d",Pulse_Encoder);				// Truyen gia tri xung do tren Ts
    			counter_Sampling  = 0;
    			if (i++ == Total_Point){
    				i  = 0;			// Neu trich duoc 500 diem thi dung dong co lai	
    				CCPR1L = 0;
    				allow = 0;
    			};
    		};	
    	};
    	if(RCIF){						// Neu co ngat nhan du lieu noi tiep
    		RC_USART =  RCREG;
    		RCIF = 0;					// Xoa co ngat RCIF
    		switch(RC_USART){
    			case 'P': 		//  ===  Bat dau cho dong co chay cho do rong xung = 100%
    			TMR1ON = 0 ; // ngung Timer1
    			TMR1H = TMR1L = 0;
    			TMR1ON = 1 ;  // bat lai Timer1
    			CCPR1L =  PR2 + 1;
    			CCP1Y  =	CCP1X 	= 0;
    			allow = 1;
    			break;
    		};		
    	};
    }
    
    //------------------------------------init
    void init(void){
    // Khoi tao cho USART
    	TRISC = TRISC | 0b11000000;			// Bit 7,6 la RX va TX phai la Input
    	SPEN = 1 ;		// Enable Serial Port communication.
    	SYNC =	 0;		// che do khong dong bo Asynchronous
    	// cho che do truyen
    	TXEN = 1;		//enable truyen
    	TX9 = 0 ;		// chon che do 8 truyen  bit du lieu
    	BRGH = 1; 		// High - speed
    	SPBRG = 129;	//Baud = 9600;	voi HS, Baud Rate = Fosc/(16(X+1))  
    	TXIE = 0;		// khong dung ngat Truyen
    	// Che do nhan du lieu
    	RCIE  =  1;		// dung ngat nhan
    	PEIE = 1;		// cho phep ngat ngoai vi
    	GIE  = 1;			// cho phep ngat toan cuc
    	RX9 = 0;			// nhan 8 bit
    	CREN = 1;		// lien tuc nhan du lieu; = 0 k lien tuc nhan du lieu
    
    //===== init for PWM
    	// PWM Period = [ PR2 +1 ] x 4 x Tosc x   (TMR2 Prescaler Value)
    	PR2 = 82;						// Tan so = 15 KHz, TMR2 Prescaler Value = 4
    	// PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x  (TMR2  Prescaler Value)
    	// =>   CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
    	CCPR1L = 0;
    	TRISC2 = 0;						// RC2 la output
    	RC2  = 1;
    	T2CON = 0b00000101;			// Timer2 on, TMR2 Prescaler Value = 4
    	CCP1CON = 0b00001100;		// CCP1 hoat dong trong che do PWM
    
    //=================   init for PORTs
    	OPTION =  0b00000000;
    	ADCON1 = 0b00000111;
    	TRISA	= 0b00000000;
    	TRISD	= 0b00000000;
    	PORTD = 0xFF;
    
    //================  Khoi tao cho Timer0
    	GIE		= 1;
    	T0IE = 1;
    	TMR0 = 6;
    	
    // ========= Khoi tao cho dem Timer1
    	TMR1CS   = 1;						// Timer1 hoat dong o che do Counter Mode
    	T1SYNC  = 1;						// TMR1 hoat dong o che do dem khong dong bo
    	T1OSCEN = 1;						// Dem xung tu chan RC1/T1OSI/CCP2
    	T1CKPS1 = T1CKPS0 = 0;			// Chon Prescaler = 1:1
    	TMR1H = TMR1L = 0;
    	TMR1IE = 0 ;						// Khong dung ngat Timer1
    	TMR1ON = 1;						// Bat Timer1
    }
    
    //------------------------------------MAIN
    void main(){
    	init();
    	while(1);
    }
    
    // === Kết thúc
    Chương trình đã test và cho đặc tính h(t) thí dụ với động cơ 12V của tôi như sau:
    Chúc các bạn thành công.
    Technical sale at WT Microelectronics S'pore
    Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
    Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

    Comment


    • #47
      Anh Bắc ơi! Em cũng đã làm cái này cho bài tập lớn vi xử lý (kì 8), thế sang kì 9 lại có cái bài tập lớn điều khiển động cơ DC nữa hở anh!
      Đáp ứng h(t) của anh có vấn đề thì phải, trục thời gian là 5s chứ có phải 50s đâu (10x500=5s).
      Sao cái động cơ của anh quá độ lâu thế (hay là có tải nặng).

      Con động cơ của em nó lên cái vù 1 phát, thẳng đứng (không tải), thời gian lấy mẫu truyền về PC của em là 40ms.

      Nếu anh dùng con động cơ có Encoder 100 xung (loại bán nhiều ở chợ) thì nó là động cơ 24V chứ ko phải 12V.
      Ở 12V vận tốc nó vào khoảng 2000v/phút. Chu kì xung khoảng 300us.
      Trong 10ms anh đếm nhiều nhất được 33 xung (nếu không dùng mạch nhân xung), độ phân giải này quá thấp cho điều khiển.
      Với Encoder thấp như thế chắc là phải dùng phương pháp đo độ rộng xung thôi.

      Anh có dùng vòng điều khiển dòng không? Chu kì trích mẫu của anh là bao nhiêu?
      Last edited by sphinx; 17-05-2006, 13:04.
      PNLab
      Mạch nạp/debug ULink2, Jlink ARM USB
      Mạch nạp AVR, PIC, 8051, MSP430 USB
      Mạch phát triển STM32, ARM9, ARM11
      more...www.pnlabvn.com

      Comment


      • #48
        Cái đáp ứng h(t) mình đo là với Ts = 100ms nên nó là 50s. Vì do cái Encoder của mình nó có ít xung quá nên phải tăng Ts nên nó cũng không chính xác lắm. Đang chờ nhận cái 1000 xung làm cho nó chính xác.

        Còn thực chất với động cơ thì thời gian quá độ của nó là khoảng 2->4s nên mình cần thời gian trích mẫu khoảng 10ms. Còn với động cơ nhỏ nhỏ xinh xinh của mình khi cho Ts = 10ms thì số xung mình đo được = tốc độ vòng/s nên sai lệch khi mà mình biểu diễn nó lớn lắm.

        Mình cũng nghĩ đến phương pháp đo độ rộng xung rồi nhưng trong điều khiển phản hồi vòng kín với PID số mình phải tính theo thời gian trích mẫu cố định.

        Chúc bạn thành công. Đi tập thể dục tí đã:d. Tối viết tiếp.
        Technical sale at WT Microelectronics S'pore
        Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
        Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

        Comment


        • #49
          Em có cái động cơ gắn Encoder 500 xung, qua mạch nhân lên là được 1000!
          Thầy Quang bảo chu kì trích mẫu của vòng điều khiển dòng khoảng 100-400us, nếu lấy gấp 10 lần thì vòng tốc độ có chu kì khoảng 1-4ms, hơi quá nhỏ để đếm xung đúng không anh!

          Em chưa cài đặt được vòng điều khiển dòng vì ADC của AVR chậm quá (em dùng Atmega), sắp tới chắc thử PIC18 hoặc dsPIC mới ổn! Bọn này còn có sẵn Encoder Interface 2x,4x nữa, đỡ mệt nhiều!

          Ta vẫn đo độ rộng xung được khi sử dụng chi kì trích mẫu cố định! Tuy nhiên tần số lẫy mẫu cần nhỏ hơn 2 lần tần số xung encoder--->giới hạn vận tốc thấp nhất của động cơ!
          PNLab
          Mạch nạp/debug ULink2, Jlink ARM USB
          Mạch nạp AVR, PIC, 8051, MSP430 USB
          Mạch phát triển STM32, ARM9, ARM11
          more...www.pnlabvn.com

          Comment


          • #50

            Đáp ứng này là PT1 chứ có phải PT2 đâu nhỉ?
            Hay là khúc đầu lượn nhỏ quá nhìn không ra???
            PNLab
            Mạch nạp/debug ULink2, Jlink ARM USB
            Mạch nạp AVR, PIC, 8051, MSP430 USB
            Mạch phát triển STM32, ARM9, ARM11
            more...www.pnlabvn.com

            Comment


            • #51
              Nhờ anh MinhHa giải đáp giúp!

              Nguyên văn bởi MinhHa
              Với PIC thì phải dùng mẹo 1 chút còn với 51 thì không cần. Vẫn có thể ngắt lồng nhau song nếu không cẩn thận nó thành đệ quy thì treo ngay.
              ****************
              Nguyên văn bởi thaithutrang
              Hihi.. mẹo gì vậy anh?
              Phải chăng là làm một biến đếm số lần vào ngắt, nếu số lần vượt quá giới hạn cho phép của ngăn xếp thì không bật GIE nữa.
              Các bước chương trình phục vụ ngắt:
              -Xóa cờ ngắt.
              -Tăng biến đếm số lần ngắt lên 1 , nếu vẫn nhỏ hơn giới hạn ngăn xếp thì GIE=1;
              -Tiếp tục chương trình phục vụ ngắt.

              Hihi... đúng ko anh MH.
              ************************
              Nguyên văn bởi MinhHa
              không đúng. 3T lưu ý khi xảy ra ngắt thì MCU làm gì và khi kết thúc ngắt thì nó làm gì nhé.
              GIE = 1 giống như MCU kết thúc ngắt đó và cho ngắt khác được hoạt động. Nhưng thực sự khi kết thúc ngắt nó còn phải POP PC ra khỏi stack nữa.
              Có bao nhiêu lần vào ngắt thì phải có bấy nhiêu lần ra ngắt. Nếu lồng vào thì có n lần vào ngắt nhưng chỉ có 1 lần ra ngắt. Như vậy sẽ treo ngay.
              Em thấy cách của thaithutrang cũng được đó chứ anh MinhHa. Nếu cách đó sai thì anh chỉ rõ nguyên nhân cụ thể là sai ở đâu giúp em cái.
              Cái chỗ anh nói là vào thì có n lần nhưng chỉ có 1 lần ra ngắt thì em chưa hiểu. Em thấy vào n lần vẫn ra đủ n lần đấy chứ. Giải đáp giúp em phát!

              Comment


              • #52
                Mình mới tìm hiểu PIC, có một trắc trở nho nhỏ mà rất to, mà vẫn không hiểu tại sao. Đó là việc dùng Delay. Sau đây là các chương trình ko hiểu vì sao chạy ko đúng. Nhờ bạn Ngohaibac và các bạn khác giúp đỡ.
                1. Chương trình Led nhấp nháy, sử dụng delay bằng cách sử dụng thời gian thực thi lệnh, chứng bệnh: Led nháy thời gian ON/OFF không đều nhau. Thời gian delay càng lớn, chênh lệch ON/OFF càng lớn.

                Code:
                #include<pic18fxxx.h>
                //Mô tả: Led đơn Anode nối vào RD7, Cathode xuống Mass. Thạch anh 4Mhz.
                __CONFIG(1, OSCSEN & XT);
                static bit a;
                void main () {
                	unsigned char k;
                		a=1;
                		PORTD	=	0x00;
                		TRISD	=	0x00;
                		while(1) {
                			a = a ^ 1;
                			RD7 = a;
                			delay(1000);
                		}
                }
                2. Dùng Delay bằng cách dùng TIMER0, dùng Prescaler. Nếu T0PS2:T0PS0='011' trở xuống thì OK, ON/OFF led đồng đều. Nếu ='100' trở lên thì delay không được luôn !

                Code:
                #include<pic18.h>
                __CONFIG(1, OSCSEN & XT);
                //__CONFIG(4, LVPDIS);
                static bit a;
                void delay_timer0() {		
                	TMR0IF	=	0;	
                	T0CS	=	0; //Enable FOSC/4 source
                	PSA	=	0;	//enable Prescaler
                	T0PS2	=	1;
                	T0PS1	=	0;
                	T0PS0	=	0;
                	T08BIT	=	0;	//16 bit mode
                	TMR0	=	-50000;
                	TMR0ON	=	1;
                	while(!TMR0IF) {}
                	TMR0IF	=	0;
                	TMR0ON	=	0;
                	TMR0	=	0;
                }
                void main () {
                		a=1;
                		PORTD	=	0x00;
                		TRISD	=	0x00;
                
                		while(1) {
                			a = a ^ 1;
                			RD7 = a;
                			delay_timer0();//Theo lý thuyết, delay này là 
                                                      //delay 50000x64 us = 3.2s
                		}
                }

                3. Dùng TIMER, không Prescaler, delay dài, xài vòng lặp. Triệu chứng: giống như triệu chứng 1 (hình như nó kỵ rơ với vòng lặp hay sao ấy)

                Code:
                #include<pic18.h>
                __CONFIG(1, OSCSEN & XT);
                static bit a;
                void delay_timer0() {		
                	TMR0IF	=	0;	
                	T0CS	=	0; //Enable FOSC/4 source
                	PSA	=	1;	//unable Prescaler
                	T08BIT	=	0;	//16 bit mode
                	TMR0	=	-50000;
                	TMR0ON	=	1;
                	while(!TMR0IF) {}
                	TMR0IF	=	0;
                	TMR0ON	=	0;
                	TMR0	=	0;
                }
                void main () {
                	unsigned char k;
                		a=1;
                		PORTD	=	0x00;
                		TRISD	=	0x00;
                
                		while(1) {
                			a = a ^ 1;
                			RD7 = a;
                			for (k=0;k<=20;k++) {
                			       delay_timer0();
                			}
                		}
                }
                Không biết nguyên nhân các trường hợp trên, ăn cơm không ngon, đi học không dui, đi chơi với em không thú ! Mong được chỉ giáo.
                Last edited by falleaf; 16-12-2006, 09:23.
                Ai bảo chăn trâu là khổ ...!?

                Comment


                • #53
                  Àh, không ai trả lời hết. Cũng may là đã phát hiện ra kịp, một thằng Watchdog chạy thường trú mà không chịu xóa nó, để nó cứ chưa kịp delay đã phải reset. Watchdog cũng làm cho dân mới lao đao chứ hả!
                  Ai bảo chăn trâu là khổ ...!?

                  Comment


                  • #54
                    Mình mới tìm hiểu về PIC. Xin hỏi cái dòng lệnh
                    _CONFIG(...)
                    Mình vào trong trong phần configure/configure bit (MPLAB v 7.42) thấy hiển thị một list các category. Nếu đặt trong này rồi thì có cần dùng đến câu lệnh trên không?
                    Nếu không thì cách viết dòng lệnh trên như thế nào nhỉ?
                    CUNG CẤP PSOC, MẠCH NẠP
                    CHUYỂN ĐỔI USB <-> RS485 AutoBaud
                    RS232 <-> RS485 MultiBaud
                    MẠCH NẠP USBPPI S7-200
                    Mobile: 0906076116
                    Email:

                    Comment


                    • #55
                      Sao mình không thấy tập lệnh (giống trong ngôn ngữ C chuẩn) của HTPICC,kiếm ở đâu bây giờ?
                      Thank.

                      Comment


                      • #56
                        CHo mình hỏi tí!!
                        cái ví dụ đầu tiên của bạn Ngô Hải Bắc (viết bằng delay),nếu theo mình hiểu thì PortD sẽ xuất ra Led theo thứ tự sau đây:
                        Rd7 Rd6 Rd5 Rd4 Rd3 Rd2 Rd1 Rd0
                        Lần 1 10000001
                        Lần 2 01000010
                        3 00100100
                        4 00011000
                        5 00011000
                        6 00100100
                        7 01000010
                        Rồi tiếp tục quay lại lần 1... Với 1 là sáng Led và 0 là Led tắt
                        Nhưng khi mình copy qua và biên dịch thử theo kiểu tạo 1 project và nạp file Hẽ cho chạy (mình cũng dùng 16F877A) thì chạy sai:cụ thể là
                        Mỗi lần delay có đến 4 Led sáng và nó nhảy ko đúng như ý nghĩa chương trình
                        không biết tại sao nhỉ???????????

                        Comment


                        • #57
                          bạn xem lại thời gian delay. Neu delay nhanh quá sẽ nhìn thấy cac led sáng cùng lúc (hiệu ứng 24hinhf/s).
                          CUNG CẤP PSOC, MẠCH NẠP
                          CHUYỂN ĐỔI USB <-> RS485 AutoBaud
                          RS232 <-> RS485 MultiBaud
                          MẠCH NẠP USBPPI S7-200
                          Mobile: 0906076116
                          Email:

                          Comment


                          • #58
                            xin chao

                            bai viet rat hay

                            Comment


                            • #59
                              bac MINHPIC 1 oi ! cho em hoi cai .... trong cai interupt bac noi dieu thu vi voi lai PWM la sao ............?
                              em dang lam bai tap tot nghiep , dung PWM .... cho output = 4V .... nhung khi em lam toi INTERUPT trong do , thi no chay len 7v, khong biet phai la problem thu vi ma bac muon noi toi , hay la code cua em co dieu gi sai .... xin bac chi giao .

                              Comment


                              • #60
                                Chào các bạn.

                                Để có thể viết được chương trình bằng HTPIC cho hợp lý và tuân theo đúng trình dịch HTPIC, các bạn nên download manual của nó
                                PICC Manual

                                Tài liệu này rất hay (của www.htsoft.com).

                                Chúc các bạn thành công.
                                Technical sale at WT Microelectronics S'pore
                                Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                                Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                                Comment

                                Về tác giả

                                Collapse

                                lick Tìm hiểu thêm về lick

                                Bài viết mới nhất

                                Collapse

                                Đang tải...
                                X