Циклы 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); // Постоянно вычисляется PI
}
// После оптимизации
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, особенно в задачах, где требуется высокая скорость реакции. Используя минимизацию итераций, предварительные вычисления и эффективную работу с массивами, можно значительно повысить производительность проектов.





