КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Бампер с 9 датчиками линий, FLASH-I2C



Общие сведения:

Модуль - Бампер с 9 датчиками линий с шагом 14мм или шагом 7мм, I2C-flash - предназначен для установки на подвижные механизмы (машины, тракторы, танки, роботы) для их движения по линии без участия оператора. Модуль снабжен световой индикацией наличия линии и поворотниками.

Управление модулем осуществляется по шине I2C. Модуль относится к серии «Flash», а значит к одной шине I2C можно подключить более 100 модулей, так как их адрес на шине I2C (по умолчанию 0x09), хранящийся в энергонезависимой памяти, можно менять программно.

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

Видео:

Редактируется ...

Спецификация:

  • Напряжение питания: 3,3 В или 5 В (постоянного тока).
  • Потребляемый ток: до 20 мА (все светодиоды включены).
  • Расстояние от трассы до датчиков: от 2 до 50 мм.
  • Максимальная скорость движения бампера (м/с): ширина линии (мм) / 3.
  • Интерфейс: I2C.
  • Скорость шины I2C: 100 кбит/с.
  • Адрес на шине I2C: устанавливается программно (по умолчанию 0x09).
  • Уровень логической 1 на линиях шины I2C: Vcc.
  • Рабочая температура: от -20 до +70 °С.
  • Габариты модуля с шагом 14мм: 119 x 25 мм (без креплений), 119 x 35 мм (с креплениями).
  • Габариты модуля с шагом 7мм: 59 x 25 мм (без креплений), 59 x 35 мм (с креплениями).
  • Вес: 10 г.

Модуль крепится на различные механизмы при помощи винтов M3 устанавливаемых в отверстия креплений бампера. При желании, некоторые (или все) крепления бампера можно удалить, для этого аккуратно согните ненужные крепления вверх или вниз.

Подключение:

Перед подключением модуля ознакомьтесь с разделом "Смена адреса модуля на шине I2C" в данной статье.

Модуль подключается по шине I2C, все выводы которой (GND, Vcc, SDA, SCL) размещены на двух одинаковых колодках.

  • SCL - вход/выход линии тактирования шины I2C.
  • SDA - вход/выход линии данных шины I2C.
  • Vcc - вход питания 3,3 или 5 В.
  • GND - общий вывод питания.

Для подключения модуля можно использовать любую из двух колодок (верхнюю или нижнюю), а оставшуюся колодку можно применить для подключения второго бампера или иного модуля к шине I2C.

Модуль удобно подключать 2 способами, в зависимости от ситуации:

Способ - 1: Используя провода и Piranha UNO

Используя провода «Папа — Мама», подключаем напрямую к контроллеру Piranha UNO.

Вывод Arduino Вывод модуля
SDA (A4) SDA
SCL (A5) SCL
5V 5V
GND GND

Способ - 2: Используя провода и Shield

Используя 4-х проводной шлейф, к Trema Shield, Trema-Power Shield, Motor Shield, Trema Shield NANO и тд.

Способ - 3: Подключение к программной шине I2C

При использовании программной шины I2C, модуль можно подключить к любым выводам Arduino, но потребуется дополнительно установить библиотеку iarduino_I2C_Software.h, для создания программной шины I2C, указав номера выбранных вами выводов. О том как это сделать читайте ниже в разделе «Подключение библиотеки», а так же на странице Wiki - Расширенные возможности библиотек iarduino для шины I2C.

Подключение к Raspberry Pi Pico

Для работы с Pi Pico необходимо установить поддержку платы в Arduino IDE. Нажмите здесь для перехода на подробную статью о том, как это сделать.

В этом случае логическую часть модуля необходимо питать от 3-х вольт Pi Pico

Для работы с Pi Pico версия установленной библиотеки должна быть 1.0.4 и выше

Модуль
Pi Pico
SDA
GP6
SCLGP7
Vcc3V3(OUT)
GNDGND

Питание:

Входное напряжение питания модуля 3,3В или 5В постоянного тока (поддерживаются оба напряжения питания), подаётся на выводы Vcc и GND.

Подробнее о модуле:

Модуль построен на базе микроконтроллера STM32F030F4 (ранние модели были построены на базе микроконтроллера STM32F030F4, но они полностью совместимы с новыми моделями), снабжен собственным стабилизатором напряжения, имеет на борту 9 датчиков отражения (линий) и кнопку калибровки. Светодиодная индикация модуля позволяет определять наличие линий под датчиками - светодиод расположенный перед датчиком светится если под датчиком есть линия. Так же на модуле установлены светодиоды сигналов поворота. У версии модуля с поддержкой определения цвета, имеются три датчика цвета расположенные по центру и по бокам бампера, каждый датчик состоит из RGB светодиода и фототранзистора.

