Chủ Nhật, 30 tháng 8, 2015

Giao tiếp thẻ RFID với Atmega8 (chế độ SPI)

Với công nghệ phát triển như hiện nay, một chế độ bảo mật cao là điều cần thiết đối với hệ thống. Bạn có thể dùng key, dùng các bàn phím, hay một số bật cập khi nhận diện khuôn mặt. Thẻ RFID là một module có thể đáp ứng đủ những yêu cầu bảo mật ở mức trung bình như vậy.

Hôm nay, mình sẽ giới thiệu và hướng dẫn cách giao tiếp thẻ RFID với AVR và STM32F103

Hình ảnh của module RFID và thẻ từ



Module RFID RC522 sử dụng IC MFRC522 của Phillip dùng để đọc và ghi dữ liệu cho thẻ NFC tần số 13.56mhz, với mức giá rẻ thiết kế nhỏ gọn, module này là sự lựa chọn hàng đầu cho các ứng dụng về ghi đọc thẻ RFID.
  • Nguồn: 3.3VDC, 13 - 26mA
  • Dòng ở chế độ chờ: 10-13mA 
  • Dòng ở chế độ nghỉ: <80uA
  • Tần số sóng mang: 13.56MHz
  • Khoảng cách hoạt động: 0~60mm(mifare1 card)
  • Giao tiếp: SPI
  • Tốc độ truyền dữ liệu: tối đa 10Mbit/s
  • Các loại card RFID hỗ trợ: mifare1 S50, mifare1 S70, mifare UltraLight, mifare Pro, mifare Desfire
  • Kích thước: 40mm×60mm

-unsigned char PcdReset(void):Khởi tạo chế độ giao tiếp SPI và viết lệnh Command


Project thực hiện trên vđk 8051,AVR, PIC, STM32
Liên hệ: DoAnDienTu


Điều khiển động cơ DC servo bằng thuật toán PID với ATMEGA8 (PID vận tốc, PID vị trí)

-Điều khiển động cơ DC là một điều gần như luôn được sử dụng trong Robot cũng như trong công nghiệp hiện nay, việc điều khiển động cơ đòi hỏi có độ chính xác cao, vì với một sai lệch nhỏ sẽ ảnh hưởng đến đường đi của Robot. Vậy để làm thế nào mà có thể điều khiển động cơ một cách chính xác nhất, để sai số của nó là nhỏ nhất??? confused 
-Các bạn đã từng nghe đến giải thuật PID(tỉ lệ, tích phân, đạo hàm) chưa nhỉ, nếu bạn nào từng học qua môn lý thuyết điều khiển chắc hẳn sẽ biết giải thuật này. Lấy cơ sở từ bộ phản hồi trong luật điều khiển cùng với các cách khác nhau để tìm ra các hệ số Kp, Kd, Ki...(với mình thường sử dụng phương pháp đối xứng vì tính đơn giản và hiệu quả khá cao) Very Happy 
-Chúng ta sẽ đi sâu hơn về phương pháp này: 
+ Lấy một ví dụ đơn giản: Chúng ta muốn điều khiển một chiếc xe đi từ A đến B cần 1 lực F để điều khiển, câu hỏi đặt ra là cần lực F thay đổi như thế nào để xe đến vị trí B một cách chính xác và nhanh nhất ???  Sleep 
+Gọi khoảng cách giữa xe và điểm B là Err(Error), Err càng lớn, đòi hỏi lực F càng lớn. Chúng ta có 1 tỷ lệ thuật F=Kp*Err, với Kp là một hằng số.
+Khi xe đến B, Err=0 nên lực F=0, tuy nhiên do quán tính xe sẽ lệch khỏi B, sai số Err<0, vì thế cần 1 lực F kéo ngược lại, tương tự thế khi xe lại lùi về trước điểm B, quá trình này cứ lặp đi lặp lại và có thể xe sẽ xa dần điểm B  cyclops   affraid Vì vậy lúc này cần 1 cái "phanh" để xe đi gần vị trí B sẽ giảm dần tốc độ so vs ở xa. Vì ở gần B thì vận tốc là max, tức là dErr/dt =max, Err sẽ thay đổi mạnh nhất. Như vậy đạo hàm của sai số Err tăng giá trị nhưng ngược chiều của lực F, nếu sử dụng đạo hàm làm thành phần phanh thì có thể giảm dc đáng kể sai số lệch tĩnh khỏi vị trí B  Laughing (tìm hiểu kĩ sai số lệch tĩnh ở lý thuyết điều khiển) và ta có F=Kp*Err + Kd*(dErr/dt)     Laughing 
+Sự có mặt của thành phần D làm giảm được sai lệch tĩnh của xe, khi xe tiến gần về B, lực F gồm 2 thành phần Kp*Err > =0 (P) và Kd*(dErr/dt) <=0. Trong một số trường hợp thành phần D có giá trị lớn hơn thành phần P và lực F đổi chiều, “phanh” xe lại, vận tốc của xe vì thế giảm mạnh ở gần điểm B. Một vấn đề ở đây là nếu thành phần D quá lớn so với thành phần P hoặc bản thân thành phần P nhỏ thì khi xe tiến gần điểm B (chưa thật sự đến B), xe có thể dừng hẳn, thành phần D bằng 0 (vì sai số Err không thay đổi nữa), lực F = Kp*Err. Lúc này cả thành phần D vs P đều nhỏ và có thể ko thắng dc lực ma sát tĩnh, chúng ta cần 1 thành phần cộng dồn để đẩy xe lại gần B hơn, đó ko gì khác ngoài thành phần I (tích phân ~ cộng dồn), lúc này ta có  F=Kp*Err + Kd*(dErr/dt)+Ki*∫Errdt .
=>>>>>>>>Đối với điều khiển số, đòi hỏi quá trình lấy mẫu nhanh (dt rất nhỏ) chúng ta tuyến tính hóa với thời gian lấy mẫu h sẽ dc pPart=Kp*Err, dPart=Kd*(Err-old_Err)/h và iPart=iPart(ở thời điểm lấy mẫu trước :h(k-1))+Err*h.








 Trên đây là hình ảnh về cấu tạo của bộ Encoder gồm 2 kênh A và B


