Список команд Arduino: синтаксис, примеры и частые ошибки
Команды Arduino с примерами и подводными камнями: pinMode, digitalWrite, analogRead, analogWrite, millis, Serial, map, tone, pulseIn и attachInterrupt.
Команды Arduino — это готовые функции, которые говорят плате, что делать: pinMode() делает пин выходом, digitalWrite() зажигает светодиод, analogRead() читает датчик, а Serial.println() отправляет сообщение на компьютер. Большинство скетчей Arduino на самом деле — это два десятка базовых команд, по-разному сочетающихся друг с другом. Когда ты понимаешь эти команды и их смысл, можно прочитать любой встретившийся код, от мигающего светодиода до робот-машинки, и написать собственный проект с нуля.
В этом руководстве самые используемые команды Arduino разбиты на четыре категории: ввод-вывод, время, математика и связь. Для каждой команды есть синтаксис, значение параметров, короткий пример, который компилируется и работает на Arduino Uno, и ошибка, которую новички делают чаще всего. В последних разделах посмотрим ещё, чем те же команды отличаются на ESP32 и какие у них аналоги на MicroPython для Raspberry Pi Pico.

Что такое команда Arduino и как выполняется скетч?
Код Arduino построен на C/C++; большинство того, что мы называем «командами», на самом деле функции, которые предоставляет ядро Arduino. Функция принимает параметры в скобках (например, номер пина и значение), а некоторые из них возвращают результат: digitalRead() даёт состояние пина, millis() — прошедшее время. В каждом скетче Arduino две обязательные функции: setup() выполняется один раз, когда плата включается или сбрасывается, а loop() затем повторяется бесконечно. Подготовка вроде настройки пинов и Serial.begin() идёт в setup(), а работа, которая должна выполняться постоянно, — в loop().
1// Her Arduino programı bu iki fonksiyondan oluşur / Every Arduino sketch has these two functions
2void setup() {
3 // Açılışta ya da resetten sonra bir kez çalışır / Runs once at power-up or after reset
4 pinMode(13, OUTPUT); // dahili LED pini çıkış / built-in LED pin as output
5}
6
7void loop() {
8 // Sonsuza kadar tekrar eder / Repeats forever
9 digitalWrite(13, HIGH); // LED'i yak / turn the LED on
10 delay(500); // 500 ms bekle / wait 500 ms
11 digitalWrite(13, LOW); // LED'i söndür / turn the LED off
12 delay(500);
13}Если с самого начала помнить три правила, можно избежать многих ошибок компиляции: команды чувствительны к регистру (если написать digitalwrite, получишь ошибку «'digitalwrite' was not declared in this scope» — имя не объявлено), каждая инструкция заканчивается точкой с запятой, а текст пишется в двойных кавычках, тогда как отдельные символы — в одинарных. О типах переменных и конструкциях вроде if и for читай в статье Основы программирования Arduino.
Список команд Arduino: таблицы по категориям
Четыре таблицы ниже охватывают почти все команды, которые понадобятся в повседневных проектах. Первая группа — команды ввода-вывода; они задают роль пина, подают на него напряжение или читают с него значение. Номера пинов своей платы можно посмотреть в утилите «Распиновка».
| Команда | Синтаксис | Что делает | Пример |
|---|---|---|---|
| pinMode | pinMode(пин, режим) | Делает пин входом или выходом | pinMode(13, OUTPUT); |
| digitalWrite | digitalWrite(пин, значение) | Ставит на пине HIGH (5 V) или LOW (0 V) | digitalWrite(13, HIGH); |
| digitalRead | digitalRead(пин) | Читает, HIGH на пине или LOW | int b = digitalRead(2); |
| analogRead | analogRead(пин) | Превращает напряжение 0–5 V в число от 0 до 1023 | int v = analogRead(A0); |
| analogWrite | analogWrite(пин, значение) | Генерирует сигнал PWM от 0 до 255 | analogWrite(9, 128); |
| analogReference | analogReference(тип) | Выбирает опорное напряжение для analogRead | analogReference(INTERNAL); |
| tone / noTone | tone(пин, частота, длительность) | Издаёт звук меандром; noTone его останавливает | tone(8, 440, 500); |
| pulseIn | pulseIn(пин, значение, таймаут) | Измеряет длительность импульса в µs | pulseIn(10, HIGH, 30000); |
| shiftOut | shiftOut(пинДанных, пинТактов, порядок, байт) | Отправляет байт по одному биту (например, в 74HC595) | shiftOut(11, 12, MSBFIRST, 255); |
| attachInterrupt | attachInterrupt(прерывание, функция, режим) | Вызывает функцию в момент изменения пина | attachInterrupt(digitalPinToInterrupt(2), say, FALLING); |
Вторая группа — команды времени. Понять разницу между delay(), которая ждёт, и millis() и micros(), которые измеряют время, — ключ к скетчу, работающему без заминок.
| Команда | Синтаксис | Что делает | Внимание |
|---|---|---|---|
| delay | delay(мс) | Ждёт заданное число миллисекунд | Программа в это время стоит |
| delayMicroseconds | delayMicroseconds(мкс) | Ждёт заданное число микросекунд | Точна от 3 до 16383 µs |
| millis | millis() | Возвращает миллисекунды с момента запуска | unsigned long; переполняется примерно через 49,7 дня |
| micros | micros() | Возвращает микросекунды с момента запуска | На Uno шаг 4 µs, переполняется примерно через 70 минут |
Третья группа — математические команды; ими переводят показание датчика в другой диапазон, ограничивают его или генерируют случайное число. Четвёртая группа, команды связи, позволяет плате обмениваться данными с компьютером и другими устройствами.
| Команда | Синтаксис | Что делает | Пример результата |
|---|---|---|---|
| map | map(x, отНиз, отВерх, вНиз, вВерх) | Пересчитывает один диапазон в другой | map(512, 0, 1023, 0, 255) → 127 |
| constrain | constrain(x, нижн, верхн) | Держит значение между двумя границами | constrain(300, 0, 255) → 255 |
| min / max | min(a, b) / max(a, b) | Возвращает меньшее или большее значение | min(7, 3) → 3 |
| abs | abs(x) | Абсолютное значение (модуль) | abs(-12) → 12 |
| pow / sqrt / sq | pow(основание, степень), sqrt(x), sq(x) | Степень, квадратный корень, квадрат | pow(2, 10) → 1024.0 |
| random | random(мин, макс) | Случайное целое число (макс не входит) | random(1, 7) → от 1 до 6 |
| randomSeed | randomSeed(зерно) | Меняет начальную точку случайной последовательности | randomSeed(analogRead(A3)); |
| Команда | Что делает | Пример |
|---|---|---|
| Serial.begin(скорость) | Открывает последовательный порт на заданной скорости в бодах | Serial.begin(9600); |
| Serial.print(данные) | Выводит данные и остаётся на той же строке | Serial.print(temperature); |
| Serial.println(данные) | Выводит данные и переходит на новую строку | Serial.println("Hello"); |
| Serial.available() | Возвращает число байтов, ожидающих чтения | if (Serial.available() > 0) |
| Serial.read() | Читает один байт, возвращает -1, если данных нет | char c = Serial.read(); |
| Serial.readStringUntil(c) | Читает текст до заданного символа | String s = Serial.readStringUntil('\n'); |
| Serial.parseInt() | Извлекает целое число из пришедшего текста | int n = Serial.parseInt(); |
| Serial.write(байт) | Отправляет сырой байт | Serial.write(65); // 'A' |
| Wire.begin() | Запускает шину I2C (Wire.h) | Wire.begin(); |
| SPI.begin() | Запускает шину SPI (SPI.h) | SPI.begin(); |
pinMode(): задаём роль пина
pinMode(pin, mode) сообщает плате, будет цифровой пин входом или выходом, и обычно пишется один раз в setup(). Режимов три: OUTPUT делает пин выходом (чтобы управлять светодиодом, зуммером или реле), INPUT — высокоомным входом (для схем с внешним подтягивающим или стягивающим резистором), а INPUT_PULLUP — входом с подключённым к 5 V внутренним резистором около 20–50 kΩ. Аналоговые пины (A0–A5) тоже можно использовать как цифровые через pinMode; например, pinMode(A0, OUTPUT) — правильная команда.
digitalWrite() и digitalRead(): цифровой выход и вход
digitalWrite(pin, HIGH) на Uno поднимает выходной пин до 5 V, а digitalWrite(pin, LOW) опускает до 0 V. Брать с пина до 20 mA безопасно (абсолютный максимум — 40 mA); светодиод всегда подключай с резистором, а нужный номинал найдёшь в калькуляторе резистора для светодиода. digitalRead(pin) смотрит на напряжение на пине и возвращает HIGH или LOW; на Uno примерно всё выше 3 V считается HIGH, а всё ниже 1,5 V — LOW. В примере ниже встроенный светодиод загорается, когда нажимаешь кнопку, подключённую к D2:
1const int BUTON_PIN = 2; // buton: bir ucu D2, diğer ucu GND / button: one leg to D2, the other to GND
2const int LED_PIN = 13; // dahili LED / built-in LED
3
4void setup() {
5 pinMode(BUTON_PIN, INPUT_PULLUP); // dahili pull-up direnci açık / internal pull-up resistor enabled
6 pinMode(LED_PIN, OUTPUT);
7}
8
9void loop() {
10 int durum = digitalRead(BUTON_PIN); // HIGH ya da LOW döner / returns HIGH or LOW
11 if (durum == LOW) { // pull-up ile basılı = LOW / with pull-up, pressed = LOW
12 digitalWrite(LED_PIN, HIGH);
13 } else {
14 digitalWrite(LED_PIN, LOW);
15 }
16}С INPUT_PULLUP логика инвертирована: когда кнопка отпущена, пин благодаря внутреннему резистору читает HIGH, а когда нажата — LOW, потому что соединён с GND. Если подключить кнопку без резистора в режиме INPUT, пин висит в воздухе, и digitalRead() возвращает случайные значения; результат может измениться даже от приближения руки. О дребезге кнопок и правильных способах подключения читай в статье Как подключить кнопку к Arduino.
analogRead() и analogWrite(): аналоговый вход и PWM
analogRead(pin) с помощью 10-битного преобразователя (АЦП) превращает напряжение от 0 до 5 V на пинах A0–A5 в число от 0 до 1023. Одно измерение занимает около 100 µs, так что можно делать примерно 10 000 измерений в секунду. Чтобы перевести число в напряжение, используют value × 5.0 / 1023; показание 512, например, означает около 2,5 V. Опорное напряжение можно изменить через analogReference(): вариант INTERNAL использует внутреннее опорное 1,1 V у Uno и повышает разрешение для малых напряжений. Подробности о разрешении и опорном напряжении — в статье АЦП и аналого-цифровое преобразование.
Вопреки названию, analogWrite(pin, value) не выдаёт настоящее аналоговое напряжение. Она очень быстро включает и выключает пин, создавая сигнал PWM: 0 — всегда выключен, 255 — всегда включён, а 127 — примерно половину времени включён. Из-за этого среднего значения светодиод кажется нам горящим вполсилы, а мотор крутится медленно. На Uno PWM дают только пины 3, 5, 6, 9, 10 и 11, отмеченные на плате знаком ~; частота на большинстве пинов 490 Hz, а на пинах 5 и 6 — 980 Hz. analogWrite() сама делает пин выходом, так что pinMode не обязателен. Код ниже задаёт яркость светодиода потенциометром и выводит показание вместе с напряжением в монитор порта; подробности о коэффициенте заполнения и частоте — в статье Что такое PWM?
1const int POT_PIN = A0; // potansiyometrenin orta bacağı / potentiometer wiper
2const int LED_PIN = 9; // ~9 PWM pini + 220 ohm direnç / ~9 PWM pin + 220 ohm resistor
3
4void setup() {
5 Serial.begin(9600);
6}
7
8void loop() {
9 int ham = analogRead(POT_PIN); // 0-1023 arası / between 0 and 1023
10 float volt = ham * (5.0 / 1023.0); // sayıyı gerilime çevir / convert the reading to volts
11 analogWrite(LED_PIN, ham / 4); // 0-1023 -> 0-255 PWM parlaklığı / 0-1023 -> 0-255 PWM brightness
12
13 Serial.print(F("Ham / raw: "));
14 Serial.print(ham);
15 Serial.print(F(" Gerilim / voltage: "));
16 Serial.print(volt, 2); // 2 ondalık basamak / 2 decimal places
17 Serial.println(F(" V"));
18 delay(200);
19}delay(), millis() и micros(): команды времени
delay(ms) ждёт заданное число миллисекунд, и в это время ни одна другая строка в loop() не выполняется; delay(1000) — это целая секунда паузы. Для коротких пауз в микросекундах есть delayMicroseconds(), которая точна от 3 до 16383 µs. millis(), напротив, не ждёт; она возвращает время с момента запуска платы в миллисекундах. Всегда храни результат в переменной unsigned long: если взять int, на Uno значение переполнится, как только превысит 32 767, то есть примерно через 33 секунды, и отсчёт времени сломается. Примерно каждые 49,7 дня millis() снова начинается с нуля; способ с вычитанием ниже правильно работает и через этот переход.
1const int LED_PIN = 13;
2const unsigned long ARALIK = 500; // yanıp sönme aralığı (ms) / blink interval (ms)
3unsigned long oncekiZaman = 0; // son değişim anı / time of the last toggle
4
5void setup() {
6 pinMode(LED_PIN, OUTPUT);
7}
8
9void loop() {
10 unsigned long simdi = millis();
11 if (simdi - oncekiZaman >= ARALIK) { // taşmada da doğru çalışır / safe across overflow
12 oncekiZaman = simdi;
13 digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // LED'i tersine çevir / toggle the LED
14 }
15 // Burada buton, sensör ve ekran işleri de yapılabilir / button, sensor and display tasks can run here
16}С таким шаблоном loop() никогда не останавливается; пока светодиод мигает, в том же цикле можно читать кнопку, измерять датчик и обновлять дисплей. micros() работает так же, но в микросекундах; на Uno она идёт шагами по 4 µs и переполняется примерно через 70 минут. Как выполнять несколько задач одновременно, подробно разбираем в статье millis() и delay() в Arduino.
Serial.begin(), Serial.print() и Serial.read(): последовательная связь
Команды Serial позволяют Arduino общаться с компьютером по USB-кабелю, и это твой главный инструмент отладки. Serial.begin(9600) открывает последовательный порт на скорости 9600 бит в секунду; если скорость в мониторе порта не совпадает, на экране будут непонятные символы. Serial.print() выводит данные и остаётся на той же строке, а Serial.println() после вывода переходит на новую. Второй параметр выбирает формат: Serial.print(78, HEX) выводит «4E», Serial.print(78, BIN) — «1001110», а Serial.print(3.14159, 3) показывает «3.142» (по умолчанию у дробных чисел 2 знака после запятой). Постоянный текст внутри F("...") экономит место в 2 КБ ОЗУ у Uno.
Чтобы читать данные, сначала через Serial.available() проверяют, есть ли в буфере ожидающие байты; приёмный буфер Uno — 64 байта. Serial.read() берёт из буфера один байт и возвращает -1, если читать нечего. Код ниже включает и выключает светодиод символами 1 и 0, отправленными из монитора порта:
1const int LED_PIN = 13;
2
3void setup() {
4 Serial.begin(9600); // Seri Monitör de 9600 olmalı / Serial Monitor must be 9600 too
5 pinMode(LED_PIN, OUTPUT);
6 Serial.println(F("1: LED açık / on, 0: LED kapalı / off"));
7}
8
9void loop() {
10 if (Serial.available() > 0) { // tamponda bayt var mı? / any bytes waiting?
11 char c = Serial.read(); // ilk baytı al / read the first byte
12 if (c == '1') { // '1' karakteri, 1 sayısı değil / the character '1', not the number 1
13 digitalWrite(LED_PIN, HIGH);
14 Serial.println(F("LED açık / on"));
15 } else if (c == '0') {
16 digitalWrite(LED_PIN, LOW);
17 Serial.println(F("LED kapalı / off"));
18 }
19 // '\n' ve '\r' gibi diğer karakterler atlanır / other characters such as '\n' and '\r' are ignored
20 }
21}Обрати внимание: сравнение идёт с '1' (в одинарных кавычках, то есть с символом): набранная на клавиатуре 1 соответствует в таблице ASCII числу 49, так что условие c == 1 никогда не выполнится. Для многозначных чисел можно использовать Serial.parseInt(), а чтобы забрать целую строку — Serial.readStringUntil('\n'). О настройках конца строки, скорости и плоттере монитора порта читай в статье Как пользоваться монитором порта Arduino.
map() и constrain(): масштабирование и ограничение значений
map(value, fromLow, fromHigh, toLow, toHigh) пропорционально переносит число из одного диапазона в другой. За ней стоит формула: (x − fromLow) × (toHigh − toLow) / (fromHigh − fromLow) + toLow. Например, map(512, 0, 1023, 0, 255) возвращает 127, а не 127.6, потому что map() работает только с целыми числами и отбрасывает дробную часть. Обратную зависимость можно получить, поменяв местами границы целевого диапазона: map(x, 0, 1023, 255, 0). map() не ограничивает результат; если вход выходит за заданный диапазон, выход тоже выходит за него. Поэтому её обычно сочетают с constrain(x, low, high).
1const int LDR_PIN = A0; // LDR + 10k gerilim bölücü / LDR + 10k voltage divider
2const int LED_PIN = 9; // ~9 PWM pini / ~9 PWM pin
3
4void setup() {
5 pinMode(LED_PIN, OUTPUT);
6}
7
8void loop() {
9 int isik = analogRead(LDR_PIN); // odada ölçülen aralık ~200-800 / measured range in the room ~200-800
10 int pwm = map(isik, 200, 800, 255, 0); // karanlıkta parlak, aydınlıkta sönük / bright in the dark, dim in the light
11 pwm = constrain(pwm, 0, 255); // aralık dışı değerleri kes / clip out-of-range values
12 analogWrite(LED_PIN, pwm);
13 delay(20);
14}В этом примере фоторезистор (LDR) в комнате даёт значения от 200 до 800. Если ночью показание падает до 100, map() вычисляет 297; без constrain() analogWrite() получила бы это значение вне диапазона 0–255. На Uno такое значение в зависимости от пина даёт разные неожиданные результаты: на пинах 3, 5, 6 и 11, использующих 8-битные таймеры, 297 переполняется и ведёт себя как 41, так что в полной темноте светодиод почти гаснет вместо того, чтобы ярко гореть. Поскольку на Uno constrain(), min(), max() и abs() определены как макросы, не пиши внутри скобок x++ или другой вызов функции: выражение может вычисляться несколько раз и давать неожиданные результаты. О подключении фоторезистора читай в статье Фоторезистор (LDR).
tone() и noTone(): звук с зуммером
tone(pin, frequency, duration) генерирует на пине меандр с заполнением 50% и заставляет пассивный зуммер или небольшой динамик звучать на этой частоте. Длительность задаётся в миллисекундах и не обязательна; без неё звук продолжается, пока не вызовешь noTone(pin). Важная деталь: tone() не ждёт; она запускает звук и сразу переходит к следующей строке. Поэтому, играя ноты одну за другой, после каждого вызова tone() нужна delay() не короче ноты, иначе услышишь только последнюю ноту.
1const int BUZZER_PIN = 8; // pasif buzzer'ın + ucu / passive buzzer + leg
2
3void setup() {
4 int notalar[] = {262, 294, 330, 349, 392}; // Do Re Mi Fa Sol (Hz) / C D E F G (Hz)
5 for (int i = 0; i < 5; i++) {
6 tone(BUZZER_PIN, notalar[i], 200); // 200 ms çal / play for 200 ms
7 delay(250); // tone() beklemez, sen bekle / tone() does not wait, so you do
8 }
9 noTone(BUZZER_PIN); // sesi kapat / stop the sound
10}
11
12void loop() {
13}- Пределы частоты: на Uno тоны ниже 31 Hz не генерируются, а верхний предел — 65 535 Hz; полезный диапазон с зуммером — примерно 100–5000 Hz.
- Один звук за раз: тон может играть только на одном пине одновременно; чтобы издать звук на другом пине, сначала останови предыдущий через noTone().
- Конфликт с PWM: на Uno tone() использует Timer2, поэтому пока звучит звук, analogWrite() на пинах 3 и 11 сбивается.
- Активный зуммер: у него свой генератор, поэтому его частоту через tone() не изменить; активный зуммер просто включай и выключай через digitalWrite(). О различиях читай в статье Что такое зуммер?
pulseIn(): измеряем длительность импульса
pulseIn(pin, HIGH) ждёт, пока пин уйдёт в HIGH, измеряет, сколько он остаётся в HIGH, и возвращает результат в микросекундах; можно измерять импульсы длительностью от 10 µs до 3 минут. Самое известное применение — ультразвуковой датчик расстояния HC-SR04: датчик выдаёт импульс длиной во время, которое звук тратит на путь туда и обратно. Звук распространяется в воздухе со скоростью около 343 м/с, или 0,0343 см/µs; поскольку путь двойной, расстояние = длительность × 0.0343 / 2.
1const int TRIG_PIN = 9;
2const int ECHO_PIN = 10;
3
4void setup() {
5 Serial.begin(9600);
6 pinMode(TRIG_PIN, OUTPUT);
7 pinMode(ECHO_PIN, INPUT);
8}
9
10void loop() {
11 digitalWrite(TRIG_PIN, LOW);
12 delayMicroseconds(2);
13 digitalWrite(TRIG_PIN, HIGH); // 10 µs tetik darbesi / 10 µs trigger pulse
14 delayMicroseconds(10);
15 digitalWrite(TRIG_PIN, LOW);
16
17 unsigned long sure = pulseIn(ECHO_PIN, HIGH, 30000UL); // en fazla 30 ms bekle / wait at most 30 ms
18 if (sure == 0) {
19 Serial.println(F("Menzil dışı / out of range"));
20 } else {
21 float mesafe = sure * 0.0343 / 2.0; // ses hızı 343 m/s, gidiş-dönüş / speed of sound 343 m/s, round trip
22 Serial.print(mesafe, 1);
23 Serial.println(F(" cm"));
24 }
25 delay(100);
26}Третий параметр, таймаут, очень важен. Без него pulseIn() при отсутствии импульса ждёт 1 секунду и возвращает 0; если провод датчика отошёл, вся программа на каждом проходе цикла замирает на секунду. Таймаут 30000 µs соответствует примерно 5 метрам, чего хватает для дальности HC-SR04 в 4 метра. О подключении и точности датчика читай в статье Датчик расстояния HC-SR04.
attachInterrupt(): мгновенная реакция через прерывания
attachInterrupt(digitalPinToInterrupt(pin), function, mode) запускает указанную функцию в момент изменения пина, чем бы ни был занят loop() в это время. Такая функция называется обработчиком прерывания (ISR). Режим может принимать четыре значения: RISING срабатывает на переход из LOW в HIGH, FALLING — из HIGH в LOW, CHANGE — на любое изменение, а LOW — всё время, пока на пине LOW. На Uno и Nano так вызывать прерывания могут только пины D2 и D3; на Mega — пины 2, 3, 18, 19, 20 и 21. Это идеально, чтобы не пропустить быстро вращающийся энкодер, импульсы анемометра или очень короткое нажатие кнопки.
1const int BUTON_PIN = 2; // Uno'da kesme pinleri: 2 ve 3 / interrupt pins on the Uno: 2 and 3
2volatile unsigned long sayac = 0; // ISR'de değişen değişken volatile olmalı / variables changed in an ISR must be volatile
3
4void say() { // kesme fonksiyonu (ISR): kısa tut / interrupt service routine: keep it short
5 sayac++;
6}
7
8void setup() {
9 Serial.begin(9600);
10 pinMode(BUTON_PIN, INPUT_PULLUP);
11 attachInterrupt(digitalPinToInterrupt(BUTON_PIN), say, FALLING); // HIGH'dan LOW'a geçişte / on a HIGH-to-LOW edge
12}
13
14void loop() {
15 noInterrupts(); // 4 baytlık değeri güvenle kopyala / copy the 4-byte value safely
16 unsigned long kopya = sayac;
17 interrupts();
18
19 Serial.print(F("Basma sayısı / presses: "));
20 Serial.println(kopya);
21 delay(500);
22}random() и randomSeed(): генерация случайных чисел
random(max) возвращает случайное целое число от 0 до max−1, а random(min, max) — от min до max−1; верхняя граница в результат не входит. Поэтому для кубика от 1 до 6 пишут random(1, 7). Arduino не создаёт настоящую случайность; она вычисляет последовательность чисел по фиксированной формуле, так что если не вызвать randomSeed(), при каждом запуске платы будут те же числа в том же порядке. На практике это решается шумом неподключённого аналогового пина в качестве зерна:
1void setup() {
2 Serial.begin(9600);
3 randomSeed(analogRead(A3)); // boştaki A3 pininin gürültüsü / noise from the unconnected A3 pin
4}
5
6void loop() {
7 int zar = random(1, 7); // 1-6 arası; üst sınır dahil değil / 1 to 6; the upper bound is exclusive
8 Serial.print(F("Zar / dice: "));
9 Serial.println(zar);
10 delay(1000);
11}Команды Arduino на ESP32: на что обратить внимание
ESP32 программируется в Arduino IDE теми же командами, и большая часть кода из этой статьи работает сразу, стоит лишь поменять номера пинов. Но из-за другого железа некоторые команды ведут себя иначе. Главное отличие — напряжение: пины ESP32 работают на 3,3 V, digitalWrite(pin, HIGH) выдаёт 3,3 V, а сигналы 5 V подключать к пинам напрямую нельзя. Чтобы лучше узнать плату, загляни в статью Что такое ESP32?
| Команда | Arduino Uno | ESP32 |
|---|---|---|
| digitalWrite(pin, HIGH) | 5 V | 3,3 V |
| analogRead() | 10 бит, 0–1023, A0–A5 | 12 бит, 0–4095; при включённом Wi-Fi только пины ADC1 (GPIO 32–39) |
| analogWrite() | Только пины ~ (3, 5, 6, 9, 10, 11), 490/980 Hz | Почти любой GPIO, способный работать на выход; частота задаётся через ledcAttach(pin, freq, resolution) |
| attachInterrupt() | Только D2 и D3 | Все GPIO; добавь к ISR IRAM_ATTR |
| tone() | Использует Timer2, сбивает PWM на 3 и 11 | Работает на аппаратном блоке LEDC |
| Serial.begin() | Обычно 9600 | Обычно 115200 (на этой скорости идут и сообщения загрузки) |
| delay() | Полностью занимает процессор ожиданием | Отдаёт время FreeRTOS; Wi-Fi продолжает работать в фоне |
1const int POT_PIN = 34; // ADC1 pini, Wi-Fi açıkken de okur / ADC1 pin, works with Wi-Fi on
2const int LED_PIN = 2; // çoğu DevKit'te dahili LED / onboard LED on most DevKits
3const int BUTON_PIN = 4; // butonun diğer ucu GND / other button leg to GND
4
5volatile bool basildi = false;
6
7void IRAM_ATTR butonISR() { // ESP32'de ISR IRAM'e yerleşmeli / on the ESP32 the ISR should live in IRAM
8 basildi = true;
9}
10
11void setup() {
12 Serial.begin(115200);
13 pinMode(BUTON_PIN, INPUT_PULLUP);
14 attachInterrupt(digitalPinToInterrupt(BUTON_PIN), butonISR, FALLING); // her GPIO kesme destekler / every GPIO supports interrupts
15}
16
17void loop() {
18 int ham = analogRead(POT_PIN); // 0-4095 (12 bit)
19 analogWrite(LED_PIN, map(ham, 0, 4095, 0, 255)); // 8 bit PWM / 8-bit PWM
20 if (basildi) {
21 basildi = false;
22 Serial.println("Butona basıldı / button pressed");
23 }
24 Serial.println(ham);
25 delay(200);
26}Поскольку analogRead() на ESP32 возвращает 0–4095, диапазон map() меняется соответственно. IRAM_ATTR перед ISR помещает код в быструю внутреннюю память; без него плата в некоторых ситуациях может перезагрузиться с ошибкой «Guru Meditation Error». Аналоговые показания ESP32 нелинейны у краёв диапазона (около 0 V и 3,3 V); если нужно более точное измерение, функция analogReadMilliVolts() возвращает откалиброванное значение в милливольтах.
Raspberry Pi Pico: аналоги команд Arduino на MicroPython
Если программировать Raspberry Pi Pico в Arduino IDE (ядро arduino-pico), все команды из этой статьи работают под теми же именами; analogRead() по умолчанию возвращает 10 бит, а analogWrite() даёт PWM 1 kHz. Однако большинство используют Pico с MicroPython. Там команды пишутся через объекты модулей machine и time; логика та же, меняется только синтаксис. Пины Pico тоже на 3,3 V, а аналоговые входы — пины GP26, GP27 и GP28. Для начала загляни в статью Что такое Raspberry Pi Pico?
| Команда Arduino | Аналог на MicroPython | Примечание |
|---|---|---|
| pinMode(15, OUTPUT) | led = Pin(15, Pin.OUT) | Объект Pin создаётся один раз |
| pinMode(14, INPUT_PULLUP) | btn = Pin(14, Pin.IN, Pin.PULL_UP) | Встроенный подтягивающий резистор |
| digitalWrite(15, HIGH) | led.value(1) | Работает и led.on() |
| digitalRead(14) | btn.value() | Возвращает 0 или 1 |
| analogRead(A0) | ADC(26).read_u16() | Возвращает 0–65535 |
| analogWrite(15, 128) | PWM(Pin(15)).duty_u16(32768) | Заполнение от 0 до 65535 |
| delay(500) | time.sleep_ms(500) | Работает и time.sleep(0.5) |
| millis() | time.ticks_ms() | Для разности используй time.ticks_diff() |
| Serial.println(x) | print(x) | Выводится в оболочке Thonny |
| tone(pin, 440) | pwm.freq(440) и pwm.duty_u16(32768) | Заглушить: duty_u16(0) |
| pulseIn(pin, HIGH, 30000) | machine.time_pulse_us(pin, 1, 30000) | При таймауте возвращает отрицательное значение |
| attachInterrupt(...) | btn.irq(trigger=Pin.IRQ_FALLING, handler=f) (по спаду сигнала) | f получает объект пина как параметр |
| random(1, 7) | random.randint(1, 6) | Верхняя граница входит |
| map() / constrain() | Встроенных нет, пишутся вручную | Для constrain: min(max(x, 0), 255) |
1from machine import Pin, ADC, PWM
2import time
3
4led = PWM(Pin(15)) # pinMode + analogWrite karşılığı / pinMode + analogWrite equivalent
5led.freq(1000) # 1 kHz PWM
6buton = Pin(14, Pin.IN, Pin.PULL_UP) # INPUT_PULLUP karşılığı / INPUT_PULLUP equivalent
7pot = ADC(26) # GP26 = ADC0
8
9def map_deger(x, giris_min, giris_max, cikis_min, cikis_max): # Arduino map() karşılığı / Arduino map() equivalent
10 return (x - giris_min) * (cikis_max - cikis_min) // (giris_max - giris_min) + cikis_min
11
12onceki = time.ticks_ms() # millis() karşılığı / millis() equivalent
13while True:
14 ham = pot.read_u16() # 0-65535 (analogRead)
15 led.duty_u16(ham) # parlaklık / brightness (analogWrite)
16 if buton.value() == 0: # digitalRead; basılı = 0 / pressed = 0
17 print("Butona basıldı / button pressed")
18 if time.ticks_diff(time.ticks_ms(), onceki) >= 1000: # saniyede bir / once a second
19 onceki = time.ticks_ms()
20 print("Yüzde / percent:", map_deger(ham, 0, 65535, 0, 100))
21 time.sleep_ms(50) # delay(50)Как видно из таблицы, random.randint(1, 6) в MicroPython включает верхнюю границу и даёт тот же результат, что random(1, 7) на Arduino; time.ticks_diff() обеспечивает ту же защиту от переполнения, что и вычитание с millis(). Именно эти мелкие различия больше всего путают при переходе между двумя платформами. О других базовых командах MicroPython читай в статье Основы MicroPython.
Идеи проектов на этих командах
- Светофор: зажигай по очереди три светодиода с помощью pinMode(), digitalWrite() и delay(); пошагово объясняем в статье Светофор на Arduino.
- Электронный кубик: генерируй число от 1 до 6 через random() и при нажатии кнопки показывай результат светодиодами или на 7-сегментном индикаторе.
- Парктроник: измеряй расстояние через pulseIn(), превращай его в интервал сигнала через map() и подавай предупреждение через tone().
- Автоматический ночник: читай уровень освещённости через analogRead() и задавай яркость analogWrite() с помощью map() и constrain().
- Пульт через последовательный порт: управляй светодиодом, реле или сервоприводом командами с компьютера через Serial.read().
- Тест реакции: зажигай светодиод в случайный момент через random() и измеряй время своей реакции на кнопку с точностью до миллисекунды через attachInterrupt() и millis().
Частые ошибки и как их исправить
| Ошибка | Симптом | Решение |
|---|---|---|
| Забыт pinMode() | Светодиод очень тусклый или вовсе не горит | Напиши pinMode(pin, OUTPUT) в setup() |
| Кнопка без резистора в режиме INPUT | digitalRead() возвращает случайные 0 и 1 | Используй INPUT_PULLUP; при нажатии читается LOW |
| Опечатка в имени команды | 'digitalwrite' was not declared in this scope (имя не объявлено) | Следи за регистром букв: digitalWrite |
| Не совпадает скорость | Непонятные символы в мониторе порта | Выставь в мониторе порта ту же скорость, что в Serial.begin() |
| analogWrite() на пине без PWM | Светодиод только полностью горит или полностью гаснет | Используй пин со знаком ~ (3, 5, 6, 9, 10, 11) |
| millis() хранится в int | Отсчёт времени ломается примерно через 33 секунды | Используй unsigned long |
| Кубик на random(1, 6) | Шестёрка (6) никогда не выпадает | Пиши random(1, 7); верхняя граница не входит |
| Ожидание дробей от map() | Результат всегда целый, мелкие изменения теряются | При необходимости напиши свою формулу с float |
| pulseIn() без таймаута | Без датчика каждый проход цикла замирает на 1 секунду | Передай 30000 третьим параметром |
| delay() или Serial внутри ISR | Программа зависает или ведёт себя странно | В ISR меняй только флаг volatile |
Команды из этой статьи — строительные блоки большинства проектов на Arduino; остальное — в основном дополнительные функции из библиотек. Если попробовать каждую команду в своей маленькой схеме и увидеть результат в мониторе порта, они запомнятся гораздо лучше, чем при заучивании. В приложении BlueGrays есть проекты, использующие эти команды: зажигание светодиода, управление светодиодом кнопкой, измерение света фоторезистором, настройка частоты зуммера, измерение расстояния HC-SR04 и кубик — пошагово, со схемами и кодом с комментариями.
Частые вопросы
Какие команды Arduino используются чаще всего?
Чаще всего используются pinMode(), digitalWrite(), digitalRead(), analogRead(), analogWrite(), delay(), millis(), Serial.begin() и Serial.println(). Добавь map() для масштабирования значений, tone() для звука, pulseIn() для датчиков расстояния и attachInterrupt() для прерываний — и можно написать почти все проекты для начинающих.
На каком языке пишутся команды Arduino?
Код Arduino построен на C и C++; ядро Arduino добавляет в язык готовые функции вроде pinMode() и digitalWrite(). Команды на английском, чувствительны к регистру, а каждая инструкция заканчивается точкой с запятой. ESP32 и Raspberry Pi Pico при желании можно программировать и на MicroPython.
Чем отличаются digitalWrite и analogWrite?
digitalWrite() ставит пин в одно из двух состояний: HIGH (5 V на Uno) или LOW (0 V). analogWrite() очень быстро включает и выключает пин, создавая сигнал PWM от 0 до 255, так что можно регулировать яркость светодиода или скорость мотора. На Uno analogWrite() работает только на пинах, отмеченных знаком ~.
Что означают void setup и void loop?
setup() — функция, которая выполняется один раз при включении или сбросе платы; сюда идёт подготовка вроде pinMode() и Serial.begin(). loop() — функция, которая бесконечно повторяется после завершения setup(). Слово void перед ними означает, что эти функции не возвращают значения.
Чем отличаются Serial.print и Serial.println?
Serial.print() выводит данные и оставляет курсор на той же строке, так что следующие данные добавляются сразу за ними. Serial.println() после вывода отправляет символы конца строки (\r\n), так что следующие данные начинаются с новой строки. Чтобы показать несколько значений рядом в одной строке, сначала используй print(), а в конце — println().
Что делает функция map в Arduino?
map() пропорционально переводит число из одного диапазона в другой; например, превращает значение 0–1023 от analogRead() в диапазон 0–255 для analogWrite() или в 0–180 градусов для сервопривода. Она работает только с целыми числами и не ограничивает результат, поэтому её рекомендуют сочетать с constrain(), чтобы обрабатывать входы вне диапазона.
Что собрать после прочтения
Все проекты
Мигающий светодиод
Самое первое «привет» в электронике: включение и выключение одного светодиода. Arduino включает и выключает светодиод через короткие промежутки, поэтому свет быстро мигает. Ты самым простым способом в

