Diecimila со стандартом Firmata не работает

Привет, я бы хотел использовать старую Diecimila с домашним помощником, и это, похоже, подразумевает установку стандарта Firmata.

Это не удалось, так как на доске недостаточно места.

Есть ли обходной путь (мне нужны только входы, возможно, даже только цифровые)?

Каким в противном случае был бы хороший путь вперед? Есть ли альтернатива фирмате для домашнего помощника? Или мне просто стоит купить новую плату?

, 👍0

Обсуждение

Вместо этого вы можете попробовать ConfigurationFirmata. Я не пробовал это с такими старыми платами, но когда вам нужен только цифровой ввод-вывод, он может быть даже меньше, чем StandardFirmata., @PMF

Сообщение об ошибке было: Sketch использует 13172 байта (91%) дискового пространства программы. Максимум — 14336 байт. Глобальные переменные используют 1113 байт (108%) динамической памяти, оставляя -89 байт для локальных переменных. Максимум — 1024 байта., @FelixHJ

Хм. Я думал, что скомпилировал его, но сейчас получаю аналогичное сообщение, хотя и с другим номером памяти, но памяти все равно недостаточно. Итак, я проголосую за ваш комментарий и удалю свой собственный. Вам следует [отредактировать](https://arduino.stackexchange.com/posts/95052/edit) эту деталь в своем вопросе, потому что это важно. Возможно, было бы полезно упомянуть, какие версии ядра платы и библиотеки Firmata используются. И даже несмотря на то, что сообщение об ошибке содержит эту информацию, вы можете явно указать на ATmega168. И я посмотрю, что я могу сделать на местном уровне с тем, что у меня есть., @timemage


1 ответ


1

Есть ли обходной путь (мне нужны только входы, возможно, даже только цифровые)?

Старая стандартная фирма

Я недостаточно знаю о домашнем помощнике, чтобы точно знать, что вам нужно. Но весьма вероятно, что вы можете и, вероятно, должны использовать OldStandardFirmata. И он настолько похож на модифицированную StandardFirmata (ниже), что, вероятно, вам подойдет. Он использует 505 (по данным) байт ОЗУ.

AllInputsFirmata также может работать, но использование оперативной памяти будет меньше лишь на процент.

Изменение стандартной фирмы

Тем не менее, похоже, что вы можете получить StandardFirmata.ino из текущей версии 2.5.9, чтобы не выходить за рамки ограничений, удалив все, что связано с I2C и Servo. Вероятно, стоит сначала попробовать OldStandardFirmata, поскольку многие из этих изменений и составляют разницу между примерами Old и неOld.

При поддержке AVR версии 1.8.7.

Sketch uses 7978 bytes (55%) of program storage space. Maximum is 14336 bytes.
Global variables use 522 bytes (50%) of dynamic memory, leaving 502 bytes for local variables. Maximum is 1024 bytes.

Итак, немного больше, чем OldStandardFirmata.

Действие Сообщаемые Глобальные переменные
Ничего 1079 байт
Удаление только I2C 650 байт
Удаление сервопривода 951 байт
Удаление I2C и SERVO 522 байта

Удаление деталей, связанных с сервоприводами, не снижает объем оперативной памяти, используя это много, но некоторые строки из этого поста удалены. Удаление analogWrite, analogRead может удалить нетривиальные объемы кода, но не сильно влияет на объем памяти. Окончательный размер аналогичен размеру OldFirmataStandard.

Вам может подойти следующее. Это пример целиком после удаления частей, связанных с I2C и сервоприводом. Я бы немного изменил форматирование, но оставив все как есть, вы сможете сравнить его с оригиналом и увидеть изменения, если захотите.

/*
Firmata — это общий протокол для связи с микроконтроллерами.
из программного обеспечения на главном компьютере. Он предназначен для работы с
любой пакет программного обеспечения главного компьютера.

Чтобы загрузить пакет программного обеспечения хоста, нажмите следующую ссылку.
чтобы открыть список клиентских библиотек Firmata в браузере по умолчанию.

https://github.com/firmata/arduino#firmata-client-libraries

Copyright (C) 2006–2008 Ханс-Кристоф Штайнер. Все права защищены.
Авторские права (C) 2010–2011, Пол Стоффреген. Все права защищены.
Авторские права (C) 2009 г. Сигэру Кобаяши. Все права защищены.
Авторские права (C) 2009–2016, Джефф Хофс. Все права защищены.

Эта библиотека является свободным программным обеспечением; вы можете распространять его и/или
изменить его в соответствии с условиями GNU Lesser General Public
Лицензия, опубликованная Фондом свободного программного обеспечения; или
версию 2.1 Лицензии или (по вашему выбору) любую более позднюю версию.

Дополнительную информацию об условиях лицензирования см. в файле LICENSE.txt.

Последнее обновление: 17 августа 2017 г.
*/

#include <Firmata.h>

// минимальный интервал выборки аналогового входа
#define MINIMUM_SAMPLING_INTERVAL   1


/*==============================================================================
 * GLOBAL VARIABLES
 *============================================================================*/

#ifdef FIRMATA_SERIAL_FEATURE
SerialFirmata serialFeature;
#endif

/* analog inputs */
int analogInputsToReport = 0; // побитовый массив для хранения отчетов о выводах

/* digital input ports */
byte reportPINs[TOTAL_PORTS];       // 1 = сообщить об этом порту, 0 = молчать
byte previousPINs[TOTAL_PORTS];     // отправлены предыдущие 8 бит

/* pins configuration */
byte portConfigInputs[TOTAL_PORTS]; // каждый бит: 1 = контакт на входе, 0 = что-нибудь еще

/* timer variables */
unsigned long currentMillis;        // сохраняем текущее значение из millis()
unsigned long previousMillis;       // для сравнения с текущим Миллисом
unsigned int samplingInterval = 19; // как часто запускать основной цикл (в мс)

/* i2c data */
struct i2c_device_info {
  byte addr;
  int reg;
  byte bytes;
  byte stopTX;
};

boolean isResetting = false;

// Вперед объявляем несколько функций, чтобы избежать ошибок компилятора в старых версиях
// IDE Arduino.
void setPinModeCallback(byte, int);
void reportAnalogCallback(byte analogPin, int value);
void sysexCallback(byte, byte, byte*);

/*==============================================================================
 * FUNCTIONS
 *============================================================================*/

void outputPort(byte portNumber, byte portValue, byte forceSend)
{
  // контакты, не настроенные как INPUT, обнуляются
  portValue = portValue & portConfigInputs[portNumber];
  // отправляем только в том случае, если значение отличается от ранее отправленного
  if (forceSend || previousPINs[portNumber] != portValue) {
    Firmata.sendDigitalPort(portNumber, portValue);
    previousPINs[portNumber] = portValue;
  }
}

/* -----------------------------------------------------------------------------
 * check all the active digital inputs for change of state, then add any events
 * to the Serial output queue using Serial.print() */
void checkDigitalInputs(void)
{
  /* Using non-looping code allows constants to be given to readPort().
   * The compiler will apply substantial optimizations if the inputs
   * to readPort() are compile-time constants. */
  if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
  if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
  if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
  if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
  if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
  if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
  if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
  if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
  if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
  if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
  if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
  if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
  if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
  if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
  if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}

// ---------------------------------------------------------------- -----------------------------
/* sets the pin mode to the correct state and sets the relevant bits in the
 * two bit-arrays that track Digital I/O and PWM status
 */
void setPinModeCallback(byte pin, int mode)
{
  if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
    return;

  if (IS_PIN_ANALOG(pin)) {
    reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // включаем/выключаем отчетность
  }
  if (IS_PIN_DIGITAL(pin)) {
    if (mode == INPUT || mode == PIN_MODE_PULLUP) {
      portConfigInputs[pin / 8] |= (1 << (pin & 7));
    } else {
      portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
    }
  }
  Firmata.setPinState(pin, 0);
  switch (mode) {
    case PIN_MODE_ANALOG:
      if (IS_PIN_ANALOG(pin)) {
        if (IS_PIN_DIGITAL(pin)) {
          pinMode(PIN_TO_DIGITAL(pin), INPUT);    // отключаем драйвер вывода
#if ARDUINO <= 100
          // устарело с версии Arduino 1.0.1 - TODO: отказаться от поддержки в Firmata 2.6
          digitalWrite(PIN_TO_DIGITAL(pin), LOW); // отключаем внутренние подтягивания
#endif
        }
        Firmata.setPinMode(pin, PIN_MODE_ANALOG);
      }
      break;
    case INPUT:
      if (IS_PIN_DIGITAL(pin)) {
        pinMode(PIN_TO_DIGITAL(pin), INPUT);    // отключаем драйвер вывода
#if ARDUINO <= 100
        // устарело с версии Arduino 1.0.1 - TODO: отказаться от поддержки в Firmata 2.6
        digitalWrite(PIN_TO_DIGITAL(pin), LOW); // отключаем внутренние подтягивания
#endif
        Firmata.setPinMode(pin, INPUT);
      }
      break;
    case PIN_MODE_PULLUP:
      if (IS_PIN_DIGITAL(pin)) {
        pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
        Firmata.setPinMode(pin, PIN_MODE_PULLUP);
        Firmata.setPinState(pin, 1);
      }
      break;
    case OUTPUT:
      if (IS_PIN_DIGITAL(pin)) {
        if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
          // Отключить ШИМ, если режим контакта ранее был установлен на ШИМ.
          digitalWrite(PIN_TO_DIGITAL(pin), LOW);
        }
        pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
        Firmata.setPinMode(pin, OUTPUT);
      }
      break;
    case PIN_MODE_PWM:
      if (IS_PIN_PWM(pin)) {
        pinMode(PIN_TO_PWM(pin), OUTPUT);
        analogWrite(PIN_TO_PWM(pin), 0);
        Firmata.setPinMode(pin, PIN_MODE_PWM);
      }
      break;
    case PIN_MODE_I2C:
      if (IS_PIN_I2C(pin)) {
        // отмечаем вывод как i2c
        // пользователь должен вызвать I2C_CONFIG, чтобы включить I2C для устройства
        Firmata.setPinMode(pin, PIN_MODE_I2C);
      }
      break;
    case PIN_MODE_SERIAL:
#ifdef FIRMATA_SERIAL_FEATURE
      serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
#endif
      break;
    default:
      Firmata.sendString("Unknown pin mode"); // TODO: поместить сообщения об ошибках в EEPROM
  }
  // TODO: сохранить здесь статус в EEPROM, если он был изменен
}

/*
 * Sets the value of an individual pin. Useful if you want to set a pin value but
 * are not tracking the digital port state.
 * Can only be used on pins configured as OUTPUT.
 * Cannot be used to enable pull-ups on Digital INPUT pins.
 */
void setPinValueCallback(byte pin, int value)
{
  if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
    if (Firmata.getPinMode(pin) == OUTPUT) {
      Firmata.setPinState(pin, value);
      digitalWrite(PIN_TO_DIGITAL(pin), value);
    }
  }
}

void analogWriteCallback(byte pin, int value)
{
  if (pin < TOTAL_PINS) {
    switch (Firmata.getPinMode(pin)) {
      case PIN_MODE_PWM:
        if (IS_PIN_PWM(pin))
          analogWrite(PIN_TO_PWM(pin), value);
        Firmata.setPinState(pin, value);
        break;
    }
  }
}

void digitalWriteCallback(byte port, int value)
{
  byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;

  if (port < TOTAL_PORTS) {
    // создаем маску контактов этого порта, доступных для записи.
    lastPin = port * 8 + 8;
    if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
    for (pin = port * 8; pin < lastPin; pin++) {
      // не трогать нецифровые контакты (например, Rx и Tx)
      if (IS_PIN_DIGITAL(pin)) {
        // не трогайте контакты в ШИМ, АНАЛОГОВОМ, СЕРВО или других режимах
        if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
          pinValue = ((byte)value & mask) ? 1 : 0;
          if (Firmata.getPinMode(pin) == OUTPUT) {
            pinWriteMask |= mask;
          } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
            // здесь обрабатываем только INPUT для обратной совместимости
#if ARDUINO > 100
            pinMode(pin, INPUT_PULLUP);
#else
            // записываем на вывод INPUT только для включения подтягиваний, если Arduino v1.0.0 или более ранняя версия
            pinWriteMask |= mask;
#endif
          }
          Firmata.setPinState(pin, pinValue);
        }
      }
      mask = mask << 1;
    }
    writePort(port, (byte)value, pinWriteMask);
  }
}