Kênh A, B nhận dc tín hiệu (A, B ở mức thấp), và ngược lại (ở mức cao)
-Từ hình vẽ, chọn chiều dương ngược chiều kim đồng hồ, khi quay theo chiều dương Kênh A có 1 cạnh xuống thì kênh B đang ở mức cao, bằng cách kiểm tra kênh B để biết dc chiều động cơ, và ngược lại khi quay theo chiều âm nếu kênh A cạnh xuống thì kênh B đang ở mức thấp.


-Ý tưởng để điều khiển kênh A: 
+Dùng input capture: Sau mỗi lần chân ICP trên AVR cạnh lên hoặc cạnh xuống thì giá trị dc gán cho thanh ghi ICR, so sánh 2 lần liên tiếp ta dc chu kì của xung kênh A, từ đó tính vận tốc động cơ DC, nhưng thường thì input capture chỉ có ở timer1 (đối vs mấy co avr ko có timer 3, timer 3 thường từ atmega 64 trở lên-hơi đắt), mà timer 1 dùng để điều khiển PWM ở động cơ nên ko thể dùng input capture cho đo xung encoder dc
+Dùng counter (đơn giản) nhưng lại thường ko xác định dc chiều quay của động cơ >>>>ko dùng
+Dùng ngắt ngoài (đơn giản), dễ hiểu là khi có 1 cạnh xuống ở kênh A (ối vs INT0 hoặc INT1) thì kiểm tra chân nối kênh B để xác định chiều và mỗi lần như thế thì xung tăng thêm 1 >>>quyết định dùng ngắt ngoài cheers 

//Dưới đây mình viết mẫu đoạn code cho điều khiển PID vận tốc và PID vị trí (đã test trên mạch thật)
//PID vận tốc

void Pid_control(float v1)  //v1 la van toc dieu khien, v2 la van toc hien tai
{
//chon chieu duong la chieu nguoc chieu kim dong ho, khi v2>0 tuong ung dir=1 va nguoc lai
     Speed=Pulse-old_Pulse;
     old_Pulse=Pulse;
     if(Speed<0)
     {
         Speed=-Speed; 
//         DIR=0;
     }
//     else DIR=1;
     Err=(float)(v1-Speed);   //tinh sai so
      //cac thanh phan PID
     pPart=Kp*Err;
     dPart=Kd*(Err-old_Err)*inv_Sampling_time;
     iPart+=Ki*Sampling_time*Err/1000.0; //tinh Sampling_time theo s
     Output+=(pPart+dPart+iPart);
//     Output=(unsigned int)Output;
     if(Output>=period) Output=period-1;
     else if(Output<=0.0) Output=1;
     PWM=(unsigned int)Output;
      
     old_Err=Err;
     
}

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
   //kenh A noi vs INT0 (ngat canh xuong)
   if(CH_B==1)  //quay theo chieu thuan
   {
       Pulse ++;
//        cnt=1;
   }
   else 
   {
        Pulse--;  //quay nguoc chieu kim dong ho 
//         cnt=0;
   }

}

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
// Place your code here
  TCNT2=60;        //ngat tran 25ms= thoi gian lay mau
  sample_count++;
  Pid_control(Ctrl_Speed,1);   //van toc ctr_speed, quay theo chieu thuan
}


//PID vị trí

