You are on page 1of 135

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN ĐIỆN

-----    -----

ĐỒ ÁN I
Đề tài: Hướng dẫn lập trình PIC với

Arduino

Giảng viên: Triệu Việt Linh

Sinh viên thực hiện:


Họ và tên: MSSV:
Lê Văn Tài 20174181
Trình Văn Sơn 20174170
Nguyễn Nam Hùng 20173925

Hà Nội, năm 2021


Mục lục
LỜI NÓI ĐẦU ...........................................................................................................7
Hour 5. Học kiến thức cơ bản về C............................................................................8
Làm việc với biến...................................................................................................8
Khai báo biến .........................................................................................................8
Xác định giá trị cho biến ........................................................................................9
Hiểu các kiểu dữ liệu ...........................................................................................10
Định tính biến.......................................................................................................11
Phạm vi của biến ..................................................................................................12
Sử dụng toán tử ....................................................................................................12
Các toán tử toán học chuẩn ..................................................................................13
Sử dụng toán tử phức hợp ....................................................................................14
Thứ tự thực hiện các phép toán ............................................................................14
Khám phá các hàm của Arduino ..........................................................................15
Sử dụng đầu ra nối tiếp ........................................................................................15
Làm việc với thời gian .........................................................................................17
Thực hiện các phép toán nâng cao .......................................................................17
Tạo số ngẫu nhiên ................................................................................................18
Sử dụng thao tác với bit .......................................................................................19
Tổng kết ...............................................................................................................19
Hour 6. Các lệnh có cấu trúc ....................................................................................20
Làm việc với Câu lệnh if......................................................................................20
Nhóm nhiều câu lệnh ...........................................................................................21
Sử dụng các câu lệnh khác ...................................................................................23
Sử dụng câu lệnh else if .......................................................................................24
Hiểu các điều kiện so sánh ...................................................................................25
So sánh số.............................................................................................................25
So sánh Boolean ...................................................................................................26
Tạo điều kiện kép .................................................................................................27
Yêu cầu kiểm tra tình trạng..................................................................................27
3
Tóm lược ..............................................................................................................29
Hour 7. Vòng lặp lập trình .......................................................................................30
Hiểu các vòng lặp.................................................................................................30
Sử dụng vòng lặp while .......................................................................................31
Sử dụng vòng lặp do-while ..................................................................................32
Sử dụng cho các vòng lặp ....................................................................................34
Sử dụng mảng trong vòng lặp của bạn ................................................................35
Tạo Mảng .............................................................................................................35
Sử dụng vòng lặp với mảng .................................................................................36
Xác định kích thước của một mảng .....................................................................37
Sử dụng nhiều biến ..............................................................................................38
Vòng lặp làm tổ ....................................................................................................38
Tóm lược ..............................................................................................................41
2. Giới thiệu .............................................................................................................42
2.1 Phương pháp phát triển phần mềm ................................................................42
2.2 Phần cứng được hỗ trợ ...................................................................................43
3. Cài đặt phần mềm ................................................................................................45
3.1 Cài đặt lần đầu................................................................................................46
3.2 Cập nhật lên phiên bản mới ...........................................................................47
5. Bắt đầu với Logic bậc thang ................................................................................49
5.1 Đầu vào và đầu ra bit đơn ..............................................................................50
5.2 Thực hiện các phép toán Boolean ..................................................................52
6. Đầu ra chốt ...........................................................................................................57
6.1 Chốt với các thành phần rời rạc .....................................................................57
6.2 Sử dụng lệnh Latch ........................................................................................59
7. Xung kích hoạt cạnh ............................................................................................62
7.1 Tạo một bảng tin được kích hoạt cạnh...........................................................64
8. Nhập từ bàn phím .................................................................................................65
8.1 Kết nối phần cứng ..........................................................................................66
8.2 Phần mềm.......................................................................................................68

4
9. Thời gian trễ sử dụng ...........................................................................................70
9.1 Tạo ra độ trễ khi bật .......................................................................................70
9.2 Chuyển đổi Debouncing ................................................................................72
9.3 Tạo độ trễ khi tắt máy ....................................................................................73
Hình 28. Độ trễ tắt làm cho đầu ra vẫn hoạt động trong một khoảng thời gian cố
định sau khi đầu vào bị loại bỏ. ...........................................................................73
9.4 Tạo xung thời lượng cố định ..........................................................................74
10. Tạo ra các dạng sóng lặp lại..............................................................................76
10.1 Tạo xung thủ công .......................................................................................76
10.2 Sử dụng lệnh timerCycle() .........................................................................77
11.1. Bộ đếm lên ..................................................................................................79
11.3 Bộ đếm lên / xuống ....................................................................................81
11.4 Gỡ lỗi ứng dụng dựa trên bộ đếm ...............................................................82
12 Dịch chuyển và xoay dữ liệu nhị phân .............................................................84
12.1 Tạo và sử dụng sổ đăng ký Shift.................................................................84
12.2 Rotaing Data ..............................................................................................87
13 Làm việc với Analogue Signals ........................................................................91
13.1 Kiểm soát độ sáng của đèn LED bằng PWM ............................................91
13.2 Kiểm soát tốc độ và hướng của động cơ......................................................91
14 Kiểm soát vị trí bằng Servos ..............................................................................94
15 So sánh các giá trị tương tự...............................................................................95
15.1 So sánh các giá trị tương tự dựa trên phần mềm .........................................95
15.2 Một ứng dụng so sánh đơn giản ...................................................................96
16 Lập trình danh sách lệnh ...................................................................................98
17 Sơ đồ khối chức năng ..........................................................................................99
17.2 Xây dựng hệ thống làm việc ......................................................................99
17.2 Ứng dụng 1: Một báo động đơn giản .......................................................100
17.3 Ứng dụng 2: Báo động bằng nhấp nháy “ Armed “ LED .........................101
18 Biểu đồ hàm tuần tự .........................................................................................105
18.1 Tạo chuỗi...................................................................................................105
18.2 Phân nhánh và hội tụ .................................................................................108
5
19 Phát triển các ứng dụng dựa trên SFC định thời ..............................................110
19.1 Chuyển đổi cơ sở thời gian ............................................................................110
19.2. Ứng dụng 1: Điều khiển đèn giao thông ...................................................112
19.3. Ứng dụng 2: Màn hình ánh sáng chạy .....................................................114
20. Văn bản có cấu trúc..........................................................................................118
20.1 Sử dụng cấu trúc chương trình ...................................................................119
21. Các khái niệm nâng cao ...................................................................................120
21.1. Cách phần mềm hoạt động........................................................................120
21.2 Sử dụng biến trong chương trình ...............................................................121
21.3. Làm việc với các biến tùy chỉnh ...............................................................123
21.4. Sử dụng các biến với mạch logic phức tạp ...............................................123
22. Lưu trữ và Logic dựa trên ngăn xếp ................................................................124
22.1 Hoạt động lôgic khối ..................................................................................126
23. Xác định Phân bổ IO Tùy chỉnh ......................................................................128
23.1 Phân bổ I / O được cấu hình sẵn ................................................................128
23.2 Nghiên cứu điển hình: Tạo Phân bổ IO Tùy chỉnh ....................................128
24. Điểm mạnh và Hạn chế của Phần mềm ...........................................................131
25. Tham chiếu lệnh ...............................................................................................132
25.1 Cấu hình chung ..........................................................................................132
25.2 Đầu vào / đầu ra kỹ thuật số một bit ..........................................................132
25.3 Logic kết hợp .............................................................................................132
25.4 Đầu vào / đầu ra tín hiệu tương tự .............................................................132
25.5 So sánh các tín hiệu tương tự .....................................................................133
25.6 Chốt ............................................................................................................133
25.7 Bộ hẹn giờ ..................................................................................................133
25.8 Xung kích hoạt cạnh ..................................................................................134
25.9 Bộ đếm .......................................................................................................134
25.10 Dịch chuyển vị trí thanh ghi ....................................................................135
25.11 Logic ngăn xếp và khối ............................................................................135
Kết Luận .................................................................................................................136

6
LỜI NÓI ĐẦU
Tự động hóa, robot hóa là xu hướng của nhân loại ngày nay. Từ ngàn xưa, con người
luôn ước ao có những cỗ máy để làm việc thay thế mình. Trong thời đại hiện nay, với sự
phát triển mạnh mẽ của khoa học kỹ thuật, con người đã dần tạo ra những máy móc thông
minh, giúp mình từ các công việc thường ngày đến những công việc khó khăn nguy hiểm.
Các máy tự động, các robot thông minh, tự hành do con người tạo nên không chỉ tồn tại ở
trái đất mà còn có mặt tại mặt trăng, sao hỏa, trong không gian.

Đi cùng với nhịp điệu phát triển của khoa học kỹ thuật trên thế giới, người Việt Nam
cũng đang rất nỗ lực trong nghiên cứu khoa học kỹ thuật, đặc biệt là trong lĩnh vực tự
động hóa, robot hóa, phục vụ cho đời sống hàng ngày, cho công cuộc xây dựng và bảo vệ
đất nước Việt Nam thân yêu. Sự nỗ lực đó đã giúp cho người Việt dần nắm bắt, làm chủ
các công nghệ tiến tiến trên thế giới, từ xây cầu dây văng đến làm hầm Sài Gòn và hiện
nay là thực hiện công trình tàu điện ngầm tại Việt Nam. Người Việt với sự cần cù sáng
tạo và tình yêu quê hương đất nước mạnh mẽ, cùng vị trí địa lý chiến lược của quốc gia
nhất định sẽ thực hiện thành công sự nghiệp công nghiệp hóa, hiện đại hóa của mình và
nhất định trong tương lai gần sẽ bắt kịp các nước phát triển trong khu vực về khoa học và
kỹ thuật.

Sự ra đời của mạch Arduino thúc đẩy sự yêu thích, tìm tòi nghiên cứu, ứng dụng tự
động hóa , robot hóa vào đời sống và công nghiệp. Với những ưu điểm riêng của mình,
Arduino đã nhanh chóng nổi tiếng toàn thế giới và được giới học sinh, sinh viên, giới
nghiên cứu, những người yêu thích kỹ thuật, những người thích làm đồ tự chế sử dụng
rộng rãi. Tại Việt Nam, số lượng người sử dụng mạch Arduino ngày càng tăng. Để đáp
ứng nhu cầu tìm hiểu Arduino, tài liệu này đã được biên soạn. Tài liệu gồm có 6 phần,
chủ yếu đáp ứng nhu cầu tự học của các bạn mới bắt đầu tìm hiểu về Arduino. Tài liệu
được viết một cách ngắn gọn, dễ hiểu, đi vào những vấn đề cốt lõi trong việc sử dụng
Arduino cho cuộc sống.

7
Hour 5. Học kiến thức cơ bản về C

Những gì bạn sẽ học trong chương này :


• Cách lưu trữ dữ liệu phác thảo của bạn trong các biến
• Cách sử dụng biến trong các phép toán
• Cách xuất giá trị biến vào cổng nối tiếp Arduino
• Cách sử dụng một số hàm Arduino C tích hợp sẵn
Chương này trước tiên sẽ đi sâu vào kiến thức cơ bản về ngôn ngữ lập trình C, nền
tảng của ngôn ngữ lập trình Arduino. Đầu tiên ta khám phá cách lưu trữ dữ liệu trong bản
nháp của bạn bằng cách sử dụng các biến. Sau đó, ta thảo luận về cách thực hiện các phép
toán số học đơn giản trong các bản nháp của bạn. Kết thúc chương bằng cách xem qua
một số hàm phổ biến trong thư viện Arduino tiêu chuẩn mà bạn có thể sử dụng.

Làm việc với biến


Trong giờ thứ 2, “Khởi tạo môi trường lập trình Arduino,” ngôn ngữ lập trình
Arduino cung cấp giao diện thann thiện với người sử dụng để viết chương trình cho cho
vi điều khiển ATmega cơ bản trên Arduino. Một trong số những giao diện đó là cách dữ
liệu được lưu trong bộ nhớ.
Thay vì phải tham chiếu các vị trí bộ nhớ cụ thể để lưu trữ dữ liệu chương trình của
bạn ( như bạn làm ở ngôn ngữ lập trình bậc thấp), ngôn ngữ lập trình Arduino sử dụng
các biến đơn giản để đại diện cho các vị trí bộ nhớ để lưu trữ dữ liệu. Phần này thảo luận
cách sử dụng các biến đó trong bản nháp Arduino để lưu trữ và khôi phục dữ liệu của bạn
.

Khai báo biến


Vì ngôn ngữ lập trình Arduino được xây dựng trên ngôn ngữ lập trình C , nó sử dụng
định dạng chuẩn của ngôn ngữ C để tạo và sử dụng các biến. Trong ngôn ngữ C, tạo biến
gồm 2 bước:
1. Khai báo biến để sử dụng trong bản nháp.
2. Gán giá trị dữ liệu cho biến.
Khi khai báo biến, trình biên dịch ngôn ngữ C lưu trữ tên biến, cùng với một số thông
tin khác, trong một bảng nội. Bảng này cho phép trình biên dịch biết chương trình dùng
biến nào và sử dụng bao niêu bộ nhớ khi bạn chạy chương trình. Tuy nhiên, khi bạn khai
báo một biến, trình biên dịch vẫn chưa thực sự gán biến đó vào một vị trí cụ thể trong bộ
nhớ hệ thống; phần đó sẽ đến sau.
Để khai báo một biến, bạn chỉ cần xác định kiểu dữ liệu mà biến đó sẽ lưu trữ và tên
biến trong một câu lệnh, như sau

8
datatype variablename;
Phần datatype xác định loại dữ liệu mà biến sẽ lưu trữ. Ngôn ngữ lập trình C sử dụng
cái được gọi là nhập nghiêm ngặt (strict typing) bắt buộc bạn phải khai báo loại dữ liệu
mà mỗi biến sẽ chứa. Một khi bạn đã khai báo kiểu dữ liệu cho một biến, bạn chỉ có thể
lưu trữ loại dữ liệu đó trong biến (tìm hiểu thêm ở phần “Hiểu các loại dữ liệu” phía sau).
Phần variablename xác định nhãn mà bạn sẽ sử dụng để tham chiếu vị trí đó trong bộ
nhớ từ bên trong bản nháp của bạn. Ví dụ, để khai báo một biến dữ liệu số nguyên, bạn
sử dụng như sau:
int pin;
Bạn phải tuân theo một số quy tắc khi khai báo tên biến trong C:
• Tên biến chỉ được chứa các chữ cái, số, dấu gạch dưới hoặc ký hiệu đô la.
• Tên biến phải bắt đầu bằng một chữ cái.
• Tên biến có phân biệt chữ hoa chữ thường.
• Không có giới hạn cho độ dài tên biến.
Vì không có giới hạn về độ dài của tên biến, bạn nên sử dụng các tên biến có ý nghĩa
cho dữ liệu trong bản phác thảo của mình. Ví dụ, bạn sử dụng các tên biến như pin,
blinkrate, speed sẽ tốt hơn là tên chung chung như A, B, C. Việc đó sẽ giúp việc kiểm tra
lỗi dễ dàng hơn và nó giúp bạn nhớ những gì mỗi biến thực hiện nếu bạn phải quay lại
bản nháp của mình vài tháng sau. Một phương pháp phổ biến khác cũng được các nhà
phát triển Arduino sử dụng là một phương pháp được gọi là camelCase. CamelCase kết
hợp hai hoặc nhiều từ trong một tên biến, viết hoa chữ cái đầu tiên của mỗi từ, ngoại trừ
từ đầu tiên, như sau:
int blinkRateSetting;
Điều đó làm cho việc đọc và nhận ra tên biến gồm nhiều từ dễ dàng hơn một chút.
Như bạn có thể mong đợi, mỗi tên biến mà bạn khai báo trong bản nháp của mình
phải là duy nhất. Bạn không thể khai báo hai biến có cùng tên; nếu không, bạn sẽ nhận
được thông báo lỗi trong cửa sổ bảng điều khiển IDE khi bạn cố gắng biên dịch bản nháp
của mình.

Xác định giá trị cho biến


Phần thứ hai của quá trình là gán giá trị cho biến đã khai báo. Để gán giá trị cho một
biến, bạn sử dụng toán tử gán, trong ngôn ngữ C là một dấu bằng:
blinkRateSetting = 10;

9
__________________________________________________________________
Mẹo: Kết thúc một câu lệnh
Trong ngôn ngữ C, bạn phải kết thúc hầu hết các câu lệnh bằng dấu chấm phẩy để
trình biên dịch biết khi nào một câu lệnh kết thúc và câu lệnh khác bắt đầu. Chúng ta sẽ
kiểm tra những câu lệnh nào không cần sử dụng dấu chấm phẩy ở cuối chương này.
__________________________________________________________________
Đây là bước thực sự gán biến vào một vị trí trong bộ nhớ. Trình biên dịch tìm kiếm
một vị trí khả dụng trong bộ nhớ đủ lớn để chứa kiểu dữ liệu và lưu trữ giá trị được gán
vào vị trí đó.
Bạn có thể sử thực hiện tắt bằng cách khai báo biến và gán giá trị cho nó trong một
câu lệnh:
int blinkRateSetting = 10;
Với phương pháp này, trình biên dịch chỉ định vị trí bộ nhớ cho biến và lưu trữ giá trị
dữ liệu trong một bước.

Hiểu các kiểu dữ liệu


Kiểu dữ liệu mà bạn khai báo cho một biến xác định độ lớn vùng bộ nhớ mà hệ thống
cần dự trữ để lưu trữ dữ liệu. Bạn có thể sử dụng nhiều kiểu dữ liệu khác nhau trong ngôn
ngữ lập trình Arduino. Bảng 5.1 liệt kê các kiểu dữ liệu khác nhau mà Arduino sử dụng
để lưu trữ các giá trị, yêu cầu bao nhiêu dung lượng bộ nhớ, và các giá trị tối đa mà
chúng có thể lưu giữ.
Kiểu dữ liệu int và long chỉ chứa giá trị số nguyên. Kiểu float và double có thể lưu trữ
giá trị số thập phân như 10.5 hoặc –1430.443456.
Kiểu dữ liệu Kích thước (Bytes) Khoảng giá trị
boolean 1 Logic đúng hoặc sai
char 1 -128 đến +127
byte 1 0 đến 255
int 2 -32,768 đến 32,767
word 2 0 đến 65,535
long 4 -2,147,483,648 đến 2,147,483,647
float 4 -3.4028235E+38 đến +3.4028235E+38
double 4 -3.4028235E+38 đến +3.4028235E+38

Bảng 5.1: Các kiểu dữ liệu ARDUINO

10
__________________________________________________________________
Chú ý: Giá trị Số nguyên ( int ) và Dấu phẩy động ( long )
Hãy cẩn thận khi bạn đang làm việc với các con số trong bản phác thảo Arduino
của mình. Khi sử dụng số nguyên, bất kỳ phép toán nào bạn sử dụng sẽ dẫn đến
một giá trị số nguyên. Vì vậy, khi chia 5 cho 3 sẽ được giá trị là 1. Để giữ lại kết
quả chính xác, bạn phải sử dụng các giá trị dấu phẩy động.
____________________________________________________________________
Sau khi bạn xác định kiểu dữ liệu cho một biến, biến sẽ chỉ lưu trữ kiểu giá trị đó. Ví
dụ: khi bạn khai báo một kiểu dữ liệu là float
float percent;
định dạng mà Arduino sẽ sử dụng để lưu trữ dữ liệu được xác định và bạn không thể
thay đổi nó. Nếu bạn lưu trữ một giá trị nguyên là 1 trong biến phần trăm, Arduino vẫn sẽ
lưu trữ nó ở định dạng dấu phẩy động là 1,0.
Lưu trữ dữ liệu ký tự ( strings) khác một chút trong ngôn ngữ lập trình C. Khi làm
việc với giá trị là ký tự, ngôn ngữ C chuyển đổi từng ký tự trong chuỗi thành giá trị nhị
phân bằng phương pháp mã hóa, chẳng hạn như mã ASCII, và sau đó lưu trữ giá trị đó
bằng kiểu dữ liệu char. Từng ký tự trong chuỗi được lưu trữ theo thứ tự tuần tự trong bộ
nhớ để nó có thể đọc lại giá trị theo cùng một thứ tự để tái tạo giá trị chuỗi. Để kết thúc
chuỗi, C đặt một ký tự null (số 0) làm byte cuối cùng của chuỗi. Đây được gọi là một
chuỗi kết thúc bằng null. Bạn sẽ tìm hiểu thêm về cách sử dụng chuỗi trong bản phác
thảo Arduino của mình sau này trong Giờ thứ 8, “Làm việc với chuỗi”.

Định tính biến


Bạn cũng có thể sử dụng các định tính biến để sửa đổi cách trình biên dịch xử lý một
biến trong bản phác thảo. Bộ định tính biến là const cho trình biên dịch biết rằng giá trị
được gán cho biến sẽ không thay đổi. Giá trị loại này được gọi là hằng số.
Trong ngôn ngữ lập trình Arduino, hằng số thường được được viết toàn bộ bằng chữ
in hoa:
const float TAX = 0.07;
Thư viện Arduino chứa một số hằng số khác nhau được xác định trước với các giá trị
thường được sử dụng trong các bản phác thảo Arduino, như HIGH cho giá trị 1 và LOW
cho giá trị 0. Các hằng số giúp việc đọc mã phác thảo dễ dàng theo dõi hơn một chút vì
bạn có thể sử dụng các tên hằng có ý nghĩa thay vì các giá trị tối nghĩa.
Loại định tính biến khác là từ khóa không dấu. Từ khóa không dấu yêu cầu trình biên
dịch không cần chỉ ra dấu của giá trị; tất cả các giá trị được lưu trữ trong biến đó sẽ là giá
trị dương.

11
Ví dụ: theo mặc định, khi bạn xác định một biến bằng kiểu dữ liệu int, trình biên dịch
sử dụng 16 bit (2 bytes) để lưu trữ giá trị. Tuy nhiên, nó sử dụng 1 bit để chỉ ra dấu của
giá trị (0 cho số dương, 1 cho số âm), nên thực tế chỉ có 15 bit để lưu giá trị. 15 bit đó chỉ
có thể lưu giá trị từ 0 đến 32,767, vì vậy phạm vi giá trị lớn nhất cho một biến số nguyên
có dấu là –32,768 đến +32,767.
Khi bạn áp dụng bộ định tính không dấu cho một biến, trình biên dịch sẽ xác định
biến đó là số dương nên không cần dành 1 bit cho dấu. Điều này cho phép trình biên dịch
sử dụng tất cả 16 bit để lưu trữ giá trị, nên phạm vi giá trị từ 0 đến 65,535.
Bảng 5.2 hiển thị phạm vi kiểu không dấu của các loại dữ liệu khác nhau.
Kiểu dữ liệu Kích thước ( Bytes) Khoảng giá trị
unsigned char 1 0 đến 255
unsigned int 2 0 đến 65,535
unsigned long 4 0 đến 4,294,967,295

Bảng 5.2: Phạm vi giá trị kiểu dữ liệu không dấu


Với bộ định tính không dấu, bạn có khả năng lưu trữ một số số nguyên khá lớn trong chương
trình của mình.

Phạm vi của biến


Tính năng cuối cùng của các biến mà bạn cần biết là phạm vi biến. Phạm vi biến xác định nơi
biến có thể được sử dụng trong bản phác thảo Arduino. Có hai cấp độ cơ bản của phạm vi
biến:
• Biến cục bộ
• Các biến toàn cục
Bạn khai báo các biến cục bộ bên trong một hàm và chúng chỉ áp dụng bên trong khối mã
chức năng đó. Ví dụ: nếu bạn khai báo một biến bên trong hàm thiết lập, giá trị biến đó chỉ
khả dụng bên trong hàm thiết lập. Nếu bạn cố gắng sử dụng biến đó trong hàm lặp sẽ có
thông báo lỗi. Ngược lại, bạn có thể sử dụng các biến toàn cục ở bất kỳ đâu trong bản phác
thảo. Bạn thường khai báo các biến toàn cục ngay khi bắt đầu phác thảo Arduino, trước khi
bạn xác định thiết lập hàm. Điều đó giúp bạn dễ dàng xem tất cả các biến toàn cục mà bản
phác thảo sử dụng. Khi bạn khai báo một biến toàn cục, bạn có thể sử dụng nó trong các hàm
thiết lập hoặc vòng lặp, hoặc bất kỳ hàm nào khác trong bản phác thảo của bạn. Mỗi khi bạn
gán giá trị cho biến, bạn có thể truy xuất giá trị đó từ bất kỳ hàm nào.

Sử dụng toán tử
Chỉ lưu trữ dữ liệu trong các biến không làm cho các chương trình thú vị. Một lúc nào đó,
bạn sẽ thực sự muốn làm điều gì đó với dữ liệu bạn lưu trữ. Phần này bao gồm một số thao
tác mà bạn có thể thực hiện với dữ liệu của mình bằng ngôn ngữ lập trình Arduino.

12
Các toán tử toán học chuẩn
Điều cơ bản nhất bạn sẽ muốn làm là thao tác với các con số, liệu đó là bộ đếm theo dõi xem
bản phác thảo của bạn thực hiện bao nhiêu vòng lặp hoặc một biến xác định tốc độ nháy đèn.
Thư viện Arduino chứa tất cả các toán tử toán học tiêu chuẩn mà bạn đã quen sử dụng trong
trường học; chỉ là một vài trong số chúng có thể trông hơi lạ.
Bảng 5.3 liệt kê các toán tử toán học khác nhau có sẵn trong thư viện Arduino.

Toán tử Mô tả
+ Cộng
- Trừ
* Nhân
/ Chia
% Lấy phần dư (modulus)
++ Tăng
-- Giảm
! Logic NOT
&& Logic AND
|| Logic OR
& Bitwise AND
| Bitwise OR
<< Dịch sang trái
>> Dịch sang phải

Bảng 5.3 Toán tử toán học trong Arduino


Bạn có thể nhận ra hầu hết các toán tử trên tử môn Toán. Ngôn ngữ C cũng sử dụng
dấu hoa thị cho phép nhân và dấu gạch chéo để chia. Toán tử modulus( %) khác một
chút; nó trả về phần dư của phép chia.
Bạn sẽ nhận thấy từ bảng rằng có hai loại toán tử AND và OR. Có một sự khác biệt
nhỏ giữa phiên bản bitwise và logic của các toán tử này. Bạn sử dụng các toán tử bitwise
trong phép tính nhị phân. Bạn sử dụng các phép tính nhị phân để thực hiện phép toán nhị
phân sử dụng các giá trị nhị phân.
Các toán tử logic cho phép bạn áp dụng logic Boolean, chẳng hạn như kết hợp các giá
trị bằng phép toán AND.

13
Để sử dụng các toán tử toán học trong các chương trình Arduino của bạn, bạn chỉ cần
viết các phương trình của mình ở phía bên phải của một câu lệnh gán:
blinkRateSetting = 10000 / inputVoltage;
Trình biên dịch tính toán biểu thức toán học ở phía bên phải của câu lệnh gán, sau đó
gán kết quả cho biến ở phía bên trái.
____________________________________________________________________
Thận trọng: Lệnh gán so với Phương trình
Đừng nhầm lẫn các câu lệnh gán với các phương trình toán học. Đối với câu lệnh
gán, bạn có thể sử dụng cùng một biến ở cả hai phía của dấu bằng:
counter = counter + 1;
Điều này vô nghĩa trong một phương trình toán học nhưng nó là một câu lệnh gán
thông thường. Trình biên dịch truy xuất giá trị hiện tại được lưu trữ trong biến
counter, thêm vào đó 1 đơn vị và sau đó lưu trữ lại kết quả vào vị trí của biến
counter .
__________________________________________________________________

Sử dụng toán tử phức hợp