// ---------------------------------------------------------------- -----------------------------
/* sets bits in a bit array (int) to toggle the reporting of the analogIns
 */
//void FirmataClass::setAnalogPinReporting(байтовый вывод, состояние байта) {
//}
void reportAnalogCallback(byte analogPin, int value)
{
  if (analogPin < TOTAL_ANALOG_PINS) {
    if (value == 0) {
      analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
    } else {
      analogInputsToReport = analogInputsToReport | (1 << analogPin);
      // предотвращаем сброс системы, иначе будут переданы значения всех аналоговых выводов
      // который может сообщать о шуме для неподключенных аналоговых контактов
      if (!isResetting) {
        // Немедленно отправить значение контакта. Это полезно при подключении через
        // Ethernet, Wi-Fi или Bluetooth, чтобы можно было узнать состояние контактов
        // повторное подключение.
        Firmata.sendAnalog(analogPin, analogRead(analogPin));
      }
    }
  }
  // TODO: сохранить здесь статус в EEPROM, если он был изменен
}

void reportDigitalCallback(byte port, int value)
{
  if (port < TOTAL_PORTS) {
    reportPINs[port] = (byte)value;
    // Немедленно отправить значение порта. Это полезно при подключении через
    // Ethernet, Wi-Fi или Bluetooth, чтобы можно было узнать состояние контактов
    // повторное подключение.
    if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
  }
  // не отключайте аналоговую отчетность по этим 8 контактам, чтобы разрешить некоторые
  // контакты используются для цифровых, остальные — для аналоговых. Вместо этого разрешите оба типа
  // отчетность должна быть включена, но проверьте, настроен ли пин
  // как аналог при выборке аналоговых входов. Аналогично, в то время как
  // сканируя цифровые контакты, portConfigInputs маскирует значения из любых
  // контакты настроены как аналоговые
}