Модуль позволяет:

      • Изменить свой адрес на шине I2C, временно (пока есть питание) или постоянно.
      • Получать аналоговые значения (АЦП) с датчиков линий.
      • Получать цифровые значения с датчиков линий (есть линия под датчиком или нет).
      • Выполнить калибровку под контраст линий и фона используемых на трассе.
      • Узнать тип трассы для которой откалиброван модуль (трасса со светлой или тёмной линией).
      • Изменить тип трассы (считать фон как линию, а линию как фон).
      • Задать скорость опроса модулем датчиков линий.
      • Узнать максимальную скорость при которой бампер обнаружит перекрёсток трассы.
      • Задать скорость мигания поворотников.
      • Управлять поворотниками самостоятельно, или указать им работать в автоматическом режиме.

      Модуль с поддержкой определения цвета дополнительно позволяет:

      • Получить аналоговые значения (АЦП) с датчиков цвета.
      • Получить автоматически выявленные цвета (чер, бел, кра, жел, зел, син).
      • Выполнить калибровку датчиков цвета по белому фону.
      • Задать скорость опроса модулем датчиков цвета.

      Специально для работы с модулем - Бампер с 9 датчиками линий с шагом 14мм или шагом 7мм, I2C-flash, нами разработана библиотека iarduino_I2C_Bumper которая позволяет реализовать все функции модуля.

      Подробнее про установку библиотеки читайте в нашей инструкции.

      Калибровка датчиков линий:

      Калибровка модуля может быть запущена методами библиотеки iarduino_I2C_Bumper, или нажатием на кнопку «калибровка».

      Калибровка позволяет модулю отличать линии трассы от фона. Автоматическая калибровка состоит из двух этапов: чтение количества отражённого света от поверхности линии и чтение количества отражённого света от поверхности фона трассы. Результаты калибровки сохраняются в энергонезависимую память модуля, а значит модуль будет отличать линии от фона и после отключения питания.

      Установите модуль так, что бы все его датчики находились над линией трассы и нажмите на кнопку «калибровка», или обратитесь к методу setCalibrationRun(). О начале калибровки сигнализирует включение левого поворотника и поочерёдное включение светодиодов расположенных перед датчиками линий, далее светодиоды отключатся, после чего все светодиоды начнут мигать в шахматном порядке, информируя о необходимости перехода к чтению фона трассы для завершения калибровки.

      Установите модуль так, что бы все его датчики находились над фоном трассы и нажмите на кнопку «калибровка», или обратитесь к методу setCalibrationEnd(). О начале калибровки сигнализирует включение правого поворотника и поочерёдное включение светодиодов расположенных перед датчиками линий, далее светодиоды отключатся, после чего все светодиоды расположенные перед датчиками одновременно включатся на пол секунды или быстро мигнут три раза, информируя о результате калибровки.

      Успех калибровки определяется модулем по контрасту между фоном и линией, при малой контрастности калибровка будет считаться неудачной, а её результаты не сохранятся в памяти модуля. Если калибровка закончилась провалом, то все светодиоды расположенные перед датчиками линий быстро мигнут три раза. Если калибровка закончилась успехом, то все светодиоды расположенные перед датчиками линий включатся на пол секунды. Так же о результате калибровки можно узнать по значению статуса калибровки, возвращаемому методом getCalibrationStage().

      В результате калибровки модуль не только сможет отличать линии от фона, но и определит тип трассы (трасса с тёмной линией на светлом фоне, или со светлой линией на тёмном фоне). Тип линии трассы можно узнать методом getLineType(). Если на трассе есть участки, где цвет линии меняется с цветом фона, то достаточно сменить тип линии трассы методом setLineType().

      Калибровка датчиков цвета:

      Только для модулей с поддержкой определения цвета.

      Калибровка модуля может быть запущена методами библиотеки iarduino_I2C_Bumper, или нажатием на кнопку «калибровка».

      Калибровка позволяет модулю настроить коэффициенты коррекции яркости каналов RGB для каждого датчика цвета. Результаты калибровки сохраняются в энергонезависимую память модуля, а значит модуль будет корректно определять цвета и после отключения питания.

      При калибровке кнопкой нужно выполнить те же действия, что и при калибровке датчиков линий, но бампер должен постоянно находиться над белым фоном (например над белым листом бумаги). Разместите модуль над белым фоном и нажмите на кнопку «калибровка». Включится левый поворотник, а светодиоды расположенные перед датчиками линий начнут поочерёдно включаться, после чего все светодиоды начнут мигать в шахматном порядке. Не меняя положение модуля, повторно нажмите на кнопку «калибровка». Включится правый поворотник, а светодиоды расположенные перед датчиками линий начнут поочерёдно включаться, после чего все светодиоды отключатся и мигнут три раза информируя о том, что калибровка датчиков линий не выполнена и не сохранена. Далее на пол секунды включатся RGB светодиоды красным или зелёным цветом информируя о результате калибровки датчиков цвета.

      Вместо нажатий на кнопку «калибровка» можно обратиться к методу setCalibrationRGB(), в этом случае калибровка начнётся сразу со второго этапа: включится правый поворотник, а светодиоды расположенные перед датчиками линий начнут поочерёдно включаться, после чего все светодиоды отключатся и мигнут три раза информируя о том, что калибровка датчиков линий не выполнена и не сохранена. Далее на пол секунды включатся RGB светодиоды красным или зелёным цветом информируя о результате калибровки датчиков цвета.

      Если цвет фона сильно отличается от белого, то калибровка будет считаться неудачной, а её результаты не сохранятся в регистрах модуля. Если калибровка закончилась провалом, то RGB светодиоды включатся красным цветом. Если калибровка закончилась успехом, то RGB светодиоды включатся зелёным цветом. Так же о результате калибровки можно узнать по значению статуса калибровки, возвращаемому методом getCalibrationStageRGB().

      Смена адреса модуля на шине I2C:

      По умолчанию все модули FLASH-I2C имеют установленный адрес 0х09. Если вы планируете подключать более 1 модуля на шину I2C, необходимо изменить адреса модулей таким образом, чтобы каждый из них был уникальным. Более подробно о том, как изменить адрес, а также о многом другом, что касается работы FLASH-I2C модулей, вы можете прочесть в этой статье.

      В первой строке скетча необходимо записать в переменную newAddress адрес, который будет присвоен модулю. После этого подключите модуль к контроллеру и загрузите скетч. Адрес может быть от 0х07 до 0х7F.

      uint8_t newAddress = 0x09;                                 //   Назначаемый модулю адрес (0x07 < адрес < 0x7F).
                                                                 //
      #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
      #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
      iarduino_I2C_Bumper bum;                                   //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper.
                                                                 //   Если при объявлении объекта указать адрес, например, bum(0xBB), то пример будет работать с тем модулем, адрес которого был указан.
      void setup(){                                              //
           Serial.begin(9600);                                   //
           if( bum.begin(&Wire) ){                               //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
               Serial.print("Найден бампер с адресом 0x");       //
               Serial.println( bum.getAddress(), HEX );          //   Выводим текущий адрес модуля.
               if( bum.changeAddress(newAddress) ){              //   Меняем адрес модуля на newAddress.
                   Serial.print("Адрес изменён на 0x");          //
                   Serial.println(bum.getAddress(),HEX );        //   Выводим текущий адрес модуля.
               }else{                                            //
                   Serial.println("Адрес не изменён!");          //
               }                                                 //
           }else{                                                //
               Serial.println("Бампер не найден!");              //
           }                                                     //
      }                                                          //
                                                                 //
      void loop(){}                                              //

      Данный пример использует библиотеку iarduino_I2C_Bumper, которая работает только с модулями бамперов, а значит позволяет менять только их адреса.

      Смена и сортировка адресов на шине I2C:

      Изменить адрес любого I2C модуля серии «Flash» можно аппаратно, используя установщик адресов FLASH-I2C. Это модуль подключаемый к шине I2C, на плате которого размещён дисплей и кнопки управления, при помощи которых можно узнать количество любых устройств на шине I2C, и менять адреса модулей Flash-I2C не отключая их от шины, что значительно сократит время сборки ваших проектов. Модуль оснащён разъемом USB через который можно запитать как сам модуль, так и шину I2C, или можно запитать шину I2C без использования разъема USB на плате модуля. Установщик адресов пригодиться в проектах с большим количеством модулей Flash-I2C.

      Изменить адрес любого I2C модуля серии «Flash» можно программно, о том как это сделать рассказано в статье Wiki - Программная установка адресов модулей FLASH-I2C. В этой статье рассмотрены примеры с использованием библиотеки iarduino_I2C_Address, которая позволяет получать адреса любых устройств на шине I2C, менять адреса модулей Flash-I2C не отключая их от шины, получать название, номер модели, версию прошивки модулей Flash-I2C, а главное - автоматически сортировать адреса модулей Flash-I2C даже если на шине есть устройства с одинаковыми адресами.

      Примеры:

      В данном разделе раскрыты примеры работы модуля по шине I2C с использованием библиотеки iarduino_I2C_Bumper. Сама библиотека содержит больше примеров, доступных из меню Arduino IDE: Файл / Примеры / iarduino_I2C_Bumper.

      Чтение линий под датчиками модуля:

      #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
      #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
      iarduino_I2C_Bumper bum(0x09);                             //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper, указывая адрес модуля на шине I2C.
                                                                 //   Если объявить объект без указания адреса (iarduino_I2C_Bumper bum;), то адрес будет найден автоматически.
      void setup(){                                              //
           Serial.begin(9600);                                   //   Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
           bum.begin(&Wire);                                     //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
      }                                                          //
                                                                 //
      void loop(){                                               //
           Serial.print( "Линия находится под датчиком:" );      //   Выводим текст.
           if( bum.getLineDigital(1) ){ Serial.print(" 1"); }    //   Выводим номер 1 датчика, если под ним находится линия.
           if( bum.getLineDigital(2) ){ Serial.print(" 2"); }    //   Выводим номер 2 датчика, если под ним находится линия.
           if( bum.getLineDigital(3) ){ Serial.print(" 3"); }    //   Выводим номер 3 датчика, если под ним находится линия.
           if( bum.getLineDigital(4) ){ Serial.print(" 4"); }    //   Выводим номер 4 датчика, если под ним находится линия.
           if( bum.getLineDigital(5) ){ Serial.print(" 5"); }    //   Выводим номер 5 датчика, если под ним находится линия.
           if( bum.getLineDigital(6) ){ Serial.print(" 6"); }    //   Выводим номер 6 датчика, если под ним находится линия.
           if( bum.getLineDigital(7) ){ Serial.print(" 7"); }    //   Выводим номер 7 датчика, если под ним находится линия.
           if( bum.getLineDigital(8) ){ Serial.print(" 8"); }    //   Выводим номер 8 датчика, если под ним находится линия.
           if( bum.getLineDigital(9) ){ Serial.print(" 9"); }    //   Выводим номер 9 датчика, если под ним находится линия.
           Serial.println(".");                                  //   Завершаем строку.
           delay(200);                                           //   Задержка позволяет медленнее заполнять монитор последовательного порта.
      }                                                          //
      

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

      В примере Arduino IDE: Файл / Примеры / iarduino I2C Bumper (бампер) / getLineDigitalFast показано как считать состояние всех датчиков одним запросом к модулю, что резко увеличивает скорость работы с ним.

      Чтение аналоговых значений с датчиков модуля:

      #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
      #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
      iarduino_I2C_Bumper bum(0x09);                             //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper, указывая адрес модуля на шине I2C.
                                                                 //   Если объявить объект без указания адреса (iarduino_I2C_Bumper bum;), то адрес будет найден автоматически.
      void setup(){                                              //
           Serial.begin(9600);                                   //   Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
           bum.begin(&Wire);                                     //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
      }                                                          //
                                                                 //
      void loop(){                                               //
           Serial.print( "Аналоговые значения датчиков 1-9: " ); //   Выводим текст.
           Serial.print( (String) bum.getLineAnalog(1) + ", " ); //   Выводим значение АЦП снятое с 1 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(2) + ", " ); //   Выводим значение АЦП снятое с 2 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(3) + ", " ); //   Выводим значение АЦП снятое с 3 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(4) + ", " ); //   Выводим значение АЦП снятое с 4 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(5) + ", " ); //   Выводим значение АЦП снятое с 5 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(6) + ", " ); //   Выводим значение АЦП снятое с 6 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(7) + ", " ); //   Выводим значение АЦП снятое с 7 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(8) + ", " ); //   Выводим значение АЦП снятое с 8 датчика линии и текст ", ".
           Serial.print( (String) bum.getLineAnalog(9) + ".\n"); //   Выводим значение АЦП снятое с 9 датчика линии и текст ".\n".
           delay(200);                                           //   Задержка позволяет медленнее заполнять монитор последовательного порта.
      }                                                          //
      

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

      Аналоговыми значениями датчиков линий являются показания АЦП (аналого-цифрового преобразователя). Чем светлее объект находящийся под датчиком линий, тем выше показания АЦП. Оперируя аналоговыми значениями бампера, можно использовать трассы с разметками разных цветов.

      Чтение ошибки центрирования линии для ПИД регулятора:

      #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
      #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
      iarduino_I2C_Bumper bum(0x09);                             //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper, указывая адрес модуля на шине I2C.
                                                                 //   Если объявить объект без указания адреса (iarduino_I2C_Bumper bum;), то адрес будет найден автоматически.
      float val_Speed   = ЗНАЧЕНИЕ;                              //   Скорость движения машины.
      float pid_KP      = ЗНАЧЕНИЕ;                              //   Коэффициент пропорциональной обратной связи ПИД регулятора.
      float pid_KI      = ЗНАЧЕНИЕ;                              //   Коэффициент интегральной     обратной связи ПИД регулятора.
      float pid_KD      = ЗНАЧЕНИЕ;                              //   Коэффициент дифференциальной обратной связи ПИД регулятора.
      float arr_ERR[10] = {0,0,0,0,0,0,0,0,0,0};                 //   Массив последних ошибок для формирования интегральной составляющей ПИД регулятора.
      uint8_t i, j;                                              //   Переменные для работы с массивом последних ошибок «arr_ERR».
                                                                 //
      void setup(){                                              //
           bum.begin(&Wire);                                     //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
      }                                                          //
                                                                 //
      void loop(){                                               //
           i++; i%=10; j=10;                                     //   Определяем значения переменных.
      //   Получаем текущую ошибку центрирования линии:          //
           arr_ERR[i] = bum.getErrPID();                         //   Функция getErrPID() возвращает ошибку от 0 до ±4.5, где 0 - линия по центру, ±4.0 - линия на крайнем датчике, ±4.5 - линия потеряна.
      //   Вычисляем все составляющие ПИД регулятора:            //
           float pid_P = arr_ERR[i];                             //   Пропорциональная составляющая «pid_P» представлена величиной текущей ошибки «ARR_ERR[i]».
           float pid_I = 0.0f; while(j--){pid_I+=arr_ERR[j-1];}  //   Интегральная     составляющая «pid_I» представлена суммой последних ошибок взятых из массива «arr_ERR».
           float pid_D = arr_ERR[i]-arr_ERR[(i+9)%10];           //   Дифференциальная составляющая «pid_D» представлена разницей между текущей «ARR_ERR[i]» и предыдущей «arr_ERR[(i+9)%10]» ошибкой.
           float PID   = pid_P*pid_KP+pid_I*pid_KI+pid_D*pid_KD; //   Вычисляем результат ПИД регулирования.
      //   Устанавливаем скорость вращения колёс:                //
           setSpeedL( val_Speed + PID );                         //   Устанавливаем скорость мотора левого  колеса.
           setSpeedR( val_Speed - PID );                         //   Устанавливаем скорость мотора правого колеса.
      }

      Данный скетч демонстрирует возможность получения ошибки центрирования линии getErrPID(), для движения машины по линии с использованием ПИД регулятора. Для маневрирования на перекрёстках, функцию getErrPID() можно вызвать с числом и знаком поворота. Число определяет толщину линии (сколько датчиков умещается над линией), а знак определяет направление поворота (-влево,+вправо).

      Для работы скетча необходимо указать скорость val_Speed, коэффициенты обратной связи ПИД регулятора (pid_KP, pid_KI, pid_KD) и определить функции управления моторами setSpeedL() и setSpeedR().

      Управление поворотниками:

      #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
      #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
      iarduino_I2C_Bumper bum(0x09);                             //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper, указывая адрес модуля на шине I2C.
                                                                 //   Если объявить объект без указания адреса (iarduino_I2C_Bumper bum;), то адрес будет найден автоматически.
      void setup(){                                              //
           bum.begin(&Wire);                                     //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
           bum.setTurnPeriod(BUM_TURN_200);                      //   Задаём скорость мигания поворотников в 200мс. Возможные значения: BUM_TURN_100, BUM_TURN_200, BUM_TURN_400 и BUM_TURN_800.
      }                                                          //
                                                                 //
      void loop(){                                               //
           bum.setTurnSignal(BUM_TURN_LEFT);      delay(5000);   //   Включаем левый поворотник и ждём 5 секунд.
           bum.setTurnSignal(BUM_TURN_RIGHT);     delay(5000);   //   Включаем правый поворотник и ждём 5 секунд.
           bum.setTurnSignal(BUM_TURN_EMERGENCY); delay(5000);   //   Включаем поворотниками аварийный сигнал и ждём 5 секунд.
           bum.setTurnSignal(BUM_TURN_POLICE);    delay(5000);   //   Включаем поворотники в полицейский режим и ждём 5 секунд.
           bum.setTurnSignal(BUM_TURN_OFF);       delay(5000);   //   Отключаем поворотники и ждём 5 секунд.
      }                                                          //
      

      После загрузки данного примера, постоянно, будут выполняться следующие действия:

      • 5 секунд мигает левый поворотник;
      • 5 секунд мигает правый поворотник;
      • 5 секунд мигают оба поворотника - аварийный сигнал;
      • 5 секунд поворотники работают в режиме полицейской машины;
      • 5 секунд поворотники не мигают.

      В примере Arduino IDE: Файл / Примеры / iarduino I2C Bumper (бампер) / setTurnSignalAuto показано как заставить поворотники включаться и отключаться в автоматическом режиме (по положению линии под датчиками).

      Калибровка датчиков линий:

      #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
      #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
      iarduino_I2C_Bumper bum(0x09);                             //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper, указывая адрес модуля на шине I2C.
                                                                 //   Если объявить объект без указания адреса (iarduino_I2C_Bumper bum;), то адрес будет найден автоматически.
      void setup(){                                              //
           Serial.begin(9600);                                   //   Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
           bool f;                                               //   Объявляем флаг для отслеживания результатов калибровки.
           bum.begin(&Wire);                                     //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
           Serial.println("Установите бампер над линией трассы");//   Выводим текст.
           Serial.println("У Вас есть 5 секунд...\r\n");         //   Выводим текст.
           delay(5000);                                          //   Ждём 5 секунд.
           Serial.println("Запускаем калибровку.\r\nЖдите.\r\n");//
           f = bum.setCalibrationRun();                          //   Запускаем калибровку.
           Serial.println( f? "Линия считана!":"Ошибка!.");      //   Выводим текст зависящий от флага f.
           Serial.println("\r\nУстановите бампер над фоном");    //   Выводим текст.
           Serial.println("У Вас есть 5 секунд...\r\n");         //   Выводим текст.
           delay(5000);                                          //   Ждём 5 секунд.
           Serial.println("Завершаем калибровку.\r\nЖдите.\r\n");//   Выводим текст.
           f = bum.setCalibrationEnd();                          //   Завершаем калибровку.
           Serial.println( f? "Фон считан!":"Ошибка!.");         //   Выводим текст зависящий от флага f.
      }                                                          //
                                                                 //
      void loop(){}                                              //
      

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

      Через 5 секунд произойдёт обращение к функции setCalibrationRun() которая запустит калибровку и модуль считает данные с датчиков. Функция может выполняться до 5 секунд, после чего в мониторе появится результат чтения линий.

      Далее, в мониторе последовательного порта, появится текст предлагающий установить модуль так, что бы все его датчики находились над фоном трассы.

      Через 5 секунд произойдёт обращение к функции setCalibrationEnd() которая инициирует завершение калибровки и модуль считает данные с датчиков. Функция может выполняться до 5 секунд, после чего в мониторе появится результат чтения фона.

      Если при выполнении всего скетча в мониторе не появилась надпись «Ошибка!», значит модуль откалиброван и способен отличать линии данной трассы от фона.

      Вместо обращения к функциям setCalibrationRun() и setCalibrationEnd(), на любом этапе калибровки, можно просто нажать на кнопку «калибровка».

        В примере Arduino IDE: Файл / Примеры / iarduino I2C Bumper (бампер) / setCalibrationManual показано как выполнить калибровку в ручном режиме. Такая калибровка выполняется за 100 мс, при этом датчики модуля могут находиться даже вне трассы.

        Автоматическая смена типа линии на трассе:

        #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
        #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
        iarduino_I2C_Bumper bum;                                   //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper.
                                                                   //   Если при объявлении объекта указать адрес, например, bum(0xBB), то пример будет работать с тем модулем, адрес которого был указан.
        void setup(){                                              //
             bum.begin(&Wire);                                     //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
        }                                                          //
                                                                   //
        void loop(){                                               //
             if( bum.getLineSum() > 4 ){                           //   Если больше 4 датчиков бампера фиксируют линию, то ...
                 bum.setLineType(BUM_LINE_CHANGE);                 //   Меняем тип линии трассы.
             }                                                     //
        }                                                          //
        

        Данный пример сменит тип линии трассы если более 4 датчиков бампера одновременно фиксируют линию. Это значит, что если ширина линии используемой вами трассы уже чем расстояние между 4 датчиками, то скетч будет корректно определять линию, даже если на трассе есть места где цвет линии меняется с цветом фона.

        Чтение цвета под датчиками модуля:

        Только для модулей с поддержкой определения цвета.

        #include <Wire.h>                                          //   Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
        #include <iarduino_I2C_Bumper.h>                           //   Подключаем библиотеку для работы с бампером I2C-flash.
        iarduino_I2C_Bumper bum;                                   //   Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper.
                                                                   //   Если при объявлении объекта указать адрес, например, bum(0xBB), то пример будет работать с тем модулем, адрес которого был указан.
        void setup(){                                              //
            Serial.begin(9600);                                    //   Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
            bum.begin(&Wire);                                      //   Инициируем работу с бампером, указав ссылку на объект для работы с шиной I2C на которой находится бампер (по умолчанию &Wire).
        }                                                          //
                                                                   //
        void loop(){                                               //
             String t[] = {"ЧЕР","БЕЛ","КРА","ЖЁЛ","ЗЕЛ","СИН"};   //   Определяем названия доступных цветов.
        //   Получаем цвет под каждым датчиком:                    //
             uint8_t  l = bum.getColorDigital(1);                  //   Получаем цвет от 1 (левого  ) датчика. Значение от 0 до 5.
             uint8_t  c = bum.getColorDigital(2);                  //   Получаем цвет от 2 (среднего) датчика. Значение от 0 до 5.
             uint8_t  r = bum.getColorDigital(3);                  //   Получаем цвет от 3 (правого ) датчика. Значение от 0 до 5.
        //   Выводим цвета всех датчиков одной строкой:            //
             Serial.println( (String) t[l]+","+t[c]+","+t[r] );    //   (l) левый, (c) средний, (r) правый.
             delay(200);                                           // * Задержка позволяет медленнее заполнять монитор последовательного порта.
        }                                                          //
        

        Данный пример выводит цвета трёх датчиков одной строкой.

        В примере цвет каждого датчика получен обращением к функции getColorDigital(), с указанием номера датчика цвета, значит для получения 3 цветов пришлось выполнить 3 запроса. Вместо этого можно обратиться к функции getColorDigital() указав в качестве параметра значение BUM_LINE_ALL, тогда функция вернёт цвета всех 3 датчиков одним запросом, это будет десятичное число из 3 разрядов, где значение старшего разряда - цвет левого датчика, среднего разряда - цвет среднего датчика и младшего разряда - цвет правого датчика. см пример библиотеки getColorDigital.

        Описание функций библиотеки:

        В данном разделе описаны функции библиотеки iarduino_I2C_Bumper для работы с модулем - Бампер с 9 датчиками линий с шагом 14мм или шагом 7мм, I2C-flash.

        Данная библиотека может использовать как аппаратную, так и программную реализацию шины I2C. О том как выбрать тип шины I2C рассказано ниже в разделе «Подключение библиотеки», а так же на странице Wiki - расширенные возможности библиотек iarduino для шины I2C.

        Подключение библиотеки:

        • Если используется аппаратная шина I2C:
        #include <Wire.h>                  // Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
        #include <iarduino_I2C_Bumper.h>   // Подключаем библиотеку для работы с модулем.
                                           //
        iarduino_I2C_Bumper bum(0x09);     // Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper, указывая адрес модуля на шине I2C.
        // iarduino_I2C_Bumper bum;        // Если адрес модуля не известен, то его можно не указывать, он будет найден автоматически.
                                           // Если адрес не указан, то на шине должен находиться только один модуль.
        void setup(){                      //
             ...                           //
             bum.begin(&Wire);             // Инициируем работу с модулем, указав ссылку на объект для работы с шиной I2C на которой находится модуль (по умолчанию &Wire).
             ...                           // Доступны объекты: &Wire, &Wire1, &Wire2...
        }                                  //
        
        • Если используется программная шина I2C:
        #include <iarduino_I2C_Software.h> // Подключаем библиотеку для работы с программной шиной I2C, до подключения библиотеки iarduino_I2C_Bumper.h
        SoftTwoWire sWire(3,4);            // Создаём объект программной шины I2C указав выводы которым будет назначена роль линий: SDA, SCL.
                                           //
        #include <iarduino_I2C_Bumper.h>   // Подключаем библиотеку для работы с модулем.
        iarduino_I2C_Bumper bum(0x09);     // Создаём объект bum для работы с функциями и методами библиотеки iarduino_I2C_Bumper, указывая адрес модуля на шине I2C.
        // iarduino_I2C_Bumper bum;        // Если адрес модуля не известен, то его можно не указывать, он будет найден автоматически.
                                           // Если адрес не указан, то на шине должен находиться только один модуль.
        void setup(){                      //
             ...                           //
             bum.begin(&sWire);            // Инициируем работу с модулем, указав ссылку на объект для работы с шиной I2C на которой находится модуль (по умолчанию &Wire).
             ...                           //
        }                                  //
        • В обоих примерах сначала подключается библиотека для работы с шиной I2C. Для аппаратной шины библиотека Wire.h (предустановлена в Arduino IDE), а для программной шины библиотека iarduino_I2C_Software.h. с созданием объекта которому указываются выбранные вами выводы шины, в примере выводы (3-SDA, 4-SCL).
        • Далее подключается библиотека и создаётся объект для работы с модулем.
        • В коде Setup(), при инициализации работы с модулем указывается ссылка на объект работы с выбранной шиной I2C begin(&ШИНА). Остальные строки кода одинаковы для любой шины I2C.

        Функция begin();

        • Назначение: Инициализация работы с модулем.
        • Синтаксис: begin( [ &ШИНА ] );
        • Параметры:
          • &ШИНА - Ссылка на объект для работы с шиной I2C на которой находится модуль.
            • Для аппаратной шины: &Wire, &Wire1, &Wire2..., если подключена библиотека Wire.h
            • Для программной шины: ссылка на объект библиотеки iarduino_I2C_Software.h.
            • Параметр является не обязательным, по умолчанию используется ссылка &Wire.
        • Возвращаемое значение: bool - результат инициализации (true или false).
        • Примечание: По результату инициализации можно определить наличие модуля на шине.
        • Пример:
        if( bum.begin(&Wire) ){ Serial.print( "Модуль найден и инициирован!" ); }
        else                  { Serial.print( "Модуль не найден на шине I2C" ); }

        Функция reset();

        • Назначение: Перезагрузка модуля.
        • Синтаксис: reset();
        • Параметры: Нет.
        • Возвращаемое значение: bool - результат перезагрузки (true или false).
        • Пример:
        if( bum.reset() ){ Serial.print( "Модуль    перезагружен" ); }
        else             { Serial.print( "Модуль не перезагружен" ); }

        Функция changeAddress();

        • Назначение: Смена адреса модуля на шине I2C.
        • Синтаксис: changeAddress( АДРЕС );
        • Параметр: uint8_t АДРЕС - новый адрес модуля на шине I2C (целое число от 0x08 до 0x7E)
        • Возвращаемое значение: bool - результат смены адреса (true или false).
        • Примечание: Текущий адрес модуля можно узнать функцией getAddress().
        • Пример:
        if( bum.changeAddress(0x12) ){ Serial.print( "Адрес модуля изменён на 0x12" ); }
        else                         { Serial.print( "Не удалось изменить адрес"    ); }

        Функция getAddress();

        • Назначение: Запрос текущего адреса модуля на шине I2C.
        • Синтаксис: getAddress();
        • Параметры: Нет.
        • Возвращаемое значение: uint8_t АДРЕС - текущий адрес модуля на шине I2C (от 0x08 до 0x7E)
        • Примечание: Функция может понадобиться если адрес модуля не указан при создании объекта, а обнаружен библиотекой.
        • Пример:
        Serial.print( "Адрес модуля на шине I2C = 0x" );
        Serial.println( bum.getAddress(), HEX );

        Функция getVersion();

        • Назначение: Запрос версии прошивки модуля.
        • Синтаксис: getVersion();
        • Параметры: Нет
        • Возвращаемое значение: uint8_t ВЕРСИЯ - номер версии прошивки от 0 до 255.
        • Пример:
        Serial.print( "Версия прошивки модуля " );
        Serial.println( bum.getVersion() );

        Функция setTurnSignal();

        • Назначение: Указание режима работы поворотников.
        • Синтаксис: setTurnSignal( РЕЖИМ );
        • Параметр: uint8_t РЕЖИМ работы поворотников, может принимать следующие значения:
          • BUM_TURN_OFF - поворотники отключены.
          • BUM_TURN_LEFT - включён (мигает) левый поворотник.
          • BUM_TURN_RIGHT - включён (мигает) правый поворотник.
          • BUM_TURN_EMERGENCY - поворотники работают в режиме аварийного сигнала.
          • BUM_TURN_POLICE - поворотники работают в режиме полицейской машины.
          • BUM_TURN_AUTO - поворотники работают в автоматическом режиме.
        • Возвращаемое значение: bool - результат применения нового режима (true или false).
        • Примечание: Параметры автоматического режима задаются функцией settingsTurnAuto().
        • Пример:
        bum.setTurnSignal(BUM_TURN_LEFT ); // Включить только левый  поворотник.
        bum.setTurnSignal(BUM_TURN_RIGHT); // Включить только правый поворотник.
        

        Функция setTurnPeriod();

        • Назначение: Указание периода мигания поворотников.
        • Синтаксис: setTurnPeriod( ПЕРИОД );
        • Параметр: uint8_t ПЕРИОД мигания поворотников, может принимать следующие значения:
          • BUM_TURN_100 - период мигания равен 100мс (10Гц) 50мс вкл / 50мс выкл.
          • BUM_TURN_200 - период мигания равен 200мс (5Гц) 100мс вкл / 100мс выкл.
          • BUM_TURN_400 - период мигания равен 400мс (2,5Гц) 200мс вкл / 200мс выкл.
          • BUM_TURN_800 - период мигания равен 800мс (1,25Гц) 400мс вкл / 400мс выкл.
        • Возвращаемое значение: bool - результат применения нового периода (true или false).
        • Примечание: Функцию можно вызывать как до включения поворотников, так и во время их работы.
        • Пример:
        bum.setTurnPeriod(BUM_TURN_800); // Задать период мигания поворотников равен 800 мс.
        

        Функция settingsTurnAuto();

        • Назначение: Указание условий работы поворотников в автоматическом режиме.
        • Синтаксис: settingsTurnAuto( ВКЛ , ВЫКЛ [, ФЛАГ] );
        • Параметры:
          • uint8_t ВКЛ - условие включения поворотников, может принимать следующие значения:
            • BUM_AUTO_ON_1 - Линия под любым из двух самых крайних датчиков.
            • BUM_AUTO_ON_2 - Линия под любым из трёх самых крайних датчиков.
            • BUM_AUTO_ON_3 - Линия под любым из четырёх датчиков со стороны поворотника.
          • uint8_t ВЫКЛ - условие отключения поворотников, может принимать следующие значения:
            • BUM_AUTO_OFF_CEN - Под центральным датчиком есть линия.
            • BUM_AUTO_OFF_ANY - Линия есть под любым датчиком кроме указанных в условии включения.
          • bool ФЛАГ - значение true или false указывающее добавить 2 мигания перед отключением. Данный параметр является необязательным, если он не указан, значит ФЛАГ = false.
        • Возвращаемое значение: bool - результат применения новых настроек (true или false).
        • Примечание: Функцию можно вызывать как до включения поворотников, так и во время их работы в автоматическом режиме.
        • Пример:
        bum.settingsTurnAuto(BUM_AUTO_ON_2, BUM_AUTO_OFF_ANY, true); // Условие работы поворотников в автоматическом режиме.
        
        • Разбор примера:
          • В условии включения указан параметр BUM_AUTO_ON_2, значит поворотник будет включаться когда линия находится под любым из трёх самых крайних датчиков со стороны поворотника.
            • Для левого поворотника это датчики № 1, 2 и 3.
            • Для правого поворотника это датчики № 7, 8 и 9.
          • В условии отключения указан параметр BUM_AUTO_OFF_ANY, значит поворотник будет отключаться если линия находится под любым датчиком (или датчиками) бампера, при условии что не соблюдается условие для включения этого поворотника.
          • В качестве третьего (необязательного) параметра указано значение true, значит при наступлении условия отключения поворотника он выключится не сразу, а спустя 2 мигания.

        Функция setCalibrationRun();

        • Назначение: Запуск автоматической калибровки датчиков линий.
        • Синтаксис: setCalibrationRun();
        • Параметры: Нет.
        • Возвращаемое значение: bool - результат запуска калибровки (true или false).
        • Примечание:
          • Обращение к данной функции равносильно первому нажатию на кнопку «калибровка».
          • Во время выполнения функции все датчики должны находиться над линией трассы.
          • Запуск автоматической калибровки приводит к началу чтения показаний АЦП со всех датчиков линий, этот процесс занимает до 7 секунд.
          • Функция ждёт завершение данной стадии калибровки.
          • По завершению чтения показаний датчиков, модуль перейдёт в стадию ожидания завершения калибровки. Инициировать завершение калибровки можно нажатием на кнопку «калибровка» или обращением к функции setCalibrationEnd().
        • Пример:
        bum.setCalibrationRun(); // Начать калибровку.
        

        Функция setCalibrationEnd();

        • Назначение: Завершение автоматической калибровки датчиков линий.
        • Синтаксис: setCalibrationEnd( [ ФЛАГ ] );
        • Параметр: bool ФЛАГ - значение true указывает на то что датчики требуется откалибровать не по отдельности, а определить одно общее значение для всех датчиков.
        • Возвращаемое значение: bool - результат инициализации завершения калибровки (true или false).
        • Примечание:
          • Обращение к данной функции равносильно второму нажатию на кнопку «калибровка».
          • Во время выполнения функции все датчики должны находиться над фоном трассы.
          • Инициализация завершения автоматической калибровки приводит к началу чтения показаний АЦП со всех датчиков линий, этот процесс занимает до 7 секунд.
          • Функция ждёт завершение данной стадии калибровки.
          • По завершению чтения показаний датчиков, модуль рассчитает граничные значения АЦП датчиков между фоном и линией трассы, определит тип линии трассы и сохранит результаты в энергонезависимую память.
          • Если функция вызвана без параметра (или с параметром false), то модуль рассчитает граничные значения АЦП для каждого датчика в отдельности (как при нажатии на кнопку «калибровка»).
          • Если функция вызвана с параметром true, то модуль рассчитает общее граничное значение АЦП, одинаковое для всех датчиков (может помочь при сильной боковой засветке трассы).
          • По сохранённым граничным значениям АЦП (между линией и фоном) модуль будет определять наличие линии под датчиками.
          • Более подробно про граничные значения АЦП рассказано в пояснении к ручной калибровке.
        • Пример:
        bum.setCalibrationEnd(); // Завершить калибровку.
        

        Функция setCalibrationManual();

        • Назначение: Выполнение ручной калибровки датчиков линий.
        • Синтаксис: setCalibrationManual( АЦП [, АЦП, АЦП, АЦП, АЦП, АЦП, АЦП, АЦП, АЦП ] );
        • Параметры:
          • uint16_t АЦП - число (0...4095) соответствующее граничному значению АЦП датчика.
        • Возвращаемое значение: bool - результат записи калибровочных значений (true или false).
        • Примечание:
          • Функция принимает 9 граничных значений АЦП для каждого датчика модуля, или одно граничное значение АЦП для всех датчиков модуля.
          • Граничное значение АЦП является средним значением между АЦП датчика для линии и АЦП датчика для фона.
          • АЦП любого датчика, для линии и фона, можно получить функцией getLineAnalog().
          • Указанные значения сохраняются в энергонезависимую память модуля и используются им в последствии для определения наличия линий под датчиками.
          • При ручной калибровке, помимо указания значений АЦП, может понадобится указание типа используемой линии при помощи функции setLineType().
        • Пример:
        bum.setCalibrationManual( 700 );                                          // Применить граничное значение 700 для всех датчиков модуля.
        bum.setCalibrationManual( 710, 770, 750, 899, 900, 700, 800, 650, 1000 ); // Применить граничное значение 710 для 1 датчика, 770 для второго и т.д.
        • Пояснение ручной калибровки:
          • Предположим что нами используется трасса с тёмной линией на светлом фоне, это можно указать модулю обратившись к функции setLineType( BUM_LINE_BLACK );
          • Предположим что при помощи функции getLineAnalog( 1 ); мы выяснили, что АЦП первого датчика для линии равно 500, а для фона 2500. Значит граничное значение АЦП для первого датчика равно 1500 (среднее значение). Аналогичным образом рассчитываются граничные значения АЦП для остальных датчиков.
          • После выполнения ручной калибровки, модуль будет знать что граничное значение АЦП первого датчика равно 1500. Так как мы указали модулю, что линия трассы темнее её фона, то все значения датчика ниже граничного, модуль будет воспринимать как линия, а выше граничного - как фон. Чем светлее поверхность под датчиком, тем выше значение АЦП.
          • Стоит учесть что зона в ±30 значений АЦП возле границы является гистерезисом.

        Функция getCalibrationManual();

        • Назначение: Получение текущих граничных значений АЦП.
        • Синтаксис: getCalibrationManual( НОМЕР );
        • Параметр: uint8_t НОМЕР датчика - число от 1 до 9 включительно.
        • Возвращаемое значение:
          • uint16_t АЦП - граничное значение АЦП (0...4095) используемое в настоящий момент тем датчиком, номер которого был указан в качестве параметра функции.
        • Примечание:
          • Функция возвращает граничное значение АЦП, вне зависимости от того как это значение было указано, вручную функцией setCalibrationManual() или рассчитано модулем по завершении калибровки линии.
        • Пример:
        uint16_t i = bum.getCalibrationManual( 1 ); // Получить граничное значение первого датчика линий.
        

        Функция getCalibrationStage();

        • Назначение: Получение текущего статуса автоматической калибровки датчиков линий.
        • Синтаксис: getCalibrationStage();
        • Параметры: Нет.
        • Возвращаемое значение: uint8_t СТАТУС - одно из возможных значений:
          • BUM_STAGE_READ_LN - выполняется чтение АЦП с датчиков над линией трассы.
          • BUM_STAGE_WAITING - модуль ожидает поступления команды на чтение фона.
          • BUM_STAGE_READ_BG - выполняется чтение АЦП с датчиков над фоном трассы.
          • BUM_STAGE_OFF_OK - калибровка завершена успехом.
          • BUM_STAGE_OFF_ERR - калибровка не выполнялась или завершена провалом.
        • Примечание:
          • Функцию можно использовать для контроля выполнения и результата автоматической калибровки, запускаемой как функциями, так и нажатием кнопки «калибровка».
          • В примере Arduino IDE: Файл / Примеры / iarduino I2C Bumper (бампер) / controlCalibrationButton показан пример контроля за ходом выполнения калибровки с кнопки.
        • Пример:
        if(bum.getCalibrationStage()==BUM_STAGE_OFF_OK){Serial.println("Калибровка выполнена успешно");}
        

        Функция getLineDigital();

        • Назначение: Чтение линий под датчиками модуля.
        • Синтаксис: getLineDigital( НОМЕР );
        • Параметр: uint8_t НОМЕР датчика, может принимать значение от 1 до 9.
        • Возвращаемое значение: uint16_t - флаг наличия линии под датчиком (true или false).
        • Примечание:
          • Если в качестве параметра НОМЕР указать не число, а значение BUM_LINE_ALL, то функция вернёт не флаг, а число состоящее из 9 бит, где каждый бит (кроме нулевого) является флагом наличия линии под датчиком, номер которого совпадает с номером бита.
        • Пример:
        bool i = bum.getLineDigital( 5 );                     // Если под 5 датчиком есть линия, то i = true.
        bool i = bum.getLineDigital( BUM_LINE_ALL ) & bit(5); // Если под 5 датчиком есть линия, то i = true.
        

        Функция getLineAnalog();

        • Назначение: Чтение значений АЦП снятых с датчиков модуля.
        • Синтаксис: getLineAnalog( НОМЕР );
        • Параметр: uint8_t НОМЕР датчика, может принимать значение от 1 до 9.
        • Возвращаемое значение: uint16_t - число от 0 до 4096 соответствующее значению АЦП датчика.
        • Примечание:
          • Обращение к функции позволяет получить значение АЦП того датчика номер которого был указан в качестве параметра.
          • Чем светлее поверхность под датчиком, тем выше значение АЦП.
        • Пример:
        uint16_t i = bum.getLineAnalog( 5 ); // Получить значение АЦП с 5 датчика в переменную i.
        

        Функция getErrPID();

        • Назначение: Чтение ошибки центрирования линии для ПИД регулятора.
        • Синтаксис: getErrPID();
        • Параметры: Нет.
        • Возвращаемое значение: float - значение ошибки центрирования от 0 до ±4,5.
        • Примечание:
          • Обращение к функции позволяет получить ошибку центрирования линии.
          • Функция возвращает отрицательные значения если центр линии находится левее центра бампера.
          • Функция возвращает положительные значения если центр линии находится правее центра бампера.
            • 0 - нет ошибки, линия находится под центральным датчиком бампера.
            • ±0,5 - линия находится между центральным и соседним с ним датчиком.
            • ±1.0 - линия находится под датчиком соседним с центральным.
            • ±3.5 - линия находится между самым крайним и соседним с ним датчиком.
            • ±4.0 - линия находится под самым крайним датчиком.
            • ±4.5 - линия потеряна, знак указывает на сторону потери линии.
          • Функция позволяет работать с линиями ширина которых находится в диапазоне от 1 до 7 дистанций между датчиками линий.
          • Функция позволяет двигаться по линии и проезжать перекрёстки в прямом направлении. Для осуществления поворотов на перекрёстках воспользуйтесь функцией getSidePID().
        • Пример:
        float i = bum.getErrPID(); // Получить ошибку центрирования линии в переменную i.
        

        Функция getSidePID();

        • Назначение: Чтение ошибки центрирования края линии для ПИД регулятора.
        • Синтаксис: getSidePID( [КРАЙ] );
        • Параметры: int8_t КРАЙ - число отличное от 0 со знаком края линии (-левый, +правый).
        • Возвращаемое значение: float - значение ошибки центрирования края от 0 до ±4,5.
        • Примечание:
          • Обращение к функции позволяет получить ошибку центрирования края линии.
          • Функция возвращает отрицательные значения если край линии находится левее центра бампера.
          • Функция возвращает положительные значения если край линии находится правее центра бампера.
            • 0 - нет ошибки, край линии находится под центральным датчиком бампера.
            • ±0,5 - край линии находится между центральным и соседним с ним датчиком.
            • ±1.0 - край линии находится под датчиком соседним с центральным.
            • ±3.5 - край линии находится между самым крайним и соседним с ним датчиком.
            • ±4.0 - край линии находится под самым крайним датчиком.
            • ±4.5 - край линии потерян, знак указывает на сторону потери линии.
          • Функция позволяет работать с линиями ширина которых находится в диапазоне от 1 до 7 дистанций между датчиками линий.
          • Функция позволяет двигаться по краю линии и осуществлять повороты на перекрёстках, для проезда перекрёстков в прямом направлении воспользуйтесь функцией getErrPID().
        • Пример:
        float i = bum.getSidePID(-1); // Получить ошибку центрирования левого  края линии в переменную i.
        float i = bum.getSidePID( 1); // Получить ошибку центрирования правого края линии в переменную i.
        

        Функция getCross();

        • Назначение: Обнаружение перекрёстков и крутых поворотов.
        • Синтаксис: getCross( ШИРИНА, [ВРЕМЯ] );
        • Параметры:
          • Параметры: uint8_t ШИРИНА - количество датчиков, расположенных над линией вне перекрёстка.
          • Параметры: uint32_t ВРЕМЯ - количество мс требуемое для преодоления перекрёстка.
        • Возвращаемое значение: bool - флаг наличия перекрёстка под бампером.
        • Примечание:
          • Обращение к функции позволяет определить наличие перекрёстка.
          • Если функция вызвана с параметром ВРЕМЯ, то она будет возвращать true в течении этого времени, уже после преодоления перекрёстка.
          • Функцию getCross() удобно использовать для перехода с getSidePID() на getErrPID().
        • Пример:
        bool i = bum.getCross(3); // Получить флаг наличия перекрёстка. Толщина линии равна 3 датчикам бампера.
        

        Функция getLineSum();

        • Назначение: Запрос количества датчиков находящихся над линией.
        • Синтаксис: getLineSum( [ПЕРЕМЕННАЯ] );
        • Параметр: uint16_t ПЕРЕМЕННАЯ для получения флагов наличия линий.
        • Возвращаемое значение: uint8_t - число от 0 до 9 соответствующее количеству датчиков находящихся над линией.
        • Примечание:
          • Данная функция позволяет получить не только количество датчиков находящихся над линией (в качестве возвращаемого значения), но и флаги наличия линий (если в качестве необязательного параметра указана переменная для получения этих флагов).
          • Флаги возвращаемые параметру соответствуют значению возвращаемому функцией getLineDigital( BUM_LINE_ALL ).
        • Пример:
        uint8_t i = bum.getLineSum( ); // Получить количество датчиков которые находятся над линией.
        uint8_t i = bum.getLineSum(j); // «i» получает количество датчиков над линией, а «j» получает флаги наличия линий под датчиками, как если написать j=getLineDigital(BUM_LINE_ALL);.
        

        Функция getLineType();

        • Назначение: Запрос типа линии трассы для которой откалиброван модуль.
        • Синтаксис: getLineType();
        • Параметры: Нет.
        • Возвращаемое значение: uint8_t - ТИП лини, может принимать следующие значения:
          • BUM_LINE_BLACK - модуль откалиброван для трассы с тёмной линией на светлом фоне.
          • BUM_LINE_WHITE - модуль откалиброван для трассы со светлой линией на тёмном фоне.
        • Пример:
        if( bum.getLineType() == BUM_LINE_BLACK ){ Serial.println("Трасса с  тёмной  линией"); }
        else                                     { Serial.println("Трасса со светлой линией"); }
        

        Функция setLineType();

        • Назначение: Установка типа линии трассы.
        • Синтаксис: setLineType( ТИП );
        • Параметры: uint8_t ТИП лини, может принимать следующие значения:
          • BUM_LINE_BLACK - указать модулю что трасса использует тёмную линию.
          • BUM_LINE_WHITE - указать модулю что трасса использует светлую линию.
          • BUM_LINE_CHANGE - изменить тип линии трассы на противоположный.
        • Возвращаемое значение: bool - результат записи нового типа линии в модуль (true или false).
        • Примечание:
          • Тип используемой линии сохраняется в энергонезависимую память модуля, а значит модуль будет работать с данным типом трассы и после отключения питания.
          • Функцию удобно использовать с параметром BUM_LINE_CHANGE, если на трассе есть участки, где цвет линии и фона резко меняют друг друга.
        • Пример:
        bum.setLineType(BUM_LINE_BLACK); // Указываем модулю что на трассе используется тёмная линия на светлом фоне.

        Функция getMaxSpeed();

        • Назначение: Получение максимальной скорости движения бампера.
        • Синтаксис: getMaxSpeed();
        • Параметры: Нет.
        • Возвращаемое значение: uint8_t - максимальная скорость в мм/с.
        • Примечание:
          • Функция возвращает максимальную скоростью движения бампера по линии в мм/с, при которой бампер сможет определить наличие перпендикулярного перекрёстка. Скорость полученную данной функцией нужно умножить на толщину линии трассы в мм.
          • Если функция вернула 100 мм/с, а ширина линии 1 см (10 мм), то бампер может двигаться по линии с максимальной скоростью: 100 мм/с * 10 мм = 1000 мм/с = 1 м/с = 3,6 км/ч.
          • Функция поддерживается бамперами с прошивкой версии 8 и выше. Версию прошивки можно узнать функцией getVersion().
        • Пример:
        i = bum.getMaxSpeed(); // Максимальная скорость движения бампера для линии в 1 мм.
        j = 10;                // Толшина линии трассы в мм
        k = i*j;               // Максимальная скорость движения бампера для линии в j мм.

        Функция setSpeedLine();

        • Назначение: Указание скорости опроса модулем датчиков линий.
        • Синтаксис: setSpeedLine( СКОРОСТЬ );
        • Параметры: uint8_t СКОРОСТЬ, может принимать следующие значения:
          • BUM_READ_NO - не опрашивать датчики линий (не поддерживается).
          • BUM_READ_LOW - медленная скорость опроса датчиков линий (по умолчанию).
          • BUM_READ_MIDDLE - средняя скорость опроса датчиков линий.
          • BUM_READ_FAST - быстрая скорость опроса датчиков линий.
        • Возвращаемое значение: bool - результат указания скорости (true или false).
        • Примечание:
          • Скорость опроса модулем датчиков линии сохраняется в энергонезависимую память, а значит модуль будет работать с данной скоростью и после отключения питания.
          • При медленной скорости опроса бампер может располагаться на высоте до 2 см от трассы.
          • При быстрой скорости опроса бампер должен располагаться на высоте до 5 мм от трассы.
          • После смены скорости опроса модулем датчиков линий, бампер нужно откалибровать.
          • Изменение скорости опроса влияет на максимальную скорость движения бампера возвращаемую функцией getMaxSpeed().
          • Функция поддерживается бамперами с прошивкой версии 8 и выше. Версию прошивки можно узнать функцией getVersion().
        • Пример:
        bum.setSpeedLine(BUM_READ_MIDDLE); // Указываем модулю опрашивать датчики линий со средней скоростью.
        

        Функция getSpeedLine();

        • Назначение: Запрос установленной скорости опроса модулем датчиков линий.
        • Синтаксис: getSpeedLine();
        • Параметры: Нет.
        • Возвращаемое значение: uint8_t СКОРОСТЬ - одно из возможных значений:
          • BUM_READ_NO - не опрашивать датчики линий (не поддерживается).
          • BUM_READ_LOW - медленная скорость опроса датчиков линий (по умолчаннию).
          • BUM_READ_MIDDLE - средняя скорость опроса датчиков линий.
          • BUM_READ_FAST - быстрая скорость опроса датчиков линий.
        • Примечание:
          • Чем быстрее модуль опрашивает свои датчики линий, тем быстрее он может двигаться по трассе, но должен быть ближе к линии трассы.
          • Функция поддерживается бамперами с прошивкой версии 8 и выше. Версию прошивки можно узнать функцией getVersion().
        • Пример:
        Serial.println("Модуль опрашивает датчики линий ");
        switch( bum.getSpeedLine() ){
            case BUM_READ_LOW:    Serial.println("медленно"); break;
            case BUM_READ_MIDDLE: Serial.println("средне"  ); break;
            case BUM_READ_FAST:   Serial.println("быстро"  ); break;
        }
        

        Дополнительные функции библиотеки:

        Функции доступны только для бамперов с поддержкой определения цвета.

        Функция setSpeedColor();

        • Назначение: Указание скорости опроса модулем датчиков цвета.
        • Синтаксис: setSpeedColor( СКОРОСТЬ );
        • Параметры: uint8_t СКОРОСТЬ, может принимать следующие значения:
          • BUM_READ_NO - не опрашивать датчики цвета.
          • BUM_READ_LOW - медленная скорость опроса датчиков цвета.
          • BUM_READ_MIDDLE - средняя скорость опроса датчиков цвета (не поддерживается).
          • BUM_READ_FAST - быстрая скорость опроса датчиков цвета (по умолчанию).
        • Возвращаемое значение: bool - результат указания скорости (true или false).
        • Примечание:
          • Скорость опроса модулем датчиков цвета сохраняется в энергонезависимую память модуля, а значит модуль будет работать с данной скоростью и после отключения питания.
          • Изменение скорости опроса влияет на максимальную скорость движения бампера возвращаемую функцией getMaxSpeed().
          • Функция поддерживается бамперами с прошивкой версии 8 и выше. Версию прошивки можно узнать функцией getVersion().
        • Пример:
        bum.setSpeedColor(BUM_READ_NO); // Указываем модулю не опрашивать датчики цвета.
        

        Функция getSpeedColor();

        • Назначение: Запрос установленной скорости опроса модулем датчиков цвета.
        • Синтаксис: getSpeedColor();
        • Параметры: Нет.
        • Возвращаемое значение: uint8_t СКОРОСТЬ - одно из возможных значений:
          • BUM_READ_NO - не опрашивать датчики цвета.
          • BUM_READ_LOW - медленная скорость опроса датчиков цвета (по умолчанию).
          • BUM_READ_MIDDLE - средняя скорость опроса датчиков цвета (не поддерживается).
          • BUM_READ_FAST - быстрая скорость опроса датчиков цвета.
        • Примечание:
          • Функция поддерживается бамперами с прошивкой версии 8 и выше. Версию прошивки можно узнать функцией getVersion().
        • Пример:
        Serial.println("Модуль опрашивает датчики цвета ");
        switch( bum.getSpeedColor() ){
            case BUM_READ_NO:     Serial.println("никогда" ); break;
            case BUM_READ_LOW:    Serial.println("медленно"); break;
            case BUM_READ_FAST:   Serial.println("быстро"  ); break;
        }
        

        Функция setCalibrationRGB();

        • Назначение: Запуск автоматической калибровки датчиков цвета.
        • Синтаксис: setCalibrationRGB();
        • Параметры: Нет.
        • Возвращаемое значение: bool - результат запуска калибровки цвета (true или false).
        • Примечание:
          • Во время выполнения функции все датчики должны находиться над белым фоном (например, над белым листом бумаги).
          • Запуск автоматической калибровки цвета приводит к началу чтения показаний АЦП со всех датчиков цвета, этот процесс занимает до 5 секунд.
          • По завершению калибровки цвета, модуль сохранит результаты в энергонезависимую память.
        • Пример:
        bum.setCalibrationRGB(); // Выполнить калибровку цвета.
        

        Функция setCalibrationManualRGB();

        • Назначение: Выполнение ручной калибровки датчиков цвета.
        • Синтаксис: setCalibrationManualRGB( R [, G, B [, R, G, B, R, G, B ]] );
        • Параметры:
          • int8_t R - коэффициент коррекции яркости красного цвета (0...±15).
          • int8_t G - коэффициент коррекции яркости зелёного цвета (0...±15).
          • int8_t B - коэффициент коррекции яркости синего цвета (0...±15).
        • Возвращаемое значение: bool - результат записи коэффициентов (true или false).
        • Примечание:
          • Функция принимает 9 коэффициентов RGB для каждого канала цвета каждого датчика цвета, или 3 коэффициента RGB для каждого датчика цвета, или одно значение для всех каналов RGB всех датчиков цвета.
          • Каждая единица указанного коэффициента меняет аналоговое значение цвета на 3%.
          • Если указать (0, 10, -10), то у каждого датчика значение красного останется без изменений, значение зелёного будет выше на 30%, а значение синего ниже на 30%.
          • Используемые коэффициенты любого датчика можно получить функцией getCalibrationManualRGB().
          • Указанные коэффициенты сохраняются в энергонезависимую память модуля.
        • Пример:
        bum.setCalibrationManualRGB( 0 );                             // Применить коэффициент 0 для всех каналов цвета всех датчиков цвета.
        bum.setCalibrationManualRGB( -5, 0, 5 );                      // Применить коэффициенты: R=-5, G=0, B=+5 для каждого датчика цвета.
        bum.setCalibrationManualRGB( -4, -3, -2, -1, 0, 1, 2, 3, 4 ); // Применить коэффициенты: R=-4, G=-3, B=-2 для левого датчика, R=-1, G=0, B=+1 для среднего датчика, R=2, G=3, B=+4 для правого датчика.
        • Пояснение ручной калибровки цвета:
          • Каждый датчик цвета считывает АЦП яркости каналов красного R, зелёного G и синего B. Ограничивая диапазон считанных значений до диапазона 0...15. Эти значения можно прочитать обратившись к функции getColorAnalog();
          • Для белого цвета значение каналов цвета должно быть R=15, G=15, B=15. Если датчик не откалиброван и показывает R=15, G=10, B=10, то можно либо указать отрицательный коэффициент R либо положительные коэффициенты G и B.
          • Вместо подбора коэффициентов вручную, можно запустить автоматическую калибровку цвета обратившись к функции setCalibrationRGB();

        Функция getCalibrationManualRGB();

        • Назначение: Запрос установленных коэффициентов коррекции яркости цвета.
        • Синтаксис: getCalibrationManualRGB( НОМЕР [, &R, &G, &B] );
        • Параметры:
          • uint8_t НОМЕР датчика - число от 1 до 3 включительно.
          • int8_t &R - адрес переменной для получения коэффициента коррекции яркости красного.
          • int8_t &G - адрес переменной для получения коэффициента коррекции яркости зелёного.
          • int8_t &B - адрес переменной для получения коэффициента коррекции яркости синего.
        • Возвращаемое значение:
          • uint16_t RGB - коэффициенты коррекции яркости всех цветов датчика, номер которого был указан в качестве параметра.
        • Примечание:
          • Функция возвращает коэффициенты коррекции яркости цветов указанного датчика, вне зависимости от того как эти коэффициенты были указаны, вручную функцией setCalibrationManualRGB() или рассчитаны модулем по завершении калибровки цвета.
          • Коэффициент коррекции красного, зелёного и синего канала цвета это число от -15 до +15.
          • Коэффициенты можно получить двумя способами, как указано в примерах ниже.
        • Пример:
        int8_t R, G, B;                             // Создаём переменные для получения коэффициентов.
        bum.getCalibrationManualRGB(1, &R, &G, &B); // Получаем коэффициенты первого (левого) датчика цвета в указанные переменные.
        • Пример:
        uint16_t i = bum.getCalibrationManualRGB(2); // Получаем коэффициенты второго (среднего) датчика цвета.
        int8_t   R = (i>>10) & 0x001F; R -= 15;      // Извлекаем коэффициент коррекции яркости красного.
        int8_t   G = (i>>5 ) & 0x001F; G -= 15;      // Извлекаем коэффициент коррекции яркости зелёного.
        int8_t   B = (i>>0 ) & 0x001F; B -= 15;      // Извлекаем коэффициент коррекции яркости синего.

        Функция getCalibrationStageRGB();

        • Назначение: Получение текущего статуса автоматической калибровки датчиков цвета.
        • Синтаксис: getCalibrationStageRGB();
        • Параметры: Нет.
        • Возвращаемое значение: uint8_t СТАТУС - одно из возможных значений:
          • BUM_STAGE_READ_COLOR - выполняется чтение АЦП с датчиков цвета.
          • BUM_STAGE_OFF_OK - калибровка завершена успехом.
          • BUM_STAGE_OFF_ERR - калибровка не выполнялась или завершена провалом.
        • Примечание:
          • Функцию можно использовать для контроля выполнения и результата автоматической калибровки цвета, запускаемой как функциями, так и нажатием кнопки «калибровка».
        • Пример:
        if(bum.getCalibrationStageRGB()==BUM_STAGE_OFF_OK){Serial.println("Калибровка выполнена успешно");}
        

        Функция getColorAnalog();

        • Назначение: Чтение аналоговых значений общей яркости и яркости каналов цвета.
        • Синтаксис: getColorAnalog( НОМЕР [, &L, &R, &G, &B] );
        • Параметры:
          • uint8_t НОМЕР датчика - число от 1 до 3 включительно.
          • uint8_t &L - адрес переменной для получения общей яркости датчика цвета.
          • uint8_t &R - адрес переменной для получения яркости красного канала датчика цвета.
          • uint8_t &G - адрес переменной для получения яркости зелёного канала датчика цвета.
          • uint8_t &B - адрес переменной для получения яркости синего канала датчика цвета.
        • Возвращаемое значение:
          • uint16_t LRGB - все аналоговые значения яркости указанного датчика.
        • Примечание:
          • Аналоговое значение общей яркости цвета (L) - это число от 0 до 15 определяющее оттенок цвета (темный или светлый).
          • Аналоговые значения яркости каналов цвета (RGB) - это три числа, диапазон которых пропорционально уменьшен так, что одно из чисел равно 15, а остальные лежат в пределах от 0 до 15.
          • Примеры определения цвета по аналоговым значениям:
            • L=3, R=6, G=15, B=5 - тёмно зелёный.
            • L=13, R=6, G=5, B=15 - светло синий.
            • L=8, R=15, G=5, B=5 - красный.
            • L=7, R=15, G=4, B=15 - фиолетовый.
            • L=0, R=15, G=15, B=15 - чёрный.
            • L=7, R=15, G=15, B=15 - серый.
            • L=15, R=15, G=15, B=15 - белый.
          • Аналоговые значения можно получить двумя способами, как указано в примерах ниже.
        • Пример:
        uint8_t L, R, G, B;                    // Создаём переменные для получения аналоговых значений цвета.
        bum.getColorAnalog(1, &L, &R, &G, &B); // Получаем аналоговые значения первого (левого) датчика цвета в указанные переменные.
        • Пример:
        uint16_t i = bum.getColorAnalog(2); // Получаем аналоговые значения второго (среднего) датчика цвета.
        uint8_t  L = (i>>12) & 0x000F;      // Извлекаем аналоговое значение общей яркости цвета.
        uint8_t  R = (i>>8 ) & 0x000F;      // Извлекаем аналоговое значение яркости красного.
        uint8_t  G = (i>>4 ) & 0x000F;      // Извлекаем аналоговое значение яркости зелёного.
        uint8_t  B = (i>>0 ) & 0x000F;      // Извлекаем аналоговое значение яркости синего.

        Функция getColorDigital();

        • Назначение: Чтение цифрового значения цвета.
        • Синтаксис: getColorDigital( НОМЕР );
        • Параметр: uint8_t НОМЕР датчика - число от 1 до 3 включительно.
        • Возвращаемое значение: uint16_t ЦВЕТ - число от 0 до 5 соответствующее цвету:
          • 0 - Чёрный.
          • 1 - Белый.
          • 2 - Красный.
          • 3 - Жёлтый.
          • 4 - Зелёный.
          • 5 - Синий.
        • Примечание:
          • Функция возвращает цифру от 0 до 5 соответствующую цвету, который определён модулем как наиболее близкий к тому, который находится под датчиком, номер которого был указан в качестве параметра функции.
          • Если в качестве параметра НОМЕР указать не номер датчика, а значение BUM_LINE_ALL, то функция вернёт не цифру 0-5, а трёхзначное число 000-555, где старший разряд - это цвет левого датчика, средний разряд - цвет среднего датчика, младший разряд - цвет правого датчика цвета.
        • Пример:
        String color[] = {"ЧЕР","БЕЛ","КРА","ЖЁЛ","ЗЕЛ","СИН"}; // Названия доступных цветов.
        uint8_t i = bum.getColorDigital(3);                     // Получаем цифровое значение цвета третьего (правого) датчика цвета.
        Serial.print( color[i] );                               // Выводим название цвета.
        
        • Пример:
        String color[] = {"ЧЕР","БЕЛ","КРА","ЖЁЛ","ЗЕЛ","СИН"}; // Названия доступных цветов.
        uint16_t i = bum.getColorDigital(BUM_LINE_ALL);         // Получаем цифровые значения цвета всех датчиков.
        Serial.print( color[i/100 %10] );                       // Выводим название цвета с левого датчика.
        Serial.print( color[i/10  %10] );                       // Выводим название цвета с среднего датчика.
        Serial.print( color[i/1   %10] );                       // Выводим название цвета с правого датчика.

        Ссылки:




        Обсуждение

        Гарантии и возврат Используя сайт Вы соглашаетесь с условями