void Motor_Vtri_PID(long int des_Alpha) //des_Vtri mong muon (dc tinh bang so goc quay dc)
{
       rAlpha=Pulse; 
//       if(rAlpha<0) rAlpha=-rAlpha;
       Err=des_Alpha-rAlpha; //tinh error
   
   //cac thanh phan PID
       if(Err<0) { Err=-Err; DIR=0;}
       else DIR=1;
       pPart=Kp*Err;
       dPart=Kd*(Err-old_Err)*inv_Sampling_time;
       iPart+=Ki*Sampling_time*Err/1000; //tinh Sampling_time theo s
       Output+=(long int)(pPart+dPart+iPart);
//       DIR=1;
       if(Err==0) {//cbi(Motor_PORT,Motor_EN); 
       DIR=0;
       Output=0;}
       if(Output>=period)
       {
           Output=period-1;
       }
       if(Output<=0)
       {
           DIR=0;
           Output=1;
       }
       

       PWM=Output; //gan gia tri dutycycle
       old_Err=Err; //luu lai gia tri Error
}


// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
   //kenh A noi vs INT0 (ngat canh xuong)
   if(CH_B==1)  //quay theo chieu thuan
   {
       Pulse ++;
//        cnt=1;
   }
   else 
   {
        Pulse--;  //quay nguoc chieu kim dong ho 
//         cnt=0;
   }

}

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
// Place your code here
  TCNT2=60;        //ngat tran 25ms= thoi gian lay mau
  sample_count++;
  Motor_Vtri_PID(Ctrl_Speed,1);   //van toc ctr_speed, quay theo chieu thuan
}



Link video test hãm động cơ: Tam BK STAR
Project full, liên hệ: DoAnDienTu

Thứ Bảy, 29 tháng 8, 2015

Giao tiếp màn hình TFT 2.4, 3.2 inch, full hiển thị và cảm ứng AVR, STM32




                                                    Một số hình ảnh về màn hình touch
                                                   


1.     Giới Thiệu.
-Màn hình TFT 3.2 inch là màn hình hiển thị, có chế độ cảm ứng touch screen.
Thông số kỹ thuật của màn hình TFT 3.2 inch:
Ø Điện áp hoạt động : 5V
Ø Độ phân giải 240x320 với 262K màu
Ø Chuẩn giao tiếp 2 chế độ 8 bit và 16 bit.

Ø Hỗ trợ cảm ứng điện trở, khe cắm thẻ nhớ SD
Sơ đồ chân:

Số thứ tự
Tên chân
Chức năng
1
GND
Nối mass nguồn 5V
2
VCC
Nối nguồn 5V
3,18,19,20,21,22,29
NC
Not connect
4
RS
RS=0 ghi lệnh
RS=1 ghi data
5
WR
1 xung cạnh lên trên chân WR, sẽ ghi data lên LCD
6
RD
1 xung cạnh lên trên chân RD, đọc trạng thái LCD
7-14
DB8-DB15
8 bit cao data
15
CS
CS=0 : Gửi lệnh lên LCD
CS=1: Gửi data lên LCD
16
F-CS
F-CS: Sử dụng bộ nhớ flash ngoài
17
REST
Reset tích cực âm
19
LED_A
Chân Anot đèn nền
23
SD_CS
Sử dụng giao tiếp SPI với thẻ nhớ SD (chân chọn Slave)
24
SD_DIN
Sử dụng giao tiếp SPI với thẻ nhớ SD (gửi lệnh command qua chân này)
25
SD_CLK
Sử dụng giao tiếp SPI với thẻ nhớ SD (chân tạo xung clock)
26
SD_DO
Sử dụng giao tiếp SPI với thẻ nhớ SD (chân đọc data từ thẻ nhớ SD)
27
T-IRQ
Khi có cảm ứng, chân này được kéo xuống mức 0.
28
T-DO
Sử dụng chức năng cảm ứng, giao tiếp SPI (đọc data-nối MISO)
30
T-DIN
Sử dụng chức năng cảm ứng, giao tiếp SPI (gửi data-nối MOSI)
31
T-CS
Sử dụng chức năng cảm ứng, giao tiếp SPI (chọn Slave)
32
T-CLK
Sử dụng chức năng cảm ứng, giao tiếp SPI (chân tạo xung clock)
33-40
DB7-DB0
8 bit thấp data(Nối GND trong mode 8 bits)


1.       Phương Thức Giao Tiếp.
Ø  Giao tiếp TFT với vi điều khiển: Sử dụng vào ra IO, giao tiếp SPI
-Chức năng screen (hiển thị):
   +Giao tiếp 8 bit : Sử dụng 8 bit cao, 8 bit thấp nối GND.
   +Giao tiếp 16 bit: Sử dụng 8 bit cao và 8 bit thấp.