/*==============================================================================
 * SYSEX-BASED commands
 *============================================================================*/

void sysexCallback(byte command, byte argc, byte *argv)
{
  byte mode;
  byte stopTX;
  byte slaveAddress;
  byte data;
  int slaveRegister;
  unsigned int delayTime;

  switch (command) {
    case SAMPLING_INTERVAL:
      if (argc > 1) {
        samplingInterval = argv[0] + (argv[1] << 7);
        if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
          samplingInterval = MINIMUM_SAMPLING_INTERVAL;
        }
      } else {
        //Firmata.sendString("Недостаточно данных");
      }
      break;
    case EXTENDED_ANALOG:
      if (argc > 1) {
        int val = argv[1];
        if (argc > 2) val |= (argv[2] << 7);
        if (argc > 3) val |= (argv[3] << 14);
        analogWriteCallback(argv[0], val);
      }
      break;
    case CAPABILITY_QUERY:
      Firmata.write(START_SYSEX);
      Firmata.write(CAPABILITY_RESPONSE);
      for (byte pin = 0; pin < TOTAL_PINS; pin++) {
        if (IS_PIN_DIGITAL(pin)) {
          Firmata.write((byte)INPUT);
          Firmata.write(1);
          Firmata.write((byte)PIN_MODE_PULLUP);
          Firmata.write(1);
          Firmata.write((byte)OUTPUT);
          Firmata.write(1);
        }
        if (IS_PIN_ANALOG(pin)) {
          Firmata.write(PIN_MODE_ANALOG);
          Firmata.write(10); // 10 = разрешение 10 бит
        }
        if (IS_PIN_PWM(pin)) {
          Firmata.write(PIN_MODE_PWM);
          Firmata.write(DEFAULT_PWM_RESOLUTION);
        }
        if (IS_PIN_DIGITAL(pin)) {
          Firmata.write(PIN_MODE_SERVO);
          Firmata.write(14);
        }
        if (IS_PIN_I2C(pin)) {
          Firmata.write(PIN_MODE_I2C);
          Firmata.write(1);  // TODO: можно присвоить номер для сопоставления с SCL или SDA
        }
#ifdef FIRMATA_SERIAL_FEATURE
        serialFeature.handleCapability(pin);
#endif
        Firmata.write(127);
      }
      Firmata.write(END_SYSEX);
      break;
    case PIN_STATE_QUERY:
      if (argc > 0) {
        byte pin = argv[0];
        Firmata.write(START_SYSEX);
        Firmata.write(PIN_STATE_RESPONSE);
        Firmata.write(pin);
        if (pin < TOTAL_PINS) {
          Firmata.write(Firmata.getPinMode(pin));
          Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
          if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
          if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
        }
        Firmata.write(END_SYSEX);
      }
      break;
    case ANALOG_MAPPING_QUERY:
      Firmata.write(START_SYSEX);
      Firmata.write(ANALOG_MAPPING_RESPONSE);
      for (byte pin = 0; pin < TOTAL_PINS; pin++) {
        Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
      }
      Firmata.write(END_SYSEX);
      break;

    case SERIAL_MESSAGE:
#ifdef FIRMATA_SERIAL_FEATURE
      serialFeature.handleSysex(command, argc, argv);
#endif
      break;
  }
}

