Arduino – Timer – Interrupt

Trong chương này chúng ta sẽ tìm hiểu:

  • Các khái niệm về Interrupt, Timer/Counter.

  • Tại sao và khi nào cần sử dụng Interrupt, Timer/Counter.

  • Cách sử dụng Interrupt, Timer/Counter.

Interrupt

Giới thiệu

Trong quá trình làm việc, bỗng nhiên bạn nhận được một yêu cầu gấp, cần phải thực hiện ngay lập tức. Lúc này, bạn buộc phải dừng công việc hiện tại để thực hiện yêu cầu đó và chỉ có thể tiếp tục công việc đang dở dang khi hoàn thành song yêu câu. Tương tự vậy, trong lập trình, chúng ta có một khái niệm, đó chính là ngắt (Interrupt).

interrupt
Figure 1. Ngắt

Ngắt là khi một tín hiệu khẩn cấp được gửi tới bộ xử lý, yêu cầu bộ xử lý tạm dừng tức khắc các hoạt động hiện tại để nhảy đến một nơi khác thực hiện một nhiệm vụ khẩn cấp nào đó, nhiệm vụ này được gọi là trình phục vụ ngắt – ISR (Interrupt Service Routine). Sau khi kết thúc trình phục vụ ngắt – ISR, bộ đếm chương trình sẽ trả về giá trị trước đó để bộ xử lý quay về thực hiện chương trình đang dang dở.

Vì sao cần sử dụng ngắt

Quay trở lại ví dụ về button đã đề cập ở phần Hello world, chúng ta phải liên tục đọc trạng thái của nút nhấn bằng hàm digitalRead() trong chương trình loop.

void loop() {
  // Đọc trạng thái của nút nhấn
  buttonState = digitalRead(buttonPin);

  // Kiểm tra nếu nút được nhấn, tức buttonState ở trạng thái LOW:
  if (buttonState == LOW) {
    // Bật LED
    digitalWrite(ledPin, HIGH);
  } else {
    // Tắt LED
    digitalWrite(ledPin, LOW);
  }
}

Điều này sẽ cực kì khó khăn khi số lượng các câu lệnh trong chương trình loop tăng lên, lúc này tốc độ đáp ứng của chương trình khi chúng ta nhấn nút sẽ không còn nhanh nữa bởi vì chương trình loop phải thực hiện song tất cả các lệnh rồi mới quay trở lại đọc trạng thái nút nhấn. Ngắt sẽ giải quyết những vấn đề này cho bạn. Lúc này, chương trình vẫn chạy liên tục những lệnh có trình chương trình loop và chỉ khi có ngắt xảy ra khi ta ấn nút nhấn thì chương trình mới thực hiện các lệnh trong chương trình phục vụ ngắt và sau đó quay trở lại thực hiện tiếp chương trình trong loop.

Điều này sẽ giúp tốc độ đáp ứng của chương trình đối với các thao tác của bạn được nhanh hơn và việc quản lý chương trình của bạn được dễ dàng và hiệu quả hơn.

Vector ngắt

Trong thực tế trên mỗi bộ xử lý đều có rất nhiều ngắt khác nhau, vậy điều gì sẽ xảy ra khi cùng một lúc có hai ngắt xuất hiện? Cũng như ví dụ đầu bài, nhưng bây giờ bạn nhận đến 2 yêu cầu cần thực hiện gấp, vậy bạn sẽ thực hiện yêu cầu nào? Tất nhiên là sẽ ưu tiên yêu cầu cấp thiết nhất, sau khi hoàn thành thì mới thực hiện yêu cầu tiếp theo và cuối cùng là trở lại công việc đang làm dở. Cũng như trong lập trình, mỗi ngắt đều được quy định một mức ưu tiên khác nhau, được gọi là vector ngắt (vector ngắt có giá trị càng nhỏ thì độ ưu tiên càng cao), Reset là ngắt có mức ưu tiên cao nhất.

Ngắt trong Arduino

Trong khuôn khổ của Arduino và mục tiêu của sách là đơn giản hóa mọi vấn đề để các bạn mới bắt đầu dễ dàng tiếp cần thì chúng ta sẽ không đi sâu vào vấn đề này.

Trong Arduino, chúng ta được hỗ trợ 2 loại ngắt như sau:

  • Ngắt số 0 được nối với chân số 2.

  • Ngắt số 1 được nối với chân số 3.

