Khi bắt đầu lập trình Arduino, việc hiểu rõ về hàm, biến và kiểu dữ liệu là cực kỳ quan trọng. Chúng là những viên gạch cơ bản để xây dựng bất kỳ chương trình nào, giúp bạn điều khiển phần cứng, xử lý thông tin và tạo ra các dự án thú vị. Hãy cùng đi sâu vào từng khái niệm nhé!
1. Biến (Variables) trong Arduino
Trong lập trình, biến có thể hình dung như những "chiếc hộp" trong bộ nhớ máy tính, dùng để lưu trữ dữ liệu. Dữ liệu này có thể thay đổi trong suốt quá trình chương trình chạy.
Khai báo biến
Trước khi sử dụng một biến, bạn cần "khai báo" nó. Việc này cho Arduino biết tên của biến và loại dữ liệu mà nó sẽ lưu trữ (kiểu dữ liệu).
Cú pháp khai báo biến:
kieu_du_lieu ten_bien;
Hoặc bạn có thể gán giá trị ban đầu ngay khi khai báo:
kieu_du_lieu ten_bien = gia_tri_khoi_tao;
Ví dụ:
int soLanNhanNut; // Khai báo một biến kiểu số nguyên
float nhietDoC = 25.5; // Khai báo và gán giá trị ban đầu cho biến nhiệt độ
Phạm vi biến (Variable Scope)
Phạm vi của biến quy định nơi mà biến đó có thể được truy cập và sử dụng trong chương trình. Có hai loại chính:
- Biến cục bộ (Local Variables): Được khai báo bên trong một hàm hoặc một khối lệnh (
{...}
). Biến này chỉ tồn tại và có thể sử dụng được trong chính hàm hoặc khối lệnh đó. Sau khi hàm/khối lệnh kết thúc, biến cục bộ sẽ bị hủy.void setup() { int denPin = 13; // denPin là biến cục bộ của hàm setup() } void loop() { // denPin không thể được truy cập ở đây }
- Biến toàn cục (Global Variables): Được khai báo bên ngoài tất cả các hàm, thường là ở đầu chương trình. Biến toàn cục có thể được truy cập và sử dụng từ bất kỳ đâu trong chương trình.
int soLanNhiepAnh = 0; // soLanNhiepAnh là biến toàn cục void setup() { // Có thể truy cập soLanNhiepAnh ở đây } void loop() { soLanNhiepAnh++; // Có thể truy cập và thay đổi soLanNhiepAnh ở đây }
Lưu ý: Mặc dù tiện lợi, việc sử dụng quá nhiều biến toàn cục có thể khiến chương trình khó quản lý và dễ gây lỗi hơn.
2. Kiểu Dữ liệu (Data Types) trong Arduino
Kiểu dữ liệu xác định loại giá trị mà một biến có thể lưu trữ và lượng bộ nhớ mà biến đó chiếm dụng. Arduino (dựa trên C++) cung cấp nhiều kiểu dữ liệu khác nhau:
Kiểu Dữ liệu | Kích thước (byte) | Phạm vi giá trị (xấp xỉ) | Mô tả | Ví dụ |
---|---|---|---|---|
boolean |
1 | true hoặc false |
Giá trị logic (đúng/sai) | boolean trangThai = true; |
byte |
1 | 0 đến 255 | Số nguyên không dấu (0 hoặc dương) | byte giaTriCamBien = 150; |
char |
1 | -128 đến 127 | Ký tự ASCII (hoặc số nguyên nhỏ) | char kyTu = 'A'; |
unsigned char |
1 | 0 đến 255 | Tương tự byte , dùng cho ký tự không dấu |
unsigned char duLieu = 200; |
int |
2 | -32,768 đến 32,767 | Số nguyên có dấu | int tocDo = 1000; |
unsigned int |
2 | 0 đến 65,535 | Số nguyên không dấu | unsigned int thoiGian = 50000; |
word |
2 | 0 đến 65,535 | Giống unsigned int |
word chuKy = 1024; |
long |
4 | -2,147,483,648 đến 2,147,483,647 | Số nguyên dài có dấu | long soLuotDem = 100000; |
unsigned long |
4 | 0 đến 4,294,967,295 | Số nguyên dài không dấu | unsigned long milisTuKhiKhoiDong = 123456789; |
float |
4 | $\pm 3.4028235E+38$ | Số thập phân (số thực) | float nhietDo = 27.5; |
double |
4 | Giống float trên Arduino Uno |
Số thập phân (chính xác hơn trên các board khác) | double pi = 3.14159265; |
void |
0 | Không có giá trị | Chỉ ra rằng một hàm không trả về giá trị | void setup() { ... } |
int
và long
có thể là 4 byte). Trên các board Arduino AVR (Uno, Nano, Mega), bảng trên là chính xác.3. Hàm (Functions) trong Arduino
Hàm là một khối mã độc lập được thiết kế để thực hiện một nhiệm vụ cụ thể. Việc sử dụng hàm giúp chương trình của bạn:
- Tổ chức: Chia chương trình lớn thành các phần nhỏ, dễ quản lý hơn.
- Tái sử dụng: Viết mã một lần và gọi nó nhiều lần ở các vị trí khác nhau trong chương trình.
- Dễ đọc: Làm cho mã nguồn rõ ràng và dễ hiểu hơn.
- Dễ bảo trì: Khi có lỗi hoặc cần thay đổi, bạn chỉ cần sửa ở một chỗ duy nhất.
Cấu trúc của một hàm
Một hàm cơ bản có cấu trúc như sau:
kieu_du_lieu_tra_ve ten_ham(kieu_tham_so1 ten_tham_so1, kieu_tham_so2 ten_tham_so2, ...) {
// Các câu lệnh trong hàm
return gia_tri_tra_ve; // Chỉ có nếu kieu_du_lieu_tra_ve không phải là void
}
kieu_du_lieu_tra_ve
: Kiểu dữ liệu mà hàm sẽ trả về sau khi thực hiện xong (ví dụ:int
,float
,boolean
). Nếu hàm không trả về bất kỳ giá trị nào, bạn sẽ dùng từ khóavoid
.ten_ham
: Tên của hàm, bạn tự đặt (nên đặt tên có ý nghĩa).(tham_so1, tham_so2, ...)
: Danh sách các tham số. Đây là những giá trị mà bạn "truyền" vào hàm để hàm xử lý. Mỗi tham số bao gồm kiểu dữ liệu và tên biến. Nếu hàm không cần tham số nào, bạn để trống dấu ngoặc đơn()
.return gia_tri_tra_ve;
: Câu lệnh này dùng để trả về một giá trị từ hàm. Nó phải phù hợp vớikieu_du_lieu_tra_ve
đã khai báo. Chỉ dùng khikieu_du_lieu_tra_ve
không phải làvoid
.
Các loại hàm phổ biến
1. Hàm không có tham số, không có giá trị trả về (void
)
Thường dùng cho các tác vụ đơn giản, không cần đầu vào hay trả về kết quả.
void nhayDen() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
nhayDen(); // Gọi hàm nhayDen()
}
2. Hàm có tham số, không có giá trị trả về (void
)
Cho phép bạn truyền dữ liệu vào hàm để hàm thực hiện tác vụ dựa trên dữ liệu đó.
void dieuKhienDen(int pinDen, boolean trangThai) {
digitalWrite(pinDen, trangThai);
}
void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
}
void loop() {
dieuKhienDen(13, HIGH); // Bật đèn ở chân 13
delay(1000);
dieuKhienDen(12, LOW); // Tắt đèn ở chân 12
delay(1000);
}
3. Hàm không có tham số, có giá trị trả về
Thực hiện một tác vụ và trả về một kết quả.
int docGiaTriCamBienA0() {
int giaTri = analogRead(A0);
return giaTri;
}
void setup() {
Serial.begin(9600);
}
void loop() {
int duLieuDocDuoc = docGiaTriCamBienA0();
Serial.print("Gia tri cam bien: ");
Serial.println(duLieuDocDuoc);
delay(100);
}
4. Hàm có tham số, có giá trị trả về
Loại hàm linh hoạt nhất, nhận đầu vào và trả về kết quả.
float chuyenDoiNhietDo(int docTho) {
// Công thức chuyển đổi từ giá trị thô sang độ C (ví dụ)
float dienAp = docTho * (5.0 / 1023.0);
float nhietDo = (dienAp - 0.5) * 100;
return nhietDo;
}
void setup() {
Serial.begin(9600);
}
void loop() {
int giaTriTho = analogRead(A0);
float nhietDoHienTai = chuyenDoiNhietDo(giaTriTho);
Serial.print("Nhiet do: ");
Serial.print(nhietDoHienTai);
Serial.println(" C");
delay(1000);
}
Hai hàm đặc biệt trong Arduino: setup()
và loop()
Mọi chương trình Arduino đều bắt buộc phải có hai hàm này:
void setup()
: Hàm này chỉ chạy một lần duy nhất khi board Arduino được bật nguồn hoặc khởi động lại. Đây là nơi bạn cấu hình các chân (pin) là đầu vào/đầu ra, khởi tạo giao tiếp Serial, LCD, hoặc các cảm biến/module khác.void setup() { pinMode(LED_BUILTIN, OUTPUT); // Đặt chân LED tích hợp là đầu ra Serial.begin(9600); // Khởi tạo giao tiếp Serial ở tốc độ 9600 baud }
void loop()
: Hàm này chạy lặp đi lặp lại vô tận sau khi hàmsetup()
hoàn thành. Đây là nơi bạn đặt mã điều khiển chính của dự án, chẳng hạn như đọc cảm biến, điều khiển động cơ, cập nhật hiển thị, v.v.void loop() { digitalWrite(LED_BUILTIN, HIGH); // Bật LED delay(1000); // Đợi 1 giây digitalWrite(LED_BUILTIN, LOW); // Tắt LED delay(1000); // Đợi 1 giây }
Tổng kết
Việc nắm vững các khái niệm về biến, kiểu dữ liệu và hàm là nền tảng vững chắc để bạn tiến xa hơn trong lập trình Arduino. Hãy thực hành thật nhiều với các ví dụ khác nhau để biến kiến thức lý thuyết thành kỹ năng thực tế nhé!
Nhận xét