Toán tử phức hợp tạo lối tắt cho các phép gán đơn giản mà bạn thường sử dụng trong
các bản phác thảo Arduino của mình. Ví dụ: nếu bạn đang thao tác trên một biến và dự
định lưu trữ kết quả trong cùng biến đó, bạn không cần phải sử dụng định dạng dài:
counter = counter + 1;
Thay vào đó, bạn có thể sử dụng toán tử phức hợp bổ sung:
counter += 1;
Toán tử phức hợp += thêm kết quả của phương trình bên phải vào giá trị của biến bạn
chỉ định ở bên trái và lưu trữ lại kết quả trong biến bên trái. Tính năng này hoạt động cho
tất cả các toán tử toán học được sử dụng trong ngôn ngữ lập trình C.

Thứ tự thực hiện các phép toán


Ngôn ngữ C tuân theo các tiêu chuẩn trong tính toán toán học bap gồm thứ tự việc
thực hiện các phép toán. Ví dụ: trong phép gán
result = 2 + 5 * 5;

14
trình biên dịch đầu tiên thực hiện phép nhân 5 lần 5 sau đó cộng thêm 2, nhận được
kết quả cuối cùng là 27, giá trị đó được gán vào biến result.
Và như trong toán học, C cho phép bạn thay đổi thứ tự phép tính bằng dấu ngoặc:
result2 = (2 + 5) * 5
Bây giở trình biên dịch sẽ cộng 2 với 5 trước rồi mới nhân kết quả với 5, giá trị cuối là 35.
Bạn có thể lồng các dấu ngoặc sâu tùy ý trong tính toán của mình. Chỉ cần cẩn thận để đảm
bảo rằng bạn khớp với tất cả các cặp dấu ngoặc đơn mở và đóng.

Khám phá các hàm của Arduino


Ngôn ngữ lập trình Arduino cũng chứa một số thư viện tiêu chuẩn để cung cấp các hàm dựng
sẵn cho chúng ta sử dụng. Các hàm giống như một hộp đen: Bạn gửi các giá trị đến hàm,
hàm thực hiện các phép tính trên các giá trị và sau đó bạn nhận lại một kết quả từ hàm. (Để
tìm hiểu thêm về cách tạo các hàm của riêng bạn, hãy xem Giờ thứ 10, “Tạo các hàm”).
Phần này bao gồm một số hàm Arduino tiêu chuẩn sẽ có ích khi bạn viết bản phác thảo
Arduino của mình.

Sử dụng đầu ra nối tiếp


Trước khi đi sâu, hãy nói về một tính năng đặc biệt của Arduino: khả năng xuất dữ liệu ra
thiết bị nối tiếp bên ngoài. Tính năng này giúp dễ dàng heo dõi những gì đang diễn ra trong
các bản phác thảo Arduino của bạn và sẽ giúp ích cho bạn khi bạn gỡ lỗi các bản phác thảo
của mình.
Để xuất dữ liệu ra cổng nối tiếp trên Arduino, bạn cần sử dụng lớp đặc biệt Serial, cùng
với các chức năng tích hợp của nó. Giờ thứ 17, “Giao tiếp với thiết bị” kiểm sẽ xem xét lớp
Serial chi tiết hơn nhiều, nhưng hiện tại chúng ta chỉ quan tâm đến ba chức năng cơ bản :
• Serial.begin() khởi tạo cổng nối tiếp cho đầu vào và đầu ra.
• Serial.print() xuất một chuỗi văn bản tới cổng nối tiếp.
• Serial.println() xuất một chuỗi văn bản tới cổng nối tiếp và kết thúc nó bằng một ký tự
trả về và nguồn cấp dữ liệu dòng.
Bạn có thể sử dụng hàm Serial.print() và Serial.println() trong bản phác thảo Arduino
của mình để xuất thông tin từ bản phác thảo của bạn để xem trong Serial monitor của
Arduino IDE. Điều này tạo ra một công cụ khắc phục sự cố tuyệt vời theo ý của bạn

Sử dụng các chức năng của Serial để gỡ lỗi bản phác thảo Arduino

15
Bài tập này hướng dẫn bạn cách thêm hàm Serial.print() và Serial.println() vào bản phác
thảo Arduino của bạn để xem các biến khi bản phác thảo của bạn chạy. Thực hiện các bước
sau:
1. Mở Arduino IDE, viết các dòng lệnh vào cửa sổ:
int radius = 0;
float area;

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

void loop() {
radius = radius + 1;
area = radius * radius * 3.14;
Serial.print("A circle with radius ");
Serial.print(radius);
Serial.print(" has an area of ");
Serial.println(area);
delay(1000);
}
2. Lưu bản phác thảo dưới tên “sketch0501”.
3. Biên dịch và tải bản phác thảo lên Arduino của bạn.
4. Mở công cụ Serial monitor và xem đầu ra.

Kết quả sẽ giống như sau:


A circle with radius 1 has an area of 3.14
A circle with radius 2 has an area of 12.56
A circle with radius 3 has an area of 28.26

16
A circle with radius 4 has an area of 50.24
A circle with radius 5 has an area of 78.50
Hàm Serial.print() hiển thị một chuỗi kí tự hoặc giá trị của một biến, nhưng giữ con trỏ đầu
ra trên cùng một dòng. Hàm Serial.println() hiển thị chuỗi kí tự hoặc giá trị biến, sau đó
xuống dòng để bắt đầu một dòng đầu ra mới.
Đó là cách bạn thêm hàm Serial.println() vào bản phác thảo của bạn để xem giá trị của các
biến khi bản phác thảo của bạn đang chạy trên Arduino.

Làm việc với thời gian


Với các ứng dụng thời gian thực, bản phác thảo của bạn thường sẽ cần phải có một số kiến
thức về thời gian. Thư viện Arduino chứa bốn hàm cho phép bạn truy cập các tính năng thời
gian trong Arduino:
• delay(x): dừng lại trong x milli-giây.
• delayMicroseconds(x): dừng lại trong x micro-giây.
• micros(): Trả về số micro giây kể từ khi Arduino được đặt lại.
• millis(): Trả về số milli giây kể từ khi Arduino được đặt lại.
Hàm delay() và delayMicroseconds() rất hữu ích khi bạn muốn làm chậm đầu ra, như chúng
ta đã làm ở ví dụ trước, hoặc nếu bạn cần bản phác thảo đợi một khoảng thời gian nhất định
trước khi chuyển sang bước tiếp theo.
Hàm millis() and micros() cho phép bạn biết Arduino đã chạy bản phác thảo của bạn trong
bao lâu. Mặc dù điều này không liên quan đến thời gian thực trong ngày, bạn có thể sử dụng
tính năng này để nhận biết khoảng thời gian trong bản phác thảo của mình.

Thực hiện các phép toán nâng cao


Các phép toán cơ bản vô cùng hữu ích nhưng bản phác thảo của bạn đôi khi có thể cần sử
dụng một số xử lý toán học nâng cao hơn. Mặc dù không hoàn thiện như một số ngôn ngữ
lập trình, ngôn ngữ Arduino có một số hỗ trợ cho các chức năng toán học nâng cao. Bảng 5.4
liệt kê các hàm toán học nâng cao bạn có thể sử dụng để làm việc với các bản phác thảo của
mình.

17
Hàm Mô tả
Abs(x) Trả về giá trị tuyệt đối của x
Constrain(x, a, b) Trả về x nếu x thuộc khoảng a đến b (trả về a nếu x<a,
trả về b nếu x>b)
Cos(x) Cos của x (radian)
Map(x, fromLow, Chuyển một giá trị từ thang đo này sang một giá trị ở
fromHigh, toLow, toHigh) thang đo khác
Max(x, y) Trả về giá trị lớn hơn giữa x và y
Min(x, y) Trả về giá trị nhỏ hơn giữa x và y
Pow(x, y) tính lũy thừa cơ số x lũy thừa y
Sin(x) Sin của x (radian)
Sqrt(x) Căn bậc 2 của x
Tan(x) Tan của x (radian)
Bảng 5.4 Các hàm toán học Arduino nâng cao
Bạn có thể nhận ra hầu hết các hàm này. Hàm map() và constrain() hơi khác biệt so với
những gì bạn thấy trong thư viện hàm toán học thông thường. Chúng chủ yếu được sử dụng
khi làm việc với cảm biến. Chúng cho phép bạn giữ các giá trị do cảm biến trả về trong một
phạm vi cụ thể mà bản phác thảo của bạn có thể quản lý.

Tạo số ngẫu nhiên


Khi làm việc với bản thảo, bạn thường xuyên gặp phải tình huống yêu cầu tạo số ngẫu nhiên.
Hầu hết các ngôn ngữ lập trình đều bao gồm chức năng tạo số ngẫu nhiên và ngôn ngữ lập
trình Arduino là một trong số đó.
Hai hàm có sẵn để làm việc với các số ngẫu nhiên:
• random([min], max): trả về giá trị ngẫu nhiên giữa min và max – 1. Tham số tối thiểu
là tùy chọn. Nếu bạn chỉ xác định một tham số, tham số tối thiểu sẽ mặc định là 0.
• randomSeed(seed): Khởi tạo trình tạo số ngẫu nhiên, khiến nó khởi động lại tại một
điểm tùy ý trong một chuỗi ngẫu nhiên.
Đối với máy tính, số ngẫu nhiên không thực sự là ngẫu nhiên. Chúng tạo ra các chuỗi số lặp
lại ngẫu nhiên. Bạn có thể nhận thấy nếu bạn gọi hàm random() đủ một số lần rằng bạn sẽ
bắt đầu lặp lại các số "ngẫu nhiên" giống nhau.
Để giải quyết vấn đề đó, hàm randomSeed() cho phép bạn chọn vị trí trong chuỗi ngẫu nhiên
mà hàm random() sẽ chọn giá trị. Điều đó giúp giảm tần suất các số có thể lặp lại.

18
Sử dụng thao tác với bit
Nhóm chức năng thao tác bit trong thư viện Arduino cho phép bạn làm việc dạng bit của các
giá trị. Bảng 5.5 liệt kê các chức năng thao tác bit có sẵn.
Hàm Mô tả
bit(n) Trả về một số nguyên
bitClear(x, n) Thay giá trị tại một bit xác định của một số nguyên thành 0,(x: số
nguyên bất kì, n: vị trí bit)
bitRead(x, n) Trả về giá trị tại một bit nào đó của một số nguyên.
bitSet(x, n) Thay giá trị tại một bit xác định của một số nguyên thành 1
bitWrite(x, n, b) Ghi đè bit tại một vị trí xác định của số nguyên (b= 1 hoặc 0)
highByte(x) Trả về byte cao nhất (bên traí) của x
lowByte(x) Trả về byte thấp nhất (bên phải) của x
Bảng 5.5 Các hàm thao tác với Bit trong Arduino
Khi làm việc với cảm biến hoặc nhiều đầu vào, bạn thường cần biết những bit nào của giá trị
được đặt. Các hàm này giúp bạn làm việc ở cấp độ bit với các dữ liệu của bạn.

Tổng kết
Chương này đã xem xét những điều cơ bản về xử lý dữ liệu trong các bản phác thảo Arduino.
Nó hướng dẫn cách khai báo các biến trong bản phác thảo của bạn và cách gán giá trị cho
chúng. Nó cũng thảo luận về các kiểu dữ liệu ngôn ngữ C và cách áp dụng chúng vào dữ liệu
trong bản phác thảo của bạn. Sau đó bạn học về phép toán và cách ngôn ngữ Arduino sử
dụng các toán tử toán học tích hợp để thực hiện các phép toán toán học tiêu chuẩn trên dữ
liệu. Sau đó chuyển sang một số chức năng có sẵn trong thư viện Arduino tiêu chuẩn. Ngoài
các chức năng để thực hiện các tính năng toán học và thời gian nâng cao còn có các chức
năng để giao tiếp với đầu ra nối tiếp trên Arduino.
Chương tiếp thảo luận về cách điều khiển các chương trình Arduino của bạn bằng cách kiểm
tra các điều kiện dữ liệu và chọn phần nào của mã phác thảo để chạy.

19
Hour 6. Các lệnh có cấu trúc

Bạn sẽ học được gì trong giờ này:


Sử dụng câu lệnh if-then
Thêm các phần khác
Chuỗi các câu lệnh if-else với nhau
Điều kiện thử nghiệm
Sử dụng câu lệnh switch

Trong các bản phác thảo Arduino mà chúng ta đã thảo luận cho đến nay, Arduino xử lý
từng câu lệnh riêng lẻ trong phác thảo theo thứ tự mà nó xuất hiện. Điều này hoạt động tốt
cho các hoạt động tuần tự, nơi bạn muốn các hoạt động để xử lý theo trình tự thích hợp. Tuy
nhiên, đây không phải là cách tất cả các bản phác thảo hoạt động.
Nhiều bản phác thảo yêu cầu một số loại điều khiển luồng logic giữa các câu lệnh trong
bản phác thảo. Điều này có nghĩa là rằng Arduino thực thi các câu lệnh nhất định trong một
tập hợp các tình huống, nhưng có khả năng thực thi các tuyên bố khác đưa ra một nhóm
hoàn cảnh khác. Có cả một lớp câu lệnh cho phép Arduino để bỏ qua hoặc lặp qua các câu
lệnh dựa trên điều kiện của biến hoặc giá trị. Những các câu lệnh thường được gọi là lệnh có
cấu trúc.
Khá nhiều lệnh có cấu trúc có sẵn trong ngôn ngữ lập trình Arduino, vì vậy chúng ta sẽ
xem xét chúng riêng lẻ. Trong chương này, chúng ta sẽ xem xét các lệnh có cấu trúc if và
switch.

Làm việc với Câu lệnh if


Loại lệnh có cấu trúc cơ bản nhất là câu lệnh if. Câu lệnh if trong C có như sau định dạng
cơ bản: nếu (điều kiện) tuyên bố
Bạn sẽ thường nghe nói về loại câu lệnh này được gọi là câu lệnh if-then. Như bạn có thể
thấy, không thực sự có từ khóa “then” trong phiên bản ngôn ngữ C của câu lệnh.
C sử dụng hướng dòng để hoạt động như từ khóa "then". Arduino đánh giá điều kiện trong
dấu ngoặc đơn, và sau đó thực hiện câu lệnh trên dòng tiếp theo nếu điều kiện trả về logic
đúng hoặc bỏ qua câu lệnh trên dòng tiếp theo nếu điều kiện trả về giá trị logic sai.
Dưới đây là một số ví dụ để hiển thị điều này trong thực tế:

int x = 50;
if (x == 50)
Serial.println("The value is 50");
if (x < 100)

20
Serial.println("The value is less than 100");
if (x > 100)
Serial.println("The value is more than 100");
Trong ví dụ đầu tiên, điều kiện sẽ kiểm tra xem biến x có bằng 50 hay không. (Chúng ta
nói về dấu bằng kép trong phần “ Tìm hiểu các điều kiện so sánh ” ở phần sau của giờ này.)
Bởi vì, trình biên dịch thực thi câu lệnh Serial.println () trên dòng tiếp theo và in ra chuỗi.
Tương tự như vậy, ví dụ thứ hai kiểm tra xem giá trị được lưu trữ trong biến x có nhỏ hơn
100 hay không. là, và do đó trình biên dịch thực thi câu lệnh Serial.println () thứ hai để hiển
thị chuỗi.
Tuy nhiên, trong ví dụ thứ ba, giá trị được lưu trữ trong biến x không lớn hơn 100, vì vậy
điều kiện trả về một giá trị logic sai, khiến trình biên dịch bỏ qua câu lệnh Serial.println ()
cuối cùng.
Nhóm nhiều câu lệnh
Định dạng câu lệnh if cơ bản cho phép bạn xử lý một câu lệnh dựa trên kết quả của
tình trạng. Tuy nhiên, thường xuyên hơn không, bạn sẽ muốn nhóm nhiều câu lệnh lại với
nhau, dựa trên kết quả của điều kiện.
Để nhóm một loạt các câu lệnh lại với nhau, bạn phải đặt chúng trong một dấu ngoặc
nhọn mở và đóng, như sau:
int x = 50;
if (x == 50) {
Serial.println("The x variable has been set");
Serial.println("and the value is 50");
}
Trong ví dụ này, đầu ra từ cả hai dòng in sẽ xuất hiện trong đầu ra của màn hình nối tiếp.
Tất cả các tuyên bố giữa các dấu ngoặc nhọn được coi là một phần của phần “thì” của câu
lệnh và được điều khiển bởi tình trạng.
Một điều về if các câu lệnh là nó có thể trở nên khó khăn khi cố gắng chọn ra mã có
trong dấu ngoặc nhọn được kiểm soát bởi điều kiện if. Một cách để giúp điều đó là thụt lề mã
bên trong dấu ngoặc nhọn, như được hiển thị trong ví dụ.
Bạn có thể định dạng thủ công bản phác thảo của mình để trông giống như vậy hoặc bạn
có thể để Arduino IDE trợ giúp cái đó. Chỉ cần căn trái tất cả mã trong bản phác thảo, sau đó
chọn Công cụ> Định dạng tự động từ thanh menu. Các Arduino IDE sẽ tự động xác định mã
nào nên được thụt vào.
Làm việc thử với Câu lệnh " if "
Để thử nghiệm các câu lệnh if trong bản phác thảo Arduino của bạn, hãy làm theo các
bước sau:
1. Mở Arduino IDE, sau đó nhập mã này vào cửa sổ trình chỉnh sửa:

