Tự động hóa

Arduino: Hàm millis() trong Arduino

 

Giới thiệu

Hàm millis() có nhiệm vụ trả về một số – là thời gian (tính theo mili giây) kể từ lúc mạch Arduino bắt đầu chương trình của bạn. Các hàm về thời gian trong Arduino gồm millis() và micros() sẽ bị tràn số sau 1 thời gian sử dụng. Với hàm millis() là khoảng 50 ngày, micros()sẽ tràn sau khoảng 70 phút. Tuy nhiên, do là kiểu số nguyên không âm (unsigned long) nên ta dễ dàng khắc phục điều này bằng cách sử dụng hình thức ép kiểu. Hai hàm millis()và micros() là các chức năng thực sự tiện dụng để sử dụng khi xử lý các tác vụ thời gian.

Tham số: không

Trả về: một số nguyên kiểu unsigned long là thời gian kể từ lúc thương trình Arduino được khởi động

Thông thường trong chương trình Arduino, khi cần dừng lại để chờ qua 1 khoảng thời gian chúng ta thường sử dụng hàm delay () để thực hiện việc chờ này. Tuy nhiên cách làm này gây hao phí thời gian của CPU một cách vô ích, chúng ta không thể vừa dừng lại để chờ, vừa chạy 1 đoạn chương trình khác được. Kĩ thuật dùng hàm millis() sẽ giúp bạn chạy được nhiều đoạn chương trình song song với nhau.

Ví dụ: Đoạn chương trình này có nghĩa là sau mỗi 1000 mili giây đèn Led ở chân số 10 sẽ thay đổi trạng thái

unsigned long time;
byte ledPin = 10;
void setup()
{
    // khởi tạo giá trị biến time là giá trị hiện tại
    // của hàm millis();
    time = millis();
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
}

void loop() 
{
    // Lưu ý các dấu ngoặc khi ép kiểu
    // đoạn chương trình này có nghĩa là sau mỗi 1000 mili giây
    // đèn Led ở chân số 10 sẽ thay đổi trạng thái
    if ( (unsigned long) (millis() - time) > 1000)
    {
        // Thay đổi trạng thái đèn led
        if (digitalRead(ledPin) == LOW)
        {
            digitalWrite(ledPin, HIGH);
        } else {
            digitalWrite(ledPin, LOW);
        }
        
        // cập nhật lại biến time
        time = millis();
    }
}

Ép kiểu

if ( (unsigned long) (millis() - time) > 1000)
    {
    /*..............*/    
    }

Thông thường, nếu ta có 2 số A, B và B lớn hơn A ( B > A) thì phép trừ thu được A-B là một số âm. Nhưng khi ép kiểu unsigned long là kiểu số nguyên dương, không có số âm nên giá trị trả về là 1 số nguyên dương lớn.
Ví dụ: kết quả của phép trừ:
unsigned long ex = (unsigned long) (0 – 1); à 4294967295, con số này chính là giá trị lớn nhất của kiểu số unsigned long. Giống như bạn đạp xe 1 vòng và quay về vạch xuất phát vậy.

Ví dụ in ra dòng chữ hello vào serial mỗi 1 giây:

// Hiển thị chữ Xin Chao sau mỗi 1 giây

unsigned long time = 0;

void setup() {
    Serial.begin(9600); 	
}

void loop() {    
    if( (unsigned long) (millis() - time) > 1000)
    {	
        time = millis();
        Serial.println(String("Time: ")+ (time/1000) + String(" Xin chao"));    	
    }
}

Tại sao sử dụng millis () thay vì delay ()?

Thời gian chính xác: Với millis(), chúng ta có thể đảm bảo rằng vòng lặp chạy thường xuyên như chúng ta muốn, bất kể thời gian thực hiện.
Không chặn:  millis() không chặn các tác vụ đang chạy

Sử dụng hàm millis() với khoảng thời gian lớn

Ví dụ in MESSAGE1 mỗi 5 giây và MESSAGE2 mỗi 7 giây và MESSAGE3 mỗi 9 giây:

#define INTERVAL1 5000
#define INTERVAL2 7000
#define INTERVAL3 9000
 
unsigned long millis_1 = 0;
unsigned long millis_2 = 0;
unsigned long millis_3 = 0;
 
void displayTime(unsigned long);
void setup() 
{
    Serial.begin(9600);
}
void loop() 
{
  if(millis() > millis_1 + INTERVAL1)
  {
    millis_1 = millis();
    displayTime(millis_1);
    Serial.println("1");
  }
  if(millis() > millis_2 + INTERVAL2)
  {
    millis_2 = millis();
    displayTime(millis_2);
    Serial.println("2");
  }
  if(millis()  > millis_3 + INTERVAL3)
  {
    millis_3 = millis();
    displayTime(millis_3);
    Serial.println("3");
  }
}
void displayTime(unsigned long time_millis)
{
    Serial.print("Time: ");
    Serial.print(time_millis/1000);
    Serial.print("s - ");
}

Sử dụng millis để tính khoảng thời gian (timer)

Tính thời gian ấn giữ phím nhấn tại chân 2 của Arduino Uno:


/*
tính thời gian phím được giữ
*/
const int switchPin = 2; // nút bấm được nối vào PIN2
long startTime; // giá trị khi nút bắt đầu bấm
long duration; // khoảng thời gian được giữ
void setup()
{
pinMode(switchPin, INPUT);
digitalWrite(switchPin, HIGH); // kéo chân 2 lên mức cao
Serial.begin(9600);
}
void loop()
{
if(digitalRead(switchPin) == LOW) // nếu nút bấm ở mức thấp
{
startTime = millis(); // giá trị ban đầu được gán bằng giá trị hiện tại của millis
while(digitalRead(switchPin) == LOW) ; // đợi cho nút bấm được giữ
long duration = millis() - startTime; // thời gian bằng giá trị hiện tại trừ giá trị ban đầu
Serial.println(duration); //in ra màn hình
}
}

Ví dụ nhấp nháy hai led song song nhau

Mục tiêu của đoạn chương trình này là nhấp nháy cùng lúc 2 đèn led, mỗi đèn có chu kì nháy sáng khác nhau.


byte led1 = 5;
byte led2 = 6;
unsigned long time1 = 0;
unsigned long time2 = 0;

void setup()
{
    pinMode(led1, OUTPUT);
    pinMode(led2, OUTPUT);
}

void loop()
{
    if ( (unsigned long) (millis() - time1) > 1000 )
    {
        if ( digitalRead(led1) == LOW )
        {
            digitalWrite(led1, HIGH);
        } else {
            digitalWrite(led1, LOW );
        }
        time1 = millis();
    }
    
    if ( (unsigned long) (millis() - time2) > 300  )
    {
        if ( digitalRead(led2) == LOW )
        {
            digitalWrite(led2, HIGH);
        } else {
            digitalWrite(led2, LOW );
        }
        time2 = millis();
    }
}

Đoạn chương trình trên có chức năng kiểm tra các biến thời gian time1, time2 so với giá trị của hàm millis(). Nếu vượt quá thời gian quy định 1000ms với biến time1 và 300ms với biến time2 thì sẽ thay đổi trạng thái đèn led. Nếu với cách làm thông thường chúng ta sẽ viết:

void loop()
{
   if ( digitalRead(led1) == LOW )
   {
        digitalWrite(led1, HIGH);
   } else {
        digitalWrite(led1, LOW );
   }
   delay (700); // giảm thời gian để tổng thời gian chờ của led 1 là 700 + 300 = 1000ms
   
   if ( digitalRead(led2) == LOW )
   {
        digitalWrite(led2, HIGH);
   } else {
        digitalWrite(led2, LOW );
   }
   delay (300);
}

Với cách viết thông thường, chương trình sẽ dừng lại ở hàm delay và chờ ở đó. Trong khi với cách viết dùng hàm millis() như ở trên, chúng ta có thể nhấp nháy nhiều led song song với nhau.

About Mr. Facebook

0 nhận xét:

Đăng nhận xét