Bài 2: Kiểm chứng tốc độ khi điều khiển các pin bằng ngôn ngữ AVR so với các lệnh trên Arduino

Mô tả dự án: 

Arduino dùng chip AVR, nếu điều khiển arduino bằng ngôn ngữ tiêu chuẩn của chip AVR thì tốc độ có thể nhanh hơn 12 lần so với cách dùng lệnh digitalWrite, nhanh hơn 4 lần so với lệnh digitalRead, nhanh 14 hơn lần so với analogRead, nhanh 10 hơn lần so với pinMode… thậm chí cách biệt còn xa hơn nữa. Điều này rất rất quan trọng. Cùng khám phá nào..

Bắt đầu nào...

Ở bài trước, ta đã biết cách điều khiển các chân port . Bây giờ hãy cùng mình  so sánh tốc độ của 2 phương pháp.

 

Tiêu chí đánh giá:

  • Bài viết sử dụng arduino uno r3 , tần số hệ thống 16mhz.
  • Mình dùng hàm micros() của hệ thống làm đồng hồ. Hàm này sẽ được đặt về 0 khi reset hoặc nạp code lần đầu. Qúa trình khảo sát diến ra rất nhanh ( < 500 micro giây) nên không lo hàm sẽ bị tràn số.
  • Công việc cần khảo sát:(đoạn code trong dấu ///) là đoạn code nằm giữa lúc bắt đầu tính thời gian và kết thúc tính thời gian (sát nhất). Các đoạn code khác (nằm trước và  sau ) chỉ mang tính chất điều kiện cần, và không liên quan đến khoảng thời gian khảo sát.
  • Khoảng thời gian khảo sát:  chỉ được bắt đầu tính từ khi đặt start lần đầu tiên, khi "công việc cần khảo sát" kết thúc, mình sẽ lấy hiệu của micros() với start. Hiệu đó sẽ mãi được giữ nguyên,đó chính là khoảng thời gian khảo sát. Cuối cùng nó được in ra bằng Print.  
  • Thống kê: mình sẽ nhấn nút  reset (giữ nguyên code), rồi lại xem kết quả để xem kết quả có bị lệch hay không giữa các lần .
  • Độ chính xác: Kết quả tìm HIỆU có thể không chính xác tuyệt đối (không có máy đo chính xác hơn), nhưng chúng ta KHÔNG thật sự cần đến nó, cái quan trọng là chúng ta sẽ so sánh  mức độ nhanh chậm gấp bao nhiêu lần của 2 loại code mà thôi(so sánh tương đối). Khi đó ở cùng một điều kiện phần cứng (không thay đổi)  thì kết quả được cho là đáng tin cậy.(Đây cũng là cách nhanh nhất và tiết kiệm nhất mà chúng ta có thể thực hiện.)
  • Điều kiện cuối: Nếu bạn chấp nhận các tiêu chí trên thì chúng ta sẽ tiếp tục laughlaugh hehe

Pin mode

Đặt pin digital 0 là output

unsigned long start;
void setup(){
    Serial.begin(9600);
    start=micros();
///
       pinMode(0,OUTPUT);
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
unsigned long start;
void setup(){
    Serial.begin(9600);
    start=micros();
///
       DDRD=B00000001;
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
Thời gian: 4 micro giây
4 micro giây

Đặt 14 pin digital là OUTPUT

unsigned long start;
void setup(){
    Serial.begin(9600);
    start=micros();
///
      for(byte pin=0; pin<14; pin++){
        pinMode(pin, OUTPUT);}
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
unsigned long start;
void setup(){
    Serial.begin(9600);
    start=micros();
///
       DDRB=B11111111;
       DDRD=B11111111;
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
Thời gian: 44 micro giây
4 micro giây
unsigned long start;
void setup(){
    Serial.begin(9600);
    start=micros();
   ///
        pinMode(0, OUTPUT);
        pinMode(1, OUTPUT);
        pinMode(2, OUTPUT);
        pinMode(3, OUTPUT);
        pinMode(4, OUTPUT);
        pinMode(5, OUTPUT);
        pinMode(6, OUTPUT);
        pinMode(7, OUTPUT);
        pinMode(8, OUTPUT);
        pinMode(9, OUTPUT);
        pinMode(10, OUTPUT);
        pinMode(11, OUTPUT);
        pinMode(12, OUTPUT);
        pinMode(13, OUTPUT);
    ///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
 
Không dùng for,Thời gian: 48 micro giây  

 

 

digitalWrite();

Đặt 1 pin là HIGH

unsigned long start;
void setup(){
    Serial.begin(9600);
    pinMode(0,OUTPUT);
    start=micros();
///
       digitalWrite(0,HIGH);
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
unsigned long start;
void setup(){
    Serial.begin(9600);
    pinMode(0,OUTPUT);
    start=micros();
///
       PORTD=B00000001;
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
Thời gian: 8 micro giây
4 micro giây

Đặt 14 pin là HIGH

unsigned long start;
void setup(){
    Serial.begin(9600);
    for(byte pin=0; pin<14; pin++){
        pinMode(pin, OUTPUT);
    }
    start=micros();
///
     for(byte pin=0; pin<14; pin++){
          digitalWrite(pin,HIGH);}
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
unsigned long start;
void setup(){
    Serial.begin(9600);
    DDRB=B11111111;
    DDRD=B11111111;
    start=micros();
///
          PORTB=B11111111;
          PORTD=B11111111;
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}

Thời gian: 52 micro giây

4 micro giây

unsigned long start;
void setup(){
    Serial.begin(9600);
    for(byte pin=0; pin<14; pin++){
        pinMode(pin, OUTPUT);
    }
    start=micros();
   ///
        digitalWrite(0,HIGH);
        digitalWrite(1,HIGH);
        digitalWrite(2,HIGH);
        digitalWrite(3,HIGH);
        digitalWrite(4,HIGH);
        digitalWrite(5,HIGH);
        digitalWrite(6,HIGH);
        digitalWrite(7,HIGH);
        digitalWrite(8,HIGH);
        digitalWrite(9,HIGH);
        digitalWrite(10,HIGH);
        digitalWrite(11,HIGH);
        digitalWrite(12,HIGH);
        digitalWrite(13,HIGH);
    ///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}

 

 
Không dùng for,Thời gian: 56 micro giây  

Khả năng điều khiển đồng bộ

pinMode/ digitalWrite
DDR/PORT
Lần lượt từng Pin (có thời gian trễ).
 Điều khiển cùng lúc 8 pin (tức thì)

 

digitalRead()

Đọc giá trị ở trạng thái digital của pin 7

unsigned long start;
void setup(){
    Serial.begin(9600);
    bool val;
    pinMode(7,INPUT);
    start=micros();
///
       val=digitalRead(7);
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}
unsigned long start;
void setup(){
    Serial.begin(9600);
    bool val;
    pinMode(7,INPUT);
    start=micros();
///
        val=PIND&(1<<7);
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}

Thời gian: 8 micro giây

4 micro giây

Đọc giá trị 4 nút ấn Game

unsigned long start;
void setup(){
    Serial.begin(9600);
    bool b[4];
    DDRB=B00000000;
    start=micros();
///
    for(byte i=0; i<4; i++){
        b[i]=digitalRead(8+i);
    }
///
    start=micros()-start;
    Serial.println(start);
}

void loop(){
}
unsigned long start;
void setup(){
    Serial.begin(9600);
    bool b[4];
    DDRB=B00000000;
    start=micros();
///
    for( byte i=0; i<4; i++){
        b[i]=PINB&( 1<<i);
    }
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}

Thời gian: 16 micro giây

4  micro giây

unsigned long start;
void setup(){
    Serial.begin(9600);
    bool b[4];
    DDRB=B00000000;
    start=micros();
///
   b[0]=digitalRead(8);
   b[1]=digitalRead(9);
   b[2]=digitalRead(10);
   b[3]=digitalRead(11);
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}

 

unsigned long start;
void setup(){
    Serial.begin(9600);
    bool b[4];
    DDRB=B00000000;
    start=micros();
///
    
        b[0]=PINB&B00000001;
        b[1]=PINB&B00000010;
        b[2]=PINB&B00000100;
        b[3]=PINB&B00001000;
    
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}

 

Không dùng for,Thời gian: 16 micro s  Không dùng for,4 micro s

 

 

 

Đọc giá trị digital trên 16 pin.

unsigned long start;
void setup(){
    Serial.begin(9600);
    DDRD=255;// = B11111111
    PORTD=255;//INTPUT PULLUP
    DDRC=255;// 
    PORTC=255;//INTPUT PULLUP
  byte R1,R2;

    start=micros();
///
    
        R1=PIND;
        R2=PINC;
///
    start=micros()-start;
    Serial.println(start);
}
void loop(){
}

 

4 micro giây

 

analogRead();

Sử dụng 2 điện trở mắc nối tiếp làm cầu phân áp, đọc giá trị điện áp bằng chân A0

 

void setup(){
    pinMode(A0,INPUT);
    Serial.begin(9600);
}

unsigned long start;
unsigned int ana;
void loop(){
    start=micros();
///
    ana=analogRead(0);
///
    start=micros()-start;
    Serial.println(start);
    Serial.println(ana);
    delay(2000);
}

 

void setup(){
    pinMode(A0,INPUT);
    Serial.begin(9600);
    ADCSRA = ((ADCSRA&(B11111000)) | B00000010);
    // Cài tần số quét 4mhz
}
unsigned long start;
unsigned int ana;
void loop(){
    start=micros();
///
    ana=analogRead(0);
///
    start=micros()-start;
    Serial.println(start);
    Serial.println(ana);
    delay(2000);
}

Tần số của bộ đếm ADC mặc định: 125khz

Ana=506;

Thời gian: 116 micro giây

Tần số của bộ đếm ADC:  4mhz
  • Ana=507;
  • Thời gian :8 micro giây ( nhanh hơn 14 lần)
Tần số 1mhz:
  • Ana=506;
  • Thời gian: 16 micro giây

 

Tốc độ lấy mẫu rất nhanh, rất thích hợp với các dự án liên quan đến analogRead().

Sử dụng 2 điện trở khác, mình dùng cả 4 chân analog A->A3 để đo.

 

unsigned long start;
uint16_t val[4];
void setup(){  
DDRC=B00000000;//cho tiện ha
Serial.begin(9600);
//// ADCSRA = ((ADCSRA&(B11111000)) | B00000010);
}
void loop(){
start=micros();
///
for(byte i=0; i<4; i++){
val[i]=analogRead(i);
}
///
start=micros()-start;
Serial.println(start);
for(byte i=0; i<4; i++){
Serial.print(val[i]);
Serial.print("|");
}
delay(2000);
}

 

unsigned long start;
uint16_t val[4];
void setup(){  
DDRC=B00000000;//cho tiện ha
Serial.begin(9600);
ADCSRA = ((ADCSRA&(B11111000)) | B00000010);
// Cài tần số quét 4mhz
}
void loop(){
start=micros();
///
for(byte i=0; i<4; i++){
val[i]=analogRead(i);
}
///
start=micros()-start;
Serial.println(start);
for(byte i=0; i<4; i++){
Serial.print(val[i]);
Serial.print("|");
}
delay(2000);
}

 

Tần số của bộ đếm ADC mặc định: 125khz

 

Thời gian: 448 us.

val[0]=val[1]=val[2]=val[3]=178.

Tần số của bộ đếm ADC:  4mhz

 

Thời gian: 24 us. (nhanh hơn 18 lần)

val[0]=val[1]=val[2]=val[3]=177.

Tạm kết.

Dưới đây là test của anh John Boxall về tốc độ điều khiển chân port.

 

http://tronixstuff.com/2011/10/22/tutorial-arduino-port-manipulation/

Hẳn là có bạn vẫn còn nghi ngờ kết quảdevil. Hihi.Các bạn hãy test lại nhé.

Hãy tìm mọi cách để đảo ngược tình thế nhé, có thể đấy.enlightened

Các code trên còn là các ví dụ mẫu cho các bạn tham khảo.

Việc điều khiển các chân port là không khó. Nó đem lại cho ta nhiều lợi ích tuyệt vời, không những Full Speed mà còn tiết kiệm dung lượng code . Bạn hãy tìm hiểu cách điều khiển port tại đây:

link: Điều khiển pin bằng ngôn ngữ chính thống .

Tác giả:  Thái Sơn.

wink

lên
32 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Bộ điều khiển PID - ứng dụng phần 2 - xe dò line dùng thuật toán PID

Tiép nối bài viết về xe dò line cảm ơn Đỗ Hữu Toàn đã viết hộ mình phần 4. hôm nay mình sẽ làm cho chiếc xe dò line đi mượt và có hồn hơn 

lên
34 thành viên đã đánh giá bài viết này hữu ích.
Các bài viết cùng tác giả

Giới thiệu module thu phát RF CC2530 tầm xa (plus CC2591) của Zigbee.

Mình mới đặt hàng được module RF này, đây là module truyền sóng 2.4 GHZ, khoảng cách rất xa, sử dụng giao tiếp Serial (TX-RX) rất thông dụng, cắm vào là chạy….Rất phù hợp với các dự án robot thám hiểm, thăm dò, tình báo,…..

lên
37 thành viên đã đánh giá bài viết này hữu ích.

Giới thiệu module ESP32 và hướng dẫn cài trình biên dịch trên Arduino Ide.

Hiện tại , module wifi esp8266 đã có mặt ở khắp nơi , nhà nhà dùng ESP8266. Vậy đâu là sự lựa chọn tiếp theo sau ESP8266 ? Câu trả lời từ nhà sản xuất ESP (espressif.com) đó là  :   “ESP32”

Cấu hình khủng, thêm chức năng , tăng số chân I/O, thêm nhiều cảm biến , giá thành phù hợp…là những gì mình sẽ giới thiệu về esp32 tại bài viết này.

lên
12 thành viên đã đánh giá bài viết này hữu ích.
Từ khóa: