COCKPIT SUITELIVE HUB /

Мастерская / ИИ и программирование

Первый модуль кокпита с помощью ИИ: четыре светодиода и OLED

Для небольшого проекта не нужен предварительный опыт программирования. Чёткая цель, точно выбранные компоненты и короткие проверки помогут использовать ИИ осмысленно. Вы сами определяете поведение индикаторов и содержание экрана.

Ваш результатУчебный проект на Arduino Uno R3: четыре независимых светодиода, три значения на OLED, полный скетч и запрос для дальнейших изменений.

Состояние материала: 18 октября 2026 года

Начните с результата, который можно проверить

Представьте небольшой блок рядом с рулём или органами управления полётом. Четыре лампочки показывают состояния, OLED — скорость, обороты и топливо. На первом этапе числа намеренно поступают из монитора последовательного порта Arduino IDE. Запускать симулятор не требуется, и каждую реакцию можно вызвать самостоятельно.

Требование: независимо управлять четырьмя светодиодами и показывать принятые значения. Задача программы: проверять сообщения целиком, принимать все поля одновременно и обозначать устаревшие данные. Результат — понятный рабочий элемент для дальнейшего развития, а не автоматическая совместимость с любым симулятором.

ИИ может объяснить соединения, предложить код и помочь разобрать ошибку. Вы решаете, что должно происходить, когда и как проверить успех. Для этого необязательно заранее знать, что такое переменная или функция. Просите объяснять новые понятия на том участке схемы, который сейчас проверяете.

Какие именно компоненты нужны

Понадобятся Arduino Uno R3, USB-кабель для передачи данных, макетная плата, провода, четыре обычных красных светодиода и четыре отдельных резистора 1 кОм мощностью не менее 0,125 Вт. Экран выбран точно: Adafruit 4440, SSD1306, 128 × 32 пикселя, I²C 0x3C, автоматический сброс. Используйте подходящий переходной кабель STEMMA QT либо правильно припаянные контакты.

Производитель допускает логику 5 В для этого модуля. Это не разрешение подключать любой похожий OLED: контроллер, порядок контактов, питание и сигнальные уровни проверяют по его документации. Для SH1106 или старой платы с отдельным reset нужны изменения. До подачи питания определите конкретное изделие.

Uno R3 достаточно для этого небольшого текстового экрана. Ограниченная память — причина начать с простого варианта. В сравнении микроконтроллеров рассмотрены критерии для графики, дополнительных устройств и более сложных задач.

Подключите светодиоды и OLED

Отключите USB перед сборкой и перестановкой проводов. Сначала соедините общую землю, затем добавляйте функции по одной. У каждого светодиода должен быть собственный последовательный резистор; один общий для четырёх не подходит. Анод обычно имеет длинный вывод, плоская сторона корпуса обозначает катод. Если выводы обрезаны, проверьте маркировку.

При падении около 2 В на красном светодиоде питание 5 В через 1 кОм даёт примерно 3 мА. Такой умеренный ток подходит для настольного опыта. Схема не предназначена для светодиодных лент, мощной подсветки или сторонних источников напряжения. Перед расширением прочтите раздел светодиодного освещения.

Фиксированные соединения Uno R3 и Adafruit 4440
Компонент / сигналСоединениеПроверка
LED 1D2 → 1 кОм → анод; катод → GNDСобственный резистор
LED 2D3 → 1 кОм → анод; катод → GNDНе подключать напрямую к D3
LED 3D4 → 1 кОм → анод; катод → GNDПроверить полярность
LED 4D5 → 1 кОм → анод; катод → GNDПроверить полярность
OLED VINUno 5VТолько выбранный модуль
OLED GNDUno GNDОбщая земля
OLED SDAUno A4 / SDAОдин и тот же сигнал
OLED SCLUno A5 / SCLОдин и тот же сигнал
OLED RSTНе подключатьУ 4440 автоматический сброс

Сначала определите смысл данных

Учебный формат: V1,скорость,обороты,топливо,маска с окончанием LF, скорость порта 115200 бод. Допустимы только неотрицательные целые числа: скорость 0–999, обороты 0–20000, топливо 0–100, маска 0–15. Без пробелов, единиц измерения и дробных частей. Отправляйте не более пяти полных сообщений в секунду.

Маска складывается из значений: LED 1 — 1, LED 2 — 2, LED 3 — 4, LED 4 — 8. Поэтому 5 включает LED 1 и 3, 15 включает все, 0 выключает все. Цифры на дисплее идут слева направо от LED 1 к LED 4: 1010 означает включённые LED 1 и 3.

После запуска отображается WAIT. Корректное сообщение получает ответ OK, экран показывает DATA. Ошибочное получает ERR, не меняя часть прежних значений. Через три секунды без корректных данных светодиоды гаснут, появляется STALE, последние числа остаются видны как устаревшие. Это поведение нужно заложить в исходное задание.

Здесь S обозначает скорость в км/ч, R — обороты в минуту, F — процент топлива. Скетч показывает числа без пересчёта; последующее преобразование единиц выполняется отправителем. Биты LED служат для проверки и не имеют заранее назначенной функции симулятора.

Составьте полноценное задание для ИИ

Полезный запрос для Arduino содержит аппаратную часть, формат данных и наблюдаемое поведение. Добавьте ссылки производителя и подтверждённую модель. Сначала запросите список соединений и уточняющие вопросы. Если у вас другие детали, выясните различия до использования предложенной схемы. Пример полного задания:

Помоги новичку собрать учебный модуль кокпита. Объясняй шаги и не выдумывай контакты или интерфейсы симуляторов.
Аппаратура: Arduino Uno R3; четыре красных LED на D2,D3,D4,D5, каждый через 1 кОм, катоды на GND. OLED Adafruit 4440, SSD1306 128x32 I2C 0x3C; VIN=5V, GND=GND, SDA=A4, SCL=A5, автоматический reset без отдельного провода.
Задача: полный скетч с Wire, Adafruit GFX и Adafruit SSD1306. Принимать мои учебные строки по USB-serial 115200 бод, максимум 5 строк/с: V1,speed,rpm,fuel,flags и LF; принимать CRLF. Диапазоны: speed 0..999, rpm 0..20000, fuel 0..100, flags 0..15. Значения 1,2,4,8 выбирают LED1..4.
Результат: четыре текстовые строки с числами и состояниями. Старт WAIT, корректные данные DATA/OK, ошибочные ERR без частичного обновления. Через 3000 мс без корректных данных выключить LED, показать STALE, сохранить последние числа.
Ограничения: фиксированный буфер 64 байта; слишком длинную строку отбросить до LF; никаких динамических String и delay в loop; обновлять экран не чаще одного раза в 200 мс. Учесть SRAM и 512 байт буфера OLED. Объяснить ошибки связи и памяти.
Дай соединения, полный код, библиотеки и тесты отдельных LED, всех LED, неверных значений, слишком длинной строки и прерывания данных. Разделяй компиляцию и проверку на реальном устройстве.

Подготовьте, загрузите и разберите скетч

В Arduino IDE выберите “Arduino Uno” и соответствующий порт. Через менеджер библиотек установите Adafruit SSD1306, Adafruit GFX Library и зависимость Adafruit BusIO. Wire входит в пакет AVR. Откройте скачанный скетч в папке uno-led-oled, сначала проверьте компиляцию, затем загрузите в свою плату.

Полный код доступен ниже и отдельным файлом. Приём выполняется небольшими порциями без ожидания через delay(); экран обновляется не чаще пяти раз в секунду. Передача I²C всё же занимает время: это не гарантия жёсткого реального времени. Длинные провода и дополнительные устройства требуют отдельных испытаний.

Буфер изображения занимает 512 байт сверх переменных, буферов библиотек и стека. Статическая цифра RAM в IDE не полностью отражает эту резервацию во время работы. F() хранит постоянные строки во flash, объекты Arduino String не используются. Успешная компиляция не подтверждает правильность проводки или работоспособность экрана.

Скетч локально скомпилирован для arduino:avr:uno с AVR 1.8.7, Adafruit SSD1306 2.5.9, GFX 1.11.9 и BusIO 1.15.0: 15 168 байт flash и 614 байт статической RAM. Дополнительно нужны 512 байт буфера изображения. Реальная сборка здесь не испытывалась.

Скачать полный скетч Arduino

Показать полный код примера
// Cockpit Suite workshop learning example. This is not a simulator protocol.
// Board: Arduino Uno R3. OLED: Adafruit 4440, SSD1306 128x32, I2C 0x3C.
// OLED VIN=5V, GND=GND, SDA=A4, SCL=A5; auto-reset, no reset wire.
// LEDs: D2/D3/D4/D5 -> individual 1k resistor -> anode; cathodes -> GND.
// Send at most 5 lines/second: V1,speed,rpm,fuel,flags followed by LF.
// Example: V1,120,3500,65,5 (LED1 and LED3 on). CR before LF is accepted.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <string.h>

const uint8_t LED_PINS[4] = {2, 3, 4, 5};
const uint8_t OLED_ADDRESS = 0x3C;
const uint32_t DATA_TIMEOUT_MS = 3000;
const uint32_t SCREEN_INTERVAL_MS = 200;
Adafruit_SSD1306 display(128, 32, &Wire, -1);
char lineBuffer[64];
uint8_t lineLength = 0;
bool discardLine = false;
bool haveData = false;
bool oledReady = false;
uint16_t speedValue = 0, rpmValue = 0, fuelValue = 0, flagValue = 0;
uint32_t lastDataMs = 0, lastScreenMs = 0;

bool parseNumber(const char *&cursor, uint16_t limit, char separator,
                 uint16_t &result) {
  if (*cursor < '0' || *cursor > '9') return false;
  uint16_t value = 0;
  while (*cursor >= '0' && *cursor <= '9') {
    uint8_t digit = *cursor++ - '0';
    if (value > limit / 10 ||
        (value == limit / 10 && digit > limit % 10)) return false;
    value = value * 10 + digit;
  }
  if (*cursor != separator) return false;
  if (separator != '\0') ++cursor;
  result = value;
  return true;
}

bool parseLine(const char *line) {
  if (strncmp(line, "V1,", 3) != 0) return false;
  const char *cursor = line + 3;
  uint16_t speed, rpm, fuel, flags;
  if (!parseNumber(cursor, 999, ',', speed) ||
      !parseNumber(cursor, 20000, ',', rpm) ||
      !parseNumber(cursor, 100, ',', fuel) ||
      !parseNumber(cursor, 15, '\0', flags)) return false;
  speedValue = speed;
  rpmValue = rpm;
  fuelValue = fuel;
  flagValue = flags;
  lastDataMs = millis();
  haveData = true;
  return true;
}

void readSerial() {
  // Bound each pass so a continuous stream cannot starve the outputs.
  for (uint8_t count = 0; count < 32 && Serial.available(); ++count) {
    char character = (char)Serial.read();
    if (character == '\r') continue;
    if (character == '\n') {
      lineBuffer[lineLength] = '\0';
      if (!discardLine && parseLine(lineBuffer)) Serial.println(F("OK"));
      else Serial.println(F("ERR"));
      lineLength = 0;
      discardLine = false;
    } else if (!discardLine) {
      // NUL and non-printable input are not part of this text protocol.
      if (character < 32 || character > 126 ||
          lineLength >= sizeof(lineBuffer) - 1) {
        discardLine = true;
      } else {
        lineBuffer[lineLength++] = character;
      }
    }
  }
}

void renderScreen(bool fresh) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print(F("S:")); display.print(speedValue);
  display.print(F(" R:")); display.println(rpmValue);
  display.print(F("F:")); display.print(fuelValue);
  display.print(F("% LED:"));
  for (uint8_t index = 0; index < 4; ++index)
    display.print(fresh && (flagValue & (1U << index)) ? '1' : '0');
  display.println();
  display.println(!haveData ? F("WAIT") : (fresh ? F("DATA") : F("STALE")));
  display.print(F("DEMO SERIAL"));
  display.display();
}

void setup() {
  for (uint8_t index = 0; index < 4; ++index) {
    digitalWrite(LED_PINS[index], LOW);
    pinMode(LED_PINS[index], OUTPUT);
  }
  Serial.begin(115200);
  Wire.begin();
#if defined(WIRE_HAS_TIMEOUT)
  Wire.setWireTimeout(25000, true);
#endif
  Wire.beginTransmission(OLED_ADDRESS);
  bool addressResponds = (Wire.endTransmission() == 0);
  oledReady = addressResponds &&
      display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS, false, false);
  if (oledReady) {
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setTextWrap(false);
    renderScreen(false);
  } else {
    Serial.println(F("OLED ERROR: check model, wiring, address, RAM"));
  }
  Serial.println(F("READY: V1,speed,rpm,fuel,flags"));
}

