Цикли 8 — Оптимізація циклів
Вступ
Оптимізація циклів в Arduino особливо важлива, коли потрібно обробляти великі масиви даних, швидко реагувати на зовнішні події або працювати з високочастотними сигналами. Навіть незначне зменшення кількості операцій у циклі може суттєво прискорити виконання програми та зменшити навантаження на мікроконтролер.
Мінімізація кількості ітерацій
Якщо заздалегідь відомо, що пошук у масиві чи наборі даних можна завершити раніше, варто скористатися оператором break. Це скорочує час виконання та вивільняє ресурси для інших завдань.
// Пошук першого значення більше 100
for (int i = 0; i < 1000; i++) {
if (data[i] > 100) {
break; // Далі шукати не потрібно
}
}
Попередні обчислення
Обчислення всередині циклу, які не залежать від індексу, варто винести за його межі. Це зменшить кількість повторюваних операцій і прискорить виконання.
// До оптимізації
for (int i = 0; i < 100; i++) {
float val = sin(3.14159 * i / 180);
}
// Після оптимізації
float factor = 3.14159 / 180;
for (int i = 0; i < 100; i++) {
float val = sin(factor * i);
}
Робота з масивами та вказівниками
Перебір масиву за допомогою вказівників іноді може бути швидшим, ніж за індексом, особливо в великих масивах. Але такий підхід вимагає обережності, щоб уникнути виходу за межі масиву.
int arr[5] = {10, 20, 30, 40, 50};
// Перебір за індексом
for (int i = 0; i < 5; i++) {
Serial.println(arr[i]);
}
// Перебір за вказівником
for (int *ptr = arr; ptr < arr + 5; ptr++) {
Serial.println(*ptr);
}
Практика: Порівняння швидкості перебору масиву
int arr[1000];
unsigned long startTime, endTime;
void setup() {
Serial.begin(9600);
for (int i = 0; i < 1000; i++) arr[i] = i;
// За індексом
startTime = micros();
long sum1 = 0;
for (int i = 0; i < 1000; i++) {
sum1 += arr[i];
}
endTime = micros();
Serial.print("За індексом: ");
Serial.print(endTime - startTime);
Serial.println(" мкс");
// За вказівником
startTime = micros();
long sum2 = 0;
for (int *p = arr; p < arr + 1000; p++) {
sum2 += *p;
}
endTime = micros();
Serial.print("За вказівником: ");
Serial.print(endTime - startTime);
Serial.println(" мкс");
}
void loop() {
}
Проєкт: «Високошвидкісний лічильник подій»
У цьому проєкті реалізується лічильник вхідних імпульсів з оптимізованим циклом для швидкої обробки сигналів. Такий підхід корисний при роботі з датчиками обертів, енкодерами або іншими джерелами швидких імпульсів.
const byte inputPin = 2;
volatile unsigned long pulseCount = 0;
unsigned long prevMillis = 0;
const unsigned long interval = 1000; // 1 секунда
void IRAM_ATTR countPulse() {
pulseCount++;
}
void setup() {
Serial.begin(115200);
pinMode(inputPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(inputPin), countPulse, RISING);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - prevMillis >= interval) {
prevMillis = currentMillis;
Serial.print("Подій за секунду: ");
Serial.println(pulseCount);
pulseCount = 0;
}
}
Висновок
Оптимізація циклів — важливий навик у роботі з Arduino, особливо коли потрібна висока швидкість реакції. Використовуючи мінімізацію ітерацій, попередні обчислення та ефективну роботу з масивами, можна суттєво підвищити продуктивність проєктів.





