Arduino - câu lệnh điều khiển. Arduino lặp Arduino trong khi thoát khỏi vòng lặp

Hôm nay chúng ta sẽ nghiên cứu một phần quan trọng không kém của ngôn ngữ lập trình, đó là vòng lặp. Họ cần chúng để làm gì. Ví dụ: chúng ta hãy đặt mục tiêu cho chính mình. Bạn cần thắp sáng lần lượt sáu đèn LED với khoảng thời gian 50 ms, sau đó lần lượt tắt chúng trong khoảng thời gian như nhau. Chà, điều gì có thể đơn giản hơn? Chúng tôi viết đoạn mã sau:
void setup() ( pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); ) vòng lặp void () ( digitalWrite(2, HIGH); độ trễ(50); digitalWrite(3, CAO); độ trễ(50); digitalWrite(4, CAO); độ trễ(50); digitalWrite(5, CAO); độ trễ(50) ; digitalWrite(6, CAO); độ trễ (50); digitalWrite(7, CAO); độ trễ (50); digitalWrite(2, THẤP); độ trễ (50); digitalWrite(3, THẤP); độ trễ (50); digitalWrite (4, THẤP); độ trễ(50); digitalWrite(5, THẤP); độ trễ(50); digitalWrite(6, THẤP); độ trễ(50); digitalWrite(7, THẤP); độ trễ(50); ) Đầu tiên chúng ta Chúng tôi đã khởi tạo sáu chân kỹ thuật số từ chân thứ hai đến chân thứ bảy làm đầu ra và trong chương trình chính, chúng tôi đã viết lần lượt bật đèn LED, độ trễ, v.v. sáu lần. Sau đó cũng vậy, nhưng mỗi lần đèn LED đều tắt. Bây giờ chúng ta tải nó lên Arduino và tận hưởng công việc. Nhưng vẫn có điều gì đó không ổn ở đây. Nếu bạn nhìn kỹ vào mã chương trình, bạn sẽ nhận thấy rằng có những phần của mã được lặp lại trong toàn bộ chương trình. Ví dụ: sự lặp lại của khoảng dừng sẽ ngay lập tức thu hút sự chú ý của bạn. Và khi khởi tạo một mã pin, chỉ có số của nó thay đổi. Khi bạn bật và tắt, chỉ có con số thay đổi. Tất nhiên, đối với một chương trình nhỏ như vậy, bạn có thể để như vậy, bộ điều khiển sẽ ăn hết và không bị sặc, nhưng nếu bạn cần thực thi mã lặp lại chẳng hạn 1000 lần. Tôi nghĩ mình có đủ kiên nhẫn để lấp đầy nó, nhưng liệu MK có đủ bộ nhớ không? Tất nhiên, bạn có thể hỏi, tại sao chúng ta lại cần 1000 thao tác giống hệt nhau? Vâng, thật khó để tưởng tượng.) Nhưng đó không phải là vấn đề, mà là nếu chúng ta có một mảng 1000 ô. Điều này thường xảy ra, chẳng hạn như một số cảm biến ghi tham số vào một mảng và làm cách nào để bạn tìm ra cách giải quyết tình trạng lộn xộn này. Nó sẽ là cần thiết để phân tích nó theo một số tham số. Chính vì những sự cố như vậy mà chu kỳ đã được phát minh. Vòng lặp là một đoạn mã được thực thi một số lần nhất định. Một phần được thực hiện của chương trình trong một vòng lặp được gọi là phép lặp. Số lần lặp có thể từ 0 đến vô cùng. Để thực hiện vòng lặp trong ngôn ngữ lập trình, có tới ba tùy chọn vòng lặp. Hãy tin tôi, điều này là đủ cho bất kỳ mã hóa phức tạp nào. Chúng ta hãy xem xét tất cả điều này chi tiết hơn.
  • trong khi(điều kiện) ()
  • do() while(điều kiện);
  • for(biến đếm; điều kiện; tăng biến đếm) ()