void loop() {
  readSerial();
  uint32_t now = millis();
  bool fresh = haveData && (uint32_t)(now - lastDataMs) < DATA_TIMEOUT_MS;
  for (uint8_t index = 0; index < 4; ++index)
    digitalWrite(LED_PINS[index],
                 fresh && (flagValue & (1U << index)) ? HIGH : LOW);
  if (oledReady && (uint32_t)(now - lastScreenMs) >= SCREEN_INTERVAL_MS) {
    lastScreenMs = now;
    renderScreen(fresh);
  }
}

Проверьте результат конкретными сообщениями

После загрузки установите 115200 бод и окончание строки “Newline” либо “Both NL & CR”. Открытие порта может перезапустить Uno: дождитесь READY. При первом запуске ожидаются WAIT и четыре погашенных светодиода.

Отправьте V1,120,3500,65,1: включиться должен только LED 1. Последовательно замените последнюю цифру на 2, 4 и 8. V1,120,3500,65,15 включает все четыре, конечный 0 выключает. Сравните три числа на экране с отправленными. Проверьте границы: V1,999,20000,100,15 и V1,0,0,0,0.

Намеренно отправьте V1,120,3500,101,5 или пропустите поле. Ожидается ERR без частичного обновления. Строка длиннее 63 символов должна отбрасываться до окончания, следующая корректная — приниматься. Подождите более трёх секунд: LED гаснут, появляется STALE. Новая корректная строка должна восстановить работу. Отдельно записывайте ожидаемое и фактическое поведение.

Прямое сравнение: V1,120,3500,65,15 включает все четыре LED, V1,120,3500,65,0 выключает все, V1,120,3500,65,5 включает только LED 1 и 3.

Опишите неисправность прежде, чем менять схему

Если не светится одна LED, проверьте полярность, её резистор и выбранный вывод. Для тёмного OLED проверьте модель, питание, землю, SDA/SCL и адрес. OLED ERROR может означать отсутствие ответа шины или неудачное выделение памяти. Даже отвечающий I²C-адрес ещё не доказывает правильную картинку.

Задайте ИИ конкретный вопрос: “Uno R3, модуль 4440, скетч без изменений. READY есть, V1,120,3500,65,1 возвращает OK, LED1 работает, OLED тёмный. Какие соединения сначала проверить без питания?” Добавьте версии библиотек и полную ошибку компилятора. Просите одно обоснованное изменение за раз.

Сохраните рабочий вариант до расширения, попросите объяснить изменения и повторите проверки. Руководство по поиску неисправностей помогает двигаться последовательно. Пароли, частные настройки и не относящиеся к задаче каталоги в запрос не включайте. Понятый небольшой шаг полезнее полной замены программы без диагноза.

От учебных сообщений к данным симулятора

Для настоящих значений симулятора нужен документированный путь на компьютере: чтение источника, преобразование единиц, проверка и передача. V1 относится только к этому упражнению, а не к обещанному интерфейсу Cockpit Suite. Уточните поддерживаемое подключение устройства до планирования автоматического моста. Монитор порта и другая программа обычно не могут одновременно занимать один порт.

Решите, что показывает индикатор: запрос переключателя или подтверждённое состояние симулятора. Отличайте отсутствие данных от выключенного состояния. Продолжите с сопоставлением данных и экранами и приборами.

Если главное — кнопки и оси как USB-джойстик, FreeJoy предлагает другой подход на подходящей плате. Этот скетч использует последовательный USB-канал Uno и не превращает его в нативный джойстик. Расширяйте панель после проверки одного полного пути сигнала.

Следующий шаг можно сделать вместе

Cockpit Suite объединяет поддерживаемые симуляторы и устройства в общей программной среде. Проект молодой, но уже имеет доступное ПО и реальные сборки. Подготовленные сочетания упрощают поддерживаемые этапы; собственный Arduino-модуль остаётся задачей обучения и интеграции. Ваши воспроизводимые наблюдения помогают улучшать эти пути.

На форуме Cockpit Suite покажите цель, список деталей и последний успешный тест. Мы хотим помочь с продолжением и стараемся отвечать в тот же день, когда это возможно; поздний вопрос может получить ответ позже. В мастерской обсуждаются также 3D-печать, портальные фрезеры CNC и лазер с LightBurn. Активное сообщество в Европе и за её пределами превращает отдельные успехи в полезные знания.

Источники и техническая основа

Проверено 18 октября 2026 года. Порядок работы, протокол и скетч — собственный учебный пример. Документация не заменяет проверку реальной сборки.

Продолжите работу над проектом