While Loop — калибровка датчика по нажатию кнопки
Как использовать цикл while в Arduino, чтобы калибровать аналоговый датчик по нажатию кнопки и управлять яркостью светодиода.
Иногда нужно, чтобы программа «зависла» в одном месте, пока выполняется какое-то условие — и продолжила работу сразу после его снятия. Для этого в Arduino (как и в обычном C++) есть while loop.
В этом уроке цикл while используется для автоматической калибровки calibrate аналогового датчика. Пока пользователь удерживает кнопку, скетч ищет минимальное и максимальное значения фоторезистора. Как только кнопка отпущена — управление возвращается в основной цикл loop(), и светодиод начинает плавно менять яркость в зависимости от освещённости.
Главное преимущество такого подхода: калибровку можно повторить в любой момент — просто снова нажать кнопку. Это удобно, когда условия освещения меняются.
Как это работает
В основном цикле скетч читает значение фоторезистора с аналогового пина A0 и с помощью функции map() преобразует его в диапазон 0–255 для управления яркостью светодиода на пине 9 через analogWrite().
Одновременно программа проверяет состояние кнопки на цифровом пине 2. Пока кнопка нажата (LOW или HIGH — зависит от схемы подключения), выполняется метод calibrate(). Внутри него цикл while удерживает выполнение программы и непрерывно считывает значения датчика, обновляя переменные sensorMin и sensorMax. Когда кнопка отпущена, while завершается и скетч возвращается в loop().
Необходимые компоненты
- Arduino Board
- Тактовая кнопка или переключатель
- Фоторезистор или другой аналоговый датчик
- 2 резистора по 10 кОм
- Резистор 220 Ом
- Макетная плата и провода
Схема подключения
Подключите фоторезистор к аналоговому входу A0 через делитель напряжения: один конец — к 5V, другой — к A0, а между A0 и GND поставьте резистор 10 кОм. Кнопку подключите к цифровому пину 2 аналогично — с подтягивающим резистором 10 кОм к GND. Светодиод подключите к пину 9 через токоограничивающий резистор 220 Ом последовательно.

На схеме: Arduino UNO, макетная плата, светодиод, кнопка, фоторезистор и резисторы. Обозначения пинов — A0, GND, 5V, 9, 2 — соответствуют оригинальной распиновке платы.
Принципиальная схема

На принципиальной схеме показаны: фоторезистор (PHOTORESISTOR) и резистор 10 кОм на входе A0; кнопка (PUSH BUTTON) с резистором 10 кОм на пине 2; светодиод (LED) с резистором 220 Ом на пине 9.
Код
/*
Условные операторы — while
Этот пример демонстрирует использование оператора while().
Пока кнопка нажата, скетч выполняет процедуру калибровки.
Показания датчика во время цикла while определяют минимальное и максимальное
ожидаемые значения фоторезистора.
Это вариант примера calibrate.
Схема:
- фоторезистор подключён от +5V к аналоговому входу pin 0
- резистор 10 кОм подключён от GND к аналоговому входу pin 0
- LED подключён от цифрового pin 9 к GND через резистор 220 Ом
- кнопка подключена от pin 2 к +5V
- резистор 10 кОм подключён от pin 2 к GND
создан 17 янв. 2009
изменён 30 авг. 2011
автор Tom Igoe
изменён 20 янв. 2017
автором Arturo Guadalupi
Этот пример кода находится в общественном достоянии.
https://www.arduino.cc/en/Tutorial/WhileLoop
*/
// Эти константы не изменяются:
const int sensorPin = A0; // пин, к которому подключён датчик
const int ledPin = 9; // пин, к которому подключён LED
const int indicatorLedPin = 13; // пин встроенного LED
const int buttonPin = 2; // пин, к которому подключена кнопка
// Эти переменные будут изменяться:
int sensorMin = 1023; // минимальное значение датчика
int sensorMax = 0; // максимальное значение датчика
int sensorValue = 0; // значение датчика
void setup() {
// настроить пины LED как выходы, а пин кнопки — как вход:
pinMode(indicatorLedPin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop() {
// пока кнопка нажата, считывать данные для калибровки:
while (digitalRead(buttonPin) == HIGH) {
calibrate();
}
// сигнализировать об окончании периода калибровки
digitalWrite(indicatorLedPin, LOW);
// считать значение датчика:
sensorValue = analogRead(sensorPin);
// применить калибровку к показанию датчика
sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);
// на случай, если значение датчика выходит за диапазон, зафиксированный при калибровке
sensorValue = constrain(sensorValue, 0, 255);
// изменить яркость LED с использованием откалиброванного значения:
analogWrite(ledPin, sensorValue);
}
void calibrate() {
// включить индикаторный LED, сигнализируя о выполнении калибровки:
digitalWrite(indicatorLedPin, HIGH);
// считать значение датчика:
sensorValue = analogRead(sensorPin);
// запомнить максимальное значение датчика
if (sensorValue > sensorMax) {
sensorMax = sensorValue;
}
// запомнить минимальное значение датчика
if (sensorValue < sensorMin) {
sensorMin = sensorValue;
}
}
Практические замечания
- Время калибровки — держите кнопку нажатой несколько секунд, медленно перемещая датчик между самым тёмным и самым светлым местом. Чем шире диапазон — тем точнее будет управление яркостью.
- Начальные значения — переменная
sensorMinобычно инициализируется максимально возможным значением (например, 1023), аsensorMax— нулём. Это гарантирует корректное обновление при первом же измерении. - Блокировка
loop()— пока выполняетсяwhileвнутриcalibrate(), основной цикл не работает. Это нормально для калибровки, но не подходит для задач, требующих постоянной реакции на события.
Типичные ошибки
- Светодиод не реагирует на освещение — проверьте, что калибровка была выполнена хотя бы один раз. До первого нажатия кнопки
sensorMinиsensorMaxмогут содержать одинаковые значения, иmap()вернёт некорректный результат. - Кнопка не срабатывает — убедитесь, что резистор подтяжки подключён правильно и пин настроен как
INPUTилиINPUT_PULLUPв соответствии со схемой. - Мерцание светодиода — может быть вызвано слишком узким диапазоном после калибровки. Повторите калибровку в более контрастных условиях освещения.
Дополнительные материалы
Больше базовых примеров можно найти в разделе built-in examples.
Также рекомендуем изучить language reference — подробный справочник по языку программирования Arduino.
Последнее обновление: 2015/08/11, SM