Связь с компьютером: Serial и монитор порта

Всё это время Arduino работала молча. Пора дать ей голос — и уши: научить разговаривать с компьютером по проводу USB.

Serial — это разговор Arduino с компьютером текстом по USB. Плата может слать данные («температура 24») и принимать команды («включи свет»). Это и отладчик, и канал управления.

Сейчас научимся выводить данные в монитор порта и принимать команды с клавиатуры. Это превратит Arduino из «вещи в себе» в устройство, которым можно управлять и за которым можно наблюдать.

Вывод данных: Arduino говорит

void setup() {
  Serial.begin(9600);    // скорость связи: 9600 бод
}

void loop() {
  int light = analogRead(A0);
  Serial.print("Свет: ");
  Serial.println(light);   // println - с переносом строки
  delay(500);
}

Открой монитор порта (значок лупы справа вверху, или Tools → Serial Monitor), выстави 9600 бод — и увидишь поток данных. Это твой главный инструмент отладки на весь курс.

Приём команд: Arduino слушает

const int LED = 13;

void setup() {
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {     // пришёл символ?
    char c = Serial.read();
    if (c == '1') digitalWrite(LED, HIGH);
    if (c == '0') digitalWrite(LED, LOW);
  }
}

Введи в монитор порта «1» — светодиод загорится, «0» — погаснет. Ты управляешь железом с клавиатуры компьютера.

Как работает под капотом

Внутри USB-кабеля Arduino и компьютер обмениваются битами по очереди (последовательно — отсюда «serial»). Скорость измеряется в бодах — сколько символов в секунду. Главное правило: скорость в коде (Serial.begin) и в мониторе порта должны совпадать, иначе вместо текста будут «кракозябры». Serial.available() возвращает, сколько символов уже пришло и ждут в буфере; Serial.read() забирает один.

# Та же логика на Python: разбор входящих Serial-команд
def handle(commands):
    led = False
    log = []
    for c in commands:
        if c == '1':
            led = True
        elif c == '0':
            led = False
        elif c == '?':
            log.append("LED горит" if led else "LED выключен")
        # прочие символы игнорируем, как делает наш скетч
    return log

print(handle("1?0?1?"))   # включить/спросить/выключить/спросить/...

Частые ошибки

  • Разная скорость в коде и мониторе — нечитаемые символы. Сверь оба значения (обычно 9600).
  • Забыли Serial.begin() в setup — вывода нет вовсе.
  • Читают Serial без проверки available() — read возвращает мусор (-1), когда данных нет.

Best practices

  • Расставляй Serial.println по коду для отладки — это лучший способ понять, что «думает» плата.
  • Для команд из нескольких символов используй Serial.readStringUntil('\n') — удобно ловить целую строку.
  • На Uno R4 и других новых платах скорость можно поднять до 115200 бод — быстрее обновление данных.

Serial как окно в мысли платы

Главная суперсила Serial — это отладка. У Arduino нет экрана и нет привычной кнопки «поставить точку останова», поэтому когда что-то идёт не так, единственный способ заглянуть внутрь — попросить плату рассказать, что она думает. Расставь Serial.println в ключевых местах: вывел значение датчика, вывел, в какую ветку if зашла программа, вывел вычисленную яркость. Глядя на поток в мониторе порта, ты буквально читаешь ход мыслей платы и мгновенно находишь, где логика свернула не туда.

Через Serial устройство может общаться не только с монитором, но и с программами. На компьютере можно написать скрипт (например, на Python с библиотекой pyserial), который читает данные с Arduino и рисует графики, пишет их в файл или отправляет в интернет. А на Uno R4 WiFi плата и вовсе умеет выходить в сеть сама. Так скромный текстовый канал по USB превращается в мост между миром физических датчиков и миром «большого» софта — и это та точка, где встраиваемая электроника встречается с обычным программированием.

Итоги

Serial — двусторонний текстовый канал по USB: print выводит, read принимает, available проверяет буфер, бод-скорость должна совпадать с двух сторон. Это твой отладчик и пульт управления. Теперь спроектируем целое устройство из всего изученного.

Проверьте себя
1. Что произойдёт, если скорость в Serial.begin() и в мониторе порта не совпадает?
AСгорит плата
BВместо текста появятся нечитаемые символы
CУскорится загрузка
DНичего
2. Зачем перед Serial.read() проверяют Serial.available() > 0?
AДля скорости
BЧтобы читать только когда данные реально пришли
CЭто обязательно по синтаксису
DЧтобы очистить буфер