Главная chevron_right Уроки chevron_right Встроенные примеры chevron_right Связь chevron_right Virtual Color Mixer: управление цветом через аналоговые датчики

Virtual Color Mixer: управление цветом через аналоговые датчики

Урок о том, как передавать несколько значений с Arduino на компьютер и управлять цветом фона в Processing или Max/MSP.

В этом уроке разберём, как отправлять сразу несколько значений с Arduino на компьютер по последовательному порту. Показания трёх аналоговых датчиков задают красную, зелёную и синюю составляющие цвета фона — в скетче Processing или в патче Max/MSP. Получается настоящий виртуальный смеситель цветов, управляемый руками.

Необходимое железо

  • 3 аналоговых датчика (потенциометр, фоторезистор, датчик силы FSR и т. п.)
  • 3 резистора 10 кОм
  • соединительные провода
  • макетная плата

Необходимое программное обеспечение

Схема подключения

Подключите аналоговые датчики к аналоговым входам A0, A1 и A2.

В схеме используются три делителя напряжения voltage divider: два резистора включаются последовательно, и напряжение распределяется между ними пропорционально их сопротивлениям. Датчик силы (FSR) меняет своё сопротивление под нагрузкой, а резистор 10 кОм задаёт опорное плечо делителя — именно поэтому analogRead() возвращает разные значения при разном давлении на датчик.

Схема подключения трёх датчиков силы (FSR) к аналоговым входам Arduino UNO через макетную плату

Принципиальная схема

Принципиальная схема: датчики силы и резисторы 10 кОм (чувствительные резисторы) подключены к входам A0A2 Arduino UNO

Как это работает

Arduino считывает три аналоговых значения (от 0 до 1023) и отправляет их в одной строке через Serial, разделяя запятыми. Принимающая сторона — Processing или Max/MSP — парсит эту строку и применяет числа как компоненты RGB-цвета.

Ключевой момент: данные передаются в формате ASCII-encoded decimal numbers, то есть каждая цифра числа кодируется отдельным ASCII-символом. Например, значение 234 занимает три байта: '2' (50), '3' (51), '4' (52). Строка завершается символами возврата каретки (\r) и перевода строки (\n), что позволяет принимающей программе понять, где заканчивается одна порция данных.

Код Arduino

/*

  Этот пример считывает три аналоговых датчика (проще всего использовать потенциометры) и

  передаёт их значения по последовательному порту. Программы Processing и Max/MSP, приведённые

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

  Схема:

  - потенциометры подключены к аналоговым входам 0, 1 и 2

  создан 2 декабря 2006 г.

  автор David A. Mellis

  изменён 30 августа 2011 г.

  авторы Tom Igoe и Scott Fitzgerald

  Код примера находится в открытом доступе (public domain).

  https://www.arduino.cc/en/Tutorial/VirtualColorMixer

*/

const int redPin = A0;      // датчик управления красным цветом

const int greenPin = A1;    // датчик управления зелёным цветом

const int bluePin = A2;     // датчик управления синим цветом

void setup() {

  Serial.begin(9600);
}

void loop() {

  Serial.print(analogRead(redPin));

  Serial.print(",");

  Serial.print(analogRead(greenPin));

  Serial.print(",");

  Serial.println(analogRead(bluePin));
}

/* Код Processing для этого примера

  // Код примера находится в открытом доступе (public domain).

  import processing.serial.*;

  float redValue = 0;        // значение красного

  float greenValue = 0;      // значение зелёного

  float blueValue = 0;       // значение синего

  Serial myPort;

  void setup() {

    size(200, 200);

    // Вывести список всех доступных последовательных портов

    // в Processing 2.1 и выше используйте Serial.printArray()

    println(Serial.list());

    // На моём Mac первый порт в списке всегда соответствует Arduino,

    // поэтому открываю Serial.list()[0].

    // Откройте тот порт, который используете вы.

    myPort = new Serial(this, Serial.list()[0], 9600);

    // не генерировать serialEvent(), пока не получен символ новой строки:

    myPort.bufferUntil('\n');

  }

  void draw() {

    // установить цвет фона по значениям цветовых компонент:

    background(redValue, greenValue, blueValue);

  }

  void serialEvent(Serial myPort) {

    // получить строку ASCII:

    String inString = myPort.readStringUntil('\n');

    if (inString != null) {

      // убрать пробельные символы по краям:

      inString = trim(inString);

      // разбить строку по запятым и преобразовать полученные подстроки

      // в массив чисел с плавающей точкой:

      float[] colors = float(split(inString, ","));

      // если массив содержит не менее трёх элементов, данные получены полностью.

      // Записать числа в переменные цвета:

      if (colors.length >= 3) {

        // привести к диапазону 0–255:

        redValue = map(colors[0], 0, 1023, 0, 255);

        greenValue = map(colors[1], 0, 1023, 0, 255);

        blueValue = map(colors[2], 0, 1023, 0, 255);

      }

    }

  }

*/

/* Патч Max/MSP для этого примера

 ----------begin_max5_patcher----------

1512.3oc4Z00aaaCE8YmeED9ktB35xOjrj1aAsXX4g8xZQeYoXfVh1gqRjdT

TsIsn+2K+PJUovVVJ1VMdCAvxThV7bO7b48dIyWtXxzkxaYkSA+J3u.Sl7kK

lLwcK6MlT2dxzB5so4zRW2lJXeRt7elNy+HM6Vs61uDDzbOYkNmo02sg4euS

4BSede8S2P0o2vEq+aEKU66PPP7b3LPHDauPvyCmAvv4v6+M7L2XXF2WfCaF

lURgVPKbCxzKUbZdySDUEbgABN.ia08R9mccGYGn66qGutNir27qWbg8iY+7

HDRx.Hjf+OPHCQgPdpQHoxhBlwB+QF4cbkthlCRk4REnfeKScs3ZwaugWBbj

.PS+.qDPAkZkgPlY5oPS4By2A5aTLFv9pounjsgpnZVF3x27pqtBrRpJnZaa

C3WxTkfUJYA.BzR.BhIy.ehquw7dSoJCsrlATLckR.nhLPNWvVwL+Vp1LHL.

SjMG.tRaG7OxT5R2c8Hx9B8.wLCxVaGI6qnpj45Ug84kL+6YIM8CqUxJyycF

7bqsBRULGvwfWyRMyovElat7NvqoejaLm4f+fkmyKuVTHy3q3ldhB.WtQY6Z

x0BSOeSpTqA+FW+Yy3SyybH3sFy8p0RVCmaMpTyX6HdDZ2JsPbfSogbBMueH

JLd6RMBdfRMzPjZvimuWIK2XgFA.ZmtfKoh0Sm88qc6OF4bDQ3P6kEtF6xej

.OkjD4H5OllyS+.3FlhY0so4xRlWqyrXErQpt+2rsnXgQNZHZgmMVzEofW7T

S4zORQtgIdDbRHrObRzSMNofUVZVcbKbhQZrSOo934TqRHIN2ncr7BF8TKR1

tHDqL.PejLRRPKMR.pKFAkbtDa+UOvsYsIFH0DYsTCjqZ66T1CmGeDILLpSm

myk0SdkOKh5LUr4GbWwRYdW7fm.BvDmzHnSdH3biGpSbxxDNJoGDAD1ChH7L

I0DaloOTBLvkO7zPs5HJnKNoGAXbol5eytUhfyiSfnjE1uAq+Fp0a+wygGwR

q3ZI8.psJpkpJnyPzwmXBj7Sh.+bNvVZxlcKAm0OYHIxcIjzEKdRChgO5UMf

LkMPNN0MfiS7Ev6TYQct.F5IWcCZ4504rGsiVswGWWSYyma01QcZgmL+f+sf

oU18Hn6o6dXkMkFF14TL9rIAWE+6wvGV.p.TPqz3HK5L+VxYxl4UmBKEjr.B

6zinuKI3C+D2Y7azIM6N7QL6t+jQyZxymK1ToAKqVsxjlGyjz2c1kTK3180h

kJEYkacWpv6lyp2VJTjWK47wHA6fyBOWxH9pUf6jUtZkLpNKW.9EeUBH3ymY

XSQlaqGrkQMGzp20adYSmIOGjIABo1xZyAWJtCX9tg6+HMuhMCPyx76ao+Us

UxmzUE79H8d2ZB1m1ztbnOa1mGeAq0awyK8a9UqBUc6pZolpzurTK232e5gp

aInVw8QIIcpaiNSJfY4Z+92Cs+Mc+mgg2cEsvGlLY6V+1kMuioxnB5VM+fsY

9vSu4WI1PMBGXye6KXvNuzmZTh7U9h5j6vvASdngPdgOFxycNL6ia1axUMmT

JIzebXcQCn3SKMf+4QCMmOZung+6xBCPLfwO8ngcEI52YJ1y7mx3CN9xKUYU

bg7Y1yXjlKW6SrZnguQdsSfOSSDItqv2jwJFjavc1vO7OigyBr2+gDYorRk1

HXZpVFfu2FxXkZtfp4RQqNkX5y2sya3YYL2iavWAOaizH+pw.Ibg8f1I9h3Z

2B79sNeOHvBOtfEalWsvyu0KMf015.AaROvZ7vv5AhnndfHLbTgjcCK1KlHv

gOk5B26OqrXjcJ005.QqCHn8fVTxnxfj93SfQiJlv8YV0VT9fVUwOOhSV3uD

eeqCUClbBPa.j3vWDoMZssNTzRNEnE6gYPXazZaMF921syaLWyAeBXvCESA8

ASi6Zyw8.RQi65J8ZsNx3ho93OhGWENtWpowepae4YhCFeLErOLENtXJrOSc

iadi39rf4hwc8xdhHz3gn3dBI7iDRlFe8huAfIZhq

-----------end_max5_patcher-----------

*/