Để sử dụng ngắt chúng ta cần phải kết nối nút nhấn hoặc cảm biến vào hai chân này để tạo tín hiệu ngắt cho bộ xử lý.

Tùy thuộc vào vi điều khiển trên board mà mỗi dòng Arduino có số lượng các ngắt khác nhau. Bạn có thể tham khảo bảng sau:

Table 1. Số lượng ngắt trên các Board Arduino
Board Int.0 Int.1 Int.2 Int.3 Int.4 Int.5

Uno. Ehternet

2

3

.

.

.

.

Mega2560

2

3

21

20

19

18

Leonardo

2

3

0

1

7

.

Arduino hỗ trợ 2 lệnh giúp ta khai báo và hủy một ngắt bất kì một cách dễ dàng đó là attachInterrupt()detachInterrupt().

Lệnh attachInterrupt()

  • Mục đích: Giúp khai báo một ngắt.

  • Cú pháp lệnh: attachInterrupt(interrupt, ISR, mode).

  • Các đối số:

    • interrupt: Lựa chọn ngắt mà bạn muốn dùng, với IoT Maker UnoX có 2 lựa chọn là:

      • 0: Ứng với ngắt số 0 trong Arduino (chân số 2).

      • 1: Ứng với ngắt số 1 trong Arduino (chân số 3).

    • ISR: Chương trình phục vụ ngắt. Chương trình này sẽ được thực hiện khi có ngắt xảy ra.

    • mode: Kiểu kích hoạt ngắt:

      • LOW: Ngắt sẽ được kích hoạt khi trạng thái chân ở mức thấp.

      • HIGH: Ngắt sẽ được kích hoạt khi trạng thái chân ở mức cao.

      • CHANGE: Ngắt khi có sự thay đổi trạng thái trên chân ngắt (trạng thái thay đổi từ mức điện áp thấp lên mức điện áp cao hoặc ngược lại, từ mức điện áp cao xuống mức điện áp thấp.

      • RISING: Ngắt sẽ được kích hoạt khi trạng thái của chân digital chuyển từ mức điện áp thấp sang mức điện áp cao.

      • FALLING: Ngắt sẽ được kích hoạt khi trạng thái của chân digital chuyển từ mức điện áp cao sang mức điện áp thấp.

Trong mode LOW và HIGH, chương trình ngắt sẽ được gọi liên tục khi chân digital vẫn còn giữ ở mức điện áp thấp hoặc cao.
  • Giá trị trả về: Không có giá trị trả về

Lệnh detachInterrupt()

  • Mục đích: Tắt ngắt hiện tại.

  • Cú pháp lệnh: detachInterrupt(pin).

  • Các đối số:

    • pin: Lựa chọn ngắt mà bạn muốn tắt, dùng board Arduino Uno có 2 lựa chọn là:

      • 0: Tắt ngắt số 0 trong Arduino ( chân số 2).

      • 1: Tắt ngắt số 1 trong Arduino ( chân số 3).

  • Giá trị trả về : Không có giá trị trả về.

Ví dụ

Yêu cầu

Thiết kế hệ thống tự động bật sáng đèn khi trời tối.

Linh kiện cần dùng

Cảm biến ánh sáng quang trở

cam bien anh sang quang tro
Figure 2. Cảm biến ánh sáng quang trở

Relay

module relay
Figure 3. Module Relay 5v 1 kênh.

Relay là công tắc chuyển mạch (có thể đóng cắt điện áp DC và AC) được điều khiển bằng tín hiệu DC. Đây là linh kiện thụ động rất thường gặp trong các mạch điện tử.

Relay có hai dạng phổ biến: Relay đóng mức thấp và đóng mức cao. Để hiểu thêm nguyên lý hoạt động của Relay, Module relay và cách sử dụng.

Phân tích chương trình:

  • Chúng ta sẽ dùng chân DO (Digital Output) của quang trở kết nối với ngắt số 0 (chân số 2). Trong điều kiện có ánh sáng, chân DO sẽ xuất ra mức 0 và ngược lại khi không có ánh sáng sẽ xuất ra mức 1.

  • Chúng ta sẽ khai báo ngắt số 0 (chân số 2) với kiểu kích hoạt là LOW (ngắt khi trạng thái chân số 2 ở mức thấp) và chương trình phục vụ ngắt là turnOffRelay (để tắt Relay).

  • Chương trình chính sẽ thực hiện việc bật Relay.

  • Khi môi trường có ánh sáng, chân DO của cảm biến sẽ xuất mức LOW, lúc này ngắt xảy ra và Relay sẽ tắt (đèn tắt).

Kết nối

Table 2. Bảng đấu nối board IoT Maker UnoX và Relay
IoT Maker UnoX Relay

5V

5V

GND

GND

A0

IN

Table 3. Bảng đấu nối board IoT Maker UnoX và Cảm biến ánh sáng
Iotmaker Uno X Cảm biến ánh sáng

5V

5V

GND

GND

2

DO

relay light sensor unox
Figure 4. Hình ảnh kết nối cảm biến ánh sáng quang trở và Relay với board IoT Maker UnoX

Source code

int relay = A0;               // khai báo chân relay là chân Ao

void turnOffRelay()
{
    digitalWrite(relay, LOW); // Tắt relay khi xảy ra ngắt.
}

void setup()
{
   pinMode(relay, OUTPUT);
   pinMode(2, INPUT_PULLUP);  // khai báo chân số 2 là ngõ vào sử dụng điện trở kéo lên.
   attachInterrupt(0, turnOffRelay, LOW);
   // khai báo ngắt số 0, xảy ra khi chân số 2 ở mức thấp
   // chương trình turnOffRelay được gọi khi ngắt xảy ra.
}

void loop()
{
  digitalWrite(relay, HIGH);  // bật relay
}
Trong ví dụ sử dụng Relay đóng mức cao. Khi sử dụng Relay đóng mức thấp thì cần phải đảo tín hiệu điều khiển.

Kết nối board IoT Maker UnoX với máy tính bằng cổng micro USB, nạp code và kiểm tra kết quả.

Timer/Counter

Giới thiệu

Timer/Counter là một trong những ngoại vi hoạt động độc lập và không thể thiếu trong bất kì vi điều khiển nào. Thực chất, Timer/Counter chỉ là một bộ đếm xung clock (có thể là xung nhịp nội bên trong vi điểu khiển hoặc xung clock bên ngoài). Nó tương tự như việc đếm giờ, thay vì ngồi canh đồng hồ và đếm từng giây thì chúng ta có thể đặt báo thức và làm những công việc khác, việc đếm thời gian thì giao cho đồng hồ xử lý.

Quá trình hoạt động của Timer/Counter được quản lý bởi thanh ghi, chúng gồm thanh ghi chứa giá trị Timer/Counter đếm được và thanh ghi điều khiển các hoạt động đếm của nó.

Trong khuôn khổ của sách này, chúng ta sẽ không tìm hiểu sâu về thanh ghi, nếu bạn có nhu cầu tìm hiễu rõ hơn có thể truy cập vào đường dẫn: http://arduino.vn/bai-viet/411-timercounter-tren-avrarduino.

Timer/Counter được sử dụng rất nhiều trong các ứng dụng định thời, đếm sự kiện, tạo xung PWM,…​

Timer/Counter trong Arduino

Một số định nghĩa mà các bạn cần lưu ý trong khi sử dụng Timer/Counter:

  • BOTTOM: Giá trị nhỏ nhất mà Timer/Counter có thể đạt được. Mặc định giá trị này bằng 0.

  • MAX: Giá trị lớn nhất mà thanh ghi giá trị của Timer/Counter có thể chứa được. Tùy thuộc vào độ rộng của thanh ghi giá trị mà chúng ta có được giá trị MAX khác nhau. Ví dụ như Timer/Counter 0 là bộ timer 8 bit tức là giá trị tối đa (MAX) của nó là 28-1=255 và đối với timer 16 bit là 216-1=65535.

  • TOP: Giá trị mà khi Timer/Counter đạt đến nó sẽ thay đổi trạng thái, giá trị này phải bé hơn hoặc bằng 255 (đối với timer 8 bit) và 65535 (đối với timer 16 bit).
    Ví dụ: Trong Timer/Counter 0 chúng ta sẽ có giá trị MAX là 255, nếu không không thiết lập giá trị TOP thì timer sẽ đếm từ 0 đến 255 và sau đó quay trở lại 0, nếu chúng ta thiết lập giá trị TOP thì timer sẽ đếm từ 0 đến giá trị TOP và quay về 0.

  • Ngắt Timer: Bất cứ khi nào Timer đếm đến giá trị TOP hoặc Timer bị tràn (đếm đến giá trị MAX) thì đều xảy ra ngắt.

Chip ATMega328p (vi điều khiển của board IoT Maker UnoX) bao gồm các Timer/Counter sau:

  • Timer/Counter 0: Là bộ timer 8 bit được sử dụng nhiều trong các hàm delay(), millis(), micros(). Chúng ta nên hạn chế sử dụng bộ timer này vì rất dễ gây ảnh hưởng đến những hàm trên.

  • Timer/Counter 1: Là bộ timer 16 bit được sử dụng trong thư viện servo.

  • Timer/Counter 2: Là một bộ timer 8 bit tương tự như Timer/Counter 0 và được sử dụng trong hàm tone().

Khi sử dụng bộ Timer/Counter nào thì chúng ta cần lưu ý đến những hàm hoặc thư viện sử dụng bộ Timer/Counter đó nhằm tránh việc chương trình bị xung đột hoặc chạy không chính xác.

Thư viện TimerOne

Trên nền tảng Arduino và mục tiêu của eBook là đơn giản hóa cho những bạn mới tiếp cận, vì vậy chúng ta sẽ không điều khiển trực tiếp Timer bằng thanh ghi mà thay vào đó sẽ sử dụng thư viện TimerOne để tiếp cận với Timer/Counter.

Đúng như tên gọi, thư viện sẽ sử dụng bộ Timer/Counter 1 (16 bit), ngoài ra nếu bạn muốn tìm hiểu rõ hơn về cách sử dụng cũng như quá trình hoạt động của tất cả Timer trong board IoT Maker UnoX, bạn có thể tham khảo bài viết sau: http://arduino.vn/bai-viet/411-timercounter-tren-avrarduino.

Các hàm cần chú ý trong thư viện:

  • initialize(microseconds): Khởi động ngắt Timer với một chu kì xác định.

    • Các đối số:

      • microseconds: chu kỳ ngắt của Timer (tính bằng micro giây). Mặc định giá trị microseconds = 1 000 000 tương ứng với 1s.

  • start(): Khởi động lại Timer sau quá trình thay đổi, chỉnh sửa.

  • startBottom(): Cho Timer đếm lại từ 0 (giá trị BOTTOM).

  • read(): Đọc giá trị Timer đếm được ở thời điểm hiện tại.

  • stop(): Dừng Timer.

  • attachInterrupt(): Thêm chương trình phục vụ ngắt khi xảy ra sự kiện ngắt Timer.

  • detachInterrupt(): Hủy hàm ngắt Timer.

  • pwm(pin, duty): Xuất xung PWM ra một chân xác định.

    • Các đối số:

      • pin: Lựa chọn chân xuất PWM.

      • duty: Chu kì xung PWM.

  • disablePwm(char pin): Hủy băm xung PWM.

    • Các đối số:

      • pin: Lựa chọn chân để hủy PWM.

Một số ví dụ

Điều khiển LED

Yêu cầu

Sử dụng Timer để điều khiển LED trên board nháy sau mỗi 0,15s và hiển thị số lần LED sáng lên OLED.

Linh kiện cần dùng

Phân tích:

  • Chúng ta sẽ khai báo một Timer để định thời gian là 0,15s. Cứ sau 0,15s Timer sẽ ngắt, thực hiện chương trình blinkLED và đếm lại từ đầu.

  • Chương trình blinkLED sẽ thực hiện việc đảo trạng thái của đèn LED từ sáng thành tắt và ngược lại, đống thời đếm số lần đèn LED sáng.

  • Vòng lặp loop() sẽ thực hiện việc hiển thị số lần LED sáng lên màn hình OLED SSD1306.

Thư viện

  • Đầu tiên, chúng ta cần download thư viện TimerOne của PaulStoffregen cho Arduino. Link download.

Sau khi tải thư viện về, bạn mở phần mềm arduino, chọn Sketch → Import Library…​ → Add Library…​. Sau đó chọn file .zip mà bạn vừa tải về để có thể sử dụng thư viện.

Source code

#include <TimerOne.h> //thư viện cho Timer1
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

const int led = LED_BUILTIN;  // LED BUILD chính là LED mặc định trên BOARD

void setup(void)
{
  pinMode(led, OUTPUT);
  Timer1.initialize(150000); //Khởi động ngắt Timer1 tràn mỗi 0.15s
  Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.15 seconds
  setUpOLED(); // thiết lập OLED
}

void setUpOLED()
{
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
}

int ledState = LOW;
volatile unsigned long blinkCount = 0; //biến đếm số lần Led sáng

void blinkLED(void)
{
  if (ledState == LOW) {
    ledState = HIGH;
    blinkCount = blinkCount + 1;  // Tăng biến đếm mỗi khi LED sáng
  } else {
    ledState = LOW;
  }
  digitalWrite(led, ledState);
}

void loop(void)
{
  unsigned long blinkCopy;  // biến linkCopy được dùng để copy số lần LED từ biến blinkCount
  //tắt ngắt nhằm tránh trường hợp biến blinkCount thay đổi (do ngắt timer xảy ra) trong quá trình copy.
  noInterrupts();
  blinkCopy = blinkCount;
  interrupts();

  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("So Lan Sang:" + String(blinkCopy));
  display.display();
  delay(1000);
}

Kết nối board với máy tính bằng cổng COM, nạp chương trình và xem kết quả.

Từ khóa volatile được dùng cho những biến sử dụng trong chương trình phục vụ ngắt và các chương trình khác.
final blink timer
Figure 5. Kết quả hiển thị trên OLED

Điều khiển tốc độ quạt

Yêu cầu

Điều khiển tốc độ quạt sử dụng băm xung PWM.

Thực tế chúng ta vẫn có thể điều khiển tốc độ quạt bằng hàm analogWrite (), nhưng vấn đề đặt ra là hàm analogWrite() chỉ xuất ra xung PWM với tần số mặc định khoảng 490Hz đến 3920Hz trong khi một số quạt hiện nay yêu cầu xung PWM có tần số trong khoảng từ 21kHz đến 28kHz. Vì vậy chúng ta sẽ phải sử dụng Timer/Counter đề điều chế xung PWM.

Linh kiện sử dụng

FAN
Figure 6. FAN

FAN nói chung hoặc quạt tản nhiệt nói riêng thông thường sẽ có 3 chân, chân (+) màu đỏ, chân GND màu đen và chân còn lại là chân điều khiển tốc độ.

Kết nối

Table 4. Bảng đấu nối board IoT Maker UnoX và quạt mini
IoT Maker UnoX FAN

5V

5V

GND

GND

4

Xanh dương

mini fan unox
Figure 7. Hình ảnh kết nối quạt mini với board IoT Maker UnoX

Source code

#include <TimerOne.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int fanPin = 4; //khai báo chân điều khiển tốc độ quạt

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

void setup(void)
{
  Timer1.initialize(40);  // thiết lập timer1 với chu kì 40us tương ứng 25kHz.
  setUpOLED(); // thiết lập OLED
}

void setUpOLED()
{
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
}

void loop(void)
{
  for (float dutyCycle = 30.0; dutyCycle < 100.0; dutyCycle++)
  {
    Timer1.pwm(fanPin, (dutyCycle / 100) * 1023);
    display.clearDisplay();
    display.setCursor(32, 0);
    display.println("PWM Fan");
    display.setCursor(0, 15);
    display.println("Duty Cycle = " + String(dutyCycle));
    display.display();
    delay(500);
  }
}

Kết nối board với máy tính bằng cổng COM, nạp chương trình và kiểm tra kết quả.

final fan control
Figure 8. Kết quả hiển thị trên OLED

Giải thích source code:

  • Đầu tiên khai báo Timer để định thời gian là 40 micro giây (tương ứng với tần số PWM là 1/40 µs = 25kHz ) bằng lệnh Timer1.initialize(40).

  • Trong chương trình loop(), chúng ta dùng một vòng lặp for để tăng tốc độ của quạt bằng cách tăng đối số duty của hàm pwm (duty tăng dần theo vòng lặp for).

Điều khiển động cơ Servo bằng biến trở

Servo là gì?

Khác với những dạng động cơ thông thường chỉ quay liên tục khi cấp nguồn điện, Servo là dạng động cơ điều khiển được góc quay bằng xung PWM. Trên thị trường có rất nhiều loại động cơ Servo với kích thước, khối lượng, cấu tạo khác nhau, từ những loại Servo kích thước nhỏ gọn (dùng cho máy bay mô hình) đến những loại sỡ hữu moment xoắn cực lớn (vài chục N/m).

Để điều khiển được góc quay Servo (trong khoảng từ 0o – 180o ) chúng ta sẽ dùng xung PWM như sau:

servo using
Figure 9. Hình điều khiển Servo

Biến trở

Biến trở là linh kiện điện tử mà giá trị điện trở có thể thay đổi được. Chúng có thể được sử dụng trong các mạch điện để điều chỉnh hoạt động của mạch điện.

bientro
Figure 10. Biến trở

Yêu cầu

  • Chúng ta sẽ đọc giá trị analog từ biến trở (sử dụng biến trở để tăng giảm mức điện áp từ 0V đến 5V tương ứng với góc quay từ 0o đến 180o).

  • Sau đó, chúng ta xuất ra xung PWM tương ứng ra chân số 9.

Sơ đồ kết nối

Table 5. Bảng đấu nối board IoT Maker UnoX với động cơ Servo
IoT Maker UnoX Servo Motor

5V

Màu Đỏ

GND

Màu nâu

9

Màu Vàng

Table 6. Bảng đấu nối board IoT Maker UnoX với Biến trở
IoT Maker UnoX Biến trở

5V

1

GND

3

A7

2

servo bientro unox
Figure 11. Hình ảnh kết nối biến trở và động cơ Servo với IoT Maker UnoX

Thư viện

Trong ứng dụng này, chúng ta sẽ sử dụng thư viện servo.h

Thư viện servo.h sử dụng bộ Timer/Counter 1, đóng vai trò quan trọng nếu bạn muốn làm về dự án robot. Nó cung cấp cho bạn một phương thức cực kì đơn giản để điều khiển động cơ Servo. Đồng thời, thư viện đã được tích hợp sẵn trong arduino IDE nên bạn không cần phải tải thêm thư viện khi sử dụng.

Một số hàm cần chú ý như:

  • myservo.attach(pin): Khai báo ngõ ra điều khiển Servo.

    • pin: lựa chọn chân ngõ ra điều khiển Servo.

  • myservo.write(deg): Điểu khiển góc quay Servo.

    • deg: giá trị góc mà bạn muốn quay (0o đến 180o).

Source code

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Servo.h>      // Thư viện điều khiển servo

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

// Khai báo đối tượng myservo dùng để điều khiển servo
Servo myservo;

int bientro = A7;       // Khai báo chân analog đọc biến trở điều khiển servo
int servoPin = 9;       // Khai báo chân điều khiển servo

void setup ()
{
   // Cài đặt chức năng điều khiển servo cho chân servoPin
   myservo.attach(servoPin);
   setUpOLED();
}
void setUpOLED()
{
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
}

void loop ()
{
   int value = analogRead(bientro);// Đọc giá trị biến trở

   // Chuyển giá trị analog (0-1023) đọc được từ biến trở sang số đo độ (0-180độ)
   // dùng để điều khiển góc quay cho servo
   int servoPos = map(value, 0, 1023, 0, 180);

   // Cho servo quay một góc là servoPos độ
   myservo.write(servoPos);
   display.clearDisplay();
   display.setCursor(20, 0);
   display.println("Control Servo");
   display.setCursor(0, 15);
   display.println("Goc quay = " + String(servoPos));
   display.display();
   delay(50);
}

Kết nối board với máy tính bằng cổng COM, nạp chương trình và xem kết quả.

final servo control
Figure 12. Kết quả hiển thị trên OLED

Summary

Qua chương này, chúng ta đã tìm hiểu được những khái niệm cơ bản về ngắt (Interrupt) Timer/counter, lý do tại sao chúng ta cần sử dụng nó trong các ứng dụng. Đồng thời chúng ta biết được thêm thư viện TimerOne giúp ta dễ dàng tiếp cận và làm chủ bộ Timer/Couter trên board IoT Maker UnoX.

Đối với những ví dụ đơn giản, khó có thể không nhận thấy sự khác biệt khi sử dụng ngắt (Interrupt) và Timer/Counter. Nhưng khi thực hiện những ví dụ phức tạp, cần khai thác tối ta khả năng xử lý của vi điều khiển thì đây sẽ là trợ thủ đắc lực cho bạn.

Leave a Comment