21
void setup() {
int x = 50;

Serial.begin(9600);

if (x > 25) {

Serial.print("The value if x is:");

Serial.println(x);

Serial.println("This value is greater than 25");

Serial.println("This statement executes no matter what the

value is");

oid loop() {

}
2. Chọn Công cụ > Định dạng Tự động từ thanh menu. Điều này sẽ định dạng mã để
thụt lề các câu lệnh bên trong khối mã if.
3. Lưu bản phác thảo dưới dạng sketch0601.
4. Để xác minh, biên dịch và tải bản phác thảo lên Arduino, hãy nhấp vào biểu tượng tải
lên trên thanh công cụ hoặc chọn Tệp> Tải lên từ thanh menu.
5. Mở màn hình nối tiếp bằng cách nhấp vào biểu tượng màn hình nối tiếp trên thanh
công cụ hoặc chọn Tools> Serial Monitor từ thanh menu. Thao tác này sẽ mở ứng
dụng màn hình nối tiếp và khởi động lại Arduino. Bạn sẽ thấy kết quả sau:

The x variable has been set

And the value is not 50

This ends the test


6. Thay đổi mã để đặt giá trị của x thành 25 trong câu lệnh gán, sau đó biên dịch lại và
tải bản phác thảo lên Arduino.
7. Mở màn hình nối tiếp. Bây giờ bạn sẽ chỉ thấy kết quả sau:
This statement executes no matter what the value is

22
Sử dụng các câu lệnh khác
Trong câu lệnh if, bạn chỉ có một tùy chọn để chạy (hoặc không) câu lệnh.
Nếu điều kiện trở lại một giá trị logic sai, trình biên dịch chỉ chuyển sang câu
lệnh tiếp theo trong bản phác thảo. Thật là tuyệt nếu được có thể thực hiện
một tập hợp các câu lệnh thay thế khi điều kiện sai. Đó chính xác là những gì
câu lệnh khác cho phép chúng tôi làm.
Câu lệnh else cung cấp một nhóm lệnh khác trong câu lệnh if:
int x = 25;
if (x == 50)
Serial.println("The value is 50");
else
Serial.println("The value is not 50");
Câu lệnh sau từ khóa else chỉ xử lý khi điều kiện if là sai.
Cũng giống như với khối mã lệnh if, bạn có thể sử dụng dấu ngoặc nhọn
để kết hợp nhiều câu lệnh trong khối mã eles :
void setup() {
int x = 25;
Serial.begin(9600);
if (x == 50) {
Serial.println("The x variable has been set");
Serial.println("and the value is 50");
} else {
Serial.println("The x variable has been set");
Serial.println("and the value is not 50");
}
Serial.println("This ends the test");
}
void loop() {
}
Bạn có thể kiểm soát đầu ra bằng cách điều chỉnh giá trị bạn gán cho biến
x. Khi bạn chạy bản phác thảo như là, bạn sẽ nhận được đầu ra này:
The x variable has been set
And the value is not 50
This ends the test
Nếu bạn thay đổi giá trị của x thành 50, bạn sẽ nhận được kết quả sau:
The x variable has been set
And the value is 50
This ends the test
23
Sử dụng câu lệnh else if
Cho đến nay, bạn đã thấy cách kiểm soát một khối câu lệnh bằng cách sử dụng câu lệnh if
hoặc if và kết hợp các câu lệnh else. Điều đó mang lại cho bạn một chút linh hoạt trong việc
kiểm soát cách các tập lệnh của bạn công việc. Tuy nhiên, còn nhiều hơn thế nữa!
Đôi khi, bạn sẽ cần phải so sánh một giá trị với nhiều phạm vi điều kiện. Một cách để giải
quyết điều đó là để xâu chuỗi nhiều câu lệnh if quay lại:
int x = 45;
if (x > 100)
Serial.println("The value of x is very large");
if (x > 50)
Serial.println("The value of x is medium");
if (x > 25)
Serial.println("The value of x is small");
if (x <= 25)
Serial.println("The value of x is very small");

Với định dạng này, chỉ một trong các câu lệnh System.println () sẽ thực thi, dựa trên giá
trị được lưu trữ trong biến x:

The value of x is small


Điều đó hiệu quả, nhưng nó là một cách xấu xí để giải quyết vấn đề. May
mắn thay, có một giải pháp dễ dàng hơn cho chúng tôi.
Ngôn ngữ C cho phép bạn xâu chuỗi các câu lệnh if-else với nhau bằng cách sử dụng câu
lệnh else if, với câu lệnh catchall else ở cuối. Định dạng cơ bản của câu lệnh else if trông
giống như sau:

if (condition1)
statement1;
else if (condition2)
statement2;
else
statement3;
Khi Arduino chạy mã này, đầu tiên nó sẽ kiểm tra kết quả condition1 . Nếu điều đó trả về
một giá trị true, Arduino chạy statement1, và sau đó thoát khỏi câu lệnh if-else if-else.
Nếu condition1 đánh giá một giá trị sai, thì Arduino sẽ kiểm tra kết quả của condition2 . Nếu
đó trả về một giá trị true, nó chạy statement2, rồi thoát khỏi câu lệnh if-else if-else.

Nếu condition2 đánh giá một giá trị fail, nó chạy condition3, và sau đó thoát khỏi if-else
ifcâu lệnh khác.

24
LISTING 6.1 Ví dụ về mã sketch0602
void setup() {
int x = 45;
Serial.begin(9600);
if (x > 100)
Serial.println("The value of x is very large");
else if (x > 50)
Serial.println("The value of x is medium");
else if (x > 25)
Serial.println("The value of x is small");
else
Serial.println("The value of x is very small");
Serial.println("This is the end of the test");
}
void loop() {
}
Khi bạn chạy mã sketch0602, chỉ một câu lệnh Serial.println () sẽ thực thi, dựa trên giá trị
bạn đặt biến x thành. Theo mặc định, bạn sẽ thấy đầu ra này trong màn hình nối tiếp:
The value of x is small
This is the end of the test
Điều này cho phép bạn kiểm soát hoàn toàn những câu lệnh mã nào mà
Arduino chạy trong bản phác thảo.

Hiểu các điều kiện so sánh


Hoạt động của câu lệnh if xoay quanh các so sánh mà bạn thực hiện. Arduino ngôn ngữ lập
trình cung cấp khá nhiều toán tử so sánh cho phép bạn kiểm tra tất cả các loại Dữ liệu. Phần
này bao gồm các loại so sánh khác nhau mà bạn có sẵn trong Arduino của mình bản phác
thảo.

So sánh số
Loại so sánh phổ biến nhất liên quan đến so sánh các giá trị số. Arduino ngôn ngữ lập trình
cung cấp một tập hợp các toán tử để thực hiện so sánh số trong if điều kiện tuyên bố. Bảng
6.1 cho thấy các toán tử so sánh số mà lập trình Arduino hỗ trợ ngôn ngữ.

25
BẢNG 6.1 Các toán tử so sánh số
So sánh Boolean
Bởi vì Arduino đánh giá điều kiện câu lệnh if cho một giá trị logic, việc kiểm tra các giá trị
Boolean là khá dễ:

Serial.begin(9600);
boolean x = true;
if (x)
Serial.println("The value is true");
x = false;
if (x)
Serial.println("The value is false");
Việc đặt giá trị biến trực tiếp thành giá trị đúng hoặc sai hợp lý khá đơn giản. Tuy nhiên, bạn
cũng có thể sử dụng so sánh Boolean để kiểm tra các tính năng khác của một biến.
Nếu bạn đặt một biến thành một giá trị, Arduino cũng sẽ thực hiện so sánh Boolean:
int a = 10;
if (a)
Serial.println("The a variable has been set");
Tuy nhiên, nếu một biến chứa giá trị 0, nó sẽ đánh giá thành điều kiện
Boolean sai:
int testing = 0;
if (testing)
Serial.println("The testing variable has been set");
So sánh cho biến thử nghiệm ở đây sẽ không thành công vì Arduino
bằng 0 được gán cho biến thử nghiệm dưới dạng giá trị Boolean sai.
Vì vậy, hãy cẩn thận khi đánh giá các biến cho Boolean các giá trị.

26
Tạo điều kiện kép
Trong tất cả các ví dụ cho đến nay, chúng tôi chỉ sử dụng một phép kiểm tra so sánh trong
điều kiện. Với Arduino ngôn ngữ lập trình, bạn có thể nhóm nhiều phép so sánh lại với nhau
trong một câu lệnh if, được gọi là điều kiện kép. Phần này hiển thị một số thủ thuật bạn có
thể sử dụng để kết hợp nhiều hơn một điều kiện kiểm tra một câu lệnh if duy nhất.
Ngôn ngữ lập trình Arduino cho phép bạn sử dụng các toán tử logic để nhóm các phép so
sánh với nhau. Bởi vì mỗi kiểm tra điều kiện riêng lẻ tạo ra một Giá trị kết quả Boolean,
Arduino chỉ áp dụng hoạt động logic cho kết quả điều kiện. Kết quả của hoạt động logic xác
định kết quả của câu lệnh if:
int a = 1;
int b = 2;
if ((a == 1) && (b == 2))
Serial.println("Both conditions passed when b=2");
if ((a == 1) && (b == 1))
Serial.println("Both conditions passed when b=1");
Khi bạn sử dụng toán tử và logic, cả hai điều kiện đều phải trả về giá trị đúng cho "then" câu
lệnh để xử lý. Nếu một trong hai không thành công, Arduino sẽ bỏ qua khối mã “sau đó”.
Bạn cũng có thể sử dụng toán tử hoặc logic để kiểm tra điều kiện kết hợp:
if ((a == 1) || (b == 1))
Serial.println("At least one condition passed");
Trong tình huống này, nếu một trong hai điều kiện vượt qua, Arduino sẽ xử lý câu lệnh
“then”.

Yêu cầu kiểm tra tình trạng


Có một mẹo câu lệnh if cuối cùng mà các lập trình viên C thích sử dụng. Đôi khi bạn đang
viết nếucác câu lệnh khác, rất hữu ích khi đảo ngược thứ tự của các khối mã “then” và các
khối mã khác.
Điều này có thể là do một trong các khối mã dài hơn khối khác, vì vậy bạn muốn liệt kê khối
mã ngắn hơn đầu tiên, hoặc có thể là do logic script có ý nghĩa hơn khi kiểm tra điều kiện
phủ định.
Bạn có thể phủ định kết quả của việc kiểm tra điều kiện bằng cách sử dụng toán tử logic not
:
int a = 1;
if (!(a == 1))
Serial.println("The 'a' variable is not equal to 1");
if (!(a == 2))
Serial.println("The 'a' variable is not equal to 2");

27
Toán tử not đảo ngược kết quả bình thường từ phép so sánh bình đẳng, vì vậy hành động
ngược lại xảy ra từ những gì sẽ xảy ra nếu không có nhà điều hành not.

Thường thì bạn sẽ thấy mình ở trong một tình huống mà bạn cần phải so sánh một biến với
một số những giá trị khả thi. Một giải pháp là viết một loạt các câu lệnh else if để xác định
biến giá trị là:
int test = 2;
if (test == 1)
Serial.println("The first option was selected");
else if (test == 2)
Serial.println("The second option was selected");
else if (test == 3)
Serial.println("The third option was selected");
else
Serial.println("None of the correct options was selected");
Càng có nhiều tùy chọn, mã này càng dài! Thay vì viết một loạt dài khác nếu , bạn có thể sử
dụng câu lệnh switch:

int test=3;
switch (test) {
case 1:
Serial.println("The first option was selected");
break;
case 2:
Serial.println("The second option was selected");
break;
case 3:
Serial.println("The third option was selected");
break;
default:
Serial.println("None of the correct options was selected");
}
Câu lệnh switch sử dụng điều kiện kiểu if-then chuẩn để đánh giá kết quả. Sau đó, bạn sử
dụng một hoặc nhiều câu lệnh trường hợp hơn để xác định các kết quả có thể có từ điều kiện
chuyển đổi. Arduino nhảy đến phù hợp với câu lệnh trường hợp trong mã, bỏ qua các câu
lệnh trường hợp khác.
Tuy nhiên, Arduino tiếp tục xử lý bất kỳ mã nào xuất hiện sau câu lệnh trường hợp, bao gồm

28
các báo cáo trường hợp khác. Để tránh điều này, bạn có thể thêm câu lệnh break vào cuối
câu lệnh trường hợp khối mã. Điều đó khiến Arduino nhảy ra khỏi khối mã lệnh lệnh switch
enter.
Bạn có thể thêm một câu lệnh mặc định vào cuối khối mã câu lệnh switch. Arduino chuyển
đến câu lệnh mặc định khi không câu lệnh trường hợp nào phù hợp với kết quả.
Câu lệnh switch cung cấp một cách dễ dàng hơn để kiểm tra một biến cho nhiều giá trị, mà
không có tất cả overhead của các câu lệnh if-then-else.

Tóm lược
Giờ này đã trình bày những kiến thức cơ bản về cách sử dụng lệnh if có cấu trúc. Câu lệnh
if cho phép bạn thiết lập một hoặc nhiều điều kiện kiểm tra dữ liệu bạn sử dụng trong các
bản phác thảo Arduino của mình. Bạn sẽ thấy điều này hữu ích khi bạn cần phải lập trình bất
kỳ kiểu so sánh logic nào trong bản phác thảo của mình. Bản thân câu lệnh if cho phép bạn
thực hiện một hoặc nhiều câu lệnh dựa trên kết quả của kiểm tra so sánh. Bạn có thể thêm
cái khác để cung cấp một nhóm câu lệnh thay thế để thực thi nếu việc so sánh không thành
công.
Bạn có thể mở rộng các so sánh bằng cách sử dụng một hoặc nhiều câu lệnh if khác trong
câu lệnh if. Chỉ tiếp tục xâu chuỗi các câu lệnh if với nhau để tiếp tục so sánh các giá trị bổ
sung.
Cuối cùng, bạn có thể sử dụng câu lệnh switch với nhiều câu lệnh trường hợp thay cho câu
lệnh if khác các câu lệnh. Điều đó giúp việc kiểm tra nhiều giá trị trong một biến dễ dàng
hơn một chút.
Giờ tiếp theo đi qua các vòng lặp trong bản phác thảo Arduino của bạn. Bạn có thể sử dụng
các vòng lặp để kiểm tra nhiều các cảm biến sử dụng cùng một mã hoặc bạn có thể sử dụng
chúng để lặp qua các khối dữ liệu mà không cần phải sao chép mã của bạn.

29
Hour 7. Vòng lặp lập trình

Bạn sẽ học được gì trong giờ này:


Tại sao chúng ta cần vòng lặp
Khám phá vòng lặp while
Vòng lặp do-while
Sử dụng vòng lặp for
Kiểm soát vòng lặp

Hiểu các vòng lặp


Bạn đã thấy một loại vòng lặp được Arduino sử dụng. Theo mặc định, chương trình Arduino
sử dụng chức năng lặp để lặp lại một khối lệnh mã vô thời hạn. Điều đó cho phép bạn viết
một ứng dụng điều đó tiếp tục lặp lại miễn là nguồn của Arduino được bật.
Tuy nhiên, đôi khi, trong các bản phác thảo Arduino của bạn, bạn sẽ thấy mình cần phải lặp
lại các thao tác khác, cho đến khi một điều kiện cụ thể được đáp ứng, hoặc chỉ lặp lại một số
lần đã đặt. Một ví dụ về điều này đang thiết lập một nhóm các cổng kỹ thuật số cho chế độ
đầu vào hoặc đầu ra.
Bạn chỉ có thể viết ra tất cả các dòng hàm pinMode riêng lẻ, nhưng điều đó có thể trở nên
cồng kềnh:

void setup() {
pinMode(0, INPUT);
pinMode(1, INPUT);
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
pinMode(6, INPUT);
pinMode(7, INPUT);
pinMode(8, INPUT);
pinMode(9, INPUT);
pinMode(10, INPUT);
pinMode(11, INPUT);
pinMode(12, INPUT);
pinMode(13, INPUT);

30
Mã này chắc chắn sẽ hoàn thành nhiệm vụ thiết lập tất cả các cổng kỹ thuật số cho đầu vào,
nhưng nó chắc chắn cần một rất nhiều mã để viết!

Ngôn ngữ lập trình Arduino cung cấp ba loại câu lệnh lặp để giúp chúng ta đơn giản hóa
việc lặp lại nhiệm vụ như vậy:
Câu lệnh while
Câu lệnh do-while
Tuyên bố for
Giờ này bao gồm từng câu lệnh trong số này, cùng với một số tính năng khác hữu ích khi sử
dụng các vòng lặp. Đầu tiên, chúng ta hãy xem cách sử dụng câu lệnh while.

Sử dụng vòng lặp while


Loại vòng lặp cơ bản nhất là câu lệnh while. Câu lệnh while lặp qua một khối mã, miễn là
một điều kiện được chỉ định đánh giá thành giá trị true Boolean. Định dạng của thời gian
như sau:
while (condition) {
code statements
}
Condition trong câu lệnh while sử dụng các toán tử so sánh chính xác giống như if-then sử
dụng câu lệnh .Ý tưởng là kiểm tra giá trị của một biến được thay đổi bên trong khối mã.
Bằng cách đó, mã của bạn kiểm soát chính xác thời điểm dừng vòng lặp.
Thử nghiệm : Vòng lặp while
1. Mở Arduino IDE, sau đó nhập mã này vào cửa sổ trình chỉnh sửa:
void setup() {
Serial.begin(9600);
int counter = 1;
while(counter < 11) {
Serial.print("The counter value is ");
Serial.println(counter);
counter = counter + 1;
}
Serial.println("The loop has ended");
}
void loop() {
}
2. Lưu bản phác thảo dưới dạng sketch0702 .
3. Nhấp vào biểu tượng Upload trên thanh công cụ để xác minh, biên dịch và tải lên bản
phác thảo của bạn Arduino.

31
4. Mở màn hình nối tiếp để xem đầu ra của bản phác thảo của bạn.

Kết quả như hình sau

HÌNH 7.1 Đầu ra từ bản phác thảo sketch0701.


Sử dụng vòng lặp do-while
Câu lệnh while luôn kiểm tra điều kiện trước, trước khi nhập vào khối mã vòng lặp các câu
lệnh. Có thể đôi khi bạn muốn chạy các câu lệnh khối mã trước, trước khi kiểm tra tình
trạng. Đây là lúc câu lệnh lặp do-while có ích.
Định dạng của câu lệnh do-while như sau:
do {
code statements
} while (condition);
Khi Arduino chạy câu lệnh do-while, nó luôn chạy các câu lệnh bên trong khối mã đầu tiên,
trước khi đánh giá so sánh điều kiện. Điều đó có nghĩa là mã được đảm bảo chạy ít nhất một
thời gian, ngay cả khi điều kiện ban đầu là sai. Hãy xem một ví dụ về việc sử dụng câu lệnh
do-while.

Ví dụ : Thử nghiệm vòng lặp do-while

1. Mở Arduino IDE, sau đó nhập mã này vào cửa sổ trình chỉnh sửa:

32
void setup() {v Serial.begin(9600);
int counter = 1;
do {
Serial.print("The value of the counter is ");
Serial.println(counter);
counter = counter + 1;
} while (counter < 1);
}
void loop() {
}
2. Lưu bản phác thảo dưới dạng sketch0702 .
3. Nhấp vào biểu tượng Upload trên thanh công cụ để xác minh, biên dịch và tải lên
bản phác thảo của bạn Arduino.
4. Mở màn hình nối tiếp để xem đầu ra của bản phác thảo của bạn.
Kết quả hiển thị trong hình sau :

HÌNH 7.2 Đầu ra từ bản phác thảo sketch0702.


Điều kiện được chỉ định cho câu lệnh do-while kiểm tra xem giá trị của biến bộ đếm có nhỏ
hơn 1. Vì câu lệnh gán đặt giá trị ban đầu của biến đếm thành 1,
lần đầu tiên điều kiện được kiểm tra, nó trả về một giá trị sai. Tuy nhiên, vòng lặp do-while
có đã chạy các câu lệnh trong khối mã trước khi kiểm tra, vì vậy bạn sẽ thấy đầu ra trong
chuỗi màn hình.

33
Sử dụng cho các vòng lặp
Các câu lệnh while và do-while là những cách tuyệt vời để lặp qua một loạt dữ liệu, nhưng
chúng có thể một chút cồng kềnh để sử dụng. Trong cả hai câu lệnh đó, bạn phải đảm bảo
rằng bạn thay đổi một biến giá trị bên trong khối mã để điều kiện lặp dừng khi cần thiết.
Ngôn ngữ lập trình Arduino hỗ trợ một loại câu lệnh lặp tất cả trong một được gọi là for
tuyên bố. Câu lệnh for tự động theo dõi các lần lặp vòng lặp cho chúng tôi.
Đây là định dạng cơ bản của câu lệnh for:
for(statement1; condition; statement2) {
code statements
}
Tham số đầu tiên, statement1 , là một câu lệnh ngôn ngữ C chạy trước khi vòng lặp bắt đầu.
Bình thường câu lệnh này đặt giá trị ban đầu của bộ đếm được sử dụng trong vòng lặp.
Tham số thứ hai, condition , là phép so sánh được đánh giá ở đầu mỗi vòng lặp. Miễn là khi
điều kiện đánh giá thành giá trị true, vòng lặp for sẽ xử lý các câu lệnh mã bên trong mã
khối. Khi điều kiện đánh giá thành giá trị sai, Arduino thoát ra khỏi vòng lặp và tiếp tục
trong mã chương trình.
Tham số cuối cùng, statement2 , là một câu lệnh ngôn ngữ C chạy ở cuối mỗi vòng lặp. Đây
là thường được đặt để thay đổi giá trị của bộ đếm được sử dụng trong điều kiện so sánh.
Một ví dụ đơn giản về câu lệnh for sẽ giống như sau:
for(i = 0; i < 14; i++) {
pinMode(i, INPUT);
}
Ba dòng mã này chỉ thay thế chức năng phải viết ra tất cả 14 dòng câu lệnh pinMode () để
đặt tất cả các dòng đầu vào kỹ thuật số cho đầu vào. Bây giờ thật tiện dụng!
Đây là một ví dụ khác về việc sử dụng câu lệnh for trong chương trình Arduino.

Ví dụ: Sử dụng “ for “


void setup() {
Serial.begin(9600);
int counter;
for(counter = 0; counter < 14; counter++) {
Serial.print("The counter value is ");
Serial.println(counter);
}
Serial.println("This is the end of the loop");
}

34
void loop () {
}
Nhấp vào biểu tượng Upload để xác minh, biên dịch và tải bản phác thảo lên
đơn vị Arduino của bạn.
Kết quả như hình sau

HÌNH 7.3 Đầu ra từ việc chạy bản phác thảo sketch0703.


Sử dụng mảng trong vòng lặp của bạn
Như bạn có thể nói, một điều mà các vòng lặp rất tuyệt vời là xử lý một chuỗi nhiều giá trị.
Tuy nhiên, nó Bạn sẽ không tốt khi lặp qua nhiều giá trị nếu tất cả dữ liệu được lưu trữ trong
các biến khác nhau.
May mắn thay, ngôn ngữ lập trình C cung cấp một cách để tham chiếu nhiều giá trị bằng
cách sử dụng một tên biến, do đó cho phép bạn dễ dàng lặp lại các giá trị khác nhau trong
một vòng lặp.
Phần này thảo luận về cách sử dụng các biến mảng trong các vòng lặp của bạn để giúp đơn
giản hóa việc xử lý một lượng lớn dữ liệu.

Tạo Mảng
Một mảng lưu trữ nhiều giá trị dữ liệu của cùng một kiểu dữ liệu trong một khối bộ nhớ, cho
phép bạn tham chiếu các biến bằng cách sử dụng cùng một tên biến. Cách nó làm điều đó là
với một giá trị chỉ mục. Các giá trị chỉ mục trỏ đến một giá trị dữ liệu cụ thể được lưu trữ
trong mảng.

35
Định dạng để khai báo một biến mảng như sau:
datatype variablename[size];
Các datatype từ khóa là một kiểu dữ liệu chuẩn được sử dụng để khai báo các biến, chẳng
hạn như int hoặc float. Các size là một giá trị số cho biết có bao nhiêu giá trị dữ liệu của dữ
liệu quy định gõ mảng di chúc giữ. Đây là một ví dụ về khai báo một mảng các giá trị số
nguyên:
int myarray [10];
Câu lệnh khai báo một biến mảng được gọi là myarray có thể lưu trữ tối đa 10 giá trị dữ liệu
số nguyên trong ký ức. Theo mặc định, các giá trị dữ liệu mảng trống.
Bạn có thể tham chiếu từng vị trí giá trị dữ liệu bằng cách chỉ định chỉ mục với biến mảng
bằng cách sử dụng hình vuông dấu ngoặc:
myarray[0] = 20;
myarray[1] = 30;
myarray[2] = 40;
myarray[3] = 50;
myarray[4] = 100;
Các câu lệnh này gán giá trị cho năm vị trí giá trị dữ liệu đầu tiên trong biến mảng myarray.

Như với một biến bình thường, bạn có thể khai báo một biến mảng và gán các giá trị cho nó
trong một câu lệnh duy nhất, như thế này:
int myarray[10] = {20, 30, 40, 50, 100};
Câu lệnh này khai báo biến mảng myarray chứa tối đa 10 giá trị số nguyên và gán giá trị đến
5 vị trí giá trị dữ liệu đầu tiên (giá trị chỉ mục từ 0 đến 4). Các dấu ngoặc nhọn được yêu cầu
để chỉ ra tất cả các giá trị thuộc cùng một mảng.
Tương tự, để truy xuất một giá trị dữ liệu cụ thể được lưu trữ trong biến mảng, bạn chỉ cần
tham chiếu giá trị vị trí chỉ mục:
area = width * myarray [0];
Arduino truy xuất giá trị dữ liệu được lưu trữ ở vị trí chỉ mục được chỉ định và sử dụng nó
trong phương trình câu lệnh gán.

Sử dụng vòng lặp với mảng


Bên cạnh việc chỉ sử dụng các số cho chỉ số mảng, bạn cũng có thể sử dụng một biến lưu trữ
giá trị số nguyên cho giá trị chỉ mục trong một mảng:
index = 4;
area = width * myarray[index];

36
Bây giờ Arduino trước tiên truy xuất giá trị được gán cho biến chỉ mục, sau đó nó sử dụng
giá trị đó như vị trí chỉ mục cho biến mảng myarray. Nó truy xuất giá trị được lưu trữ tại vị
trí giá trị dữ liệu đó cho phương trình trong câu lệnh gán.
Bây giờ bạn đang sử dụng một biến làm chỉ mục, bước tiếp theo trong quy trình là thay đổi
giá trị chỉ mục trong để bạn có thể lặp lại qua tất cả các giá trị dữ liệu được lưu trữ trong một
mảng, như được hiển thị trong đoạn mã này:
int values[5] = {10, 20, 30, 40, 50};
for(int counter = 0; counter < 5; counter++) {
Serial.print("One value in the array is ");
Serial.println(values[counter]);
}
Lưu ý rằng bộ đếm vòng lặp for phải bắt đầu bằng giá trị 0, vì chỉ số mảng bắt đầu bằng 0.
Điều kiện kiểm tra trong vòng lặp for cũng phải dừng lại trước khi bạn đến cuối mảng; nếu
không, chương trình sẽ trả về các giá trị lẻ, vì nó sẽ tiếp tục đọc các vị trí bộ nhớ khi nghĩ
rằng chúng là một phần của mảng.

Xác định kích thước của một mảng


Bạn có thể gặp phải tình huống mà bạn không biết chính xác có bao nhiêu giá trị dữ liệu
trong một biến mảng nhưng bạn vẫn cần phải lặp lại tất cả chúng. Đây là nơi hàm sizeof của
ngôn ngữ C xuất hiện tiện dụng.
Hàm sizeof của ngôn ngữ Arduino trả về số byte được sử dụng để lưu trữ một đối tượng.
Bạn có thể dùng nó để xác định có bao nhiêu byte mà một biến mảng chiếm trong bộ nhớ và
sau đó với một chút toán học, bạn có thể chỉ xác định có bao nhiêu giá trị dữ liệu hiện được
lưu trữ trong mảng:
size = sizeof(myarray) / sizeof(int);
Sizeof (int) trả về số byte mà hệ thống sử dụng để lưu trữ kiểu dữ liệu số nguyên. Bằng cách
chia tổng kích thước của mảng bằng kích thước của một giá trị số nguyên duy nhất, bạn có
thể xác định chỉ có bao nhiêu dữ liệu các phần tử có trong mảng. Ví dụ, trong ví dụ về vòng
lặp for trước đó, bạn có thể sử dụng như sau:
for(counter = 0; counter < (sizeof(value)/sizeof(int)); counter++)
{
Arduino sẽ chỉ lặp qua số phần tử dữ liệu được xác định cho mảng. Đây là một phổ biến
thực hành trong thế giới lập trình C và có thể giúp bạn tiết kiệm rất nhiều phép tính trong mã
Arduino của mình.

37
Sử dụng nhiều biến
Một thủ thuật khác thường được sử dụng trong câu lệnh for là khả năng theo dõi nhiều bộ
đếm trong một câu lệnh duy nhất. Thay vì chỉ khởi tạo một biến đếm duy nhất trong câu lệnh
for, bạn có thể khởi tạo nhiều biến các biến, được phân tách bằng dấu phẩy. Tương tự như
vậy, bạn có thể thay đổi giá trị của tất cả các biến đó ở cuối của vòng lặp. Định dạng để làm
điều đó trông giống như sau:
int a,b;
for (a = 0, b = 0; a < 10; a++, b++) {
Serial.print("One value is ");
Serial.print(a);
Serial.print(" and the other value is ");
Serial.println(b);
}
Câu lệnh for này sử dụng hai bộ đếm: biến a và biến b. Vào cuối mỗi lần lặp lại, chương
trình tăng cả hai biến, nhưng điều kiện chỉ kiểm tra giá trị của một biến để xác định khi nào
thì dừng vòng lặp.

Vòng lặp làm tổ

Một cách sử dụng phổ biến khác của vòng lặp được gọi là lồng nhau. Lồng vòng lặp là khi
bạn đặt một vòng lặp bên trong một vòng lặp khác vòng lặp, mỗi vòng được điều khiển bởi
một biến riêng biệt.
Mẹo để sử dụng vòng lặp bên trong là bạn phải hoàn thành vòng lặp bên trong trước khi hoàn
thành vòng lặp bên ngoài.
Dấu ngoặc đóng cho vòng lặp bên trong phải được chứa trong mã vòng lặp bên ngoài:
int a,b;
for(a = 0; a < 10; a++) {
for(b = 0; b < 10; b++) {
Serial.print("One value is ");
Serial.print(a);
Serial.print(" and the other value is ");
Serial.println(b);
} // closing brace for the 'b' loop
} // closing brace for the 'a' loop
Lệnh “ break “

38
Bạn sử dụng câu lệnh break khi bạn cần thoát ra khỏi vòng lặp trước khi điều
kiện bình thường dừng vòng lặp. Hãy xem một ví dụ về cách hoạt động của
điều này.
void setup() {
Serial.begin(9600);
int i;
for(i = 0; i <= 20; i++) {
if (i == 15)
break;
Serial.print("Currently on iteration: ");
Serial.println(i);
}
Serial.println("This is the end of the test");
}
void loop() {
}
Nhấp vào biểu tượng Upload để xác minh, biên dịch và tải bản phác thảo lên
đơn vị Arduino của bạn.

Kết quả hiển thị như sau

39
HÌNH 7.4 Đầu ra từ việc chạy phác thảo sktech0704.
Câu lệnh break kết thúc vòng lặp for trong lần lặp 15, trước điều kiện được xác định cho
vòng lặp đã được đáp ứng.
Lệnh “ continue “
Lệnh continue có thể hơi kỳ lạ để làm theo. Thay vì yêu cầu Arduino nhảy ra khỏi vòng lặp,
nó yêu cầu Arduino ngừng xử lý mã bên trong vòng lặp, nhưng vẫn nhảy trở lại phần bắt đầu
của vòng. Điều đó nghe có vẻ hơi khó hiểu, vì bạn nghĩ rằng dừng xử lý bên trong vòng lặp,
bạn sẽ thoát vòng lặp (giống như câu lệnh break).
Có lẽ cách dễ nhất để làm theo cách hoạt động của câu lệnh continue là xem nó hoạt động:

void setup() {
Serial.begin(9600);
int i;
for(i = 0; i < 20; i++) {
if ((i > 5) && (i < 10)) {
continue;
}
Serial.print("The value of the counter is ");
Serial.println(i);
}
Serial.println("This is the end of the test");
}
void loop() {
}
Nhấp vào biểu tượng Upload để xác minh, biên dịch và tải bản phác thảo lên
đơn vị Arduino của bạn.
Kết quả hiển thị như sau :

40
HÌNH 7.5 Đầu ra từ việc chạy bản phác thảo sketch0705.
Câu lệnh continue khiến Arduino ngừng xử lý mã bên trong vòng lặp nếu
giá trị của biến nằm trong khoảng từ 5 đến 10, nhưng nó quay trở lại đầu vòng lặp và tiếp tục
với lặp vòng lặp. Đầu ra trong Hình 7.5 cho thấy rằng vòng lặp for vẫn tiếp tục, ngay cả khi
tiếp tục các quy trình tuyên bố.
Tóm lược
Giờ này đề cập đến cách lặp qua các khối mã nhiều lần. Thường gặp tình huống nơi bạn cần
lặp lại một hoặc nhiều câu lệnh nhiều lần với các giá trị khác nhau. Bằng cách sử dụng vòng
lặp các câu lệnh, bạn có thể giảm số lượng câu lệnh bạn phải viết. Vòng lặp while cho phép
bạn kiểm tra một điều kiện xác định thời điểm dừng vòng lặp. Với vòng lặp while, bạn có
trách nhiệm đảm bảo rằng giá trị điều kiện thay đổi bên trong vòng lặp. Vòng lặp do-while
hoạt động tương tự như vòng lặp while, nhưng nó kiểm tra điều kiện ở cuối vòng lặp chứ
không phải ở đầu. Cho vòng lặp giúp đơn giản hóa mọi thứ cho chúng tôi bằng cách cung
cấp bộ đếm, kiểm tra điều kiện và câu lệnh sửa đổi bộ đếm tất cả trong một câu lệnh mã.
Giờ này cũng đã giới thiệu cho bạn ý tưởng về các biến mảng, cho phép bạn lưu trữ nhiều dữ
liệu các giá trị được tham chiếu bởi cùng một tên biến nhưng với các chỉ mục khác nhau.
Chúng có ích khi làm việc với các vòng lặp.
Trong giờ tới, bạn học cách làm việc với văn bản trong các chương trình Arduino của mình,
điều này sẽ tỏ ra hữu ích nếu bạn đang sử dụng bất kỳ kiểu giao diện người nào cho bản
phác thảo của mình.

41
Lập trình PIC với Arduino
2. Giới thiệu
Các plcLib thư viện cho phép bạn phát triển các ứng dụng phần mềm điều khiển định
hướng 'PLC-style' cho Arduino và khả năng tương thích.

Hình 1. Chuyển đổi một mạch điện đơn giản thành một sơ đồ bậc thang và sau đó thành một
chương trình đơn giản.

Một loạt các bản phác thảo ví dụ cũng sẽ có sẵn sau khi bạn đã cài đặt thư viện. Các
chương trình trên - có lẽ là chương trình đơn giản nhất làm được điều gì đó hữu ích - sau đó
sẽ có sẵn từ trình đơn kéo xuống của Arduino IDE bằng cách chọn Tệp> Ví dụ> plcLib>
InputOutput>BareMinimum .
2.1 Phương pháp phát triển phần mềm
Trong phương pháp thiết kế quen thuộc nhất, một mạch điện có chứa các phần tử như công
tắc và đèn lần đầu tiên được biểu diễn dưới dạng đồ họa dưới dạng biểu đồ bậc thang - sau
đó phải được chuyển đổi thành văn bản- dựa trên chương trình Arduino (hoặc bản phác
thảo ), trước khi được biên dịch và tải xuống theo cách thông thường. Bạn có thể cũng mô tả
hệ thống dưới dạng sơ đồ khối (sơ đồ khối chức năng) hoặc hệ thống dựa trên trình tự (biểu
đồ chức năng tuần tự), tất cả đều có thể được trộn với mã C / C ++ gốc (văn bản có cấu trúc),
vì vậy bạn được tự do sử dụng phương pháp thiết kế phù hợp nhất với vấn đề.
Phần mềm được cung cấp dưới dạng thư viện Arduino có thể cài đặt, được included theo
cách thông thường tại bắt đầu chương trình của bạn. Một loạt các lệnh kiểu PLC dựa trên văn
bản sau đó sẽ có sẵn để sử dụng trong các chương trình.

42
Lưu ý: Không giống như một PLC thương mại hiện đại, phần mềm hiện không hỗ trợ
chương trình đồ họa mục nhập, mô phỏng hoặc giám sát thời gian chạy. Các chương trình
phải được nhập bằng Arduino IDE tiêu chuẩn. Các sơ đồ được cung cấp trong Hướng dẫn
sử dụng nhằm minh họa quá trình thiết kế và được liên kết với bản phác thảo ví dụ được
cung cấp với thư viện.
Các tính năng phần mềm được hỗ trợ bởi phiên bản plcLib hiện tại bao gồm đầu vào (kỹ
thuật số / tương tự), đầu ra
(kỹ thuật số / PWM / servo), toán tử logic Boolean, chốt, bộ định thời và dạng sóng lặp
lại. Thêm nữa chi tiết có sẵn trong các phần sau của Hướng dẫn Sử dụng , bao gồm cả tải
xuống và cài đặt hướng dẫn.

2.2 Phần cứng được hỗ trợ

Thư viện plcLib có thể được sử dụng với nhiều loại phần cứng, bao gồm bảng nguyên
mẫu , lá chắn I / O và thậm chí là các PLC tương thích với Arduino .

Hình 2. Sử dụng bảng nguyên mẫu để kết nối bộ thu điều khiển từ xa với Arduino Uno.

Các lá chắn Arduino ô tô được hỗ trợ như là tiêu chuẩn, cho phép tốc độ và hướng kiểm soát
lên đến hai DC động cơ.

43
Hình 3. Điều khiển tối đa hai động cơ bằng Lá chắn động cơ Arduino.

Hệ thống xây dựng và thử nghiệm mô-đun như Grove cho phép nhiều loại đầu vào và
thiết bị đầu ra được kết nối mà không cần nối dây hoặc hàn bảng nguyên mẫu.

Hình 4. Một tấm chắn cơ sở Grove và mô-đun Bluetooth nối tiếp được kết nối với Arduino
Uno.

Phiên bản 1.2 của phần mềm được cung cấp với một loạt các cấu hình mẫu thường
phần cứng có sẵn, bao gồm Điều khiển và khiên công nghiệp PLC tương thích với
Arduino. Chi tiết của phần cứng được hỗ trợ được đưa ra trong phần Xác định Phân bổ IO
Tùy chỉnh .

44
Hình 5 . Bộ điều khiển logic lập trình điển hình (PLC).

Các cấu hình I / O tùy chỉnh cũng có thể được phát triển cho phần cứng khác, không được hỗ
trợ theo tiêu chuẩn. Điều này quy trình được minh họa sau, sử dụng lá chắn I / O Velleman
cho Arduino như một nghiên cứu điển hình.

Hình 6 . Tấm chắn Đầu vào / Đầu ra Velleman cung cấp một loạt các đầu vào và đầu ra được
định cấu hình trước.

3. Cài đặt phần mềm


Vui lòng làm theo hướng dẫn thích hợp bên dưới, tùy thuộc vào việc bạn đang cài đặt
phần mềm lần đầu tiên hoặc nâng cấp phiên bản hiện có.

45
3.1 Cài đặt lần đầu

Phần mềm plcLib được cung cấp dưới dạng tệp ZIP có thể được tải xuống và sau đó
được thêm vào Arduino của bạn IDE theo cách thông thường. Với phần mềm được cài đặt,
bạn sẽ có thể duyệt qua ví dụ và tạo các bản phác thảo kiểu PLC của riêng bạn. Tải
xuống: plcLib Phiên bản 1.2, phát hành ngày 21 tháng 12 năm 2015. (Xem Lịch sử sửa
đổi cho tất cả các bản đã xuất bản phiên bản.) Chi tiết chính xác của quá trình cài đặt phụ
thuộc vào phiên bản Arduino IDE được cài đặt. Đối với Arduino 1.6.4 trở lên, chọn tùy
chọn Phác thảo> Bao gồm Thư viện> Thêm Thư viện .Zip và duyệt đến tệp Zip đã tải
xuống trước đó. Nếu bạn đang sử dụng Phiên bản 1.0.5 của Arduino IDE, hãy chọn Phác
thảo> Nhập Thư viện ...> Thêm Thư viện ... từ trình đơn kéo xuống, duyệt để tìm tệp Zip
đã tải xuống trước đó. Quá trình cài đặt được giải thích đầy đủ trong hướng dẫn
Arduino này .

3.1.1 Tải và chạy ứng dụng đầu tiên của bạn

Với phần mềm được cài đặt, duyệt đến phần ví dụ và tải bản phác thảo Bare Minimum .

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Bare Minimum - Single bit digital input and output

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Output - LED connected to output Y0 (Arduino pin 3)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read Input 0 out(Y0); // Send to Output
0
}

Liệt kê 1. Bare Minimum (Nguồn: File> Examples> plcLib> InputOutput>


BareMinimum)
Lưu ý: Tất cả các ví dụ được hiển thị đều có sẵn từ phần Tệp> Ví dụ của Arduino IDE.
Bản phác thảo trên đọc một công tắc được kết nối với đầu vào X0 (chân A0 trên Arduino) và
gửi công tắc trạng thái đầu ra Y0 (chân 3 trên Arduino). Để xem nó hoạt động, bạn có thể kết

46
nối một bảng nguyên mẫu hoặc sử dụng bất kỳ phạm vi phần cứng được hỗ trợ nào, như
được giải thích trong phần Định cấu hình Phần cứng .

Hình 7. Thử nghiệm chương trình Bare Minimum bằng cách sử dụng hệ thống thử nghiệm
mô-đun.

3.2 Cập nhật lên phiên bản mới


Các phiên bản mới của phần mềm plcLib được phát hành định kỳ. Quy trình nâng cấp được
đề xuất là trước tiên hãy xóa phiên bản hiện có của thư viện và sau đó cài đặt phiên bản mới,
như được mô tả bên dưới.

1. Xác định vị trí của tệp thư viện trên máy tính của bạn, tệp này sẽ nằm trong thư mục
thư viện bên dưới các Arduino Sketchbook địa điểm. Chi tiết chính xác có thể khác nhau
nhưng nó thường sẽ là một cái gì đó như [Tài liệu của tôi] / Arduino / thư viện , với một thư
mục plcLib tồn tại bên dưới thư mục này nếu phần mềm có đã được cài đặt trước đó. Bạn có
thể kiểm tra đường dẫn đến thư mục Sketchbook bằng cách chọn Tệp>Các tùy chọn từ
Arduino IDE.

2. Đóng Arduino IDE, rồi xóa thư mục plcLib đã xác định ở trên. (Đó là một ý tưởng hay để
thực hiện một sao lưu bản sao của bất kỳ tệp hiện có nào trước khi xóa chúng - đề phòng
trường hợp bạn mắc lỗi.)

3. Cài đặt lại thư viện như đã giải thích trước đó.
Phần tiếp theo giới thiệu cách sắp xếp phần cứng được sử dụng bởi phần mềm.

4 Định cấu hình phần cứng


Bộ đầu vào và đầu ra cơ bản được bật theo mặc định. Cấu hình mặc định này được chọn
trước tiên
47
'bao gồm' tệp thư viện plc ( #include <plcLib.h> ) và thứ hai bằng cách gọi hàm setupPLC
() từ
trong phần setup () của bản phác thảo của bạn, như đã thấy trong bản phác thảo ví dụ của
Liệt kê 1.
Ở mức tối thiểu, phần mềm xác định bốn đầu vào X0 , X1 , X2 và X3 (đầu vào tương
tự A0 - A3 ) và bốn đầu vào
đầu ra Y0 , Y1 , Y2 và Y3 (chân 3, 5, 6 và 9).

Hình 8. Phân bổ đầu vào / đầu ra mặc định cho các bo mạch Arduino thông thường

Các chân bổ sung được phân bổ cho các bảng Arduino lớn hơn
( Mega , Mega2560 hoặc Due ), như được hiển thị tại đúng, cho tổng cộng 8 đầu vào và 8
đầu ra. Các tính năng chính của bố cục phần cứng này được giải thích dưới đây:
• Đầu vào có khả năng đọc các giá trị kỹ thuật số hoặc tương tự.
• Đầu ra có thể tạo ra các giá trị kỹ thuật số, PWM hoặc servo.
• Các chân Arduino có chức năng trùng lặp đã được tránh ở bất cứ nơi nào có thể, để giảm
thiểu phần cứng
xung đột.
• Hướng dữ liệu của đầu vào và đầu ra được định cấu hình tự động và đầu ra bị tắt ban đầu
(dựa trên giả định rằng 0 = 'tắt' và 1 = 'bật')

Lưu ý: Hầu hết các tệp ví dụ được cung cấp đều sử dụng cấu hình I / O tiêu chuẩn.

Nếu sự sắp xếp mặc định này không phù hợp, thì một số thiết lập phần cứng tùy chỉnh
thay thế sẽ có sẵn - hoặc bạn có thể thích tạo của riêng bạn. Hãy xem Xác định Tuỳ chỉnh IO
phân bổ phần để biết thêm chi tiết.
48
Phần tiếp theo giới thiệu việc sử dụng sơ đồ bậc thang để mô tả sự sắp xếp và hoạt động
của một hệ thống đơn giản và chuyển đổi của nó thành chương trình dựa trên logic bậc
thang . Các khái niệm logic bậc thang là xa hơn được phát triển trong các phần tiếp theo của
Hướng dẫn sử dụng plcLib.

5. Bắt đầu với Logic bậc thang

Phương pháp thiết kế PLC thường bắt đầu với một mạch điện hoặc sơ đồ khối, sau đó
được vẽ lại như
một sơ đồ bậc thang , và sau đó chuyển đổi thành một bản phác thảo Arduino trước khi được
biên soạn và tải về tại cách bình thường. Hình dưới đây minh họa quá trình này.

Hình 9. Chuyển đổi mạch điện thành sơ đồ bậc thang và sau đó thành chương trình logic bậc
thang.

Tên 'biểu đồ bậc thang' xuất phát từ sự giống bề ngoài với một cái thang vật lý, với chiều
dọc ray điện ở mỗi bên, và các nhánh mạch ngang được gọi là bậc nối giữa các ray. Hơn sơ
đồ bậc thang phức tạp có một loạt các bậc thang, mỗi bậc thang biểu thị một mạch riêng biệt.

Sơ đồ bậc thang là sự thích ứng của một công nghệ trước đó gọi là logic rơle , trong đó
các công tắc và rơ le được sử dụng để điều khiển các mạch công nghiệp. Một mạch logic rơle
đơn giản được hiển thị bên dưới.

49
Hình 10. Một mạch Logic Relay đơn giản.

Lưu ý đường ray điện dương ở bên trái và tiêu cực ở bên phải. Các công tắc SW1 và
SW2 được đẩy sang- loại tạo và đẩy để ngắt, làm cho các đèn liên quan của chúng sáng khi
nhấn công tắc hoặc được phát hành, tương ứng. Công tắc SW3 được kết nối với cuộn dây
rơle RL1 và các tiếp điểm rơle chuyển đổi được sau đó liên kết với đèn BL3 và BL4. Các
tiếp điểm rơ le được bố trí sao cho chỉ có một đèn sáng ở bất kỳ thời gian.
Bất kỳ chương trình nào sử dụng thư viện phần mềm plcLib phải được nhập dưới dạng
văn bản Arduino tiêu chuẩn- dựa trên bản phác thảo , mà các lập trình viên PLC có thể gọi
là lập trình danh sách lệnh . Với thực hành, quá trình chuyển đổi một sơ đồ bậc thang thành
một bản phác thảo Arduino trở nên tương đối đơn giản. A có sẵn số lượng lựa chọn thay thế
cho phương pháp thiết kế logic bậc thang, bao gồm cả khối chức năng lập trình, biểu đồ chức
năng tuần tự vàvăn bản có cấu trúc, mỗi trong số đó được thảo luận riêng biệt.

Lưu ý: Năm phương pháp lập trình này (sơ đồ bậc thang, danh sách lệnh, khối chức năng,
tuần tự biểu đồ chức năng và văn bản có cấu trúc) được xác định theo Phần 3 của tiêu chuẩn
IEC 61131 (IEC 61131-3, cũng ở Vương quốc Anh được gọi là BS EN 61131-3), đề cập đến
các ngôn ngữ lập trình để lập trình bộ điều khiển.

5.1 Đầu vào và đầu ra bit đơn

Phần mềm plcLib cho phép các đầu vào và đầu ra bit đơn được điều khiển bình thường
50
tắt hoặc bình thường trên các biểu mẫu. Một đầu vào bình thường tương đương với một công
tắc nhấn để thực hiện và được biểu diễn bởi một cặp đường thẳng đứng trong sơ đồ bậc
thang. Một công tắc nhấn để ngắt cung cấp một công tắc thường đóng kết nối và điều này
được hiển thị bằng cách thêm một đường chéo giữa các tiếp điểm dọc. Một tương tự sự sắp
xếp được sử dụng cho các đầu ra được hiển thị dưới dạng một cặp đường cong (hoặc thậm
chí là một hình tròn), với một đường chéo được thêm vào để có đầu ra đảo ngược. Sơ đồ bậc
thang dưới đây cho thấy đầu vào và đầu ra của các giá trị ở dạng bình thường và dạng đảo
ngược.

Hình 11. Sơ đồ bậc thang thể hiện các phương pháp đọc đầu vào và điều khiển đầu ra.

Sơ đồ bậc thang có thể dễ dàng chuyển đổi thành bản phác thảo dựa trên văn bản, như được
hiển thị bên dưới.
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Digital Input / Output - Single bit I/O in normal and inverted forms
Connections:

Input - switch connected to input X0 (Arduino pin A0)


Input - switch connected to input X1 (Arduino pin A1)
Input - switch connected to input X2 (Arduino pin A2)
Input - switch connected to input X3 (Arduino pin A3)
Output - LED connected to output Y0 (Arduino pin 3)
Output - LED connected to output Y1 (Arduino pin 5)

51
Output - LED connected to output Y2 (Arduino pin 6)

Output - LED connected to output Y3 (Arduino pin 9)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/
void setup() {

setupPLC(); // Setup inputs and outputs


}

void loop() {
in(X0); // Read Input 0
out(Y0); // Send to Output 0

inNot(X1); // Read Input 1 (inverted) out(Y1); // Send to Output 1

in(X2); // Read Input 2


outNot(Y2); // Send to Output 2 (inverted)

inNot(X3); // Read Input 3 (inverted) and send to Output 3 (inverted)


outNot(Y3); // (The double negative cancels out) }

Liệt kê 2. Đầu vào / đầu ra kỹ thuật số (Nguồn: Tệp> Ví dụ> plcLib>


inputOutput> DigitalInputOutput)

Phần mềm PLC tính toán lặp lại từng bậc của sơ đồ bậc thang theo trình tự - từ trái sang
phải và từ trên xuống dưới - bằng cách 'quét' các đầu vào, thực hiện tính toán và xuất kết
quả; a quá trình được gọi là chu kỳ quét . Mỗi bậc của sơ đồ bậc thang thực sự là một nhiệm
vụ riêng biệt và máy tính chia sẻ sức mạnh xử lý giữa các tác vụ này theo một trình tự lặp
lại. Xử lý cao tốc độ làm cho có vẻ như PLC đang thực hiện một số hoạt động cùng một lúc.

Các đầu vào có thể được kết nối theo chuỗi hoặc song song để tạo ra Logic Boolean đơn
giản (logic tổ hợp) như đã thảo luận trong phần tiếp theo.

5.2 Thực hiện các phép toán Boolean

Các hàm logic Boolean như AND và OR có thể đạt được bằng cách sử dụng sắp xếp
chuỗi / song song của chuyển đổi danh bạ. Ví dụ: hai công tắc nối tiếp sẽ cung cấp chức năng
AND, vì cả hai công tắc phải được đóng lại để hoàn thành mạch. Tương tự, một chức năng
OR có thể đạt được bằng hai công tắc được kết nối song song, vì việc đóng một hoặc nhiều
công tắc sẽ cho phép dòng điện chuyển sang giai đoạn tiếp theo.

52
Hình 12. Các bộ chuyển mạch nối tiếp và song song thực hiện các chức năng logic AND và OR.

Các hàm logic Boolean cơ bản AND, OR, XOR và NOT có thể được biểu diễn ở dạng
biểu đồ bậc thang bằng sử dụng kết hợp nối tiếp / song song của công tắc đầu vào và tiếp
điểm đầu ra, như hình dưới đây.

53
Hình 13. Các hàm logic bậc thang logic Boolean và các hàm logic tương đương của chúng.

Sự sắp xếp sơ đồ bậc thang này có thể được mã hóa dễ dàng, như thể hiện trong bản phác
thảo sau.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

AND, OR, XOR and Not - Basic Boolean Logic Functions

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Input - switch connected to input X1 (Arduino pin A1)
Output - ANDed Output - LED connected to output Y0 (Arduino pin 3)
Output - ORed Output - LED connected to output Y1 (Arduino pin 5)
Output - XORed Output - LED connected to output Y2 (Arduino pin 6)
Output - Inverted Output - LED connected to output Y3 (Arduino pin 9)
Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

void setup() {
setupPLC(); // Setup inputs and outputs }

void loop() {
in(X0); // Read Input 0 andBit(X1); // AND with Input 1
out(Y0); // Send result to Output 0

in(X0); // Read Input 0 orBit(X1); // OR with Input 1


out(Y1); // Send result to Output 1

in(X0); // Read Input 0 xorBit(X1); // XOR with Input 1


out(Y2); // Send result to Output 2

in(X0); // Read Input 0


outNot(Y3); // Send inverted result to Output 3
}

Liệt kê 3. Các hàm AND, OR, XOR và Not (Nguồn: Tệp> Ví dụ> plcLib> Logic>
AndOrXorNot

Nếu yêu cầu đầu ra hoạt động ở mức thấp thì các hàm tương đương NAND, NOR và XNOR
có thể được tạo trong logic bậc thang.

54
Hình 14. Các mạch logic bậc thang NAND, NOR và XNOR và các chức năng logic tương
đương của chúng.

Việc mã hóa các hàm này đạt được bằng cách thay thế các lệnh out () của ví dụ trước bằng
tương đương logic âm outNot () , như được hiển thị bên dưới.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


NAND, NOR, and XNOR - Boolean Logic functions with inverted outputs

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Input - switch connected to input X1 (Arduino pin A1)
Output - NAND Output - LED connected to output Y0 (Arduino pin 3) Output - NOR Output - LED connected to output Y1
(Arduino pin 5)
Output - XNOR Output - LED connected to output Y2 (Arduino pin 6)
Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/ */

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
// NAND
in(X0); // Read Input 0 andBit(X1); // AND with Input 1

55
outNot(Y0); // Send result to Output 0 (inverted)

// NOR
in(X0); // Read Input 0 orBit(X1); // OR with Input 1
outNot(Y1); // Send result to Output 1 (inverted)

// XNOR
in(X0); // Read Input 0 xorBit(X1); // XOR with Input 1
outNot(Y2); // Send result to Output 2 (inverted)

Liệt kê 4. Các hàm NAND, NOR và XNOR. (Nguồn: Tệp> Ví dụ> plcLib> Logic>
NandNorXnor)

Các phép toán logic cũng có thể được thực hiện với một hoặc nhiều đầu vào được đảo
ngược, như được thấy ở đây.

Hình 15. Thực hiện các phép toán Boolean liên quan đến các tín hiệu đầu vào đảo ngược.

Dưới đây là một bản phác thảo tương đương.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Inverted Input Logic - Boolean logic operations using inverted inputs


(equivalent to normally closed input switches)

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Input - switch connected to input X1 (Arduino pin A1)
Output - ANDed output - LED connected to output Y0 (Arduino pin 3) Output - ORed output - LED connected
to output Y1 (Arduino pin 5)

Software and Documentation:

56
http://www.electronics-micros.com/software-hardware/plclib-arduino/
*/

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read Input 0
andNotBit(X1); // AND with Input 1 (inverted) out(Y0); // Send result to
Output 0

in(X0); // Read Input 0


orNotBit(X1); // OR with Input 1 (inverted) out(Y1); // Send result to
Output 1
}

Liệt kê 5. Logic đầu vào đảo ngược (Nguồn: Tệp> Ví dụ> plcLib> Logic>
InvertedInputLogic)

Cũng có thể thực hiện các phép toán logic liên quan đến trạng thái của các tiếp điểm
đầu ra, có hiệu lực áp dụng phản hồi từ đầu ra đến đầu vào. Tất nhiên, đây là cơ sở của logic
tuần tự , đơn giản nhất của đó là chốt Cài đặt-Đặt lại - sẽ được xem xét tiếp theo.

6. Đầu ra chốt
Bạn có thể chốt một đầu vào tạm thời, làm cho nó vẫn hoạt động (hoặc được đặt ) cho đến
khi nó cần được hủy (hoặc đặt lại ). Có ba cách tiếp cận khác nhau, như được mô tả trong
các phần sau.

6.1 Chốt với các thành phần rời rạc

Chốt Set-Reset là một trong những trụ cột chính của thiết bị điện tử và là chốt đơn giản
nhất của các mạch logic tuần tự - thường được thấy là một cặp cổng NAND hoặc NOR được
kết nối chéo. Nó cũng khá dễ dàng để tạo ra một bản than chốt mạch chỉ sử dụng một rơ
le (một công tắc hoạt động bằng điện từ) và một vài thành phần khác, như được thấy trong
mạch logic rơle sau đây.

57
Hình 16. Các thành phần rời rạc đã được sử dụng ở đây để tạo ra một mạch tự chốt.

Kiểm tra mạch điện ở bên trái, trước hết hãy nhận thấy rằng hai công tắc được nối dây
song song, đó là của khóa học một sự sắp xếp hợp lý HOẶC. Tuy nhiên, để bắt đầu, dòng
điện không chạy qua một trong hai con đường! Nhánh phía trên tắt, do không nhấn công tắc
nhấn để tạo. Công tắc bên dưới là công tắc nhấn để ngắt loại, nhưng đường dẫn này cũng bị
tắt, bị chặn bởi các tiếp điểm rơ le ở vị trí tắt (xuống).
Nhấn nhanh công tắc đầu vào Đặt sẽ cho phép nguồn điện đến cuộn dây rơ le kích hoạt,
di chuyển các tiếp điểm chuyển tiếp đến vị trí Bật (lên). Dòng điện bây giờ chạy qua nhánh
dưới, vì vậy role vẫn được bật, ngay cả khi đầu vào Đặt được giải phóng. Rơ le vẫn hoạt
động cho đến khi đầu vào Đặt lại công tắc được nhấn, do đó ngắt kết nối cuộn dây rơle và
đưa các tiếp điểm rơle về trạng thái Tắt
Chức vụ.

Lưu ý: Các chốt Reset thường có đầu ra bình thường và đầu ra ngược. Chức năng này có
thể dễ dàng được thêm vào, nếu yêu cầu, bằng cách đấu dây đèn thứ hai qua bộ tiếp điểm
công tắc không sử dụng, nhưng có cực tính ngược lại với đầu ra chính.

Một bản phác thảo Arduino tương đương được hiển thị bên dưới.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Latch using Discrete Components - Self latching circuit with Q and Not Q outputs

Connections:
Input - Set - switch connected to input X0 (Arduino pin A0)
Input - Reset - switch connected to input X1 (Arduino pin A1)
Output - Q - LED connected to output Y0 (Arduino pin 3)

58
Output - NotQ - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read switch connected to Input 0 (Set) orBit(Y0); // Self latch using Output 0
(Q) andNotBit(X1); // Reset latch using Input 1 (Reset)

out(Y0); // Output to Output 0 (Q)

in(Y0); // Read Q output


outNot(Y1); // Produce inverted output on Output 1 (Not Q) }

Liệt kê 6. Latch bằng cách sử dụng các thành phần rời rạc (Nguồn: Tệp> Ví dụ> plcLib>
Latch>LatchDiscreteComponents)

Mạch tự chốt ở trên hoạt động tốt, nhưng khá dài dòng. Một phiên bản đơn giản hóa
được hiển thị trong phần tiếp theo.

6.2 Sử dụng lệnh Latch

Lệnh latch () về mặt chức năng giống như cách sắp xếp tự chốt đã thấy ở trên, nhưng yêu
cầu tối thiểu hai dòng mã. Một tương đươngbiểu diễn sơ đồ khối chức năng được hiển thị
bên dưới, biến thể đầu tiên có đầu ra bình thường và đảo ngược và biến thể thứ hai chỉ có
một đầu ra bình thường duy nhất.

59
Hình 17. Đặt các ký hiệu chốt thiết lập lại, được hiển thị cả khi có và không có đầu ra đảo
ngược.

Bản phác thảo sau đây cho thấy một chốt với cả đầu ra bình thường và đầu ra đảo ngược,
mặc dù hai dòng sau
được sử dụng để tạo đầu ra đảo ngược là tùy chọn.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Latch Command - Set Reset latch with Q and NotQ outputs, based on the 'latch' command
Connections:

Input - Set - switch connected to input X0 (Arduino pin A0)


Input - Reset - switch connected to input X1 (Arduino pin A1)
Output - Q - LED connected to output Y0 (Arduino pin 3)
Output - NotQ - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read switch connected to Input 0 (Set input) latch(Y0, X1); // Latch, Q = Output 0, Reset =
Input 1

in(Y0); // Read Q output and generate NotQ on Output 1 outNot(Y1); // (These two lines are optional)
}

Liệt kê 7. Lệnh Latch (Nguồn: File> Examples> plcLib> Latch> LatchCommand)

Lưu ý rằng đầu vào Đặt thành chốt được lấy từ giá trị trước đó từ cùng một 'nấc' của
sơ đồ bậc thang (đọc đầu vào X0 trong trường hợp này). Lệnh nhận hai đối số là các Q đầu ra
và đặt lại đầu vào tương ứng

6.3 Sử dụng các lệnh Set và Reset

Một phương pháp thay thế để tạo đầu ra được chốt là sử dụng các lệnh set() và reset() riêng
biệt , như thể hiện trong bản phác thảo sau.

60
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Using Set and Reset commands to create a Set-Reset Latch

Connections:
Input - Set - switch connected to input X0 (Arduino pin A0)
Input - Reset - switch connected to input X1 (Arduino pin A1)
Output - Q - LED connected to output Y0 (Arduino pin 3)
Output - NotQ - LED connected to output Y1 (Arduino pin 5)

Software and Documentation: http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read switch connected to Input 0 (Set input) set(Y0); // Set Y0 to 1 if X0 = 1, leave Y0
unaltered otherwise

in(X1); // Read switch connected to X1


reset(Y0); // Clear Y0 to 0 if X1 = 1, leave Y0 unaltered otherwise
}

Liệt kê 8. Các lệnh Đặt và Đặt lại (Nguồn: Tệp> Ví dụ> plcLib> Latch SetResetCommands)

Các lệnh set () và reset () có sẵn trong Phiên bản 0.7 trở lên của thư viện plcLib.
Một chữ cái được thêm vào biểu tượng đầu ra tiêu chuẩn cho biết đầu ra là loại 'đặt' hay 'đặt
lại', như thể hiện trong sơ đồ bậc thang tương đương.

Hình 18. Một chốt được thực hiện bằng cách sử dụng đầu ra Set và Reset.

61
Phương pháp này cho phép logic riêng biệt để kiểm soát việc bật và tắt đầu ra đã chốt,
thường tiện lợi. Abiểu đồ chức năng tuần tự là một ứng dụng điển hình, trong đó các lệnh
này có thể được sử dụng để kiểm soát quá trình chuyển đổi giữa các bước trong một trình tự.

7. Xung kích hoạt cạnh


Phiên bản 1.1 của phần mềm plcLib giới thiệu khả năng tạo ra các xung được kích hoạt
cạnh, đầu ra của chỉ hoạt động trong một chu kỳ quét.

Điều này có thể hữu ích trong nhiều trường hợp, chẳng hạn như kích hoạt đầu ra một lần
duy nhất, đảm bảo đầu ra kéo dài trong khoảng thời gian ngắn hơn đầu vào hoặc ngăn hệ
thống dựa trên chốt bị khóa trong một vị trí do công tắc bên ngoài bị lỗi.

Một hệ thống kích hoạt cạnh đơn giản được hiển thị bên dưới.

Hình 19. Các xung đầu ra ngắn gọn có thể được tạo ra từ các cạnh tăng hoặc giảm của dạng
sóng đầu vào.

Điều này có thể được biểu diễn như thể hiện trong sơ đồ bậc thang sau, với các cạnh tăng
hoặc giảm đầu vào X0 được sử dụng để đặt đầu ra Y0 và Y1 trong giây lát , tương ứng.

62
Hình 20. Các xung đầu ra trên Y0 và Y1 được tạo ra bởi các cạnh tăng hoặc giảm của dạng
sóng đầu vào X0.

Dưới đây là một bản phác thảo tương đương.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Generate rising-edge and falling-edge pulses using a digital input
Connections:

Clock input - switch connected to input X0 (Arduino pin A0)


Rising-edge output - LED connected to output Y0 (Arduino pin 3)
Falling-edge output - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Pulse pulse1; // Create a pulse object called 'pulse1'

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read switch connected to Input 0 and pulse1.inClock(); // connect it to the clock input

pulse1.rising(); // Read rising edge


out(Y0); // Output rising edge for 1 scan cycle only

pulse1.falling(); // Read falling edge


out(Y1); // Output falling edge for 1 scan cycle only

delay(50); // Slow down scan cycle to enable viewing pulses


// (remove this delay in the final code) }

63
Liệt kê 9. Tạo xung cạnh lên và xung xuống (Nguồn: Tệp> Ví dụ> plcLib> Xung>
PulseInput)

Kiểm tra danh sách trên, một đối tượng xung được gọi là 'xung1' được tạo ra đầu
tiên. Đầu vào bên ngoài X0 sau đó là kết nối với đầu vào xung clock của xung đã tạo trước
đó. Cuối cùng, các tín hiệu cạnh tăng và giảm là được sử dụng để điều khiển đầu
ra Y0 và Y1 tương ứng.

Các xung đầu ra chỉ kéo dài trong một chu kỳ quét duy nhất, do đó, độ trễ thời gian 50 mili
giây đã được thêm vào phác thảo trên để 'kéo dài' các xung đầu ra đủ dài để có thể nhìn thấy
khi kết nối với đèn LED. Sự chậm trễ này nên được gỡ bỏ sau khi kiểm tra để tránh làm
chậm chu kỳ quét.

7.1 Tạo một bảng tin được kích hoạt cạnh

Một chốt đặt lại đơn giản có thể được tạo bằng một số phương pháp khác nhau, như được
trình bày trong các Phần kết quả đầu ra . Với khả năng xảy ra các công tắc đầu vào bị lỗi đã
đề cập trước đó, nó rất hữu ích để xem xét những gì sẽ xảy ra cho một mạch chốt dựa trên
nếu cả hai Set và Thiết lập lại các đầu vào là được kích hoạt đồng thời hoặc nếu một trong
các công tắc đầu vào bên ngoài bị kẹt ở vị trí 'Bật'?

Những vấn đề tiềm ẩn này có thể được khắc phục ở một mức độ lớn bằng cách sử dụng
các tín hiệu được kích hoạt cạnh để thúc đẩy đầu vào chốt, như thể hiện trong sơ đồ bậc
thang sau đây.

Hình 21. Sử dụng các đầu vào được kích hoạt cạnh để đặt hoặc đặt lại một đầu ra.

Dưới đây là một bản phác thảo tương đương.

64
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Set or reset an output using edge-triggered inputs

Connections:
Set input - switch connected to input X0 (Arduino pin A0) Reset input - switch connected to
input X1 (Arduino pin A1)
Latched output - LED connected to output Y0 (Arduino pin 3)
Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Pulse setPulse; // Create a pulse object to set the latch


Pulse resetPulse; // Create a pulse object to reset the latch

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read switch connected to Input 0 and
setPulse.inClock(); // connect it to the set pulse clock input

in(X1); // Read switch connected to Input 1 and resetPulse.inClock(); // connect it to reset pulse clock input

setPulse.rising(); // Read rising edge of X0


set(Y0); // Set Y0 to 1 on using rising edge of X0

resetPulse.rising(); // Read rising edge of X1


reset(Y0); // Reset Y0 to 0 on using rising edge of X1 }

Liệt kê 10. Đặt hoặc đặt lại đầu ra bằng đầu vào được kích hoạt cạnh (Nguồn: Tệp> Ví dụ>
plcLib>Pulse> SetResetEdge)

8. Nhập từ bàn phím

Bàn phím ma trận có thể được sử dụng làm thiết bị đầu vào, cho phép bật hoặc tắt đầu ra
PLC khi các phím cụ thể được nhấn. Để minh họa khái niệm, một bàn phím màng tiêu chuẩn
sẽ được sử dụng, cùng với thư viện bàn phím có thể tải xuống miễn phí , để thúc đẩy một loạt
các đầu ra LED được chốt.

65
Hình 22. Mạch thử nghiệm và bản phác thảo, với đầu vào bàn phím và đầu ra LED được
chốt.

Lưu ý: Trước khi thử các ví dụ, bạn cần tải xuống và cài đặt thư viện Bàn phím
Arduino. Các các tệp ví dụ về bàn phím có sẵn với Phiên bản 0.6 trở lên của phần mềm
plcLib .

8.1 Kết nối phần cứng

Chúng tôi sẽ sử dụng bảng mạch chính Arduino Uno cho các ví dụ, mà phần mềm
plcLib định nghĩa là có bốn đầu vào (X0 – X3) và bốn đầu ra (Y0 – Y3). Bàn phím được
chọn là bàn phím màng Adafruit với 12 phím, được sắp xếp dưới dạng ma trận với bốn hàng
và ba cột, do đó yêu cầu thêm bảy chân IO .Tổng cộng. Hình ảnh sau đây cho thấy phân bổ
đầu vào / đầu ra đã chọn ở dạng sơ đồ.

66
Hình 23. Cấp phát IO cho Arduino Uno và bàn phím màng.

Một cách sắp xếp hệ thống dây bảng nguyên mẫu có thể được hiển thị bên dưới (được
vẽ bằng cách sử dụng Fritzing ) .

Hình 25. Các kết nối bàn phím và đèn LED (bên trái), chi tiết hệ thống dây dẫn của bảng
nguyên mẫu (bên phải).

67
8.2 Phần mềm

Danh sách sau sử dụng chương trình nhập bàn phím khá tiêu chuẩn và sử
dụng latchKey () tùy chỉnh chức năng bật hoặc tắt một bit đầu ra dựa trên các lần nhấn tạm
thời của Đặt và Đặt lại được phân bổ chìa khóa.

/* Programmable Logic Controller Library for the Arduino and Compatibles

Matrix Keypad with On/Off Control of Latched LED Outputs


Arduino Uno Pin Connections:
Input X0 - unused (Arduino pin A0)
Input X1 - unused (Arduino pin A1)
Input X2 - unused (Arduino pin A2)
Input X3 - unused (Arduino pin A3)
Output - LED connected to output Y0 (Arduino pin 3)
Output - LED connected to output Y1 (Arduino pin 5)
Output - LED connected to output Y2 (Arduino pin 6)
Output - LED connected to output Y3 (Arduino pin 9)

4X3 Matrix Keypad Connections:


ROW1 - Arduino pin 8
ROW2 - Arduino pin 7
ROW3 - Arduino pin 4
ROW4 - Arduino pin 2
COL1 - Arduino pin 12
COL2 - Arduino pin 11
COL3 - Arduino pin 10

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

#include <Keypad.h> // Include the Keypad library


#include <plcLib.h> // Include the plcLib library

char keyPress = 0; // Holds the currently pressed key value (if any)
const byte ROWS = 4; // Keypad has four rows const byte COLS = 3; //
Keypad has three columns

// Define the Keymap char


keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'}, {'*','0','#'}

};

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 8, 7, 4, 2 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins. byte colPins[COLS] = { 12, 11, 10 };

// Create the Keypad


Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

68
void setup() {
setupPLC(); // Define input / output pins
}

void loop()
{
keyPress = kpd.getKey(); // Read key pressed (if any)

latchKey('1', '2', Y0); // Keyboard latch, Set = '1', Reset = '2',


// output = Y0 (pin 3)

latchKey('3', '4', Y1); // Keyboard latch, Set = '3', Reset = '4', // output = Y1 (pin 5)

latchKey('5', '6', Y2); // Keyboard latch, Set = '5', Reset = '6',


// output = Y2 (pin 6)

latchKey('7', '8', Y3); // Keyboard latch, Set = '7', Reset = '8',


// output = Y3 (pin 9)
}

// Keypad-based Set-Reset latch, outputting to a pin. unsigned int latchKey(char en, char dis, int outPin) {
if(keyPress) {

if (keyPress == en) {
digitalWrite(outPin, HIGH);
}
if (keyPress == dis) { digitalWrite(outPin, LOW);

}
}
}

Liệt kê 11. Bàn phím ma trận với Điều khiển Bật / Tắt các đầu ra LED được chốt (Nguồn:
Tệp> Ví dụ> plcLib> Bàn phím> LedOnOff)

Tác dụng tổng thể của bốn lệnh latchKey () trong bản phác thảo trên là kích hoạt các đèn
LED được kết nối với đầu ra Y0 , Y1 , Y2 hoặc Y3 khi các phím '1', '3', '5' hoặc '7' được nhấn,
với các phím '2', '4', '6' và '8' xoay đầu ra tương ứng lại tắt.

Một thay đổi nhỏ đối với phân bổ công tắc cho phép một phím đầu vào duy nhất hoạt
động như một thiết lập lại chính, như được hiển thị trong
phần trích sau.

void loop()
{
keyPress = kpd.getKey(); // Read key pressed (if any)

latchKey('1', '*', Y0); // Keyboard latch, Set = '1', Reset = '*',


// output = Y0 (pin 3)

69
latchKey('2', '*', Y1); // Keyboard latch, Set = '2', Reset = '*',
// output = Y1 (pin 5)

latchKey('3', '*', Y2); // Keyboard latch, Set = '3', Reset = '*',


// output = Y2 (pin 6)

latchKey('4', '*', Y3); // Keyboard latch, Set = '4', Reset = '*',


// output = Y3 (pin 9) }

Liệt kê 12. Sửa đổi khóa đặt lại chính (Nguồn: Tệp> Ví dụ> plcLib> Bàn phím> LedStop)

Cũng có thể lưu trữ bit đầu ra chốt trong một biến do người dùng xác định, thay vì gửi
trực tiếp đến một chân đầu ra. Một ví dụ dựa trên cách tiếp cận này được đưa ra trong bản
phác thảo ví dụ LedVariable , trong khi cách tiếp cận cơ bản được thảo luận trong phần Sử
dụng biến trong chương trình .

9. Thời gian trễ sử dụng

Phần mềm plcLib có các lệnh để tạo ra độ trễ thời gian dựa trên việc kích hoạt hoặc hủy
kích hoạt tín hiệu đầu vào (lệnh timerOn () và timerOff () ), và cũng có thể tạo ra xung đầu
ra cố định thời lượng (lệnh timerPulse () ). Tất cả các lệnh chấp nhận hai tham số trước hết
là tên của biến bộ hẹn giờ đã trôi qua và thứ hai là thời gian trễ yêu cầu tính bằng mili giây.

Tránh sử dụng lệnh delay () của chính Arduino nếu có thể, vì điều này sẽ tạm dừng chu
kỳ quét PLC đối với khoảng thời gian trì hoãn và chỉ hỗ trợ một thời gian trễ duy nhất đang
hoạt động bất kỳ lúc nào. Xem phần Nâng cao Phần khái niệm để biết thêm chi tiết.

9.1 Tạo ra độ trễ khi bật

Lệnh timerOn () trì hoãn việc kích hoạt đầu ra cho đến khi đầu vào liên tục hoạt động
cho khoảng thời gian được chỉ định tính bằng mili giây.

70
Hình 26. Một bộ định thời trễ cung cấp việc kích hoạt một đầu ra bị trì hoãn .

Hệ thống dựa trên bộ đếm thời gian có thể được biểu diễn thuận tiện bằng cách sử
dụng sơ đồ khối hoặc khối chức năng biểu đồ, như trong ví dụ sau.

Hình 27. Một cặp bộ định thời gian trễ tạo ra các độ trễ riêng biệt, được điều khiển bởi hai
đầu vào khác nhau.

Hai bộ hẹn giờ trễ cung cấp độ trễ thời gian kích hoạt độc lập là 2 giây và 4 giây khi bật
Đầu ra 0 và 1 tương ứng. Đầu ra 0 sẽ hoạt động sau khi tín hiệu được kết nối với Đầu vào 0
đã được hoạt động trong 2 giây, trong khi Đầu ra 1 yêu cầu Đầu vào 1 phải hoạt động trong
khoảng thời gian 4 giây. Các bản phác thảo tương đương được hiển thị bên dưới.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Turn-on Delay - Delays turning an output on after an input is applied

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Input - switch connected to input X1 (Arduino pin A1)
Output with 2 s delay - LED connected to output Y0 (Arduino pin 3)
Output with 4 s delay - LED connected to output Y1 (Arduino pin 5)

Software and Documentation: http://www.electronics-micros.com/software-hardware/plclib-


arduino/

*/

unsigned long TIMER0 = 0; // Variable to hold elapsed time for Timer 0 unsigned long TIMER1 = 0; //
Variable to hold elapsed time for Timer 1

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {

71
in(X0); // Read Input 0 timerOn(TIMER0, 2000); // 2 second
delay out(Y0); // Output to Output 0

in(X1); // Read Input 1 timerOn(TIMER1, 4000); // 4 second


delay out(Y1); // Output to Output 1

Liệt kê 13. Độ trễ khi bật (Nguồn: File> Examples> plcLib> TimeDelays> DelayOn)

Lưu ý rằng mỗi bộ hẹn giờ sử dụng nội bộ biến bộ hẹn giờ đã trôi qua thuộc loại 'unsigned
long', phải được khai báo khi bắt đầu chương trình.

9.2 Chuyển đổi Debouncing

Một vấn đề phổ biến với các hệ thống dựa trên công tắc hoặc bàn phím là số liên lạc bị trả
lại trong đó một lần nhấn phím khiến các địa chỉ liên hệ bị trả lại thực tế vài lần - trong
khoảng thời gian vài mili giây - trước khi giải quyết. Hiệu ứng cơ học này có thể được loại
bỏ bằng cách sử dụng bộ đếm thời gian trễ có thời gian trễ phù hợp,
như thể hiện trong ví dụ sau.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Switch Debounce - Delays a switch input by 10 ms to remove contact bounce

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Output - debounced output - LED connected to output Y0 (Arduino pin 3)
Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

unsigned long TIMER0 = 0; // Define variable used to hold timer 0 elapsed time

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read Input 0
timerOn(TIMER0, 10); // 10 ms delay out(Y0); // Output to
Output 0
}

Liệt kê 14. Switch Debounce (Nguồn: File> Examples> plcLib> TimeDelays>


SwitchDebounce)

72
9.3 Tạo độ trễ khi tắt máy

Bộ hẹn giờ trễ tắt bật sẽ hoạt động ngay lập tức và sau đó trì hoãn việc tắt trong một
khoảng thời gian nhất định sau đầu vào kiểm soát bị loại bỏ.

Hình 28. Độ trễ tắt làm cho đầu ra vẫn hoạt động trong một khoảng thời gian cố định sau
khi đầu vào bị loại bỏ.

Một ứng dụng của độ trễ khi tắt máy là 'giãn xung' trong đó tín hiệu đầu vào ngắn gọn
được mở rộng để có độ rộng xung tối thiểu. Sơ đồ khối chức năng sau đây cho thấy bộ hẹn
giờ tắt trễ với 2 giây độ trễ tắt máy.

Hình 29. Một bộ hẹn giờ tắt có độ trễ 2 giây.

Bản phác thảo tương đương được đưa ra dưới đây.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Turn-off Delay - Delays turning an output off after an input is removed

Connections:
Input - switch connected to input X0 (Arduino pin A0) Output - LED connected to output
Y0 (Arduino pin 3)

73
Software and Documentation:
http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

unsigned long TIMER0 = 0; // Variable to hold elapsed time for Timer 0

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read Input 0
timerOff(TIMER0, 2000); // 2 second turn-off delay
out(Y0); // Output to Output 0 }

Liệt kê 15. Độ trễ tắt (Nguồn: File> Examples> plcLib> TimeDelays> DelayOff)

9.4 Tạo xung thời lượng cố định

Lệnh timerPulse () (có sẵn với Phiên bản 1.0 trở lên) tạo xung đầu ra có độ rộng cố định
khi được kích hoạt bởi một xung đầu vào ngắn. Điều này tương đương với một mạch ổn
định điện tử .

Hình 30. Một xung có độ rộng cố định được tạo bởi lệnh timerPulse() .

Một bản phác thảo ví dụ được hiển thị bên dưới.

74
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Fixed Pulse - Activates an output for a fixed period after a momentary input is applie d

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Output with 2 s pulse - LED connected to output Y0 (Arduino pin 3)
Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

unsigned long TIMER0 = 0; // Variable to hold elapsed time for Timer 0


void setup() {
setupPLC(); // Setup inputs and outputs }

void loop() {
in(X0); // Read Input 0 timerPulse(TIMER0, 2000); // 2 second pulse
out(Y0); // Output to Output 0

Liệt kê 16. Xung độ rộng cố định (Vị trí nguồn: File> Examples> plcLib> TimeDelays>
FixedPulse)

Lưu ý: Trong phiên bản 1.1 trở lên, hoạt động của lệnh timerPulse được sửa đổi để được
kích hoạt cạnh chứ không phải mức được kích hoạt. Do đó, bộ hẹn giờ được kích hoạt lại bởi
quá trình chuyển đổi từ thấp đến cao đầu tiên của đầu vào kích hoạt sau khi xung trước đó
đã kết thúc. (Điều này hiện đồng ý với hành vi tiêu chuẩn trong IEC tiêu chuẩn 61131-3.)
Phần tiếp theo mở rộng các khái niệm về thời gian trễ được giới thiệu ở đây để tạo liên tục
lặp lại dạng sóng.

75
10. Tạo ra các dạng sóng lặp lại
Một xung lặp lại có thể được xác định bằng cách sử dụng khoảng thời gian của các thành
phần thấp và cao của dạng sóng

Hình 31. Một xung lặp lại có thể được xác định theo thời lượng của phần thấp và phần cao.

Thời gian thực hiện cho một chu kỳ hoàn chỉnh được gọi là thời gian theo chu kỳ (hoặc theo
chu kỳ), có được bằng cách thêm thời lượng của các thành phần thấp và cao (khoảng thời
gian 1 giây trong ví dụ trên). Xung lặp lại có thể được tạo thủ công, từ các thành phần đơn
giản hơn hoặc bằng cách sử dụng một lệnh chuyên dụng.

10.1 Tạo xung thủ công

Một cặp bộ định thời gian trễ được kết nối chéo có thể được sử dụng để tạo xung lặp lại, như
thể hiện trong ví dụ sau.
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Repeating pulse using a pair of linked on-delay timers

Connections:

Input - switch connected to input X0 (Arduino pin A0)


Output - LED connected to output Y0 (Arduino pin 3)

Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/
void setup() {
setupPLC(); // Setup inputs and outputs

}
void loop() {

in(X0); // Read Input 0 (enable)

andNotBit(Y0); // And with inverted output


timerOn(TIMER0, 900); // 900 ms (0.9 s) delay
set(Y0); // Set Output 0 on time-out

in(X0); // Read Input 0 (enable)

76
Listing 17. Xung lặp lại bằng cách sử dụng một cặp bộ định thời gian trễ được liên
kết (Source: File > Examples > plcLib> Waveforms > PulsedOutputManual)
Khi chương trình đang chạy, bạn sẽ thấy rằng liên tục nhấn enable đầu vào (X0) làm cho
đầu ra (Y0) bật trong 0,1 giây, sau đó tắt 0,9 giây theo một trình tự lặp lại..
Chương trình sử dụng một cặp bộ định thời gian trễ, cộng với một chốt cài đặt lại dựa trên
đầu ra Y0. Bộ hẹn giờ đầu tiên được bật ban đầu, giả sử đầu ra Y0 bằng 0 và đầu vào cho
phép cũng được bật. Đầu ra bộ hẹn giờ đầu tiên tăng cao sau 900 ms, lần lượt đặt đầu ra
Y0 thành 1. Tại thời điểm này, bộ định thời trễ thứ hai được bật và bắt đầu đếm. Sau 100
ms nữa, đầu ra bộ định thời thứ hai được đặt, điều này làm cho đầu ra Y0 bị xóa và toàn bộ
chu kỳ bắt đầu lại.
Đây là một ví dụ về Máy trạng thái hữu hạn (FSM) rất đơn giản, là cơ sở của biểu đồ chức
năng tuần tự.
Đừng lo lắng nếu ví dụ trên có vẻ khá phức tạp, vì chức năng tương tự này được cung cấp
bởi lệnh timerCycle (), sẽ được thảo luận tiếp theo.

10.2 Sử dụng lệnh timerCycle()


Lệnh timerCycle () có thể được sử dụng để tạo ra dạng sóng xung lặp lại, ví dụ, có thể được
sử dụng để nhấp nháy đèn LED liên tục. (Như tên lệnh cho thấy, điều này đôi khi được gọi
là bộ đếm thời gian chu kỳ.)
Biểu tượng sơ đồ khối chức năng tương đương được hiển thị bên dưới.

Hình 32. Bộ định thời chu kỳ tạo ra dạng sóng xung lặp lại khi được kích hoạt..

Lệnh yêu cầu bốn tham số được chỉ định cho mỗi dạng sóng. Thông số 1 và 3 phải là được
chỉ định dưới dạng các biến (thuộc loại unsigned long) và được phần mềm plcLib sử dụng
nội bộ để đo lường thời gian trôi qua cho các phần thấp và cao của dạng sóng tương ứng.
Liên kết thấp và cao độ rộng xung được xác định trong tham số thứ 2 và thứ 4 . Ví dụ sau
minh họa quá trình này.

77
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Pulsed Output - Creating a repeating pulse using the timerCycle command

Connections:
Input - Enable input connected to input X0 (Arduino pin A0)
Output - Pulse Waveform on LED connected to output Y0 (Arduino pin 3)
Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

// Variables:
unsigned long AUX0 = 0; // Pulse low timer variable
unsigned long AUX1 = 0; // Pulse high timer variable

void setup() {
setupPLC(); // Define inputs and outputs }

void loop() {
in (X0); // Read Enable input (1 = enable)
timerCycle(AUX0, 900, AUX1, 100); // Repeating pulse, low = 0.9 s, high = 0.1 s
// (hence period = 1 second)
out(Y0); // Send pulse waveform to Output 0 }

Listing 18. Đầu ra xung - Tạo xung lặp lại bằng lệnh timerCycle
(Source: File > Examples > plcLib > Waveforms > PulsedOutput)
Lưu ý: Một ứng dụng điển hình là việc tạo ra một xung nhấp nháy 'vũ trang báo động' lặp lại,
như được minh họa trong bản phác thảo ví dụ File> Examples> plcLib> Applications>
AlarmWithArmedStatu

11. Đếm và Bộ đếm

Phiên bản 0.8 của phần mềm giới thiệu các bộ đếm, có thể kích hoạt một đầu ra khi được
xác định trước số sự kiện đã xảy ra. Một 'đối tượng' bộ đếm có thể được cấu hình để đếm
lên, đếm xuống hoặc kết hợp của cả hai.

78
Hình 33. Một đối tượng bộ đếm có thể được cấu hình để đếm lên, đếm xuống hoặc cả hai.

Mỗi bộ đếm có bốn đầu vào và bốn đầu ra, được hiển thị ở bên trái và bên phải của sơ đồ
trên, tương ứng. Trong thực tế, chỉ một tập hợp con trong số này có thể được yêu cầu, tùy
thuộc vào loại bộ đếm cần thiết.
11.1. Bộ đếm lên
Đơn giản nhất, một bộ đếm lên đếm các xung nhận được trên đầu vào countUp của nó,
kích hoạt finished ' hoặc đầu ra upperQ khi số lượng xung đầu vào yêu cầu đã được phát
hiện. Để minh họa quy trình, ví dụ sau tạo một bộ đếm tăng đếm từ 0 đến 10, được điều
khiển bởi công tắc áp dụng cho đầu vào X0.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Up Counter - Counts 10 pulses on Input 0 with switch debounce

Connections:
Count input - switch connected to input X0 (Arduino pin A0)
Clear input - switch connected to input X1 (Arduino pin A1)
Preset input - switch connected to input X2 (Arduino pin A2)
Lower Q output - LED connected to output Y0 (Arduino pin 3)
Upper Q output - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(10); // Final count = 10, starting at zero


unsigned long TIMER0 = 0; // Define variable used to hold timer 0 elapsed time

void setup() {
setupPLC(); // Setup inputs and outputs }

void loop() {
in(X0); // Read Input 0
timerOn(TIMER0, 10); // 10 ms switch debounce delay ctr.countUp(); // Count up

in(X1); // Read input X1


ctr.clear(); // Clear counter (counter at lower limit)

in(X2); // Read input X2

79
ctr.preset(); // Preset counter (counter at upper limit)

ctr.lowerQ(); // Display Count Down output on Y0


out(Y0);

ctr.upperQ(); // Display Count Up output on Y1 out(Y1);

Listing 19. Bộ đếm lên (Source: File > Examples > plcLib > Counters > CountUp)

Kiểm tra danh sách trên, bước đầu tiên là sử dụng lệnh Counter để tạo đối tượng truy cập
ctr, đồng thời đặt giá trị cuối cùng thành 10, tương đương với thuộc tính presetValue của
quầy tính tiền. Bộ đếm mặc định là bộ đếm tăng, vì vậy giá trị đếm bên trong ban đầu bằng
0, gây ra
đầu ra Q thấp hơn sẽ được kích hoạt. Các xung được áp dụng cho đầu vào X0 được liên kết
với đầu vào countUp, làm cho giá trị đếm bên trong được tăng lên theo mỗi lần chuyển đổi
từ 0 đến 1. Sau 10 xung, số đếm trở nên bằng với giá trị giới hạn trên hoặc giá trị đặt trước,
khiến đầu ra Q trên được bật.
Một vấn đề thường gặp với mạch bộ đếm là switch bounce, nơi công tắc tiếp xúc ' bounce '
nhiều lần (trong khoảng thời gian vài mili giây) trước khi giải quyết. Điều này có thể gây ra
nhấn một công tắc để cập nhật bộ đếm nhiều lần liên tiếp. Để tránh ảnh hưởng này, hãy lưu
ý rằng bộ hẹn giờ trễ 10 mili giây đã được liên kết nối tiếp với công tắc X0 được kết nối với
đầu vào countUp.
Cũng có thể cần phải buộc bộ đếm quay lại bắt đầu theo cách thủ công, điều này đạt được
trong ví dụ trên bằng cách kết nối đầu vào công tắc X1 với đầu vào rõ ràng của bộ đếm. Đầu
vào đặt trước (được kết nối với đầu vào chuyển đổi X2) thực hiện một chức năng tương tự,
nhưng lần này đặt số lượng nội bộ thành giá trị cuối cùng hoặc giá trị đặt trước. Do đó, việc
nhấn các công tắc được kết nối với đầu vào X1 hoặc X2 sẽ gây ra đầu ra Q thấp hơn hoặc Q
trên sẽ được kích hoạt ngay lập tức, tương ứng.

11.2 Bộ đếm xuống


Việc tạo ra down counter giá khá giống nhau, như trong danh sách sau

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Down Counter - Counts 5 pulses on Input 0 with switch debounce


Connections:

80
Count input - switch connected to input X0 (Arduino pin A0)
Clear input - switch connected to input X1 (Arduino pin A1)
Preset input - switch connected to input X2 (Arduino pin A2)
Lower Q output - LED connected to output Y0 (Arduino pin 3)
Upper Q output - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(5, 1); // Counts down, starting at 5


unsigned long TIMER0 = 0; // Define variable used to hold timer 0 elapsed time

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read Input 0
timerOn(TIMER0, 10); // 10 ms switch debounce delay
ctr.countDown(); // Count down

in(X1); // Read input X1


ctr.clear(); // Clear counter (counter at lower limit)

in(X2); // Read input X2


ctr.preset(); // Preset counter (counter at upper limit)

ctr.lowerQ(); // Display Count Down output on Y0


out(Y0);

ctr.upperQ(); // Display Count Up output on Y1 out(Y1);


}

Listing 20. Bộ đếm xuống (Source: File > Examples > plcLib > Counters > CountDown)
Sự khác biệt đầu tiên là trong việc tạo đối tượng Counter ctr, sử dụng Counter ctr (5, 1); chỉ
huy. Như cài đặt tốt giá trị đặt trước thành 5, tham số thứ hai tùy chọn có giá trị 1, gây ra giá
trị đếm được đặt bằng giới hạn trên, phù hợp với bộ đếm giảm. (Bỏ qua tham số thứ hai hoặc
đặt nó thành 0 sẽ phủ nhận số đếm thành 0). Đầu vào X0 sau đó được kết nối với đầu vào
countDown, trong khi đầu ra Y0 được điều khiển bởi lowerQ. Do đó Y0 sẽ tăng cao sau khi
có 5 xung được nhận trên đầu vào X0.

11.3 Bộ đếm lên / xuống


Thật đơn giản khi kết hợp hai phương pháp này để tạo ra một thiết bị có khả năng đếm
hoặc xuống, như thể hiện trong ví dụ bên dưới

81
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Up-down Counter - Counts up or down in the range 0-10
Connections:

Count up input - switch connected to input X0 (Arduino pin A0)


Count down input - switch connected to input X1 (Arduino pin A1)
Clear input - switch connected to input X2 (Arduino pin A2)
Preset input - switch connected to input X3 (Arduino pin A3)
Lower Q output - LED connected to output Y0 (Arduino pin 3)
Upper Q output - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(10); // Counts up or down in range 0-10, starting at zero unsigned long TIMER0 = 0; // Define variable used to
hold timer 0 elapsed time
unsigned long TIMER1 = 0; // Define variable used to hold timer 1 elapsed time

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read Input 0
timerOn(TIMER0, 10); // 10 ms switch debounce delay
ctr.countUp(); // Count up

in(X1); // Read Input 1


timerOn(TIMER1, 10); // 10 ms switch debounce delay
ctr.countDown(); // Count down

in(X2); // Read input X1


ctr.clear(); // Clear counter (counter at lower limit)

in(X3); // Read input X2


ctr.preset(); // Preset counter (counter at upper limit)

ctr.lowerQ(); // Display Count Down output on Y0


out(Y0);

ctr.upperQ(); // Display Count Up output on Y1 out(Y1);


}

Listing 21. Bộ đếm lên xuống. (Source: File > Examples > plcLib > Counters>
CountUpDown)
Bộ đếm trên có các đầu vào đếm ngược và đếm ngược riêng biệt được liên kết với đầu vào
các công tắc X0 và X1 tương ứng, và mỗi đầu vào bộ đếm có đầu vào công tắc gỡ lỗi riêng
của nó.

11.4 Gỡ lỗi ứng dụng dựa trên bộ đếm

82
Đầu ra của bộ đếm được kích hoạt khi số lượng xung xác định đã được phát hiện, nhưng
giá trị đếm nội bộ thường không được hiển thị cho người dùng. Trên thực tế, bộ đếm là '
finished' hoặc ‘not finished '. Đôi khi có thể hữu ích khi xem số lượng nội bộ cho mục
đích gỡ lỗi, như được hiển thị trong ví dụ sau đây.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Up-down Counter - Counts up or down in the range 0-10
(Sends current count to serial monitor)

Connections:
Count up input - switch connected to input X0 (Arduino pin A0)
Count down input - switch connected to input X1 (Arduino pin A1)
Clear input - switch connected to input X2 (Arduino pin A2) Preset input - switch connected to
input X3 (Arduino pin A3)
Lower Q output - LED connected to output Y0 (Arduino pin 3)
Upper Q output - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(10); // Counts up or down in range 0-10, starting at zero unsigned long TIMER0 = 0; // Define variable used to
hold timer 0 elapsed time unsigned long TIMER1 = 0; // Define variable used to hold timer 1 elapsed time

void setup() {
setupPLC(); // Setup inputs and outputs Serial.begin(9600); // Open serial connection over USB
}

void loop() {
in(X0); // Read Input 0
timerOn(TIMER0, 10); // 10 ms switch debounce delay
ctr.countUp(); // Count up

in(X1); // Read Input 1


timerOn(TIMER1, 10); // 10 ms switch debounce delay ctr.countDown(); // Count down

in(X2); // Read input X1


ctr.clear(); // Clear counter (counter at lower limit)

in(X3); // Read input X2


ctr.preset(); // Preset counter (counter at upper limit)

ctr.lowerQ(); // Display Count Down output on Y0


out(Y0);

ctr.upperQ(); // Display Count Up output on Y1 out(Y1);

Serial.println(ctr.count()); // Send count to serial port delay(100);


}

83
Listing 22. Bộ đếm lên xuống có gỡ lỗi. (Source: File > Examples > plcLib >
Counters >CountUpDownDebug)

Để gỡ lỗi ứng dụng, chỉ cần mở Serial Monitor trong khi bản phác thảo đang chạy. Điều này
sẽ lặp lại hiển thị giá trị đếm bên trong, với khoảng thời gian lặp lại được điều khiển bởi lệnh
trễ hướng tới cuối danh sách. (Tuy nhiên, đừng quên xóa mã gỡ lỗi, khi ứng dụng của bạn
làm việc như dự định.)

12 Dịch chuyển và xoay dữ liệu nhị phân


Phiên bản 0.9 của phần mềm giới thiệu các thanh ghi shift có thể được sử dụng để chuyển
dữ liệu nhị phân sang trái hoặc bên phải, theo từng vị trí bit.

Hình 34. Một thanh ghi dịch chuyển đơn giản di chuyển dữ liệu sang một vị trí bên
phải trên mỗi cạnh lên của Đồng hồ
Ví dụ trên cho thấy một thanh ghi dịch chuyển 8 bit đơn giản, dịch chuyển dữ liệu từ
một vị trí sang bên phải trên mỗi cạnh lên của đầu vào Đồng hồ. Dữ liệu mới được
chuyển sang ở phía bên trái, trong khi dữ liệu bị loại bỏ vì nó lá ở bên phải. Nội dung
của các bit riêng lẻ có thể được đọc từ các kết nối đầu ra ở trên cùng.
Xét nội dung số của thanh ghi dịch chuyển, việc chuyển dữ liệu sang bên phải tương đương
với phép chia bằng hai, vì bit quan trọng nhất nằm ở bên trái. Ngược lại, dịch chuyển sang
trái sẽ tương đương với nhân với hai.

12.1 Tạo và sử dụng sổ đăng ký Shift


Bước đầu tiên là sử dụng lệnh Shift để tạo một đối tượng thanh ghi shift, có độ rộng dữ
liệu cố định 16-bit. Nội dung ban đầu của sổ đăng ký có thể được thiết lập tùy ý khi tạo.
Ví dụ: Lệnh Shift shift1 (0x8888); tạo một đối tượng thanh ghi shift gọi là shift1 với hệ
thập lục phân ban đầu nội dung của 0x8888, tương đương với 1000 1000 1000 1000
trong hệ nhị phân..
Một số tác vụ cấu hình khác cũng được yêu cầu, bao gồm định nghĩa đầu vào dữ liệu nối
tiếp, đồng hồ đầu vào (chuyển dữ liệu sang phải trong trường hợp này), đặt lại đầu vào và
bất kỳ kết nối đầu ra song song nào, như minh họa bằng ký hiệu khối chức năng sau.

84
Hình 35. Biểu diễn khối chức năng của thanh ghi dịch chuyển..
Mã hóa thực tế của thanh ghi ca được đưa ra trong bản phác thảo sau.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Shift register: Shift data to the right

Connections:
Serial Input - switch connected to input X0 (Arduino pin A0)
Clock Input - switch connected to input X1 (Arduino pin A1)
Reset Input - switch connected to input X2 (Arduino pin A2 ) Output - LED connected to output Y0
(Arduino pin 3)
Output - LED connected to output Y1 (Arduino pin 5)
Output - LED connected to output Y2 (Arduino pin 6)
Output - LED connected to output Y3 (Arduino pin 9)

Software and Documentation: http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Shift shift1(0x8888); // Create a 16 bit shift register with initial value 0x8888
// Bit 1 1 1 1 1 1
// Positions 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// |||| |||| |||| ||||
// X0 -> -> -> -> 1 0 0 0 -> 1 0 0 0 -> 1 0 0 0 -> 1 0 0 0 ->
// ||||
// X1 -> Clock | | | |
// ||||
// X2 -> Reset | | | | //
// YYYY
// Outputs 3 2 1 0

unsigned long TIMER0 = 0; // Define variable used for switch debounce

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {

in(X0); // Read input to shift register from X0 shift1.inputBit();

85
in(X1); // Shift Right on rising edge of input X1 timerOn(TIMER0, 10); // 10 ms switch debounce delay on X1

shift1.shiftRight();

in(X2); // Reset the shift register value to zero if X2 = 1


shift1.reset();

shift1.bitValue(15); // Send bit 15 value to output Y3


out(Y3);

shift1.bitValue(14); // Send bit 14 value to output Y2


out(Y2);

shift1.bitValue(13); // Send bit 13 value to output Y1


out(Y1);

shift1.bitValue(12); // Send bit 12 value to output Y0


out(Y0);
}

Listing 23. Thanh ghi Shift dịch chuyển dữ liệu sang bên phải (Source: File >
Examples > plcLib > ShiftRotate >
ShiftRight)
Dữ liệu được dịch sang phải bởi cạnh lên của đầu vào đồng hồ được lấy từ một công tắc
được kết nối với đầu vào X1, với dữ liệu mới được chuyển vào ở bên trái lấy từ công tắc
đầu vào X0. (Lưu ý rằng vấn đề tiềm ẩn của liên hệ dội lại trên đầu vào đồng hồ được tránh
bằng cách sử dụng độ trễ gỡ lỗi công tắc 10 ms.) swicth X2 cung cấp đầu vào đặt lại, xóa
thanh ghi dịch chuyển về 0 khi được nhấn. Các đầu ra song song là được lấy từ bit 15â €
“12, cho phép mọi dữ liệu nối tiếp mới được nhập vào đều hiển thị ngay trên đầu ra. Thật dễ
dàng để sửa đổi phác thảo trên để chuyển dữ liệu sang trái, như hình dưới đây

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Shift register: Shift data to the left

Connections:
Serial Input - switch connected to input X0 (Arduino pin A0)
Clock Input - switch connected to input X1 (Arduino pin A1)
Reset Input - switch connected to input X2 (Arduino pin A2)
Output - LED connected to output Y0 (Arduino pin 3)
Output - LED connected to output Y1 (Arduino pin 5)
Output - LED connected to output Y2 (Arduino pin 6)
Output - LED connected to output Y3 (Arduino pin 9)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Shift shift1(0x1111); // Create a 16 bit shift register with initial value 0x1111

86
// Bit 1 1 1 1 1 1
// Positions 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// |||| |||| |||| ||||
// <- 0 0 0 1 <- 0 0 0 1 <- 0 0 0 1 <- 0 0 0 1 <-
X0
// ||||
// X1 -> Clock ||||
// ||||
// X2 -> Reset ||||
//
// YYYY
// Outputs 3 2 1 0

unsigned long TIMER0 = 0; // Define variable used for switch debounce

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {

in(X0); // Read input to shift register from X0


shift1.inputBit();

in(X1); // Shift Left on rising edge of input X1


timerOn(TIMER0, 10); // 10 ms switch debounce delay on X1 shift1.shiftLeft();

in(X2); // Reset the shift register value to zero if X2 = 1 shift1.reset();

shift1.bitValue(3); // Send bit 3 value to output Y3 out(Y3);

shift1.bitValue(2); // Send bit 2 value to output Y2 out(Y2);

shift1.bitValue(1); // Send bit 1 value to output Y1 out(Y1);

shift1.bitValue(0); // Send bit 0 value to output Y0 out(Y0);


}

Listing 24. Thanh ghi Shift dịch chuyển dữ liệu sang trái (Source: File > Examples >
plcLib > ShiftRotate > ShiftLeft)
Sự khác biệt chính trước hết là kết nối của đồng hồ (công tắc X1) với đầu vào shiftLeft, và
thứ hai là kết nối của các đầu ra song song với bit 3â € “0 của thanh ghi dịch chuyển. (Cái
sau cho phép dữ liệu được dịch chuyển sang bên phải để hiển thị ngay lập tức trên các đầu ra,
khi nó di chuyển sang bên trái).

12.2 Rotaing Data


Việc thêm kết nối phản hồi vào thanh ghi dịch chuyển của chúng tôi từ đầu ra đến đầu
vào cho phép dữ liệu được luân chuyển trong vòng lặp liên tục, như hình dưới đây

87
Hình 36. Thêm kết nối phản hồi làm cho dữ liệu được xoay sang phải hoặc sang trái
trong một vòng lặp liên tục.

Trên thực tế, kết nối phản hồi có thể được lấy từ bất kỳ bit đầu ra thuận tiện nào, do đó
tạo ra
mẫu bit lưu hành có độ rộng mong muốn bất kỳ. Ví dụ, bản phác thảo sau sử dụng thanh
ghi shift bit 12 như kết nối phản hồi với đầu vào nối tiếp (tức là bit thứ 4 từ bên trái), để
xoay một từ dữ liệu 4 bit rẽ phải..
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Shift register: Rotate data to the right

Connections:

Clock Input - switch connected to input X0 (Arduino pin A0)


Reset Input - switch connected to input X1 (Arduino pin A1)
Output - LED connected to output Y0 (Arduino pin 3)

Output - LED connected to output Y1 (Arduino pin 5)


Output - LED connected to output Y2 (Arduino pin 6)
Output - LED connected to output Y3 (Arduino pin 9)

Shift shift1(0x8000); // Create a shift register with initial value 0x8000

// (Leftmost 4 bits are rotated to the right)


// Outputs Y Y Y Y
3 2 1 0
//
Bit 1 1 1 1
// Positions
5 4 3 2
//
| | | | | |
// | |
X0 -> Clock -<--<--<--<--
//

// X1 -> Reset

unsigned long TIMER0 = 0; // Define variable used for switch debounce

88
setupPLC(); // Setup inputs and outputs
}

void loop() {

in(X0); // Rotate Right on rising edge of input X0

timerOn(TIMER0, 10); // 10 ms switch debounce delay on X0


shift1.shiftRight();
in(X1); // Reset the shift register value to zero if X1 = 1

shift1.reset();
shift1.bitValue(15); // Send bit 15 value to output Y3
out(Y3);

shift1.bitValue(14); // Send bit 14 value to output Y2


out(Y2);

shift1.bitValue(13); // Send bit 13 value to output Y1


out(Y1);

shift1.bitValue(12); // Send bit 12 value to output Y0


out(Y0);
}

Listing 25. Thanh ghi Shift xoay dữ liệu sang bên phải (Source: File > Examples >
plcLib > ShiftRotate >RotateRight)
Một bản phác thảo tương đương để xoay một từ dữ liệu 4 bit sang trái sẽ sử dụng bit 3 ( bit
thứ 4 từ bên phải) như kết nối phản hồi, như được hiển thị trong ví dụ sau.

89
Listing 26. Thanh ghi Shift xoay dữ liệu sang trái (Source: File > Examples > plcLib
> ShiftRotate > RotateLeft)

90
13 Làm việc với Analogue Signals
Lệnh inAnalog () đọc đầu vào tương tự. Điều này sau đó có thể được sử dụng để kiểm
soát liên tục giá trị đầu ra thay đổi, chẳng hạn như độ sáng của đèn LED, tốc độ của động
cơ hoặc vị trí của servo.Việc chia tỷ lệ đầu vào và đầu ra được thực hiện tự động bởi phần
mềm plcLib.
Biến toàn cục scanValue giữ giá trị đã nhập, nằm trong phạm vi 0-1023 cho một giá trị
tương tự đầu vào. Điều này được tự động điều chỉnh tỷ lệ trong phạm vi 0-255 hoặc 0-
179 khi được sử dụng để điều khiển PWM hoặc servo đầu ra, tương ứng.

13.1 Kiểm soát độ sáng của đèn LED bằng PWM


Liên kết lệnh inAnalog() với lệnh outPWM(), cho phép điều khiển đầu ra PWM từ
một đầu vào tương tự. Ví dụ, bản phác thảo sau đây đọc một chiết áp được kết nối với
đầu vào X0 và tạo ra dạng sóng xung lặp lại với chu kỳ nhiệm vụ thay đổi trên đầu ra
Y0.
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

PWM (Pulse Width Modulation) - Analogue control of a PWM output

Connections:

Input - potentiometer connected to input X0 (Arduino pin A0)


Output - LED connected to output Y0 (Arduino pin 3)

Software and Documentation:


void setup() {
setupPLC(); // Setup inputs and outputs

}
void loop() {

inAnalog(X0); // Read Analogue Input 0


outPWM(Y0); // Send to Output 0 as PWM waveform

Listing 27. Điều khiển tương tự của đầu ra PWM (Source: File > Examples > plcLib
> InputOutput >PWM)

13.2 Kiểm soát tốc độ và hướng của động cơ


Lá chắn động cơ Arduino dựa trên vi mạch điều khiển cầu H có sẵn trên thị trường, cho
phép tốc độ và hướng của tối đa hai động cơ DC được điều khiển. Một kết nối phần cứng
có thể được hiển thị bên dưới.

91
Figure 37. Lá chắn động cơ Arduino cho phép điều khiển tối đa hai động cơ.
Hai kênh động cơ có sẵn "Kênh A và Kênh B" và tấm chắn cũng hỗ trợ một
số lượng đầu nối đầu vào và đầu ra tương thích Tinkerkit (cộng với hai giao diện TWI / I2C
thì không xem xét ở đây). Hình ảnh trên cho thấy một chiết áp tuyến tính được kết nối với
chân X2 (A2), được sử dụng để điều khiển tốc độ động cơ thông qua PWM và một công tắc
nghiêng điều khiển hướng động cơ, được liên kết với chân X3 (A3).

Ví dụ sau đây điều khiển tốc độ và hướng của động cơ được kết nối với Kênh A.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Motor Channel A - Simple Motor Control on Arduino Motor Shield Channel A

Connections:

Input - Speed - potentiometer connected to input X2 (Arduino pin A2)


Input - Direction - switch connected to input X3 (Arduino pin A3)
Output - Channel A Direction (DIRA) - Arduino pin 12

Output - Channel A PWM (PWMA) - Arduino pin 3


Output - Channel A Brake (BRAKEA) - Arduino pin 9

Software and Documentation:


void setup() {
setupPLC(); // Setup inputs and outputs

// Turn off Channel A Brake


in(RUN);
out(BRAKEA); // Read RUN variable (0 = brake off)
}

void loop() {

// Control direction of motor


// Read Analog Input 2 and send to Channel A PWM
inAnalog(X2);
outPWM(PWMA); // Read from potentiometer connected to Analogue Input 2
}

92
Listing 28. Điều khiển động cơ đơn giản trên Arduino Motor Shield Kênh A (Source:
File > Examples > plcLib > Motor > MotorChannelA)

Lưu ý: Xem phần Động cơ của tệp ví dụ để có bản phác thảo tương đương để điều khiển
động cơ được kết nối đến Kênh B.
Lưu ý rằng một số biến được xác định trước có sẵn để đơn giản hóa việc mã hóa điều khiển
động cơ phần mềm càng nhiều càng tốt, như tóm tắt bên dưới:
· BRAKEA và BRAKEB bật hoặc tắt phanh trên mỗi kênh (0 = brake off).
· DIRA và DIRB đặt chiều thuận hoặc nghịch của mỗi động cơ.
· PWMA và PWMB kiểm soát tốc độ động cơ của các kênh liên quan.

93
14 Kiểm soát vị trí bằng Servos
Việc điều khiển một servo phức tạp hơn một chút, do nhu cầu làm việc với thư viện Servo
vốn là được cung cấp như một phần tiêu chuẩn của môi trường Arduino. OutServo() thay
thế lệnh outPWM() đã được sử dụng trước đó và được định nghĩa cục bộ, như được hiển thị
bên dưới..
#include <Servo.h>
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Single Servo - Controlling the position of a servo using a potentiometer

Connections:

Input - potentiometer connected to input X0 (Arduino pin A0)


Output - servo connected to output Y0 (Arduino pin 3)

Software and Documentation:


Servo servo1; // Create a servo object to control a single servo

extern int scanValue; // Link to scanValue defined in PLC library file

void setup() {

setupPLC(); // Setup inputs and outputs


void loop() {
inAnalog(X0); // Read potentiometer connected to input 0
outServo(servo1);
// Output to Servo 1 (connected to Output 0)
}
// The outServo function is defined locally
int outServo(Servo &ServoObj) {

ServoObj.write(map(scanValue, 0, 1023, 0, 179));


return(scanValue);

Listing 29. Một động cơ Servo (Source: File > Examples > plcLib > InputOutput >
ServoSingle)
Lưu ý: Xem phần InputOutput của tệp ví dụ để biết bản phác thảo điều khiển servo kép.

94
15 So sánh các giá trị tương tự
Các lệnh so sánh tương tự cung cấp chức năng tương đương với mạch so sánh điện tử, đưa
ra kết quả đúng / sai dựa trên tín hiệu nào trong hai tín hiệu tương tự được thử nghiệm lớn
hơn.

Hình 38. Một bộ so sánh 'kiểm tra' độ lớn tương đối của hai đầu vào tương tự
Biểu tượng mạch cho bộ so sánh điện tử có hình tam giác, với hai đầu vào tương tự ở bên
trái và đầu ra kỹ thuật số duy nhất ở bên trái. Một đầu ra cao được tạo ra nếu điện áp được
áp dụng cho đầu vào V + , đầu cuối lớn hơn thiết bị đầu cuối được kết nối với đầu vào V
thấp hơn (được gọi là đầu vào không đảo ngược và đầu vào đảo ngược, tương ứng). Nếu
không, sản lượng thấp sẽ được tạo ra.

15.1 So sánh các giá trị tương tự dựa trên phần mềm
So sánh các giá trị tương tự trong phần mềm là một quá trình gồm ba bước::
1. Nhập giá trị tương tự đầu tiên.

2. So sánh giá trị này với giá trị thứ hai.

3. Xuất kết quả so sánh ra đầu ra kỹ thuật số.

Hai biến thể có sẵn của thao tác so sánh là CompareGT() và CompareLT() để kiểm tra
liệu đầu vào có lớn hơn hay nhỏ hơn giá trị tham chiếu tương ứng hay không.
Ví dụ sau kiểm tra xem điện áp tương tự trên đầu vào X0 có lớn hơn điện áp trên đầu vào
X1 hay không, thiết lập đầu ra Y0 nếu điều này là đúng

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles


Comparator - Greater than test between two input pins

Connections:
Analogue Input - potentiometer connected to input X0 (Arduino pin A0)
Analogue Input - potentiometer connected to input X1 (Arduino pin A1)
Digital Output - LED connected to output Y0 (Arduino pin 3)

95
Software and Documentation: http://www.electronics-micros.com/software-hardware/plclib-
arduino/

*/

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
inAnalog(X0); // Read Analogue Input 0 compareGT(X1); // X0 > X1 ?

out(Y0); // Y0 = 1 if X0 > X1, Y0 = 0 otherwise

Listing 30. Kiểm tra lớn hơn giữa hai chân đầu vào bằng bộ so sánh (Source: File >
Examples >plcLib > AnalogCompare > GreaterThan)

Cũng có thể so sánh một đầu vào tương tự với một tham chiếu cố định, như được hiển thị
trong phần sau thí dụ.
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Comparator - Less than test between an input and a fixed threshold

Connections:

Analogue Input - potentiometer connected to input X0 (Arduino pin A0)


Digital Output - LED connected to output Y0 (Arduino pin 3)

Software and Documentation:


void setup() {
setupPLC(); // Setup inputs and outputs

}
void loop() {
inAnalog(X0); // Read Analogue Input 0
compareLT(threshold);
out(Y0); // X0 < 500?

Listing 31. Kiểm tra so sánh nhỏ hơn giữa đầu vào và ngưỡng cố định (Source: File >
Examples > plcLib > AnalogCompare > LessThanThreshold)

15.2 Một ứng dụng so sánh đơn giản


Trong ví dụ này, một cặp bộ so sánh được sử dụng để kiểm tra xem đầu vào tương tự có nằm
trên một ngưỡng trên (lớn hơn 3,5 V) hoặc dưới ngưỡng thấp hơn (nhỏ hơn 1,5 V), như hình
dưới đây.

96
Hình 39. Bộ so sánh ngưỡng kép cho biết đầu vào ở trên hay dưới 'cửa sổ' được phép.

Bộ so sánh trên làm cho đèn LED liên quan của nó sáng nếu điện áp đầu vào, V 1 lớn hơn
giá trị cố định ngưỡng 3,5 V. Ngược lại, bộ so sánh thấp hơn cho đầu ra nếu điện áp đầu
vào của nó nhỏ hơn ngưỡng điện áp 1,5 V. (Lưu ý cẩn thận cực tính của mỗi kết nối đầu
vào bộ so sánh với hiểu cách đạt được các bài kiểm tra 'lớn hơn' hoặc 'nhỏ hơn'.)
Một bản phác thảo tương đương được đưa ra bên dưới, sử dụng cả hai dạng lệnh so sánh
cùng nhau với các giá trị ngưỡng được tính toán dựa trên nguồn điện 5 V.
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Comparator - Maximum / minimum test using fixed threshold values

Connections:

Analogue Input - potentiometer connected to input X0 (Arduino pin A0)


Digital Output - 'High' LED connected to output Y0 (Arduino pin 3)
Digital Output - 'Low' LED connected to output Y1 (Arduino pin 5)

Software and Documentation:

http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

unsigned int lowLimit = 307; // Analogue lower threshold = 307


void setup() {
setupPLC(); // Setup inputs and outputs

}
void loop() {
inAnalog(X0); // Read Analogue Input 0
compareGT(highLimit);
out(Y0); // X0 > upper threshold?

inAnalog(X0); // Read Analogue Input 0


compareLT(lowLimit);
out(Y1); // X0 < lower threshold?
}

Listing 32. Kiểm tra bộ so sánh tối đa / tối thiểu sử dụng các giá trị ngưỡng cố định
(Source: File >Examples > plcLib > AnalogCompare > MaxMin)

97
16 Lập trình danh sách lệnh
Lập trình danh sách lệnh là một ngôn ngữ dựa trên văn bản, được sử dụng để mô tả các
chương trình PLC và là một trong năm các phương pháp được quy định bởi tiêu chuẩn quốc
tế IEC 61131-3, với các phương pháp khác là sơ đồ bậc thang , chức năng sơ đồ khối , biểu
đồ chức năng tuần tự và văn bản có cấu trúc .
Ví dụ về các lệnh trong danh sách hướng dẫn bao gồm đọc đầu vào, thực hiện các hoạt
động logic và kiểm soát đầu ra, mặc dù chi tiết về cú pháp lệnh có xu hướng khác nhau
giữa các nhà sản xuất. Một đóng tồn tại mối quan hệ giữa danh sách hướng dẫn và các
phương pháp thiết kế đồ họa, bao gồm sơ đồ bậc thang và sơ đồ khối chức năng, như
minh họa sau.

Figure 40. Tồn tại sự tương đương gần nhau giữa danh sách hướng dẫn và các
phương pháp thiết kế đồ họa.
Danh sách lệnh đôi khi được cho là 'ngôn ngữ cấp thấp', gợi nhớ đến ngôn ngữ hợp ngữ,
nhưng 'mức thấp hơn một chút' (so với phương pháp đồ họa) có thể chính xác hơn.
Lưu ý: Danh sách lệnh không liên quan trực tiếp đến bộ vi xử lý đang chạy chương trình,
không giống như assembly ngôn ngữ hoặc mã máy tương đối gần của nó có khả năng đã
được triển khai bằng ngôn ngữ cấp cao như C hoặc C ++.
Danh sách lệnh có thể được sử dụng như một phương thức nhập chương trình theo đúng
nghĩa của nó, mặc dù điều này ít phổ biến hơn trong PLC hiện đại, có sẵn trên thị trường.

98
17 Sơ đồ khối chức năng
Một sơ đồ khối chức năng cho phép một hệ thống điện tử được biểu diễn dưới dạng một
sơ đồ khối, có thể sau đó được dịch thành một bản phác thảo Arduino dựa trên văn bản
theo cách thông thường

Figure 41. Một sơ đồ khối có thể đại diện cho nhiều loại hệ thống điện tử..
Sơ đồ khối chức năng thường được tạo thành từ một loạt các hộp (thường có
hình dạng chữ nhật), có đầu vào ở bên trái và đầu ra ở bên phải. Các đầu vào
bên ngoài thường được hiển thị ở phía bên trái của sơ đồ và kết quả đầu ra ở
bên phải. Kết nối giữa các phần tử này cho phép các tín hiệu tiến triển nói
chung là từ trái sang phải, mặc dù trong một số trường hợp, các tín hiệu phản
hồi, cũng có thể xuất hiện, trở lại tín hiệu trở lại giai đoạn trước đó để xử lý
thêm.
Một loạt các loại chức năng được hỗ trợ, bao gồm cổng logic , bộ so sánh ,
chốt , thời gian sự chậm trễ và máy phát dạng sóng .

Hình 42. Nhiều ký hiệu có thể được sử dụng để biểu diễn các mạch điện tử.

17.2 Xây dựng hệ thống làm việc


Kết nối giữa các khối có thể sử dụng nhiều loại tín hiệu khác nhau, được biểu diễn bằng
máy tính như một kiểu dữ liệu tương đương. Ví dụ, một sơ đồ logic đơn giản, bao gồm
các cổng logic, chuyển các giá trị bit đơn (0/1) giữa các phần tử. Một hệ thống kỹ thuật số

99
phức tạp hơn có thể yêu cầu một số tham số được chỉ định dưới dạng số nguyên (có dấu
hoặc không dấu) hoặc dưới dạng số dấu phẩy động (các số có thể nhận bất kỳ giá trị nào).
Rõ ràng, phải cẩn thận để không liên kết các tín hiệu không tương thích khi tạo kết nối.
Tuy nhiên, lưu ý rằng phần mềm được thiết kế để 'tha thứ' nhất có thể. Ví dụ, một đầu vào
tương tự có thể được kết nối trực tiếp với đầu ra PWM hoặc với servo mà không gặp sự
cố và phần mềm sẽ tự động chia tỷ lệ các giá trị.
Cần có hiểu biết tốt về cách phần mềm 'giải mạch' để viết một văn bản tương đươngphác
thảo dựa trên. Phần Khái niệm nâng cao giải thích cách phần mềm sử dụng biến
scanValue để giải quyết từng bậc của một sơ đồ bậc thang, tiến triển từ trái sang phải qua
từng bậc và từ trên xuống dưới cùng trong một trình tự lặp lại gọi là chu kỳ quét. Trên
thực tế, đầu ra của mỗi lệnh là được lưu trữ tạm thời trong biến scanValue và sau đó được
sử dụng lại làm đầu vào đầu tiên cho lệnh tiếp theo.
Điều này hoạt động tốt cho các mạng đơn giản, nhưng có thể cần phải lưu trữ các kết quả
tạm thời để sử dụng lại sau này trong mạch phức tạp hơn.
Quá trình giải quyết một hệ thống được biểu diễn dưới dạng sơ đồ khối tương tự như sơ
đồ bậc thang. Trong tóm tắt, nhằm mục đích làm việc từ trái sang phải và từ trên xuống
dưới. Cố gắng cho phép biến scanValue tự động chuyển tín hiệu giữa các khối hệ thống,
bất cứ khi nào có thể. Bạn có thể sử dụng nhiều bên trái để phải 'vượt qua' â € “giống như
'bậc thang' của sơ đồ bậc thang - và kết quả tạm thời có thể được lưu trữ và sau này truy
xuất, nếu cần thiết. Hai ví dụ sau đây chứng minh việc áp dụng phương pháp thiết kế này
với một số mạch tương đối đơn giản.

17.2 Ứng dụng 1: Một báo động đơn giản


Một mạch cảnh báo đơn giản có thể được xây dựng bằng cách sử dụng cổng HOẶC và
chốt Cài đặt lại, như được minh họa bởi minh họa sau đây.

Hình 43. Một mạch cảnh báo đơn giản với 3 cảm biến đầu vào, một đầu ra cảnh báo có
chốt và một đầu vào reset.
Báo động có ba cảm biến, được kết nối với cổng OR 3 đầu vào. Nếu một hoặc nhiều cảm
biến
trở nên hoạt động, điều này làm cho đầu ra của cổng logic tăng cao, do đó đặt chốt và
kích hoạt đầu ra cảnh báo (Q). Báo thức sẽ vẫn hoạt động do chốt, ngay cả khi bản gốc
đầu vào cảnh báo bị xóa, nhưng có thể bị hủy theo cách thủ công bằng cách kích hoạt đầu
vào Đặt lại.
Một bản phác thảo tương đương được hiển thị bên dưới.

100
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Simple Alarm - A 3-input alarm circuit with a latched output and manual Reset input

Connections:
Input - Sensor 0 - switch connected to input X0 (Arduino pin A0)
Input - Sensor 1 - switch connected to input X1 (Arduino pin A1)
Input - Sensor 3 - switch connected to input X2 (Arduino pin A2)
Input - Reset Alarm - switch connected to input X3 (Arduino pin A3)
Output - Alarm Output - LED connected to output Y0 (Arduino pin 3)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
in(X0); // Read Sensor 0 (Input 0) orBit(X1); // OR with Sensor 1 (Input
1)
orBit(X2); // OR with Sensor 2 (Input 2)

// Sensor result is used as Set input to latch


latch(Y0, X3); // Latch command, Q = Output 0, Reset = Input 3 }

Listing 33. Một cảnh báo đơn giản (Source: File > Examples > plcLib > Applications
> SimpleAlarm)

17.3 Ứng dụng 2: Báo động bằng nhấp nháy “ Armed “ LED

Ví dụ này dựa trên ứng dụng trước đó, nhưng sử dụng bộ đếm thời gian chu kỳ để tạo ra
nhấp nháy Đầu ra có trang bị khi cảnh báo đang hoạt động, nhưng không được kích hoạt. Sơ
đồ mạch được hiển thị bên dưới.

101
Hình 44. Một cảnh báo cải tiến tạo ra một xung trên Y1 khi cảnh báo được trang bị
nhưng không được kích hoạt.

Hoạt động của cổng OR và chốt Cài đặt lại giống như cảnh báo cơ bản đã mô tả trước
đây. Các bộ tạo xung (hoặc bộ định thời chu kỳ) được bật khi đầu vào Đặt lại không hoạt
động (sử dụng cổng Không được kết nối với đầu vào X3) và được định cấu hình để tạo ra
một xung ngắn có thời lượng 0,1 giây sau mỗi 2 giây. Đầu ra Q của bộ hẹn giờ chu kỳ
được kết nối với đầu ra Được trang bị (Y1) qua cổng AND, cổng này sẽ vô hiệu hóa đầu
ra Armed nếu cảnh báo chính đã được kích hoạt. Danh sách phần mềm tương đương là
hiển thị bên dưới

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Alarm with Armed Status LED - 3 input alarm controller with flashing Armed LED
Connections:

Input - Sensor 0 - switch connected to input X0 (Arduino pin A0)


Input - Sensor 1 - switch connected to input X1 (Arduino pin A1)
Input - Sensor 3 - switch connected to input X2 (Arduino pin A2)
Input - Reset Alarm - switch connected to input X3 (Arduino pin A3) Output - Alarm Output - LED connected
to output Y0 (Arduino pin 3)
Output - Armed Output - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

// Timer Variables
unsigned long AUX0 = 0; // Pulse low timer variable unsigned long AUX1 = 0; // Pulse high
timer variable

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {

in(X0); // Read Sensor 0


orBit(X1); // OR with Sensor 1 orBit(X2); // OR with Sensor 2

// Set input to latch taken from sensors latch(Y0, X3); // Latch command, Q = Output 0,
Reset = Input 3
inNot (X3); // Enable input (0 = enable) timerCycle(AUX0, 1900, AUX1, 100); // Repeating pulse 1.9 s low,
0.1 s high. andNotBit(Y0); // Disable armed pulse if alarm is triggered

out(Y1); // Armed pulse on output Y0 }

Listing 34. Báo động với đèn LED trạng thái được trang bị (Source: File >
Examples> plcLib > Applications > AlarmWithArmedStatus)
102
17.4. Tạo các khối chức năng do người dùng xác định
Bạn có thể mở rộng phần mềm plcLib bằng cách xác định một hoặc nhiều hàm dựa trên
văn bản (hoặc các khối chức năng để sử dụng thuật ngữ dành riêng cho PLC) ‘cục bộ’
trong bản phác thảo, có thể hữu ích nếu một tính năng được yêu cầu không được hỗ trợ bởi
phần mềm, theo tiêu chuẩn. Mọi hàm do người dufng tạo sau đó có thể được gọi từ chương
trình, hoạt động giống như các lệnh cài sẵn
Lưu ý: Để tạo các lệnh tùy chỉnh của riêng bạn, bạn sẽ cần phải tự tin một cách hợp lý với C
/ C ++ lập trình và có kiến thức cơ bản về các hàm Arduino . Bạn cũng sẽ cần phải làm quen
với phần Khái niệm Nâng cao và Sử dụng Biến trong Chương trình của Hướng dẫn Sử dụng.
Ví dụ sau đây gọi một hàm do người 103ung xác định để tính giá trị trung bình của hai
đầu vào tương tự, sử dụng kết quả để điều khiển độ sáng của đèn LED
#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Average – Create a custom function to calculate the mean of two analogue inputs
Connections:
Input - Potentiometer connected to analogue input X0 (Arduino pin A0)
Input - Potentiometer connected to analogue input X1 (Arduino pin A1)
Output - LED connected to output Y0 (Arduino pin 3)

Software and Documentation:


http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

unsigned int reading1;


unsigned int reading2;
extern int scanValue; // Link to scanValue defined in PLC library file

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
reading1 = inAnalog(X0); // Read analogue Input 0 reading2 = inAnalog(X1); // Read
analogue Input 1
scanValue = average(reading1, reading2); // Set scanValue to average reading outPWM(Y0); // Send to Output 0

// User defined function to calculate


// the average of two values

unsigned int average(unsigned int value1, unsigned int value2) {


int result;
result = (value1 + value2) / 2;
return result; }

103
Listing 35. Tạo khối chức năng do người dùng xác định (Source: File > Examples >
plcLib > Function Block > Average)
Bản phác thảo trên đọc lặp lại hai đầu vào tương tự, lưu trữ các giá trị này trong hai người
dùng xác định biến, đọc1 và đọc2. Chúng được 'chuyển' cho hàm Average (), hàm này
tìm giá trị trung bình của read1 và read2, trả kết quả về chương trình chính. Kết quả trả
về này được lưu trữ trong biến scanValue, tự động cung cấp giá trị làm đầu vào cho lệnh
tiếp theo trong chu kỳ quét. Định nghĩa chức năng thực tế được tìm thấy ở cuối danh
sách
Note: The scanCycle variable must be initially defined as an external variable, as it is
used internally by the plcLib library software.

104
18 Biểu đồ hàm tuần tự
Biểu đồ chức năng tuần tự (SFC), cho phép PLC di chuyển qua một loạt các bước dưới sự
điều khiển của chương trình.
Quá trình chuyển đổi từ bước này sang bước khác xảy ra nếu (các) điều kiện chuyển đổi
được đáp ứng và mỗi bước có thể tùy chọn sản xuất một hoặc nhiều đầu ra. Như tên cho
thấy, SFC thường được đại diện trong dạng sơ đồ, như được hiển thị trong ví dụ sau.

Hình 45. Một chương trình ba bước đơn giản được biểu diễn dưới dạng biểu đồ
chức năng tuần tự.

18.1 Tạo chuỗi


SFC cho phép hệ thống dựa trên trình tự được biểu diễn dưới dạng ngắn gọn. Mỗi bước
trong trình tự là được hiển thị trong một hình hộp chữ nhật ở bên trái, với bước đầu tiên có
đường viền kép. Điều kiện chuyển tiếp được hiển thị bên cạnh các đường ngang giữa các
bước liền kề trong trình tự. Một bước hoạt động có thể tùy chọn sản xuất một hoặc nhiều
đầu ra và những đầu ra này được hiển thị trong một hộp ở bên phải của bươc.
Trong trường hợp trên, hệ thống sẽ tự động bắt đầu ở bước Khởi động. Tiến trình đến
Bước 1 xảy ra khi đầu vào X0 được nhấn, làm cho đầu ra Y0 được hiển thị. Với Y0 được
hiển thị, việc nhấn đầu vào X1 gây ra hệ thống chuyển sang Bước 2, kích hoạt đầu ra Y1
Một bản phác thảo tương đương được đưa ra dưới đây..

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

Simple Sequence - A Three step sequence with push button control

Connections:
Input - switch connected to input X0 (Arduino pin A0)
Input - switch connected to input X1 (Arduino pin A1) Output - LED connected to output
Y0 (Arduino pin 3)
Output - LED connected to output Y1 (Arduino pin 5)

Software and Documentation:

105
http://www.electronics-micros.com/software-hardware/plclib-arduino/

Sequential Function Chart

|=========|
| START |
|=========|
|
-|-- X0
|
|----|----| |------|
| STEP1 |----| Y0 |
|---------| |------|
|
-|-- X1
|
|----|----| |------|
| STEP2 |----| Y1 |
|---------| |------|

The Start step is active when the system is switched-on or reset


Press X0 to activate Step 1, displaying Y0
Next, press X1 to activate Step 2, displaying Y1

*/

// Define state names

unsigned int START = 1; // Start-up state (START = 1 to automatically start here) unsigned int STEP1 = 0; // Step 1
unsigned int STEP2 = 0; // Step 2

void setup() {
setupPLC(); // Setup inputs and outputs
}

void loop() {
// Do state transitions

in(START); // Read Start-up state


andBit(X0); // AND with Step 1 transition input set(STEP1); // Activate Step 1

reset(START); // Cancel Start-up state

in(STEP1); // Read Step 1


andBit(X1); // AND with Step 2 transition input set(STEP2); // Activate Step 2

reset(STEP1); // Cancel Step 1

// Display current state


in(STEP1);

106
out(Y0); // Send to Output 0

in(STEP2);
out(Y1); // Send to Output 1

Listing 36. Một chuỗi đơn giản (Source: File > Examples > plcLib >
SequentialFunctionChart > SimpleSwitchSequence)
Danh sách trên bao gồm ba phần chính:
1: Các biến được định nghĩa để đại diện cho từng bước trong chuỗi.

// Define state names

unsigned int START = 1; // Start-up state (START = 1 to automatically start here) unsigned int STEP1 = 0; // Step 1
unsigned int STEP2 = 0; // Step 2

Một bước hoạt động nếu biến được kết hợp của nó bằng 1 và không hoạt động khi bằng 0.
Do đó, các điều kiện ban đầu ở power-up hoặc reset được xác định dựa trên các giá trị
biến được phân bổ ở trên.
2: Các bước được kích hoạt theo một trình tự được xác định trước, khi mỗi điều kiện
chuyển tiếp xảy ra.

// Do state transitions

in(START); // Read Start-up state


andBit(X0); // AND with Step 1 transition input set(STEP1); // Activate Step 1

reset(START); // Cancel Start-up state

in(STEP1); // Read Step 1


andBit(X1); // AND with Step 2 transition input set(STEP2); // Activate Step 2

reset(STEP1); // Cancel Step 1

Lưu ý rằng các điều kiện chuyển đổi được ANDed với trạng thái hiện tại, điều này đảm bảo
đầu vào chuyển đổi là chỉ được chấp nhận khi bước được liên kết của nó đang hoạt động.
Chương trình cũng nên hủy bước trước đó khi bước tiếp theo được kích hoạt và đạt được
điều này bằng cách sử dụng lệnh chốt set () và reset (), ở trên trích xuất.
3: (Các) đầu ra được tạo ra dựa trên (các) bước hoạt động
// Display current state

in(STEP1);
// Send to Output 0
out(Y0);
in(STEP2);
// Send to Output 1
out(Y1);

107
Lưu ý: Chương trình đơn giản này có một đầu ra duy nhất cho mỗi bước. Một hệ thống
phức tạp hơn, chẳng hạn như bộ điều khiển đèn giao thông (xem sau), có thể yêu cầu 'ánh
xạ' tùy chỉnh giữa các bước và đầu ra thường được thực hiện với các hàm Boolean OR.
Ví dụ trên có thể dễ dàng được mở rộng để tạo một chuỗi lặp lại, như hình dưới đây.

Figure 46 . Một chuỗi lặp lại đơn giản (Source: File > Examples > plcLib >
SequentialFunctionChart > RepeatingSwitchSequence)
Hệ thống khởi động trong bước khởi động với đầu ra Y0 đang hoạt động. Nhấn X0 sẽ
kích hoạt Bước 1, sau đó đầu vào X1, X2 và X3 gây ra tiến trình lặp lại qua các Bước 1 -
3, với đầu ra Y1 - Y3 được kích hoạt, tương ứng.
Lưu ý: Danh sách chương trình đã được bỏ qua trong phần còn lại của phần này vì lợi ích
ngắn gọn, nhưng có sẵn từ phần Ví dụ trong Arduino IDE, với plcLib được cài đặt..

18.2 Phân nhánh và hội tụ

Một nhánh song song cho phép một số bước được kích hoạt đồng thời, như thể hiện trong
hình sau hình minh họa.

Hình 47. Kích hoạt một số bước đồng thời với một nhánh song song (Source: File
>Examples > plcLib> SequentialFunctionChart > ParallelSwitchBranch)
Bước Bắt đầu được kích hoạt ban đầu với đầu ra Y0 được bật. Nhấn đầu vào X0 đồng
thời kích hoạt
Bước 1 - 3, hiển thị đầu ra Y1 - Y3.
Một nhánh song song có thể được theo sau bởi sự hội tụ đồng thời, như hình dưới đây.

108
Figure 48. Sự hội tụ đồng thời theo một nhánh song song (Source: File > Examples >
plcLib > SequentialFunctionChart > ParallelSwitchBranchConverge)
Lưu ý: Mọi bước trước đó phải được hủy bỏ sau khi hội tụ đồng thời.
Một nhánh chọn lọc cho phép đưa ra quyết định trắc nghiệm trong đó một bước duy nhất
được kích hoạt từ nhiều tùy chọn khả thi, như được hiển thị bên dưới.

Hình 49. Một nhánh chọn lọc kích hoạt một bước duy nhất từ một loạt các tùy chọn
(Source: File > Examples > plcLib > SequentialFunctionChart > SelectiveSwitchBranch)
Một nhánh chọn lọc có thể được theo sau bởi một hội tụ, như hình dưới đây.

Figure 50. Một nhánh chọn lọc theo sau là hội tụ (Source: File > Examples > plcLib
> SequentialFunctionChart > SelectiveSwitchBranchConverge)
Phần tiếp theo thảo luận về việc sử dụng độ trễ để tạo ra các trình tự dựa trên thời gian và
sự phát triển của các ứng dụng dựa trên SFC đơn giản..

109
19 Phát triển các ứng dụng dựa trên SFC định thời
Phần trước đã giới thiệu các khái niệm cơ bản liên quan đến Biểu đồ chức năng tuần tự
(SFC), nhưng với chuyển đổi giữa các bước được thực hiện bởi các lần nhấn công tắc. Phần
này giới thiệu việc sử dụng on-delay bộ hẹn giờ để tạo chuyển tiếp theo thời gian giữa các
bước và sau đó phát triển một số đơn giản dựa trên SFC các ứng dụng.

19.1 Chuyển đổi cơ sở thời gian


Đầu ra của bộ hẹn giờ trễ sẽ hoạt động (tức là bằng 1) sau khi đầu vào cho bộ định thời
liên tục hoạt động trong một thời gian xác định trước, như hình dưới đây

Figure 51. Một thời gian trễ tạo ra sự kích hoạt trễ của tín hiệu đầu vào.
Quá trình chuyển đổi dựa trên công tắc hiện tại có thể được chuyển đổi thành chuyển đổi
tương đương dựa trên thời gian chỉ bằng cách thay thế chuyển đổi quá trình chuyển đổi
bằng bộ hẹn giờ trễ, như được hiển thị trong phần trích xuất chương trình sau đây.

Trong trường hợp này, trạng thái Khởi động sẽ tự động được đặt thành 1 sau khi máy tính
được bật hoặc đặt lại. Điều này bật bộ đếm thời gian bắt đầu đếm (sử dụng biến người
dùng DELAY0). Sau 2 giây đồng hồ đầu ra thay đổi thành 1, làm cho bước tiếp theo
trong trình tự được kích hoạt và bước trước đó đã hủy bỏ
Biểu đồ chức năng tuần tự dựa trên thời gian đơn giản được hiển thị bên dưới.

Figure 52. Một hệ thống dựa trên thời gian đơn giản được biểu diễn dưới dạng biểu đồ
chức năng tuần tự
Danh sách phần mềm tương đương được đưa ra dưới đây

110
111
Listing 37. Một trình tự thời gian đơn giản (Source: File > Examples > plcLib >
SequentialFunctionChart > SimpleTimedSequence)

Sau khi đề cập đến các yếu tố chính của biểu đồ chức năng tuần tự, các phần sau sẽ phát
triển một số ứng dụng dựa trên SFC đơn giản.

19.2. Ứng dụng 1: Điều khiển đèn giao thông


Ứng dụng đầu tiên trình bày trình tự thời gian cho một bộ đèn giao thông (Vương quốc
Anh), bao gồm trạng thái khởi động ban đầu, như được hiển thị bằng biểu đồ chức năng
tuần tự sau.

Hình 53. Trình tự cho một bộ đèn giao thông (UK).

Bản phác thảo liên quan được đưa ra bên dưới.

112
113
Danh sách 38. Đèn giao thông Vương quốc Anh (Source location: File > Examples >
plcLib > Applications> SingleTrafficLight)

Lưu ý việc sử dụng các hướng dẫn logic tổ hợp ở cuối danh sách ở trên, để tạo 'ánh xạ' giữa
các bước trình tự và kết quả đầu ra được tạo. Do đó, đèn LED Đỏ được hiển thị nếu Bước
1 hoặc 2 đang hoạt động, Màu hổ phách được hiển thị trong Bước 2 hoặc 4, v.v. Kỹ thuật
tương tự này được sử dụng trong ví dụ tiếp theo.

19.3. Ứng dụng 2: Màn hình ánh sáng chạy


Trình tự hiển thị đèn chạy đơn giản mang lại ấn tượng trực quan khi di chuyển một hoặc
nhiều đèn LED chiếu sáng luân phiên sang trái và phải, như được minh họa trong bản phác
thảo sau.

114
115
116
117
Danh sách 39. Màn hình ánh sáng chạy(Source: File > Examples > plcLib > Applications
> RunningLightDisplay)

20. Văn bản có cấu trúc


Phần mềm được phát triển để sử dụng thư viện PLC có thể kết hợp nhiều câu lệnh chương
trình tiêu chuẩn, chẳng hạn như phép gán biến, tính toán và chức năng do người dùng xác
định, cộng với nhiều cấu trúc chương trình, bao gồm các quyết định và vòng lặp.

Khả năng viết mã phần lớn bị giới hạn bởi trí tưởng tượng của bạn - và tất nhiên là kiến
thức về lập trình C / C ++. Tuy nhiên, có một số lưu ý, bạn nên hiểu rõ về hoạt động bên
trong của phần mềm plcLib và cách sử dụng các biến của nó trước khi cố gắng phát triển
các chương trình văn bản có cấu trúc của riêng bạn.
Lưu ý: Rất nhiều thông tin liên quan đến lập trình Arduino có sẵn trực tuyến, bao gồm các
trang Tham khảo và Ví dụ về Arduino.

118
20.1 Sử dụng cấu trúc chương trình
Bạn có thể sử dụng nhiều cấu trúc chương trình khác nhau trong bản phác thảo của mình,
nhưng cần cẩn thận để tránh tạm dừng chu kỳ quét PLC, vì điều này sẽ làm ngừng việc xử
lý bất kỳ tác vụ nào khác.
Cấu trúc chương trình có sẵn bao gồm: -
• if – thực thi có điều kiện
• if ... else – thực hiện có điều kiện của một phần chính hoặc một phần thay thế, dựa
trên một điều kiện logic đã được kiểm tra
• do ... while – lặp lại một phần trong khi một điều kiện là đúng. (Kiểm tra ở cuối, vì
vậy loại vòng lặp này luôn chạy ít nhất một lần, ngay cả khi điều kiện kiểm tra ban
đầu là sai.)
• while – lặp lại một phần trong khi một điều kiện là đúng. (Thử ở khi bắt đầu, do đó,
loại vòng lặp này có thể hoàn toàn không chạy nếu thử nghiệm ban đầu là sai.)
• for – lặp lại một phần một số lần cố định, với biến vòng lặp tiến trình thông qua một
chuỗi giá trị được xác định trước.
• Switch case – thực hiện một phần duy nhất, được chọn từ một loạt các tùy chọn

Ví dụ, bản phác thảo sau đây đọc đầu vào kỹ thuật số X0. Sau đó, nó sử dụng câu lệnh if,
dựa trên trạng thái của đầu vào kỹ thuật số, để đọc có điều kiện đầu vào tương tự, sử dụng
kết quả này để điều khiển độ sáng của đèn LED.

Danh sách 40. Sử dụng lệnh IF để điều khiển có điều kiện đầu ra PWM (Source: File >
Examples > plcLib > StructuredText > If)

119
Bản phác thảo trên cho phép thay đổi độ sáng của đèn LED, nhưng chỉ khi công tắc được
nhấn. Vào những lúc khác, giá trị PWM đã đặt trước đó được sử dụng, có tác dụng như một
bộ điều chỉnh độ sáng 'có thể lập trình'.

Một loạt các ví dụ khác có sẵn từ cùng một thư mục như ví dụ trên, với mỗi ví dụ minh họa
một cấu trúc điều khiển khác nhau.

21. Các khái niệm nâng cao


Phần này giải thích hoạt động bên trong của phần mềm plcLib. Sự hiểu biết về những khái
niệm này không cần thiết đối với lập trình cơ bản, nhưng có thể hữu ích khi phát triển các
ứng dụng nâng cao hơn hoặc để hiểu tại sao mọi thứ không hoạt động tốt như bạn mong
đợi.

21.1. Cách phần mềm hoạt động


PLC hoạt động bằng cách đọc lặp lại các đầu vào, thực hiện các phép tính, sau đó gửi kết
quả đến các đầu ra. Quá trình này được gọi là chu kỳ quét. Một ứng dụng dựa trên sơ đồ
bậc thang điển hình được 'quét' từng bậc một, từ trái sang phải, bắt đầu từ bậc trên cùng và
làm việc dần dần xuống dưới. Quá trình này lặp lại liên tục.

Hình 54. Mỗi hàng được quét trong một quá trình lặp lại như một phần của chu kỳ quét.

Mỗi bậc của bậc thang có thể được coi là một quá trình song song, quá trình này nhận được
phần riêng của nó về thời gian của bộ xử lý khi chu kỳ quét lặp đi lặp lại. Do đó, các ứng
dụng dựa trên PLC thể hiện khả năng xử lý song song đơn giản, nhưng không cần sử dụng
đến các kỹ thuật lập trình nâng cao.

Đối với hoạt động cơ bản, phần mềm PLC sử dụng một biến duy nhất được gọi là scanValue
để lưu giữ kết quả tính toán đang chạy của nó khi mỗi nhánh được giải quyết. Hãy xem xét
đoạn mã sau để xem cách này hoạt động như thế nào đối với các giá trị bit đơn:

Lệnh đầu vào bit đơn in(X0) đọc chân đầu vào kỹ thuật số X0 và lưu trữ kết quả của nó
trong biến scanValue là 1 hoặc 0. Lệnh xuất bit tiếp theo out(Y0) chỉ cần đọc biến
scanValue và gửi giá trị này đến chân đầu ra kỹ thuật số Y0. Quá trình này lặp lại khi mỗi
bậc của sơ đồ bậc thang được tính toán, với scanValue được khởi tạo, cập nhật liên tục và
sau đó bị loại bỏ khi chương trình logic bậc thang thực thi.

120
Quy trình tương tự đối với đầu vào tương tự, được đọc từ bộ chuyển đổi tương tự sang kỹ
thuật số dưới dạng giá trị 10 bit trong dải 0-1023 bằng lệnh inAnalog () - như được minh
họa bằng đoạn mã sau.

Cùng một biến scanValue được sử dụng để giữ giá trị tương tự này, đây không phải là vấn
đề vì biến thực sự là một kiểu biến số nguyên không dấu. Phần mềm plcLib tự động xử lý
tỷ lệ của bất kỳ đầu ra 'tương tự' nào, vì vậy lệnh outPWM () được chia phạm vi 0-255 (nhị
phân 8 bit), trong khi lệnh outServo () sẽ sử dụng giá trị trong phạm vi 0-179 (đại diện cho
góc quay 180 °).

Phần tiếp theo giải thích cách sử dụng biến scanValue đã đề cập ở trên và thảo luận về các
ứng dụng có thể có của biến do người dùng tạo trong bản phác thảo.

21.2 Sử dụng biến trong chương trình


Phần này xem xét một số ứng dụng của các biến trong bản phác thảo của người dùng, bắt
đầu bằng biến scanValue, theo dõi kết quả tính toán hiện tại khi chu kỳ quét được thực
hiện. Việc tạo các biến do người dùng định nghĩa sau đó sẽ được thảo luận, cuối cùng dẫn
đến việc áp dụng các biến do người dùng định nghĩa để giải quyết các mạch logic nhiều
nhánh, phức tạp.

21.2.1 Sử dụng biến scanValue


Trước đây, người ta đã thấy rằng scanValue được phần mềm plcLib sử dụng nội bộ khi chu
trình quét PLC được thực thi lặp đi lặp lại. Tuy nhiên, biến này không có sẵn trực tiếp trong
các chương trình người dùng, vì nó chỉ được xác định bên trong tệp tiêu đề plcLib (nó được
cho là 'nằm ngoài phạm vi' bên trong bản phác thảo của bạn). Bạn có thể tùy chọn cung cấp
scanValue bằng cách xác định nó là một biến bên ngoài, như được hiển thị trong ví dụ sau.

121
Listing 41. Làm cho biến scanValue có sẵn cho nhiều thư viện (Source: File > Examples
> plcLib > InputOutput > ServoSingle)

Để thay thế cho cách tiếp cận trên, hướng dẫn plcLib có thể tùy chọn trả lại giá trị
scanValue hiện tại cho một biến người dùng đã xác định trước đó (chỉ chính xác tại điểm
cụ thể đó trong chu kỳ quét). Nội dung của một biến do người dùng xác định cũng có thể
được sử dụng làm 'đầu vào' cho lệnh plcLib, thay cho đầu vào hoặc đầu ra trực tiếp từ một
chân được đặt tên. Ví dụ sau minh họa một số khả năng.

Listing 42. Trả lại scanValue cho một biến do người dùng xác định (Source: File >
Examples > plcLib > Variables > LachCommandVariables)

Những điều cần lưu ý ở trên là việc lưu biến scanValue trong một biến do người dùng xác
định (AUX1 = in (X1);), và cả việc sử dụng tên biến thay cho tên pin trong các lệnh plcLib
khác.

122
21.3. Làm việc với các biến tùy chỉnh
Khi đề cập đến các tên như X0, X1, Y0, AUX0, AUX1, trong danh sách trước. bạn có thể
tự hỏi làm thế nào phần mềm 'biết' liệu bạn đang đề cập đến tên ghim hay nội dung của một
biến do người dùng xác định? Câu trả lời là tất cả các tên pin (X0, X1 và Y0) được xác
định bên trong bởi phần mềm plcLib là các biến số nguyên có dấu, trong khi các biến do
người dùng xác định trong chương trình trên (AUX0 và AUX1) thuộc loại biến không dấu.
Phần mềm plcLib thực sự có ít nhất hai phiên bản của mỗi lệnh và trình biên dịch chọn
phiên bản thích hợp dựa trên kiểu biến được cung cấp (đây được gọi là quá tải hàm).

Chỉ cần nhớ chỉ định các biến kiểu số nguyên do người dùng xác định là số nguyên không
dấu (16-bit) hoặc dài không dấu (32-bit) để tránh nhầm lẫn giữa biến người dùng và tên
pin.

21.4. Sử dụng các biến với mạch logic phức tạp

123
Listing 43. Giải quyết logic phức tạp với các biến người dùng (Source: File > Examples >
plcLib > Variables > ComplexLogic)

Ví dụ trên trước tiên giải quyết nhánh trên của mạch logic và sau đó lưu trữ (hoặc 'đầu ra')
đây là kết quả tạm thời cho một biến do người dùng xác định - out (AUX0) ;. (Dòng này
có thể đã được bỏ qua hoàn toàn bằng cách viết lại dòng trước là AUX0 = andNotBit (X1)
;.) Sau đó, nhánh thứ hai được giải quyết và kết quả từ nhánh đầu tiên HOẶC với kết quả
tạm thời trước đó - orBit(AUX0) ;.
Một giải pháp thay thế cho cách tiếp cận 'biến người dùng' được thảo luận ở trên là áp dụng
các lệnh logic khối, sẽ được thảo luận trong phần tiếp theo.

22. Lưu trữ và Logic dựa trên ngăn xếp


Phiên bản 1.0 của phần mềm plcLib bổ sung khả năng tạo và sử dụng ngăn xếp dựa trên
phần mềm để lưu trữ tạm thời và truy xuất các giá trị bit đơn. Khả năng này có thể được
kết hợp với các lệnh logic khối, để đơn giản hóa giải pháp của các mạng phức tạp dựa trên
đại số Boolean - nhưng không cần tạo các biến người dùng riêng lẻ để lưu trữ tạm thời, như
đã thảo luận trước đây.
Ngăn xếp là một vùng bộ nhớ đặc biệt có thể được sử dụng để lưu trữ và truy xuất dữ liệu
tạm thời thông tin được lưu trữ bằng cách đẩy vào ngăn xếp và sau đó được truy xuất bằng
cách bật ra từ ngăn xếp. Thông tin được lưu trữ gần đây nhất luôn là thông tin được xóa
đầu tiên, do đó, ngăn xếp hoạt động như một kho lưu trữ cuối cùng vào trước.

Hình 55. Sử dụng ngăn xếp làm nơi lưu trữ dữ liệu cuối cùng vào trước xuất trước.

Một phép tương tự hữu ích để hỗ trợ về lưu trữ và truy xuất dữ liệu dựa trên ngăn xếp là
một chồng các tấm, trong đó mỗi tấm đại diện cho một phần thông tin. Việc lưu trữ dữ liệu
tương đương với việc thêm một tấm mới vào đầu chồng, điều này làm cho 'chồng' các tấm
tăng cao hơn. Ngược lại, thông tin được truy xuất bằng cách loại bỏ một tấm. Đĩa được
thêm gần đây nhất sẽ luôn ở trên cùng và đĩa cũ nhất ở dưới cùng.

Bước đầu tiên khi viết một bản phác thảo dựa trên ngăn xếp là sử dụng lệnh Stack để tạo
một đối tượng ngăn xếp. (Ví dụ: lệnh Stack stack1; tạo một ngăn xếp được gọi là stack1,
có khả năng chứa tối đa 32 số bit đơn.) Các giá trị có thể được thêm vào hoặc xóa khỏi
ngăn xếp bằng cách sử dụng phương thức push () hoặc pop () của phương thức trước đó
đối tượng ngăn xếp đã tạo. Bản phác thảo sau minh họa việc sử dụng ngăn xếp để lưu trữ
và sau đó lấy ra một loạt các giá trị bit đơn.

124
Listing 44. Đẩy và bật các giá trị từ một ngăn xếp phần mềm một bit (Source: File >
Examples > plcLib > Stack > PushPop)

Khả năng lưu trữ kết quả tính toán tạm thời trên ngăn xếp có thể được sử dụng để đơn giản
hóa giải pháp của các mạng logic phức tạp. Có sẵn các tùy chọn để kết hợp các nhánh song
song hoặc chuỗi bằng cách sử dụng các phép toán logic AND và OR, như được thảo luận
trong phần tiếp theo.

125
22.1 Hoạt động lôgic khối
Một mạng logic bao gồm hai nhánh song song có thể được giải quyết bằng cách tính toán
nhánh trên trước tiên, sau đó lưu kết quả trung gian này vào ngăn xếp. Nhánh thứ hai sau
đó có thể được giải quyết và kết hợp với kết quả trước đó, sử dụng phương thức orBlock
() của đối tượng ngăn xếp (cũng loại bỏ kết quả trước đó khỏi ngăn xếp).

Hình 56. Phép toán Block-OR có thể được sử dụng để kết hợp một nhánh song song với
một kết quả tính toán đã được lưu trữ trước đó trên ngăn xếp.
Bản phác thảo sau đây thể hiện cách tiếp cận.

Listing 45. Performing a logical OR of two parallel switch branches using Block OR
instruction (Source: File > Examples > plcLib > Stack > OrBlock)

126
Một kỹ thuật tương tự có thể được áp dụng với các kết nối nối tiếp của các nhóm chuyển
mạch, có thể được kết hợp bằng cách sử dụng Khối AND.

Hình 57. Một khối AND có thể được sử dụng để giải quyết một mạng phức tạp bao gồm
các phần tử nối tiếp.

Ví dụ sau đây đầu tiên tính toán kết quả của nhóm chuyển đổi ở bên trái, được lưu trữ dưới
dạng kết quả trung gian trên ngăn xếp. Khối bên phải sau đó được giải quyết và kết hợp với
kết quả trước đó bằng cách sử dụng phương thức andBlock () của đối tượng ngăn xếp.

127
Danh sách 46. Logic AND của hai nhóm chuyển đổi chuỗi sử dụng lệnh Block AND
(Nguồn: File> Examples> plcLib> Stack> AndBlock)

Phần tiếp theo thảo luận về các phương pháp tạo phân bổ đầu vào / đầu ra tùy chỉnh, nếu
cấu hình tiêu chuẩn không phù hợp.

23. Xác định Phân bổ IO Tùy chỉnh


Trong một số trường hợp, cấu hình đầu ra đầu vào mặc định có thể không phù hợp. Phân
bổ I / O tùy chỉnh có thể phù hợp nếu cần thêm đầu vào hoặc đầu ra, phần cứng tùy chỉnh
đang được sử dụng hoặc nếu quy ước đặt tên pin khác được ưu tiên.

23.1 Phân bổ I / O được cấu hình sẵn


Phiên bản 1.2 của thư viện PLC cung cấp một loạt các tệp I / O tùy chỉnh để phù hợp với
nhiều loại phần cứng. Các tệp cấu hình sau có sẵn từ phần menu Tệp> Ví dụ> Tùy chỉnh.

• Arduino Uno và Mega với cấu hình pin mặc định (Uno, Mega)
• Điều khiển PLCs (ControllinoMaxiPLC, ControllinoMegaPLC,
ControllinoMiniPLC)
• Tấm chắn công nghiệp Ardbox PLCs (ArdboxAnalogPLC, ArdboxPNPPLC,
ArdboxRelayPLC, ArdboxTCHPLC)
• Tấm chắn công nghiệp M-Duino PLCs (MDuino19RelayPLC, MDuino21PLC,
MDuino38RelayPLC, MDuino42PLC, MDuino57RelayPLC, MDuino58PLC)
• Seedstudio Grove shields for Uno and Mega (GroveUno, GroveMega)
• TinkerKit shields for Uno and Mega (TinkerkitUno, TinkerkitMega)
• Velleman I/O Shield (VellemanIOShield)
• Use of custom pin names and user defined variable names (CustomIO)

Nếu cấu hình được cung cấp không phù hợp, thì bạn có thể cần phải tạo cấu hình của riêng
mình từ đầu, như được thảo luận tiếp theo.

23.2 Nghiên cứu điển hình: Tạo Phân bổ IO Tùy chỉnh


Phần này trình bày việc tạo ánh xạ IO tùy chỉnh cho Tấm chắn đầu vào / đầu ra Velleman
cho Arduino.

Hình 58. Tấm chắn Đầu vào / Đầu ra Velleman cho Arduino cung cấp một loạt các đầu
vào và đầu ra hữu ích.

128
Mô-đun cung cấp tổng cộng mười tám kết nối IO, được sắp xếp như sáu đầu vào tương tự,
sáu đầu vào kỹ thuật số và sáu đầu ra kỹ thuật số dựa trên rơle. Các chi tiết khác về kết nối
và chi tiết đi dây bên trong có sẵn trong sách hướng dẫn và biểu dữ liệu.

Nhiệm vụ đầu tiên là chọn một quy ước đặt tên phù hợp cho các đầu vào và đầu ra, đồng
thời xác định các kết nối chân liên quan.
• Đầu vào tương tự có thể tiếp tục sử dụng các tên hiện có A0 – A5.
• Đầu vào kỹ thuật số sẽ được cấp phát tên D0 – D5, được liên kết với các chân
Arduino 2, 3, 4, 5, 6 và 7.
• Đầu ra rơ le sẽ được gọi là R0 – R5, sử dụng các chân 8, 9, 10, 11, 12 và 13.

Hình 59. Ánh xạ IO cho lá chắn IO Velleman Arduino.


Bản phác thảo sau đây bắt đầu bằng cách vô hiệu hóa định nghĩa của các tên pin mặc định
(X0, X1, ..., Y0, Y1, ...) bằng cách sử dụng lệnh #define noPinDefs, sau đó chỉ định các
tên pin bắt buộc dưới dạng một chuỗi các hằng số nguyên.

129
Liệt kê 47. Tạo ánh xạ đầu vào / đầu ra của Velleman IO Shield (Nguồn: File> Examples>
plcLib> CustomIO> VellemanIOShield)

Hàm customIO () được sử dụng (thay cho hàm setupPLC () tiêu chuẩn) để xác định hướng
dữ liệu cho tất cả các đầu vào và đầu ra như được hiển thị trong phần trích xuất chương
trình sau (có sẵn bằng cách nhấp vào tab IO của bản phác thảo).

Các điểm sau đây cần được lưu ý từ ví dụ trên.


• Tên cho đầu vào kỹ thuật số và đầu ra chuyển tiếp phải được xác định trên toàn cầu,
bằng cách xác định chúng bên ngoài phần setup () {...} và loop () {...}, do đó làm
cho chúng có sẵn để sử dụng ở bất kỳ đâu trong sketch.
• Tên ghim và phân bổ sẽ không thay đổi vì vậy được định nghĩa là hằng số hơn là
biến.
• Phần mềm plcLib yêu cầu các tên pin phải được xác định theo kiểu số nguyên có
dấu (tức là 'int' thay vì 'unsigned int'), vì các lý do đã thảo luận trước đó, trong phần
Sử dụng biến trong chương trình

130
24. Điểm mạnh và Hạn chế của Phần mềm
Phần mềm plcLib được cung cấp miễn phí và cho phép phát triển các chương trình kiểu
PLC đơn giản trên phần cứng tương thích với Arduino chi phí thấp. Do đó, nó cung cấp
một điểm đầu vào hợp lý cho những người muốn phát triển các ứng dụng phần mềm theo
định hướng điều khiển hoặc sử dụng Arduino cho các mục đích giáo dục liên quan.

Các lệnh được viết dưới dạng phần mở rộng cho ngôn ngữ lập trình C / C ++ và do đó sử
dụng cú pháp lệnh tương thích C / C ++. Các chương trình có thể được thiết kế bằng sơ đồ
bậc thang, sơ đồ khối chức năng, biểu đồ chức năng tuần tự hoặc văn bản có cấu trúc, nhưng
phải được nhập vào Arduino IDE ở định dạng chỉ văn bản, thường được gọi là danh sách
hướng dẫn. Tuy nhiên, quá trình này trở nên dễ dàng hơn khi thực hành và được hỗ trợ bởi
sự sẵn có của các ví dụ.

Mặc dù cú pháp lệnh không giống với bất kỳ nhà sản xuất cụ thể nào, nhưng cần dễ dàng
chuyển giao kiến thức hiện có giữa các hệ thống hoặc so sánh hoạt động của một tính năng
nhất định với tiêu chuẩn thích hợp (IEC 61131).

Các điểm sau đây có thể hữu ích khi quyết định có sử dụng giải pháp dựa trên plcLib trong
một tình huống cụ thể hay không.

• Cách tiếp cận logic bậc thang đặc biệt hiệu quả khi triển khai các hệ thống có thể dễ
dàng được biểu diễn bằng sơ đồ bậc thang, sơ đồ khối hoặc hệ thống dựa trên trình
tự. Các hệ thống này thường liên quan đến việc thực hiện song song một số tác vụ
đáng kể, đây là một thế mạnh cụ thể. Đối với các hệ thống khác được biểu diễn dễ
dàng nhất bằng cách sử dụng lưu đồ hoặc tương tự, thì phương pháp lập trình truyền
thống có thể hiệu quả hơn. Trong một số trường hợp, có thể sử dụng kết hợp các
cách tiếp cận này, có thể sử dụng văn bản có cấu trúc.
• Chu kỳ quét chắc chắn sẽ chậm lại khi nhiều tác vụ song song được thêm vào. Cần
luôn cẩn thận để đảm bảo rằng thời gian đáp ứng của hệ thống là đủ cho hệ thống
đang được kiểm soát.
• Trong một số trường hợp, hệ thống có thể yêu cầu một số lần vượt qua chu kỳ quét
để hoàn thành các phép tính phức tạp và các kết quả trung gian hoặc 'trục trặc' có
thể xảy ra nhanh chóng tại thời điểm này. Ngoài ra, kết quả đầu ra được cập nhật ở
mỗi bước trong chu kỳ quét (không chỉ ở phần cuối). Bạn nên kiểm tra các chương
trình một cách cẩn thận để đảm bảo rằng bất kỳ kết quả trung gian nào sẽ không ảnh
hưởng đến hoạt động chính xác của hệ thống.
• Nói chung, bạn nên tránh sử dụng lệnh delay () trong các chương trình logic bậc
thang, vì điều này sẽ tạm dừng chu kỳ quét trong khoảng thời gian trễ (gỡ lỗi phần
mềm là một ngoại lệ, trong đó mục đích có thể là cố tình làm chậm chu kỳ quét) .
Nếu hoạt động dựa trên thời gian là bắt buộc thì hãy xem xét sử dụng lệnh hẹn giờ
như timerOn (), timerOff (), timerPulse () hoặc timerCycle (), vì các lệnh này sử
dụng phương pháp điều khiển ngắt không ảnh hưởng đến chu kỳ quét.

131
25. Tham chiếu lệnh

Trang này liệt kê tất cả các lệnh được hỗ trợ bởi phần mềm plcLib.

25.1 Cấu hình chung


Lệnh Mô tả Ví dụ Phần
setupPLC(); Định cấu hình cài đặt PLC cơ bản setupPLC(); Định cấu hình phần cứng

25.2 Đầu vào / đầu ra kỹ thuật số một bit


Lệnh Mô tả Ví dụ Phần
in(input); Đọc đầu vào kỹ in(X0); Đầu vào / đầu ra bit
thuật số. đơn
out(output); Kết quả đầu ra kỹ out(Y0); Đầu vào / đầu ra bit
thuật số. đơn
inNot(input); Đọc đầu vào kỹ inNot(X0); Đầu vào / đầu ra bit
thuật số đảo ngược. đơn
outNot(output); Đầu ra tín hiệu outNot(Y0); Đầu vào / đầu ra bit
ngược sang kỹ thuật đơn
số đầu ra.

25.3 Logic kết hợp


Lệnh Mô tả Ví dụ Phần
andBit(input); Logical AND với đầu in(X0); andBit(X1); Thực hiện các
vào kỹ thuật số. out(Y0); phép toán Boolean
orBit(input); Logical OR với đầu in(X0); orBit(X1); Thực hiện các
vào kỹ thuật số. out(Y0); phép toán Boolean
xorBit(input); Logical XOR với đầu in(X0); xorBit(X1); Thực hiện các
vào kỹ thuật số. out(Y0); phép toán Boolean
andNotBit(input); Logical AND với đầu in(X0); Thực hiện các
vào kỹ thuật số đảo andNotBit(X1); phép toán Boolean
ngược. out(Y0);
orNotBit(input); Logical OR với đầu in(X0); Thực hiện các
vào kỹ thuật số đảo orNotBit(X1); phép toán Boolean
ngược. out(Y0);

25.4 Đầu vào / đầu ra tín hiệu tương tự


Lệnh Mô tả Ví dụ Phần
inAnalog(input); Đọc đầu vào tương inAnalog(X0); Làm việc với tín
tự. hiệu tương tự

132
outPWM(output); Xuất ra dạng sóng outPWM(Y0); Làm việc với tín
PWM. hiệu tương tự
outServo(output); Xuất ra servo. outServo(Y0); Làm việc với tín
hiệu tương tự

25.5 So sánh các tín hiệu tương tự


Lệnh Mô tả Ví dụ Phần
compareGT(input); So sánh đầu vào inAnalog(X0); So sánh các giá trị
tương tự với giá trị compareGT(X1); tương tự
tương tự thứ hai, trả out(Y0);
về 1 nếu giá trị
trước lớn hơn
compareLT(input); So sánh đầu vào inAnalog(X0); So sánh các giá trị
tương tự với giá trị compareLT(X1); tương tự
tương tự thứ hai, trả out(Y0);
về 1 nếu giá trị
trước nhỏ hơn

25.6 Chốt
Lệnh Mô tả Ví dụ Phần
latch(latch_output, Chốt giá trị đầu vào in(X0); latch(Y0, Kết quả đầu ra
reset_input); kỹ thuật số trước đó. X1);

atchKey(set_key, Chốt đầu ra kỹ thuật latchKey('1', '2', Y0); Kết quả đầu ra
reset_key, output); số dựa trên mục nhập
bàn phím.
set(latch_output); Chốt (đặt) một đầu ra in(X0); set(Y0); Kết quả đầu ra
kỹ thuật số nếu giá trị
trước đó là true.

reset(latch_output); Xóa (hủy đặt) đầu ra in(X0); reset(Y0); Kết quả đầu ra
đã chốt nếu giá trị
trước đó là true.

25.7 Bộ hẹn giờ


Lệnh Mô tả Ví dụ Phần
timerOn(timer_variable, Tạo ra một đầu ra in(X0); Sản xuất
delay_ms); bị trễ sau khi một timerOn(TIMER0, dạng sóng
đầu vào được 2000); out(Y0) lặp lại
bật.
timerOff(timer_variable, Trì hoãn tắt đầu in(X0); Sản xuất
delay_ms); ra sau khi đầu timerOff(TIMER0, dạng sóng
vào bị xóa. 2000); out(Y0) lặp lại
timerPulse(timer_variable, Tạo ra xung độ in(X0); Sản xuất
pulse_ms); rộng cố định timerPulse(TIMER0, dạng sóng
được kích hoạt 2000); out(Y0); lặp lại

133
bởi một đầu vào
ngắn gọn
timerCycle(low_variable, Tạo một dạng in(X0); Sản xuất
low_ms, high_variable, sóng xung lặp timerCycle(AUX0, dạng sóng
high_ms); lại, nếu được bật. 900, AUX1, 100); lặp lại
out(Y0);

25.8 Xung kích hoạt cạnh

Lệnh Mô tả Ví dụ Phần
Pulse pulse_name; Tạo một đối tượng Pulse pulse1; Xung kích hoạt
xung. cạnh
pulse_name.inClock(); Kết nối tín hiệu đầu in(X0); Xung kích hoạt
vào với đối tượng pulse1.inClock(); cạnh
xung.
pulse_name.rising(); Đọc cạnh tăng của pulse1.rising(); Xung kích hoạt
dạng sóng xung out(Y0); cạnh
pulse_name.falling(); Đọc cạnh rơi của pulse1.falling(); Xung kích hoạt
dạng sóng xung out(Y1); cạnh

25.9 Bộ đếm

Lệnh Mô tả Ví dụ Phần
counter_name(preset Tạo và cấu hình một đối Counter ctr1(5); Đếm và
_value [, direction]); tượng bộ đếm. Counter ctr2(10,1); Bộ đếm
counter_name.count Đếm lên, nếu số đếm nhỏ in(X0); Đếm và
Up(); hơn giá trị đặt trước. ctr1.countUp(); Bộ đếm
counter_name.count Đếm ngược, nếu số đếm lớn in(X0); Đếm và
Down(); hơn 0 ctr1.countDown(); Bộ đếm
counter_name.preset( Đặt số lượng nội bộ thành giá in(X1); Đếm và
); trị đặt trước, kích hoạt ctr1.preset(); Bộ đếm
đầu ra Q trên
counter_name.clear() Đặt số lượng nội bộ thành 0, in(X2); ctr1.clear(); Đếm và
; kích hoạt đầu ra Q thấp hơn Bộ đếm
counter_name.upper Bằng 1 nếu số lượng bên ctr1.upperQ(); Đếm và
Q(); trong bằng giá trị đặt trước, out(Y0); Bộ đếm
bằng 0 nếu không
counter_name.lower Bằng 1 nếu số đếm bên trong ctr1.lowerQ(); Đếm và
Q(); bằng 0, ngược lại bằng 0. out(Y0); Bộ đếm
counter_name.count( Trả về giá trị đếm bên trong. Serial.println(ctr1.c Đếm và
); ount()); Bộ đếm
counter_name.preset Trả về giá trị đặt trước. Serial.println(ctr1.p Đếm và
Value(); resetValue()); Bộ đếm

134
25.10 Dịch chuyển vị trí thanh ghi

Lệnh Mô tả Ví dụ Phần
Shift Tạo và cấu hình Shift shift1(); Dịch chuyển
register_name([start_value]); một đối tượng Shift và xoay dữ
thanh ghi shift shift2(0x8888); liệu nhị phân
register_name.inputBit(); Đặt bit đầu vào in(X0); Dịch chuyển
nối tiếp dựa trên shift1.inputBit(); và xoay dữ
đầu vào trước đó. liệu nhị phân
register_name.shiftLeft(); Di chuyển dữ liệu in(X0); Dịch chuyển
sang trái một chỗ, shift1.inputBit(); và xoay dữ
trên cạnh lên của liệu nhị phân
đầu vào trước đó.
register_name.shiftRight(); Di chuyển dữ liệu in(X2); Dịch chuyển
sang phải một shift1.shiftRight( và xoay dữ
nơi, trên cạnh lên ); liệu nhị phân
của đầu vào trước
đó.
register_name.reset(); Đặt lại giá trị in(X3); Dịch chuyển
thanh ghi dịch shift1.reset(); và xoay dữ
chuyển nội bộ về liệu nhị phân
0 nếu đầu vào
trước đó bằng.
register_name.bitValue(bit_posi Trả về giá trị của shift1.bitValue(0 Dịch chuyển
tion); bit thanh ghi dịch ); out(Y0); và xoay dữ
chuyển tại vị trí liệu nhị phân
đã chỉ định.
register_name.value(); Trả về giá trị của Serial.println(shi Dịch chuyển
thanh ghi shift ft1.value()); và xoay dữ
dưới dạng số delay(200); liệu nhị phân
nguyên không
dấu.

25.11 Logic ngăn xếp và khối

Lệnh Mô tả Ví dụ Phần
Stack stack_name; Tạo một ngăn xếp Stack stack1; Logic ngăn xếp
32 cấp, một bit. và khối
stack_name.push(); Đẩy scanValue, stack1.push(); Logic ngăn xếp
được biểu thị dưới và khối
dạng số bit đơn, lên
ngăn xếp.
stack_name.pop(); Cập nhật stack1.pop(); Logic ngăn xếp
scanValue với một và khối
giá trị bit đơn bị
xóa khỏi ngăn xếp.
135
Kết Luận

Như vậy, với đề tài đồ án : Hướng dẫn lập trình PIC với Arduino, nhóm thực hiện
đã hiểu được những vấn đè căn bản đối với thiết kế và lập trình một số loại bo mạch
Arduino. Ngoài ra cung cấp những kiến thức về các phần mềm ứng dụng trong thiết kế
mạch phần cứng. Nhưng một điều quan trọng không thể nói đến đó là tạo cho em những
kỹ năng mềm của bản than, khả năng tư duy và làm việc độc lập. Với sự nỗ lực trong việc
tìm hiểu nghiên cứu các linh kiện, thiết bị cần thiết cho đề tài, cừng với vận dụng các kiến
thức đã học vào công việc thiết kế, lắp đặt, và sự giúp đỡ, hướng dẫn nhiệt nhiệt tình của
thầy giáo Triệu Việt Linh, nhóm em đã hoàn thành được đề tài đồ án.
Do đây mới là lần đầu tiên những thành viên trong nhóm làm một đề tài đồ án, cộng
với kiến thức còn nhiều hạn chế, chúng em thấy đề tài của mình thực hiện vẫn còn rất
nhiều sai sót, khiếm khuyết. Chúng em tự rất mong được sự ủng hộ và giúp đỡ của thầy
giáo để đè tài chúng em thực hiện được hoàn thiện hơn và có thêm nhiều cải tiến đáng kể
và ứng dụng tốt hơn và thực tiễn.

136

You might also like