Управление светодиодом кнопкой (удержание)
Как дверной звонок: свет горит, пока ты нажимаешь, и гаснет, когда отпускаешь. Arduino всё время слушает кнопку; пока она нажата, светодиод горит, а как только ты убираешь палец, он гаснет. Эта просте

Измерение освещённости с LDR
Хочешь увидеть яркость своей комнаты в виде числа? LDR — маленькая деталь, реагирующая на свет, — измеряет освещённость вокруг, а Arduino каждые полсекунды выводит значение на экран компьютера. Закрой

Настройка частоты зуммера
Ты управляешь звуком зуммера четырьмя кнопками: одна включает звук, другая выключает, а две оставшиеся делают его выше или ниже. Удерживай кнопку вверх или вниз, и высота звука меняется шаг за шагом,

Измерение расстояния HC-SR04 (вывод в порт)
Датчик HC-SR04 работает совсем как летучая мышь, которая находит дорогу в темноте: он посылает звук, которого ты не слышишь, слушает эхо и измеряет, насколько далеко предмет перед ним. Arduino каждые

Светодиодный эффект Knight Rider с регулируемой скоростью
Свет бежит от одного края шести светодиодов к другому, разворачивается и бежит обратно. Поверни ручку потенциометра, и скорость этого бега сразу изменится: в одном крайнем положении свет почти летит,

Управление сервоприводом потенциометром
Когда ты поворачиваешь ручку потенциометра, рычаг сервопривода поворачивается вместе с ней: одно крайнее положение ручки — ноль градусов, другое — пол-оборота. Arduino всё время читает положение ручки

Игральный кубик
Больше никаких потерянных кубиков во время настольных игр: при каждом нажатии кнопки на семисегментном индикаторе появляется случайное число от 1 до 6. Каждое нажатие даёт ровно один результат, и он т
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