·        Trong chế độ 8 bit: Gửi 8 bit cao trước, sau đó gửi 8 bit thấp.
   Sample:  VH, VL theo thứ tự là 8 bits cao và 8 bits thấp của data.
           xuat_data_8bit(VH);
            LCD_WR_OFF;
            LCD_WR_ON;
            xuat_data_8bit(VL);         
            LCD_WR_OFF;
            LCD_WR_ON;


-         Nhận xét:
+ Ưu điểm:Tiết kiệm được chân vi điều khiển (chỉ sử dụng 8 chân để truyền data cho màn hình TFT)
+ Nhược điểm: Tốc độ chậm hơn so với 16 bit.




·        Trong chế độ 16 bit: Sử dụng cả 16 chân DB0-DB15 để truyền data
   Sample:  VH, VL theo thứ tự là 8 bits cao và 8 bits thấp của data.

           PORT_H_Data=VH;
            LCD_WR_OFF;
            LCD_WR_ON;
            PORT_L_Data=VL;
            LCD_WR_OFF;
            LCD_WR_ON;


-         Nhận xét:
+ Ưu điểm:Tốc độ nhanh vì chế độ là song song, trực tiếp.
                                        + Nhược điểm: Không tiết kiệm chân vi điều khiển sử dụng
-Quá trình khởi tạo màn hình TFT (theo thứ tự hàm init)
   * Đưa chân CS =1, tạo 1 xung cạnh xuống  và 1 xung cạnh lên trên chân RESET để đánh thức IC màn hình TFT
   * Tiếp tục đưa chân RD và chân WR =1 để ghi lệnh cho TFT.

   + Set SRAM nội
   + Set SS và SM bit
   + Set 1 line ngược
   + Set viết GRAM và BGR=1
   + Resize thanh ghi
   + Thiết lập cổng sau và trước
   + Thiết lập khu vực không hiển thị
   + Hàm FMARK
  + Thiết lập giao tiếp RGB
  + Đánh dấu vị trí
  + Giao diện RGB
  + SAP, BT[3:0], AP, DSTB,
  SLP, STB
  + DC1[2:0], DC0[2:0],
  VC[2:0]
  + Điện áp VREG1OUT
  + VDV[4:0] để khuếch đại VCOM
  + SAP, BT[3:0], AP, DSTB,
  SLP, STB
  + DC1[2:0], DC0[2:0],
  VC[2:0]
  + Điện áp tham chiếu nội Vci




Ø Chế độ cảm ứng màn hình TFT.
-         Sử dụng giao tiếp SPI, ic chức năng cảm ứng trên màn hình là XPT2046
-         Màn hình nhận data qua chân DIN, nhận bit MSP trước
-         MCU nhận data qua chân T-DO


·        Quá trình khởi tạo chế độ SPI, truyền data, nhận data
-Khởi tạo: Đưa các chân CS, SCK, MOSI (DIN) lên 1.


/***********************************************************************************************
Chuc nang    :                       Ham dung de khoi tao cho giao tiep SPI: Che do cam ung (Mode touch).
Tham so                    :
Tra ve                        :                       Khong
***********************************************************************************************/
void spistar(void)
{
              CS=1;
             DCLK=1;
             DIN=1;
             DCLK=1;
}







-Truyền data: Data được gửi bit cao (MSB) trước, tạo 1 xung cạnh lên trên chân SCK để truyền từng bit trên đường truyền MOSI (DIN).
                                       
/***********************************************************************************************
Chuc nang    :                       Ham dung de ghi data len IC cam ung
Tham so                    :       Data can truyen (Truyen bit MSP truoc)
Tra ve                        :                       Khong
***********************************************************************************************/

void WriteCharTo7843(unsigned char num)
{

    unsigned char count=0;
    unsigned char temp;
    temp=num;
    DCLK=0;
    for(count=0;count<8;count++)
    {
        if(temp&0x80)
        DIN=1;
        else
        DIN=0;

        temp=temp<<1;

        DCLK=0;               
        DCLK=1;
  }
}
-Nhận data: Data được nhận bit cao (MSB) trước, bằng cách tạo xung cạnh xuống để lấy bit dữ liệu.

/***********************************************************************************************
Chuc nang    :                       Ham dung doc data tu ic cam ung
Tham so                    :       Khong
Tra ve                        :                       Data nhan ve (16bit)
***********************************************************************************************/

u16 ReadFromCharFrom7843()
{
            u8 count=0;
            u16 Num=0;
            for(count=0;count<12;count++)
            {
                        Num<<=1;              
                        DCLK=1; //delay_us(3);              
                        DCLK=0; //delay_us(3);
                        if(DOUT)
                        {
                                    Num|=1;
                        }
                       
            }

return(Num);

}



>>>>>>>Code cho AVR (ATMEGA32) và ARM liên hệ: DoAnDienTu