Практические замечания

  • Выбор датчиков. Потенциометр — самый предсказуемый вариант: диапазон хорошо растянут, нет дребезга. Фоторезистор и FSR зависят от условий окружения, поэтому результирующий цвет будет «живым» и непредсказуемым — что само по себе интересно.
  • Стабильность показаний. Если значения скачут, добавьте простое скользящее среднее или используйте constrain() и map() для нормировки.
  • Скорость обмена. В скетче используется 9600 бод. Убедитесь, что в Processing или Max/MSP выставлена та же скорость — иначе вместо цифр получите мусор.
  • Порт COM. В Processing нужно указать правильный номер порта. Запустите Serial.list() в Processing, чтобы увидеть доступные порты, и выберите тот, к которому подключена Arduino.

Код Processing

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

Код Max/MSP

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

Патч Max/MSP принимает строку с тремя числами (от 0 до 1023), разделёнными запятыми, преобразует их в целые числа и устанавливает цвет фона. Нажмите на элемент управления портом, чтобы открыть последовательный порт и запустить патч.

Типичные ошибки

  • Ничего не происходит в Processing. Проверьте номер порта в коде Processing — он должен совпадать с тем, который использует Arduino IDE.
  • Цвет «застрял» на одном значении. Убедитесь, что делитель напряжения собран правильно: один конец датчика на 5V, другой — через резистор 10 кОм на GND, а средняя точка — на аналоговый вход.
  • Значения не меняются при нажатии на FSR. Возможно, резистор и датчик перепутаны местами в делителе — поменяйте их местами и проверьте снова.
  • Цвет мигает или дёргается. Добавьте небольшую задержку (delay(10)) в конец loop(), чтобы не перегружать последовательный буфер.

Как проверить результат

Откройте Serial Monitor в Arduino IDE и убедитесь, что в каждой строке приходят три числа, разделённые запятыми, например: 512,0,1023. Если строки выглядят корректно — Arduino работает правильно, и можно переходить к запуску Processing или Max/MSP.

Дополнительные материалы

Больше базовых уроков можно найти в разделе built-in examples.

Также изучите language reference — подробный справочник по языку программирования Arduino.

Последнее обновление: 11.08.2015, SM