Chu kỳ đầu tiên trong khi(điều kiện) (). Anh ấy làm việc như thế nào. Sau lời nói trong khi phải có điều kiện trong ngoặc đơn. Điều kiện có thể là bất cứ điều gì miễn là nó đúng. Ngay khi điều kiện trở thành sai, vòng lặp sẽ ngừng chạy và chương trình sẽ tiếp tục chạy từ dòng tiếp theo sau vòng lặp. Hãy sử dụng một ví dụ.
char i = 0; trong khi tôi Trên thực tế, những gì được viết ở đây. Đầu tiên chúng ta khởi tạo biến đếm Tôi và thiết lập lại nó. Tiếp theo, chúng ta đi vào vòng lặp và bắt đầu kiểm tra điều kiện trong ngoặc. Nếu giá trị Tôi nhỏ hơn 10 thì thực thi phần thân vòng lặp. Trong phần thân của vòng lặp, chúng ta chỉ cần tăng giá trị của biến đếm lên một đơn vị và kiểm tra lại điều kiện. Trong trường hợp của chúng tôi, vòng lặp sẽ được thực hiện 10 lần. Nghĩa là, ý nghĩa đầu tiên Tôi bằng không. Số không nhỏ hơn mười. Tiếp theo, chúng tôi tăng biến lên một và so sánh, một nhỏ hơn mười, v.v. Ngay khi biến đếm bằng mười, chúng ta kiểm tra xem mười có nhỏ hơn mười không? Tất nhiên là không, và sau khi kiểm tra chu trình sẽ ngừng hoạt động. Đây là cách chu kỳ này hoạt động. Bạn nên làm gì nếu chỉ cần thực thi mã trong phần thân vòng lặp một lần, ngay cả khi mã đó không thỏa mãn điều kiện? Có một chu kỳ khác cho việc này được gọi là do() trong khi(điều kiện). Nó hoạt động giống hệt như chu kỳ trước, ngoại trừ một điều. Trong vòng lặp này, phần thân của vòng lặp được thực thi trước tiên và sau đó quá trình kiểm tra sẽ diễn ra. Hãy xem nó trông như thế nào trong mã.
char i = 0; làm ( i++; ) while((i > 0) & (i Nhìn nó thú vị làm sao. Đầu tiên, giống như lần trước, chúng ta khởi tạo biến đếm về 0, nhưng trong điều kiện chúng ta viết rằng Tôi lớn hơn 0 và nhỏ hơn 10. Nghĩa là giá trị của biến phải nằm trong khoảng từ một đến chín. Nếu chúng ta viết nó theo cách này bằng vòng lặp trước đó thì nó sẽ không bao giờ được thực thi. Nhưng chúng ta có một từ kỳ diệu LÀM. Đó là, những gì sẽ xảy ra. Đầu tiên, trong phần thân vòng lặp, giá trị của biến đếm sẽ tăng lên và trở thành 1, giá trị này lớn hơn 0 thì điều kiện sẽ trở thành đúng. Theo đó, vòng lặp sẽ tiếp tục thực hiện cho đến khi biến đếm bằng 10. Và cuối cùng là phiên bản thứ ba của chu trình. Anh ấy làm việc như thế nào:
ký tự tôi; vì(i = 0; tôi Làm thế nào nó hoạt động. Đầu tiên, chúng ta bắt đầu lại biến đếm nhưng không có giá trị cụ thể. Tiếp theo chúng ta viết từ , nhưng trong ngoặc đơn, trước tiên chúng ta viết biến đếm của mình và gán cho nó một giá trị ban đầu. Sau đó, chúng ta kiểm tra điều kiện và nếu nó đúng thì chúng ta thực thi phần thân vòng lặp và tăng giá trị của biến đếm. Về cơ bản điều này giống như trong khi()() vì vậy việc sử dụng chu kỳ nào là tùy thuộc vào bạn. Một vài lời về một số điểm. Ví dụ, nếu bạn viết trong khi(1);, thì vòng lặp sẽ chạy mãi mãi. Hoặc nếu với , sau đó nó sẽ trông như thế này vì(;;);. Hãy cẩn thận. Đôi khi khi thực hiện một chu trình, bạn thực sự muốn vứt bỏ mọi thứ và thoát khỏi nó nhưng điều kiện không cho phép. Tôi nên làm gì? Có một lệnh khác cho việc này phá vỡ;. Ngay khi MK gặp lệnh này trong phần thân vòng lặp, nó sẽ ngay lập tức thoát khỏi vòng lặp và tiếp tục thực hiện chương trình từ dòng tiếp theo sau vòng lặp. Nhưng điều gì sẽ xảy ra nếu trong quá trình hoạt động của vòng lặp, một điều kiện phát sinh không thỏa mãn điều kiện đó hoặc, ví dụ, tại một thời điểm mà chúng ta không cần tiếp tục thực hiện đến cuối phần thân vòng lặp thì sao? Nhóm sẽ giúp chúng tôi ở đây Tiếp tục;. Ngay khi MK gặp lệnh này, nó sẽ bỏ mọi thứ và chuyển sang lần lặp tiếp theo của vòng lặp. Tôi hy vọng tôi đã giải thích mọi thứ rõ ràng. Bây giờ khi đã nhận được kiến ​​thức này, hãy viết lại chương trình của chúng ta nhưng sử dụng vòng lặp.
void setup() ( byte i = 2; // Biến đếm while(i // Nếu i nhỏ hơn 8 thì thực thi phần thân vòng lặp ( pinMode(i, OUTPUT); // Khởi tạo các chân bắt đầu từ 2 tôi++; //Tăng biến đếm lên một) ) void loop() ( byte i = 2; while(i Chúng ta hãy xem xét kỹ hơn. Đầu tiên chúng ta khởi tạo biến đếm Tôi và gán cho nó một giá trị là hai. Tại sao lại là hai? Nhưng bởi vì tôi đã chọn cụ thể các chân từ thứ hai đến thứ bảy, để đảm bảo rằng giá trị ban đầu không thành vấn đề. Hóa ra đó là một kiểu chơi chữ nào đó) Tất nhiên là có. Tiếp theo chúng ta viết điều kiện vòng lặp. Chúng ta cần thực hiện sáu lần lặp vì chúng ta có sáu đèn LED. Tuyệt vời, chúng tôi nghĩ hai cộng sáu bằng tám. Vâng, vậy chúng ta cần kiểm tra biến đếm cho đến khi nó nhỏ hơn 8. Đó là những gì họ đã viết while(i . Bây giờ vòng lặp của chúng ta sẽ chạy sáu lần. Chúng ta cần làm gì bên trong phần thân vòng lặp? Không có gì phức tạp, chỉ cần nhập hàm khởi tạo đầu ra trên đầu ra, chỉ cần thay thế một biến đếm thay vì số đầu ra. Là gì? thủ thuật. Ngay khi MK vào vòng lặp body, trước khi thực hiện chức năng khởi tạo đầu ra, chúng ta hãy xem các đối số được truyền. Một trong số chúng phải mang số đầu ra và chúng ta có một biến đếm ở đó. Chúng ta nên làm gì làm gì? Nhưng không có gì, một MK thông minh sẽ xem biến ở đó là gì và tự hào rút nó ra số. Và chúng ta có hai ở đó. Chà, tuyệt, hãy khởi tạo đầu ra thứ hai. Sau đó, chúng ta sẽ tăng giá trị của biến đếm bằng một biến khác và kiểm tra điều kiện. Vâng, ba nhỏ hơn tám, chúng ta hãy làm lại từ đầu, chỉ có biến hiện có ba. Điều đó có nghĩa là chúng ta sẽ khởi tạo đầu ra lần thứ ba, và sau đó tăng số đếm biến theo một. Bằng cách này, bằng cách đi qua vòng lặp, chúng ta sẽ thiết lập tất cả các đầu ra mà chúng ta cần. Hơn nữa, việc tăng biến đếm lên một không phải là một điều kiện nghiêm ngặt. Không ai làm phiền bạn khi viết một cái gì đó như thế này: i = ((127*i)/31) & 0xF4; Và điều này cũng sẽ hoạt động nếu điều kiện đúng sau khi thực hiện. Đối với vòng lặp, điều gì xảy ra trong cơ thể không quan trọng; nó quan tâm đến việc điều kiện có đúng hay không. Đó là tất cả. Trong bài học tiếp theo, chúng ta sẽ xem xét các hàm, tại sao chúng cần thiết và thử viết hàm của riêng mình.

Chúng ta hãy xem cách các toán tử vòng lặp for, while và do while hoạt động trong Arduino IDE, cách sử dụng chính xác các vòng lặp trong bản phác thảo và những lỗi cần tránh. Sử dụng các ví dụ đơn giản, chúng tôi sẽ minh họa cách bạn có thể dừng một vòng lặp hoặc chuyển từ vòng lặp này sang vòng lặp khác. Để hiểu được tính đúng đắn của chu trình viết, trước hết bạn nên nghiên cứu các loại và tính chất của các thuật toán trong chế tạo robot.

Cách các vòng lặp hoạt động trong Arduino IDE

Bất kỳ vòng lặp nào trong C++ và ngôn ngữ lập trình Arduino đều là một hành động được lặp lại nhiều lần hoặc vô số lần. Không một chương trình nào dành cho vi điều khiển Arduino hoàn chỉnh nếu không có vòng lặp, ví dụ, vòng lặp void được gọi trong vòng lặp vô hạn. Có ba loại toán tử vòng lặp: for, while và do while - hãy xem xét từng toán tử và xem cách chúng hoạt động bằng cách sử dụng các ví dụ.

Nguyên lý hoạt động của for và while có thể được giải thích bằng các ví dụ đơn giản sau. Vòng lặp for được thực hiện với số lần hữu hạn (được biểu thị trong điều kiện của người vận hành); nó được sử dụng khi chương trình, chẳng hạn, yêu cầu đèn LED nhấp nháy nhiều lần. Vòng lặp while có thể chạy vô tận, ví dụ như khi đèn LED trên Arduino nhấp nháy cho đến khi dữ liệu từ cảm biến thay đổi.

Mô tả vòng lặp for trong Arduino kèm ví dụ

Cấu trúc for trong Arduino được định nghĩa như sau:

for (khởi tạo; điều kiện; thay đổi)( )

Vòng lặp for được sử dụng để lặp lại các lệnh cụ thể được đặt trong dấu ngoặc nhọn. Chu trình này phù hợp để thực hiện bất kỳ hành động lặp đi lặp lại.
Tại khởi tạo một biến được tạo và một giá trị ban đầu được gán.
TRONG tình trạng giá trị của biến tại đó vòng lặp sẽ được thực thi sẽ được ghi lại.
TRONG thay đổi cho biết biến sẽ thay đổi như thế nào ở mỗi bước của vòng lặp.

cho (byte i=0; tôi<=5; i++){ digitalWrite (13, HIGH ); delay (500); digitalWrite (13, LOW ); delay (500); }

Trong ví dụ phác thảo, một biến có giá trị ban đầu được đặt tôi=0, điều kiện cho biết vòng lặp sẽ chạy cho đến khi biến bằng hoặc lớn hơn năm Tôi<=5 . Sự thay đổi nêu rõ rằng biến sẽ được tăng thêm một ở mỗi bước của vòng lặp. Cuối cùng, vòng lặp for sẽ thoát khi biến bằng 5, do đó đèn LED sẽ nhấp nháy năm lần trước khi vòng lặp kết thúc.

Bước thay đổi (thay đổi) có thể là bất cứ điều gì. Nếu cần tăng một biến lên hai đơn vị cùng một lúc thì sự thay đổi của bộ đếm phải được viết như sau: tôi=tôi+2. Vòng lặp for có thể được sử dụng bên trong quy trình thiết lập void, ví dụ, để chỉ ra chế độ hoạt động của một số chân cùng một lúc. Và cả trong quy trình vòng lặp void, chẳng hạn như trong chương trình bật đèn LED tuần tự trên Arduino.



Mô tả chương trình Arduino với vòng lặp for và while

Mô tả vòng lặp while của Arduino kèm ví dụ

Cấu trúc while trong Arduino được định nghĩa như sau:

trong khi (điều kiện)( // các lệnh sẽ được lặp lại }

Vòng lặp while sẽ chạy liên tục và vô tận miễn là điều kiện trong ngoặc là đúng. Sẽ thoát khỏi vòng lặp khi biến trong điều kiện while thay đổi, do đó phải có thứ gì đó thay đổi giá trị của nó. Việc thay đổi một biến có thể xảy ra trong mã chương trình bên trong một vòng lặp hoặc khi đọc các giá trị từ bất kỳ cảm biến nào, chẳng hạn như từ máy đo khoảng cách siêu âm HC-SR04.

byte i=0; // cần tạo một biến trước vòng lặp trong khi tôi<5){ // vòng lặp chạy miễn là i nhỏ hơn 5 digitalWrite(13, CAO); độ trễ (500); digitalWrite(13, THẤP); độ trễ (500); tôi++; // thay đổi biến }

Khi sử dụng hàm while, biến phải được tạo trước khi vòng lặp bắt đầu. Trong ví dụ phác thảo, đèn LED sẽ nhấp nháy năm lần trước khi chu kỳ kết thúc. Nếu bạn không thay đổi biến bên trong dấu ngoặc nhọn tôi++, sau đó chu kỳ sẽ lặp lại vô tận. Cách thứ hai để thoát khỏi vòng lặp while của Arduino Uno là đọc dữ liệu từ cảm biến và sử dụng câu lệnh if để thay đổi biến.

Một vòng lặp khác có thể được sử dụng trong Arduino IDE là vòng lặp hậu điều kiện. làm trong khi. Khi sử dụng cấu trúc này, các lệnh trong vòng lặp sẽ được thực thi ít nhất một lần, bất kể điều kiện nào, vì điều kiện được kiểm tra sau khi thân vòng lặp được thực thi. Trong ví dụ về mã sau đây, đèn LED sẽ bật bất kể số đọc của cảm biến và chỉ sau đó mới kiểm tra điều kiện sau.

nước int; // tạo một biến trước vòng lặp làm ( digitalWrite(13, HIGH ); nước = analogRead (AO); ) while (water<5) // kiểm tra cảm biến digitalWrite(13, THẤP);

Làm thế nào để thoát khỏi vòng lặp while hoặc for

Trong trường hợp cần thoát khỏi phần thân vòng lặp, bất kể các điều kiện đã chỉ định, toán tử sẽ được sử dụng phá vỡ hoặc đi đến. Câu lệnh break cho phép bạn thoát khỏi vòng lặp và chương trình sẽ tiếp tục thực hiện các lệnh sau. Câu lệnh goto cho phép bạn không chỉ thoát khỏi vòng lặp mà còn tiếp tục thực hiện chương trình từ điểm mong muốn dọc theo nhãn, ví dụ: bạn có thể chuyển sang vòng lặp khác trong Arduino.

Vòng lặp sử dụng câu lệnh trong khi là một trong những cấu trúc quan trọng nhất của ngôn ngữ C++ làm nền tảng cho Arduino. Chúng được tìm thấy hoàn toàn trong mọi bản phác thảo, ngay cả khi bạn không biết về nó. Trong bài viết này, chúng ta sẽ xem xét kỹ hơn các vòng lặp, tìm hiểu sự khác biệt giữa for và while, cách bạn có thể đơn giản hóa việc viết chương trình với sự trợ giúp của chúng và những lỗi nào nên tránh.

Nếu bạn vẫn là một lập trình viên mới làm quen và muốn hiểu vòng lặp là gì và tại sao nó lại cần thiết, hãy xem phần mô tả chi tiết tiếp theo của bài viết này.

Toán tử WHILE được sử dụng trong C++ và Arduino để lặp lại cùng một lệnh với số lần tùy ý. So với vòng lặp FOR, vòng lặp WHILE trông đơn giản hơn; nó thường được sử dụng khi chúng ta không cần đếm số lần lặp trong một biến mà chỉ cần lặp lại mã cho đến khi có điều gì đó thay đổi hoặc sự kiện nào đó xảy ra.

Cú pháp WHILE

trong khi(<условие или список условий>)
{
<программный блок, который будет повторяться>
}

Bất kỳ cấu trúc ngôn ngữ nào trả về giá trị Boolean đều có thể được sử dụng làm điều kiện. Điều kiện có thể là phép toán so sánh, hàm, hằng, biến. Giống như bất kỳ hoạt động logic nào khác trong Arduino, mọi giá trị khác 0 sẽ được coi là đúng, 0 – sai.

// Vòng lặp vô tận while(true)( Serial.println("Đang chờ..."); ) // Vòng lặp chạy cho đến khi giá trị của hàm checkSignal() thay đổi while(!checkSignal())( Serial.println ("Chờ..."); )

Lưu ý rằng câu lệnh while có thể được sử dụng mà không cần chặn khối bằng dấu ngoặc nhọn, trong trường hợp đó lệnh đầu tiên gặp sau vòng lặp sẽ được lặp lại. Rất không nên sử dụng khi không có dấu ngoặc nhọn, bởi vì trong trường hợp này rất dễ mắc sai lầm. Ví dụ:

While(true) Serial.print("Đang chờ gián đoạn"); độ trễ (1000);

Trong trường hợp này, dòng chữ sẽ được hiển thị trong một vòng lặp vô tận không có điểm dừng, vì lệnh delay(1000) sẽ không được lặp lại. Bạn có thể dành nhiều thời gian để tìm ra những lỗi như vậy - việc sử dụng dấu ngoặc nhọn sẽ dễ dàng hơn nhiều.

Ví dụ về sử dụng vòng lặp while

Thông thường, while được sử dụng để chờ đợi một sự kiện nào đó. Ví dụ: mức độ sẵn sàng của đối tượng Serial cho công việc.

Serial.begin(9600); while (!Serial) ( ; // Một số bo mạch Arduino yêu cầu bạn đợi cho đến khi cổng nối tiếp trống)

Ví dụ về việc chờ ký tự đến từ thiết bị bên ngoài thông qua UART:

While(Serial.available())( int byteInput = Seria.read(); // Một số hành động khác)

Trong trường hợp này, chúng ta sẽ đọc các giá trị miễn là Serial.available() trả về giá trị khác 0. Khi hết dữ liệu trong bộ đệm, vòng lặp sẽ dừng lại.

Vòng lặp FOR trong Arduino

Trong vòng lặp FOR, chúng ta không chỉ có cơ hội đặt các điều kiện biên mà còn có thể xác định ngay một biến cho bộ đếm và cho biết giá trị của nó sẽ thay đổi như thế nào sau mỗi lần lặp.

Cú pháp vòng lặp FOR

Ở đây thiết kế sẽ phức tạp hơn một chút:
(<начальное значение счетчика>;<условие продолжения выполнения цикла>;<изменение значения счетчика на каждом шаге>){
<список_команд>
}

Ví dụ đơn giản nhất:

Vì(int i=5;i<10;i++){ // Конструкция «3 в одном» pinMode(i, OUTPUT); }

Chúng tôi ngay lập tức tạo một biến, khởi tạo nó và chỉ ra rằng vào cuối mỗi chu kỳ, giá trị bộ đếm sẽ tăng thêm một. Và thế là xong - bây giờ bạn có thể sử dụng biến bên trong vòng lặp.

Bước thay đổi có thể khác nhau. Dưới đây là ví dụ:

  • for(int i=0; i<10; i=i+2) // Шаг 2
  • for(int i=0; i<10; i+=2) // Аналогичен предыдущему
  • for(int i=10; i>0; i–) // Quay lại – từ 10 đến 1

thực hiện vòng lặp while

Trong một số trường hợp, chúng ta cần tổ chức vòng lặp sao cho các lệnh của khối được thực thi ít nhất một lần và sau đó việc kiểm tra được thực hiện. Đối với các thuật toán như vậy, bạn có thể sử dụng cấu trúc do while. Ví dụ:

Thực hiện ( Serial.println("Đang làm việc"); ) while (checkSomething());

Phiên bản vòng lặp này không gặp bất kỳ khó khăn nào - chúng tôi chỉ cần di chuyển khối có điều kiện xuống dưới, do đó tất cả nội dung bên trong dấu ngoặc nhọn sau toán tử do sẽ được thực thi trước lần kiểm tra đầu tiên.

Tiếp tục và ngắt câu lệnh

Có những tình huống khi bạn cần dừng khẩn cấp việc thực hiện một vòng lặp bên trong khối vòng lặp mà không cần chờ chuyển sang khối kiểm tra điều kiện. Để làm điều này bạn có thể sử dụng toán tử phá vỡ:

Trong khi (true) ( ​​​​if (checkSomething()) ( break; ) )

Nếu chúng ta chỉ muốn dừng tiến trình của vòng lặp hiện tại, nhưng không thoát khỏi vòng lặp mà đi đến khối kiểm tra điều kiện, thì chúng ta phải sử dụng toán tử Tiếp tục:

Trong khi (true) ( ​​​​if (checkSomething()) ( continue; ) )

Câu lệnh continue và break có thể được sử dụng với tất cả các biến thể của vòng lặp FOR và WHILE.

Các vòng lặp lồng nhau trong Arduino

Bất kỳ biến thể nào của vòng lặp đều có thể dễ dàng kết hợp với nhau, tạo thành các cấu trúc lồng nhau. Các biến được xác định trong khối của vòng lặp “nằm trên” sẽ có sẵn ở khối bên trong. Ví dụ phổ biến nhất của loại vòng lặp này là duyệt mảng hai chiều. Trong ví dụ sau, chúng ta sử dụng vòng lặp kép: vòng lặp đầu tiên sẽ lặp qua các hàng (biến i), vòng lặp thứ hai, lồng nhau, sẽ lặp qua các cột (biến j) của mảng mà chúng ta đã xác định trong biến arr.

Int mảng; void setup() ( for (int i = 0; i< 10; i++) { for (int j = 0; j < 3; j++) { arr[i][j] = i * j; Serial.println(arr[i][j]); } } }

Tìm hiểu thêm về chu kỳ

Nếu bạn chưa bao giờ làm việc với vòng lặp, hãy cùng tìm hiểu một chút về thế giới lý thuyết và tìm hiểu vòng lặp là gì và tại sao chúng ta cần những cấu trúc ngôn ngữ bí ẩn này.

Tại sao chúng ta cần một vòng lặp?

Trên thực tế, nhiệm vụ chính của vòng lặp là lặp lại cùng một cấu trúc ngôn ngữ nhiều lần. Nhu cầu này xuất hiện ở hầu hết mọi chương trình và chắc chắn không một bản phác thảo Arduino nào có thể thực hiện được nếu không có vòng lặp - hàm loop() cũng được gọi trong vòng lặp vô hạn.

Hãy xem ví dụ sau. Bạn cần cấp nguồn đồng thời cho 5 đèn LED kết nối với bo mạch Arduino từ chân 5 đến chân 9. Tùy chọn rõ ràng nhất cho việc này là đặt năm hướng dẫn liên tiếp:

digitalWrite(5, CAO);

digitalWrite(6, CAO);

digitalWrite(7, CAO);

digitalWrite(8, CAO);

digitalWrite(9, CAO);

Bây giờ chúng ta hãy bỏ qua vấn đề về tính rủi ro của hành động như vậy, bởi vì việc đưa vào đồng thời một số lượng đèn LED như vậy sẽ tạo ra tải tăng lên cho mạch điện của bo mạch. Điều quan trọng đối với chúng tôi bây giờ là chúng tôi đã tạo được năm dòng mã, mỗi dòng chỉ khác nhau một chữ số. Cách tiếp cận này có những nhược điểm sau:

  • Với bất kỳ sự thay đổi nào, bạn sẽ phải thực hiện thay đổi trên nhiều dòng cùng một lúc. Ví dụ: nếu chúng ta cần chuyển đèn LED sang chân 2 đến chân 6 hoặc tắt điện áp thay vì bật, chúng ta sẽ phải thực hiện 5 lần thay đổi mã. Nếu có thêm hướng dẫn và thay đổi thì sao?
  • Mã lớn với số lượng lớn các hướng dẫn tương tự sẽ gây bất tiện và khó đọc. Năm dòng giống hệt nhau không đáng sợ lắm. Nhưng thói quen viết code bẩn cuối cùng sẽ dẫn đến việc có thêm hàng chục, hàng trăm trang trong danh sách, điều này sẽ khiến cả bạn và đồng nghiệp đều chán nản.
  • Trong quá trình “sao chép-dán” các hướng dẫn gần như giống hệt nhau, bạn rất dễ mắc lỗi, chẳng hạn như quên thay đổi số pin: digitalWrite(5, HIGH); digitalWrite(5, CAO);
  • Bạn có thể dễ dàng trượt cuộc phỏng vấn ở bất kỳ công ty phần mềm thông thường nào nếu cho người phỏng vấn xem mã này.

Từ tất cả những điều này, chúng ta có thể kết luận rằng việc sử dụng lại cùng một chuỗi nhiều lần hầu như luôn nên tránh và thay thế bằng các vòng lặp. Hơn nữa, trong nhiều tình huống không thể thực hiện được nếu không có chu trình, không gì có thể thay thế được chúng. Bạn không thể thay đổi số lần lặp lại mã trong khi chương trình đang chạy. Ví dụ bạn cần xử lý từng phần tử mảng dữ liệu, nhận được từ các thiết bị bên ngoài. Bạn sẽ không bao giờ dự đoán được sẽ có bao nhiêu dữ liệu, quá trình xử lý sẽ được lặp lại bao nhiêu lần và do đó bạn sẽ không thể chèn đủ số lượng hướng dẫn cần thiết tại thời điểm viết bài.

Và ở đây các chu kỳ sẽ hỗ trợ chúng ta.

Quy tắc cú pháp

Vòng lặp trong Arduino là một khối chương trình đặc biệt sẽ được gọi một số lần nhất định trong quá trình thực hiện chương trình. Trong khối này, chúng tôi mô tả chính các lệnh sẽ được gọi và các quy tắc mà bộ điều khiển sẽ xác định số lần chúng cần được gọi.

Trong ví dụ trên, chúng ta có thể nói với bộ điều khiển như sau:

Lặp lại lệnh kỹ thuật sốViết 5 lần

Trong một thế giới lý tưởng có các lập trình viên robot, điều này có lẽ là đủ, nhưng vì chúng ta đang nói chuyện với máy tính bằng C++ nên chúng ta cần dịch cụm từ này sang ngôn ngữ này:

Lặp lại lệnh – bạn cần sử dụng các hướng dẫn đặc biệt để báo cho bộ điều khiển biết rằng điều gì đó thú vị sắp bắt đầu bằng vòng lặp while hoặc for

Viết kỹ thuật số – để nguyên nhưng viết một lần và đặt trong dấu ngoặc nhọn. Phải làm gì với số pin - ngay bên dưới.

5 lần – sử dụng bộ đếm cho việc này, bộ đếm sẽ tăng lên sau mỗi lần lặp lại. Ở đầu (hoặc cuối) của một khối, bạn có thể so sánh giá trị của bộ đếm này với giá trị giới hạn (trong trường hợp này là 5) bằng cách sử dụng thao tác so sánh.

Hãy xem một ví dụ về lệnh vòng lặp được "dịch" bằng câu lệnh while:

Bộ đếm int = 0; // Một biến sẽ lưu trữ giá trị bộ đếm // Chúng ta yêu cầu bộ xử lý lặp lại cấu trúc trong dấu ngoặc nhọn cho đến khi điều kiện trong ngoặc đơn trả về đúng. // Trong trường hợp của chúng ta, counter là bộ đếm của chúng ta, 5 là giá trị giới hạn, điều kiện là giá trị bộ đếm nhỏ hơn 5. // Nhưng chúng ta có thể chỉ định các toán tử logic hoàn toàn khác nhau while (counter< 5) { digitaWrite(5, HIGH); // Будем включать светодиод counter++; // Увеличиваем значение счетчика } // Дойдя до сюда, исполняющий процессор переместится в начало блока и опять займется проверкой условий. Если условия вернут истину, команды в блоке между { и } выполнятся еще раз. Если условие не выполнится - процессор переместится к концу блока и пойдет дальше. Этот цикл больше его не заинтересует.

Đối với những người nhận thấy lỗi trong mã đã cho, chúng tôi đưa ra điểm 5 và viết khối vòng lặp theo cách khác:

Trong khi (bộ đếm< 5) { // Вот теперь мы будем включать разные светодиоды, с 5 (0+5) по 9 (4+5) digitalWrite(counter + 5, HIGH); counter++; }

Có thể đạt được kết quả tương tự bằng cách sử dụng vòng lặp FOR:

For(int bộ đếm =0; bộ đếm<5; counter ++){ digitalWrite(counter+5, HIGH); }

Như bạn có thể thấy, trong trường hợp này, chúng ta đặt ngay tất cả các thao tác cần thiết với bộ đếm vào một lệnh FOR - điều này thuận tiện hơn nhiều nếu bạn cần đếm số lượng được yêu cầu.

Bạn có thể nhận thông tin chi tiết về các quy tắc sử dụng vòng lặp trong các phần liên quan của bài viết này.

Phần kết luận

Trong bài viết này, chúng ta đã xem xét các cấu trúc rất quan trọng của ngôn ngữ Arduino: vòng lặp FOR và WHILE. Bạn có thể tìm thấy các toán tử này trong hầu hết mọi bản phác thảo phức tạp ít nhiều, bởi vì nếu không có vòng lặp thì nhiều thao tác trên dữ liệu sẽ không thể thực hiện được. Cú pháp của vòng lặp không có gì phức tạp - bạn có thể dễ dàng làm quen với chúng và có thể chủ động sử dụng chúng trong các dự án của mình.

Mọi ngôn ngữ lập trình đều có một bộ hướng dẫn điều khiển cho phép thực hiện lặp lại cùng một mã (vòng lặp), lựa chọn đoạn mã thích hợp (điều kiện) và hướng dẫn thoát khỏi đoạn mã hiện tại.

Arduino IDE mượn hầu hết các điều khiển cần thiết từ C/C++. Cú pháp của chúng giống hệt C. Dưới đây chúng tôi sẽ mô tả ngắn gọn cú pháp của chúng.

câu lệnh if

Câu lệnh if cho phép bạn thực thi một đoạn cụ thể của chương trình tùy thuộc vào kết quả của việc kiểm tra một điều kiện nhất định. Nếu thỏa mãn điều kiện thì mã chương trình sẽ được thực thi, còn nếu không đáp ứng điều kiện thì mã chương trình sẽ bị bỏ qua. Cú pháp của lệnh if như sau:

Nếu(điều kiện) ( lệnh1; lệnh2; )

Điều kiện có thể là bất kỳ so sánh nào của một biến hoặc giá trị được hàm trả về. Tiêu chí chính cho điều kiện if là câu trả lời phải luôn đúng hoặc sai. Ví dụ về điều kiện cho câu lệnh if:

Nếu(a!=2) ( ) if(x<10) { } if(znak==’B’) { }

Trong dấu ngoặc được viết bên trong điều kiện, bạn có thể thực thi mã.

Những người bắt đầu học lập trình thường mắc lỗi khi đánh đồng giá trị của một biến chỉ định bằng một dấu "=". Ký hiệu như vậy biểu thị rõ ràng việc gán một giá trị biến và do đó, điều kiện sẽ luôn là “đúng”, nghĩa là được thỏa mãn. Việc kiểm tra xem một biến có bằng một giá trị nhất định luôn được biểu thị bằng dấu bằng kép (==).

Bạn có thể sử dụng trạng thái hàm làm điều kiện, ví dụ:

If(init()) ( Serial.print("ok"); )

Ví dụ trên sẽ được thực thi như sau: Trong bước đầu tiên, hàm init() được gọi. Hàm này trả về một giá trị sẽ được hiểu là "true" hoặc "false". Tùy thuộc vào kết quả so sánh, văn bản “ok” sẽ được gửi hoặc không có gì được gửi.

câu lệnh if…else

Câu lệnh if mở rộng là câu lệnh if….else. Nó đảm bảo rằng một đoạn mã được thực thi khi điều kiện đúng (đúng) và đoạn mã thứ hai được thực thi khi điều kiện không được đáp ứng (sai). Cú pháp của câu lệnh f if….else như sau:

Nếu (điều kiện) ( // lệnh A ) khác ( // lệnh B )

Lệnh "A" sẽ chỉ được thực hiện khi điều kiện được đáp ứng, lệnh "B" sẽ được thực hiện khi điều kiện không được đáp ứng. Không thể thực hiện đồng thời lệnh “A” và “B”. Ví dụ sau đây cho thấy cách sử dụng cú pháp if...else:

Nếu (init()) ( Serial.print("ok"); ) else ( Serial.print("error"); )

Bằng cách này, bạn có thể kiểm tra việc thực hiện đúng chức năng và thông báo cho người dùng về nó.

Một thực tế phổ biến là từ chối điều kiện. Điều này là do thực tế là một hàm được thực thi đúng sẽ trả về giá trị 0 và một hàm được thực thi không chính xác vì lý do nào đó sẽ trả về giá trị khác 0.

Lời giải thích cho “sự phức tạp của cuộc sống” này rất đơn giản. Nếu hàm được thực thi chính xác thì đây là thông tin duy nhất chúng ta cần. Trong trường hợp có lỗi, đôi khi bạn cần hiểu điều gì đã xảy ra và tại sao chức năng đó không được thực hiện chính xác. Và ở đây, các số khác 0 sẽ được giải cứu, tức là sử dụng mã kỹ thuật số, chúng ta có thể xác định loại lỗi. Ví dụ: 1 - vấn đề khi đọc một số giá trị, 2 - không còn chỗ trống trong bộ nhớ hoặc trên đĩa, v.v.

Ví dụ sửa đổi cuối cùng cho thấy cách gọi một hàm trả về 0 khi được thực thi đúng:

Nếu (!init()) ( Serial.print("ok"); ) else ( Serial.print("error"); )

Tuyên bố trường hợp chuyển đổi

Câu lệnh if chỉ cho phép bạn kiểm tra một điều kiện. Đôi khi cần phải thực hiện một trong các hành động tùy thuộc vào giá trị được trả về hoặc đọc. Toán tử chuyển đổi nhiều lựa chọn là lý tưởng cho việc này. Cú pháp của lệnh switch được hiển thị bên dưới:

Switch (var) ( case 1: //lệnh cho var=1 break; case 2: //lệnh cho var=2 break; mặc định: //lệnh mặc định (nếu var khác 1 và 2) )

Tùy thuộc vào giá trị của biến var, các lệnh trong các khối cụ thể sẽ được thực thi. Nhãn trường hợp cho biết phần đầu của khối đối với giá trị đã chỉ định. Ví dụ trường hợp 1: nghĩa là khối này sẽ được thực thi với giá trị của var bằng 1.

Mỗi khối phải được kết thúc bằng lệnh break. Nó làm gián đoạn việc thực thi tiếp theo của câu lệnh switch. Nếu lệnh break bị bỏ qua thì các lệnh sẽ được thực thi trong các khối tiếp theo trước lệnh break. Nhãn mặc định là tùy chọn, giống như nhãn khác trong câu lệnh if. Các lệnh nằm trong khối mặc định chỉ được thực thi khi giá trị của biến var không khớp với bất kỳ mẫu nào.

Điều thường xảy ra là các lệnh giống nhau phải được thực thi cho một trong nhiều giá trị. Điều này có thể đạt được như sau:

Switch (x) ( case 1: //lệnh ngắt x=1; case 2: case 3: case 5: //lệnh break x=2 hoặc 3 hoặc 4; case 4: //lệnh break x=4 ; trường hợp 6: // lệnh ngắt x=6; mặc định: // lệnh mặc định (nếu x khác 1,2,3,4,5,6) )

Tùy thuộc vào giá trị của biến x mà khối lệnh tương ứng sẽ được thực thi. Lặp lại trường hợp 2: trường hợp 3: trường hợp 5: thông báo cho trình biên dịch rằng nếu biến x có giá trị 2 hoặc 3 hoặc 5 thì đoạn mã tương tự sẽ được thực thi.

cho tuyên bố

Câu lệnh for được sử dụng để thực thi lặp đi lặp lại cùng một đoạn mã. Thông thường cần phải thực hiện các hướng dẫn tương tự, chỉ thay đổi giá trị của một số biến. Vòng lặp for là lý tưởng cho việc này. Cú pháp lệnh như sau:

Int tôi; vì(i=0;i<10;i++) { // инструкции для выполнения в цикле }

Tham số đầu tiên được đưa ra trong câu lệnh for là giá trị ban đầu của biến. Một phần tử khác đang kiểm tra điều kiện để tiếp tục thực hiện vòng lặp. Vòng lặp chạy miễn là điều kiện được đáp ứng. Phần tử cuối cùng là sự thay đổi giá trị của biến. Thông thường chúng ta tăng hoặc giảm giá trị của nó (nếu cần thiết). Trong ví dụ này, các lệnh chứa trong vòng lặp sẽ được thực thi tại i=0...9.

Thông thường một biến được sử dụng trong một vòng lặp được khai báo ở đó:

Vì(int i=0;i<10;i++) { // инструкции для выполнения в цикле }

Một biến được sử dụng để đếm các bước tiếp theo của vòng lặp có thể được sử dụng trong đó để gọi hàm với các tham số thích hợp.

For(int i=10;i>0;i—) ( Serial.print(i); // các số 10,9,8,7,6,5,4,3,2,1 sẽ được gửi)

câu lệnh while

Vòng lặp for là lý tưởng khi chúng ta muốn đếm. Trong tình huống mà chúng ta cần thực hiện một số hành động nhất định do một sự kiện nào đó không nhất thiết có thể dự đoán được (ví dụ: chúng ta đang đợi một nút được nhấn), thì chúng ta có thể sử dụng câu lệnh while để thực thi khối câu lệnh như miễn là điều kiện được thỏa mãn. Cú pháp của câu lệnh while như sau:

While(điều kiện) ( // khối lệnh thực thi)

Điều quan trọng là việc kiểm tra trạng thái diễn ra vào đầu chu kỳ. Có thể xảy ra trường hợp các lệnh bên trong vòng lặp while không bao giờ được thực thi. Cũng có thể tạo một vòng lặp vô hạn. Chúng ta hãy xem hai ví dụ:

Int x=2; while(x>5) ( Serial.print(x); ) ——————————————- int y=5; while(y>0) ( Serial.print(y); )

Khối câu lệnh đầu tiên nằm bên trong while sẽ không bao giờ được thực thi. Biến x có giá trị là 2 và nó sẽ không lớn hơn 5. Trong ví dụ thứ hai, chúng ta đang xử lý một vòng lặp vô hạn. Biến “y” có giá trị là 5, tức là lớn hơn 0. Không có sự thay đổi nào đối với biến "y" bên trong vòng lặp, do đó vòng lặp sẽ không bao giờ hoàn thành.

Đây là một lỗi phổ biến khi chúng ta quên thay đổi một tham số khiến vòng lặp kết thúc. Dưới đây là hai ví dụ đúng về việc sử dụng vòng lặp while:

Int x=0; trong khi(x<10) { //блок инструкций x++; } —————————————- while(true) { if(условие) break; // блок инструкций }

Trong ví dụ đầu tiên, chúng ta đã quan tâm đến việc thay đổi giá trị của biến được kiểm tra trong điều kiện. Kết quả là, chu kỳ cuối cùng sẽ kết thúc. Trong ví dụ thứ hai, một vòng lặp vô hạn được cố ý tạo ra. Vòng lặp này tương đương với hàm loop() trong Arduino IDE. Ngoài ra, việc kiểm tra điều kiện đã được đưa vào bên trong vòng lặp, sau đó vòng lặp kết thúc bằng lệnh break.

toán tử do…while

Một biến thể của vòng lặp while là vòng lặp do...while. Ngoài cú pháp, nó còn khác ở chỗ điều kiện được kiểm tra. Trong trường hợp do...while, điều kiện được kiểm tra sau khi khối lệnh được thực thi. Điều này có nghĩa là khối lệnh trong thân vòng lặp sẽ được thực thi ít nhất một lần. Dưới đây là cú pháp của lệnh do...while:

Thực hiện ( // khối lệnh ) while(điều kiện)

Mọi thứ được viết về toán tử while cũng áp dụng cho do...while. Dưới đây là một ví dụ về việc sử dụng vòng lặp do...while:

Int x=10; do ( // khối lệnh x—; ) while(x>0); —————————————- do ( // khối lệnh if (điều kiện) hỏng; ) while(true);

tuyên bố phá vỡ

Câu lệnh break cho phép bạn thoát khỏi vòng lặp (do...while, for, while) và thoát khỏi tùy chọn chuyển đổi. Trong ví dụ sau, hãy xem xét việc thực thi lệnh break:

Vì(i=0;i<10;i++) { if(i==5) break; Serial.print(i); }

Vòng lặp phải được thực thi cho các số từ 0 đến 9, nhưng đối với số 5, một điều kiện được đáp ứng sẽ kích hoạt câu lệnh break. Điều này sẽ thoát khỏi vòng lặp. Kết quả là chỉ có các số 0,1,2,3,4 được gửi tới cổng nối tiếp (Serial.print).

Tiếp tục toán tử

Toán tử continue làm cho các lệnh vòng lặp (do...while, for, while) dừng thực thi đối với giá trị hiện tại và chuyển sang bước vòng lặp tiếp theo. Ví dụ sau đây cho thấy cách hoạt động của câu lệnh continue:

Vì(i=0;i<10;i++) { if(i==5) continue; Serial.print(i); }

Không khó để nhận thấy, vòng lặp sẽ được thực thi với các giá trị từ 0 đến 9. Đối với giá trị 5, lệnh tiếp tục sẽ được thực thi, do đó các lệnh sau lệnh này sẽ không được thực thi. Kết quả là các số 0,1,2,3,4,6,7,8,9 sẽ được gửi về cổng nối tiếp (Serial.print).

tuyên bố trở lại

Câu lệnh return kết thúc việc thực thi hàm được gọi và trả về một giá trị thuộc một kiểu cụ thể. Bạn có thể chỉ định một số, một ký hiệu hoặc một biến thuộc loại cụ thể làm tham số lệnh. Điều quan trọng là giá trị trả về phải khớp với loại hàm được khai báo. Ví dụ sau đây cho thấy cách sử dụng câu lệnh return:

Int checkSensor())( if (analogRead(0) > 400) ( // đọc đầu vào analog return 1; // Đối với các giá trị lớn hơn 400, 1 được trả về else( return 0; // đối với các giá trị khác, 0 là trả lại) )

Như bạn có thể thấy, bạn có thể sử dụng nhiều câu lệnh return trong một hàm, nhưng chỉ một trong số chúng sẽ luôn hoạt động. Có thể chấp nhận sử dụng toán tử trả về không có tham số. Điều này cho phép bạn chấm dứt sớm một hàm không trả về bất kỳ giá trị nào.

Void function_name() ('guide1; if(x==0) return;''''''''''''''''''''''''''''''''''''''''''

Trong ví dụ trên, lệnh1 sẽ thực thi bất cứ khi nào hàm được gọi. Việc thực hiện lệnh 2 và lệnh 3 phụ thuộc vào kết quả của lệnh if. Nếu điều kiện đúng (true), lệnh return sẽ được thực thi và hàm sẽ thoát.

Trong trường hợp điều kiện không được đáp ứng, lệnh return cũng không được thực thi mà chỉ thị lệnh 2 và lệnh 3 được thực thi, sau đó hàm sẽ hoàn thành công việc của nó.

tuyên bố đi đến

Vì lý do ý thức hệ, cần phải bỏ qua phần mô tả này... Câu lệnh goto là một lệnh không nên được sử dụng trong lập trình thông thường. Nó gây ra sự phức tạp của mã và là một thói quen lập trình xấu. Chúng tôi thực sự khuyên bạn không nên sử dụng lệnh này trong các chương trình của mình. Vì goto được bao gồm trong tài liệu chính thức trên trang web arduino.cc nên đây là mô tả ngắn gọn về nó. Cú pháp lệnh goto:

…. đánh dấu goto; // đi đến dòng có nhãn 'metka' ....... …. metka: // nhãn mà chương trình sẽ tiếp tục hoạt động...

Lệnh cho phép bạn đi đến điểm được chỉ định, tức là đến một vị trí trong chương trình.