/*==============================================================================
 * SETUP()
 *============================================================================*/

void systemResetCallback()
{
  isResetting = true;

  // инициализируем состояние по умолчанию
  // TODO: возможность загрузки конфигурации из EEPROM вместо стандартной

#ifdef FIRMATA_SERIAL_FEATURE
  serialFeature.reset();
#endif

  for (byte i = 0; i < TOTAL_PORTS; i++) {
    reportPINs[i] = false;    // по умолчанию отчет отключен
    portConfigInputs[i] = 0;  // пока не активировано
    previousPINs[i] = 0;
  }

  for (byte i = 0; i < TOTAL_PINS; i++) {
    // контакты с аналоговыми возможностями по умолчанию используются для аналогового входа
    // в противном случае контакты по умолчанию используют цифровой выход
    if (IS_PIN_ANALOG(i)) {
      // выключаем подтягивание, все настраиваем
      setPinModeCallback(i, PIN_MODE_ANALOG);
    } else if (IS_PIN_DIGITAL(i)) {
      // устанавливает вывод в 0, настраивает portConfigInputs
      setPinModeCallback(i, OUTPUT);
    }
  }
  // по умолчанию не сообщать об аналоговых входах
  analogInputsToReport = 0;

  /* send digital inputs to set the initial state on the host computer,
   * since once in the loop(), this firmware will only send on change */
  /*
  TODO: this can never execute, since no pins default to digital input
        but it will be needed when/if we support EEPROM stored config
  for (byte i=0; i < TOTAL_PORTS; i++) {
    outputPort(i, readPort(i, portConfigInputs[i]), true);
  }
  */
  isResetting = false;
}

void setup()
{
  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);

  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
  Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
  Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
  Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
  Firmata.attach(SET_PIN_MODE, setPinModeCallback);
  Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.attach(SYSTEM_RESET, systemResetCallback);

  // чтобы использовать порт, отличный от последовательного, например Serial1 на Arduino Leonardo или Mega,
  // Вызов Begin(baud) на альтернативном последовательном порту и передача его в Firmata, чтобы начать следующим образом:
  // Serial1.begin(57600);
  // Фирмата.begin(Serial1);
  // Однако не делайте этого, если вы используете SERIAL_MESSAGE

  Firmata.begin(57600);
  while (!Serial) {
    ; // ждем подключения последовательного порта. Требуется для плат на базе ATmega32u4 и Arduino 101.
  }

  systemResetCallback();  //сброс к конфигурации по умолчанию
}

/*==============================================================================
 * LOOP()
 *============================================================================*/
void loop()
{
  byte pin, analogPin;

  /* DIGITALREAD - as fast as possible, check for changes and output them to the
   * FTDI buffer using Serial.print()  */
  checkDigitalInputs();

  /* STREAMREAD - processing incoming messagse as soon as possible, while still
   * checking digital inputs.  */
  while (Firmata.available())
    Firmata.processInput();

  // TODO - убедиться, что размер буфера потока не превышает 60 байт

  currentMillis = millis();
  if (currentMillis - previousMillis > samplingInterval) {
    previousMillis += samplingInterval;
    /* ANALOGREAD - do all analogReads() at the configured sampling interval */
    for (pin = 0; pin < TOTAL_PINS; pin++) {
      if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
        analogPin = PIN_TO_ANALOG(pin);
        if (analogInputsToReport & (1 << analogPin)) {
          Firmata.sendAnalog(analogPin, analogRead(analogPin));
        }
      }
    }
  }

#ifdef FIRMATA_SERIAL_FEATURE
  serialFeature.update();
#endif
}

Обновление доски

Или мне просто стоит купить новую доску?

Вероятно, вам это не нужно из-за вышесказанного. Но у вас также есть возможность обновить его до версии ATmega328P, используя только чип и записать загрузчик, или сделать это за вас. В некоторых заведениях для хобби их продают, сожженные с помощью optiboot.

,