Опубликовано

Взаимодействие Arduino с компьютерной программой Processing

По материалам книги Джереми Блума “Изучаем Arduino: инструменты и методы технического волшебства. 2-е изд.: пер. с англ.“(Глава 7. Последовательный интерфейс USB)

Изучаем Arduino: инструменты и методы технического волшебства. 2-е изд.

Прежде чем рассмотреть взаимодействие Arduino с компьютерной программой, рассмотрим как такое взаимодействие организовано посредством программы Монитора порта.

Отправка одиночных символов для управления светодиодом

Прежде чем приступать к обработке чисел, состоящих из нескольких цифр, разработаем скетч для управления светодиодом с помощью одного символа. В частности, при получении символа “1” скетч будет включать светодиод, а символа “0” — выключать его. Для работы этого скетча нужно подключить светодиод к контакту 9 платы Arduino, как показано на рис. 7.10.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image10.jpeg

Рис. 7.10. Подключение светодиода к контакту 9 платы Arduino (Рисунок создан в программе Fritzing)

Как мы разобрались в предыдущем разделе, при отправке одиночного символа проще всего сравнить его с целевым символом в операторе условия if. Каждый помещаемый в буфер символ сравнивается с символом ‘0’ или ‘1’, и в зависимости от того, с каким символом он совпадает, предпринимается соответствующее действие. Создайте новый скетч, скопируйте в него код из листинга 7.4, загрузите его в свою плату Arduino и экспериментируйте, отправляя одиночные символы 0 и 1 из монитора порта.

Листинг 7.4. Программа single_char_control.ino для управления светодиодом с помощью одиночных символов

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Управление светодиодом с помощью одиночных символов
const int LED=9;
char data; // Переменная для хранения получаемого символа
void setup()
{
Serial.begin(9600); // Запускаем последовательный порт
// со скоростью в бодах = 9600
pinMode(LED, OUTPUT);
}
 
void loop()
{
// Предпринимаем действие только при наличии данных в буфере
if (Serial.available() > 0)
{
data = Serial.read(); // Считываем входящий байт данных
// Включаем светодиод
if (data == '1')
{
digitalWrite(LED, HIGH);
Serial.println("LED ON");
}
 
// Выключаем светодиод
else if (data == '0')
{
digitalWrite(LED, LOW);
Serial.println("LED OFF");
}
}
}

Обратите внимание на то, что вместо простого оператора условия if…else в коде присутствует его вариант if…else…if. Поскольку в каждой передаче вместе с символами управления светодиодом монитор порта также отправляет и символ новой строки, важно удалить этот символ из буфера. Считываемый функцией Serial.read() символ новой строки не проходит проверку на превышение символа ‘0’, и в скетче не предпринимается никакого действия по его обработке. Обрабатываются только получаемые символы ‘0’ и ‘1’. Если же в коде использовался бы вариант if…else, то светодиод выключался бы при получении как символа ‘0’, так и символа новой строки ‘\n’. Более того, даже при получении символа ‘1’ скетч сразу же после включения светодиода выключал бы его при получении символа новой строки ‘\n’, следующего за символом ‘1’.

Управление разноцветным светодиодом с помощью списка значений

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

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image11.jpeg

Рис. 7.11. Подключение разноцветного светодиода к плате Arduino (Рисунок создан в программе Fritzing)

Для управления разноцветным светодиодом нам нужно посылать плате Arduino три значения в диапазоне 0–100, задающие яркость каждого из составляющих его трех светодиодов. Например, чтобы задать полную яркость для всех трех составляющих светодиодов, нам нужно отправить значения 100,100,100. Решение этой задачи сопряжено с несколькими проблемами:

  • Нам нужно как-то отличить числа от запятых.
  • Последовательность символов нужно преобразовать в целые числа и сопоставить эти числа значениям в диапазоне 0–255 для управления светодиодами, используя функции analogWrite().
  • Нам также нужно учитывать, что мы работаем со светодиодом с общим анодом, и сигналы управления подаются на катоды составляющих его светодиодов. Иными словами, значение 255 выключит светодиод, а значение 0 включит его на полную яркость.
  • Необходимо учитывать возможность, что значения яркости могут состоять из одной, двух или трех цифр.
  • Наша программа должна быть достаточно надежной, способной обрабатывать полученные данные, форматирование которых не соответствует норме, таким образом, чтобы они не искажали данные последующих передач (в разумных пределах).

К счастью среда Arduino IDE содержит очень удобную функцию Serial.parseInt() для определения и извлечения целых чисел. Функция ожидает, пока во входной буфер последовательного порта не поступит нецифровое значение, после чего она преобразовывает все предыдущие цифры в целое число. В нашем случае, первые два значения считываются по обнаружению следующих за ними запятых, а последнее — после обнаружения символа перевода строки.

Чтобы увидеть работу этой функции, загрузите код из листинга 7.5 в свою плату Arduino.

Листинг 7.5. Программа list_control.ino для управления разноцветным светодиодом

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Отправляем одновременно несколько значений
// Данные отправляются в следующем формате: <0-100>,<0-100>,<0,100)>\n
// Здесь числа представляют яркость в процентах красного,
// зеленого и синего светодиодов
// Контакты платы Arduino, к которым подключаются катоды светодиодов
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
void setup()
{
Serial.begin(9600); // Запускаем последовательный порт
// со скоростью в бодах = 9600
Serial.setTimeout(10); // Таймаут, в течение которого
// ожидать целое число
// Задаем выходной режим работы для контактов управления светодиодами
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
// Выключаем светодиоды
// Поскольку светодиод имеет общий анод, для выключения светодиода
// на катод подается сигнал высокого уровня
digitalWrite(RED, HIGH);
digitalWrite(GREEN, HIGH);
digitalWrite(BLUE, HIGH);
}
void loop()
{
// Считываем данные, когда они присутствуют в буфере
if (Serial.available() > 0)
{
// Ожидаем получить три целых числа по последовательному каналу связи
// Функция parseInt() заблокирует исполнение следующего кода
// до тех пора, пока не будет получено действительное целое число
// Целое число определяется по завершающей запятой
// или символу новой строки
// Недействительные символы удаляются перед найденным целым числом,
// а не после него
int val1 = Serial.parseInt();
int val2 = Serial.parseInt();
int val3 = Serial.parseInt();
// После считывания всех целых чисел, очищаем буфер
while (Serial.available())
{
Serial.read();
}
// Ограничиваем полученные значения диапазоном 0–100%
int val1c = constrain(val1,0,100);
int val2c = constrain(val2,0,100);
int val3c = constrain(val3,0,100);
// Сопоставляем аналоговые значения процентным значениям
int rval = map(val1c,0,100,255,0); // Первое действительное
// целое число
int gval = map(val2c,0,100,255,0); // Второе действительное
// целое число
int bval = map(val3c,0,100,255,0); // Третье действительное
// целое число
// Устанавливаем яркость светодиода
analogWrite(RED, rval);
analogWrite(GREEN, gval);
analogWrite(BLUE, bval);
// Выводим на экран использованные значения яркости
Serial.println("Red: " + String(val1c) + "%");
Serial.println("Green: " + String(val2c) + "%");
Serial.println("Blue: " + String(val3c) + "%\n");
}
}

В функции setup() запускаем последовательный интерфейс, а затем с помощью функции setTimeout() задаем величину таймаута, равную 10 мс для функции parseInt(). Если в течение 10 мс по последовательному каналу не будет получен следующий символ, эта функция считает завершенным извлечение текущего целого числа. Это просто мера предосторожности, чтобы не допустить зависания программы в случае отправки неполного списка значений.

Вспомним, что поскольку наш разноцветный светодиод с общим анодом, мы управляем составляющими светодиодами, подключая их катоды на землю. Таким образом, подача высокого уровня на катод светодиода препятствует протеканию тока через него, т. е. выключает светодиод. Подобным образом необходимо инвертировать значения аргументов функции analogWrite(), т. е. значение 255 выключает светодиод, а значение 0 включает его на полную яркость. Код главного цикла loop() ожидает наличия данных в буфере последовательного порта и извлекает из него первые три целых числа. Если буфер содержит какие-либо дополнительные данные, все они удаляются функцией Serial.read(), оставляя буфер пустым. Затем вызывается функция constrain(), ограничивающая все значения диапазоном 0–100. Далее функция map() сопоставляет 0 процентов значению 255, а 100 процентов значению 0, чтобы обеспечить использование функции analogWrite(). Наконец, устанавливаются уровни яркости составляющих цветных светодиодов, значения которых также дополнительно выводятся в окно монитора порта. Затем цикл ожидает поступления следующего набора команд.

Загрузите эту программу в свою плату Arduino и откройте окно монитора последовательного порта. Наберите в строке ввода монитора порта три числа со значениями в диапазоне 0–100, например, 80,10,80, и нажмите кнопку Отправить. Попробуйте немного поэкспериментировать, устанавливая разные цвета для светодиода.

Взаимодействие с компьютерной программой

Со временем вам надоест взаимодействовать с платой Arduino посредством программы монитора порта. К счастью, это не единственная программа, с помощью которой можно обмениваться информацией между компьютером и платой Arduino: практически любой язык программирования содержит библиотеки, позволяющие работать с последовательным портом компьютера. Из наиболее популярных языков программирования, обладающих обширными, хорошо задокументированными библиотеками последовательной связи, можно назвать, например, Python, Java, C, Node.js и другие. Таким образом, если вы знаете какой-либо из этих языков программирования, то сможете разрабатывать на нем программы для двустороннего обмена данными через последовательный интерфейс между компьютером и платой Arduino.

В этой книге мы будем использовать для этого язык Processing, поскольку он очень похож на язык программирования Arduino, с которым вы уже знакомы. Более того, язык программирования Arduino разработан на основе языка Processing. Сначала мы разработаем программу на языке Processing для считывания данных, получаемых в последовательный порт, а затем создадим простой графический интерфейс пользователя для отправки команд плате Arduino.

Интерфейс программирования языка Processing достаточно простой, похожий на интерфейс среды Arduino IDE. В этом разделе мы установим язык Processing на компьютер, а затем разработаем на нем простой графический интерфейс для визуального представления данных, получаемых с платы Arduino по последовательному каналу. Разобравшись с работой этой программы, мы создадим другую: графический интерфейс для передачи данных с компьютера на плату Arduino.

Установка Processing

Чтобы разрабатывать программы на языке Processing, нам нужно установить этот язык на свой компьютер. Загрузите установочный архив для своей операционной системы со страницы загрузки Processing (https://processing.org/download/) на свой компьютер. Для установки просто распакуйте загруженный архив в какую-либо папку. Запустите приложение Processing, выполнив двойной щелчок мышью по значку приложения. Должно открыться главное окно среды IDE, которое выглядит, как показано на рис. 7.12.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image12.jpeg

Рис. 7.12. Главное окно среды Processing IDE

Управление приложением Processing посредством платы Arduino

Для первого эксперимента с Processing мы будем управлять цветом окна приложения на компьютере с помощью потенциометра, подключенного к плате Arduino. Для этого подключите потенциометр к плате Arduino, руководствуясь монтажной схемой на рис. 7.6. Мы уже знаем, как передавать аналоговые значения сигнала потенциометра на компьютер. Тот факт, что принимаемые на компьютере данные подаются в программу на языке Processing, никак не влияет на способ их передачи.

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

Листинг 7.6. Программа Arduino arduino_read_pot.ino для передачи данных на компьютер

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Передача значения уровня сигнала с потенциометра на компьютер
const int POT=0; // Сигнал с потенциометра подается
// на аналоговый контакт A0
int val; // Переменная для хранения сопоставленного
// значения сигнала с потенциометра
void setup()
 
{
Serial.begin(9600); // Запускаем последовательную передачу данных
}
 
void loop()
{
val = map(analogRead(POT), 0, 1023, 0, 255); // Считываем сигнал
// с потенциометра и сопоставляем его
// значению в диапазоне 0–255
Serial.println(val); // Отправляем значение на компьютер
delay(50); // Выдерживаем паузу, чтобы
// не переполнить входной буфер
}

А теперь следует интересная часть задачи: создание скетча Processing для приема и обработки данных, передаваемых платой Arduino. Программа, приведенная в листинге 7.7, считывает данные из входного буфера последовательного порта компьютера, и изменяет яркость одного из основных цветов созданного им окна на основе значений, получаемых от Arduino. Создайте новый скетч Processing и скопируйте в него код из листинга 7.7. Затем вам нужно будет внести в скопированный код одну важную корректировку. В частности, скетчу Processing необходимо знать, на каком последовательном порту ожидать поступающие от Arduino данные. Это будет тот же самый порт, к которому подключена ваша плата Arduino. Поэтому в листинге 7.7 замените COM3 номером этого последовательного порта. (В системах под Linux и Mac OS обозначение этого порта будет выглядеть наподобие /dev/ttyUSB0). Чтобы избежать ошибок при ручном вводе, номер последовательного порта можно скопировать из среды Arduino IDE.

Листинг 7.7. Скетч processing_display_color.pde для приема данных по последовательному каналу и изменения цвета окна

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Скетч Processing для приема данных по последовательному каналу
// и изменения цвета окна
// Импортируем и инициализируем библиотеку последовательного порта
import processing.serial.*;
Serial port;
float brightness = 0; // Переменная для хранения значения сигнала
// с потенциометра
 
void setup()
{
size(500,500); // Размер окна
port = new Serial(this, "COM3", 9600); // Инициализируем
// последовательный порт
port.bufferUntil('\n'); // Конфигурируем порт для чтения
// данных до символа новой строки
}
 
void draw()
{
background(0,0,brightness); // Обновляем окно
}
void serialEvent (Serial port)
{
brightness = float(port.readStringUntil('\n')); // Получаем значение
// от Arduino
}

Скопировав код в свой скетч и указав в нем правильный номер последовательного порта, проверьте, что программа монитора порта среды Arduino IDE не открыта. Последовательный порт компьютера может одновременно использоваться только одной программой. Нажмите кнопку Run окна Processing IDE (левая кнопка со значком треугольника в ней, расположенная в верхнем левом углу окна). Откроется небольшое окно (рис. 7.13). Вращайте подключенный к плате Arduino потенциометр; цвет окна должен плавно изменяться с черного на синий.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image13.jpeg

Increasing analog values

Увеличивающиеся аналоговые значения

Рис. 7.13. Пример исполнения скетча Processing для изменения цвета окна

Убедившись, что наш скетч работает должным образом, рассмотрим пошагово его код, чтобы разобраться, как он работает. В отличие от скетчей Arduino, библиотека для работы с последовательным портом не импортируется автоматически в программы на Processing. Эту задачу выполняет оператор import processing.serial.*, а оператор Serial port создает объект последовательной связи, называющийся port.

Подобно скетчам Arduino, программы на Processing содержат функцию setup(), которая исполняется один раз в начале кода. В данном коде Processing эта функция выполняет настройки последовательного порта и посредством команды size(500,500) создает окно размером 500 × 500 пикселов. Оператор port = new Serial(this, “COM3”, 9600) предоставляет Processing всю необходимую информацию для создания экземпляра объекта последовательного порта. При исполнении в этом скетче данный экземпляр порта (называющийся port) будет поддерживать связь через порт COM3 (или через другой конкретный порт) со скоростью 9600 бод. Скорость последовательной передачи данных должна быть одинаковой, как в скетче Arduino, так и в скетче Processing; в противном случае передаваемые символы будут искажаться в процессе приема. Оператор port.bufferUntil(‘\n’) дает указание Processing помещать полученные данные во входной буфер и не предпринимать никаких действий до тех пор, пока не будет получен символ новой строки.

В Processing вместо цикла loop() предусмотрены другие специальные функции, в частности, функции draw() и serialEvent(). Функция draw() Processing похожа на функцию loop() Arduino: она исполняется в бесконечном цикле и обновляет дисплей. Функция background() устанавливает цвет окна, задавая интенсивность составляющих цветов: красного, зеленого и синего (значения которых передаются функции в аргументах). В данном случае выходной сигнал от потенциометра управляет интенсивностью синего цвета, а для красного и зеленого цветов установлены нулевые значения. Можно изменить управляемый потенциометром цвет, просто разместив аргумент brightness в соответствующей позиции списка аргументов. Значения красного, зеленого и синего цветов задаются значениями в диапазоне от 0 до 255, поэтому значения выходного сигнала с потенциометра перед их передачей сопоставляются значениям в этом диапазоне.

Функция serialEvent() вызывается всякий раз, когда выполняется условие bufferUntil(), заданное в функции setup(). Таким условием является получение символа новой строки. Поступающие по последовательному каналу данные считываются в строку оператором port.readStringUntil(‘\n’). Строку можно рассматривать, как массив текстовых символов. Содержимое строки преобразуется в число с плавающей запятой посредством функции float(). Результат этой функции присваивается переменной brightness, в итоге изменяется цвет фона окна приложения.

Чтобы остановить исполнение приложения Processing, нажмите кнопку Stop в окне среды Processing IDE (круглая кнопка со значком квадрата внутри нее, расположенная справа от кнопки Run).

Передача скетчем Processing данных на плату Arduino

Очевидным следующим шагом будет передача данных в обратном направлении: с компьютера на Arduino. Для этого эксперимента нам нужно будет подключить к плате Arduino разноцветный светодиод с общим анодом, как показано на монтажной схеме на рис. 7.11 и загрузить в плату Arduino программу из листинга 7.5. Только теперь вместо отправки плате Arduino трех числовых значений через монитор порта, мы будем отправлять цвет, выбираемый с помощью палитры цветов, встроенной в Processing.

Создайте в Processing новый скетч, скопируйте в него код, приведенный в листинге 7.8, и запустите программу на исполнение. (Не забудьте изменить номер порта в коде на номер порта, используемый вашей платой Arduino, как это нужно было сделать в предыдущем скетче.)

Листинг 7.8. Скетч processing_control_RGB.pde для управления разноцветным светодиодом на Arduino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import processing.serial.*; // Импортируем библиотеку serial
PImage img; // Объект изображения
Serial port; // Объект последовательного порта
void setup()
{
size(640,256); // Размер изображения в цветовой модели HSV
img = loadImage("hsv.jpg"); // Загружаем фоновое изображение
port = new Serial(this, "COM3", 9600); // Открываем последовательный
// порт
}
void draw()
{
background(0); // Черный фон
image(img,0,0); // Накладываемое изображение
}
void mousePressed()
{
color c = get(mouseX, mouseY); // Получаем цвет RGB в точке,
// где находится курсор мыши
int r = int(map(red(c), 0, 255, 0, 100));
int g = int(map(green(c), 0, 255, 0, 100));
int b = int(map(blue(c), 0, 255, 0, 100));
String colors = r+","+g+","+b+"\n"; // Извлекаем значения из цвета
print(colors); // Выводим значения цветов
// на экран для целей отладки
port.write(colors); // Отправляем значения
// на плату Arduino
}

Скетчи Processing автоматически загружают сопутствующие файлы из папки data, вложенной в папку скетча. Файл hsv.jpg входит в состав кода для этой главы. Загрузите его и поместите в папку data в папке своего скетча. По умолчанию Processing сохраняет скетчи в папке Processing, находящейся в папке Мои документы текущего пользователя, автоматически создавая папку для скетча с таким же самым названием, как и скетч. Структура папок проекта выглядит подобно показанной на рис. 7.14. Изображение в папке data будет использоваться в качестве цветовой палитры.

C:\Users\Anansi\AppData\Local\Temp\FineReader10\media\image14.jpeg

Рис. 7.14. Структура папок проекта Processing

Запустите скетч Processing на исполнение; отроется окно приложения, заполненное палитрой, как на рис. 7.15.

7

Рис. 7.15. Окно программы Processing для выбора цвета

Щелкайте мышью по разным цветам; в консоли окна среды Processing IDE будут выводиться значения составных цветов выбранного цвета, которые передаются на плату Arduino, вызывая соответствующее изменение цвета подключенного к ней разноцветного светодиода.

Убедившись, что все составляющие проекта функционируют должным образом, рассмотрим код скетча Processing более подробно, чтобы разобраться, как он работает. Как и в предыдущем скетче Processing, импортируется библиотека последовательного интерфейса serial и создается объект последовательного порта с названием port. Кроме этого создается объект типа PImage с названием img, который будет содержать фоновое изображение. В функции setup() выполняется инициализация последовательного порта, устанавливается размер окна приложения, равный размеру выводимого в нем изображения, и осуществляется импорт изображения в объект изображения, с помощью оператора img = loadImage(“hsv.jpg”). Операция импорта предполагает, что файл hsv.jpg находится в папке data текущего скетча Processing.

В функции draw() изображение загружается в окно посредством оператора image(img,0,0). В данном случае аргумент img обозначает изображение, которое мы хотим отображать в окне приложения, а аргументы 0,0 обозначают координаты, в которых нужно начинать выводить это изображение. Эти координаты представляют верхний левый угол окна приложения.

При каждом щелчке мышью по изображению палитры в окне приложения вызывается функция mousePressed(). Цвет пиксела, по которому пришелся щелчок, сохраняется в виде объекта типа color с названием c. Сам цвет извлекается методом get(), который предоставляет приложению информацию, откуда получить значения цвета (в данном случае, координаты X и Y щелчка мыши). Затем вызывается функция map(), которая сопоставляет значения составных цветов процентным значениям, ожидаемых скетчем Arduino. Полученные процентные значения далее конкатенируются в строку, которая отправляется по последовательному каналу на плату Arduino. Для справки эти значения также выводятся в консоли главного окна Processing IDE.

Подключите свою плату Arduino (с подсоединенным к ней разноцветным светодиодом) к компьютеру и загрузите в нее код из листинга 7.5. Запустите на исполнение скетч Processing (предварительно исправив в нем номер последовательного порта должным образом), и щелкайте по разным цветам в палитре в открывшемся окне приложения. Выбранный таким образом цвет должен устанавливаться на разноцветном светодиоде, подключенном к плате Arduino.

Резюме

В этой главе мы узнали следующее:

  • Платы Arduino подключаются к компьютеру через преобразователь USB/RS-232.
  • Для преобразования USB/RS-232 в разных платах Arduino может быть предусмотрена специальная микросхема или реализована встроенная поддержка функциональности USB.
  • Плата Arduino может отправлять данные на компьютер через интерфейс USB.
  • Для форматирования текста, выводимого в окне монитора порта, можно использовать символы новой строки и табуляции.
  • Данные передаются по последовательному каналу в виде символов, которые можно преобразовать в целые числа несколькими способами.
  • По последовательному каналу с компьютера в скетч Arduino можно отправлять наборы целых чисел, разделенных запятыми. В скетче Arduino составляющие числа можно извлечь из набора с помощью специальных функций и использовать их в качестве команд для скетча.
  • По последовательному каналу можно отправлять данные из скетча Arduino в программу на Processing, исполняющуюся на компьютере.
  • Из программы на Processing можно отравлять данные в скетч Arduino для управления подключенными к плате Arduino периферийными устройствами.
Опубликовано

Графопостроитель FlexiPlot

По материалам книги В. Яценкова  «Здоровье, спорт и окружающая среда в проектах Arduino» (глава 5. «Визуализация данных»)

Здоровье

Графопостроитель FlexiPlot находится в процессе разработки, но уже сейчас обладает большим количеством настроек и функций. Скачайте архив файлов программы по адресу https://github.com/xcoder123/FlexiPlot/releases. Программа не требует установки. Распакуйте архив в удобное место.

FlexiPlot позволяет открыть несколько рабочих окон графопостроителя (Chart), и в каждом окне можно независимо и одновременно строить до 256-ти графиков. Каждому окну присвоено уникальное имя (индекс окна). Этот индекс необходимо указать в пакете данных, чтобы программа поняла, в какое окно направить пакет.

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

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

{Index|Name_1|Colour_1|Value_1|Name_2|Colour_2|Value_2}

где:

  • Index — имя окна, в которое отправлен пакет;
  • Name_1 — подпись первой кривой в легенде графика;
  • Colour_1 — цвет первой кривой графика в формате R,G,B (например, 255,0,0);
  • Value_1 — текущее значение для первой кривой графика;
  • Name_2 — подпись второй кривой в легенде графика;
  • Colour_2 — цвет второй кривой графика в формате R,G,B;
  • Value_2 — текущее значение для второй кривой графика,

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

Пакет должен завершаться символом перевода строки.

Такой объемный пакет данных позволяет очень гибко настраивать отображение графиков. Например, можно на ходу менять цвет линии графика в зависимости от величины отображаемого параметра. Но большая длина пакета вынуждает использовать высокую скорость передачи данных в порт (115200 бод) и выдерживать паузу не менее 5 мс между пакетами, чтобы избежать переполнения буфера порта и потерю данных.

Загрузите в плату Arduino демонстрационный скетч из листинга 5.3. Этот скетч отправляет текущее значение аргумента angle в окно P0, а значения тригонометрических функций sin() и cos() — в окно P1.

Листинг 5.3. Пример работы с графопостроителем FlexiPlot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define DEG_TO_RAD 0.01745329
void setup() {
Serial.begin(115200);
}
 
void loop() {
for (float angle = 0; angle < 360; angle++)
{
// Пакет данных для окна P0
Serial.print("{P0|Angle|0,0,255|");
Serial.print(angle);
Serial.println("}");
 
 
// Пакет данных для окна P1
Serial.print("{P1|Sin|255,0,0|");
Serial.print(sin(DEG_TO_RAD * angle)*10);
Serial.print("|Cos|0,255,0|");
Serial.print(cos(DEG_TO_RAD * angle));
Serial.println("}");
}
}
  1. Запустите программу FlexiPlot. Настройте номер последовательного порта (опция Port) и установите скорость обмена 115200 бод (опция Baudrate).
  2. Выберите пункт меню Graph | Add Line Chart или нажмите кнопку графического меню с изображением графика — на экране появится рабочее окно графопостроителя, которое надо настроить. Растяните это окно на всю ширину окна программы и на половину его высоты.
  3. Перейдите на вкладку Settings и введите в поле Title название окна — например, Аргумент функций.
  4. В поле Buffer введите значение 1000 — это размер буфера. С такой настройкой буфер будет хранить 1000 выборок. Вновь поступающие значения вытесняют устаревшие данные.
  5. В поле Refresh Rate введите значение 10 — это интервал между обновлениями изображения в миллисекундах. Чем меньше его значение, тем плавнее движется график, но выше нагрузка на процессор компьютера.
  6. Уберите флажок Auto Scaling Y (автомасштабирование по оси Y). В нашем случае мы заранее знаем, что отображаемое значение изменяется в диапазоне от 0 до 360, поэтому можем настроить масштаб вручную. Для этого в поле Min Y введите 0, а в поле Max Y — 400.
  7. Добавьте еще одно рабочее окно и расположите его под предыдущим окном. Введите заголовок окна — например, Значения функций. Значения Buffer и Refresh Rate скопируйте из настроек первого окна, чтобы графики прорисовывались синхронно.
  8. Уберите флажок Auto Scaling Y. В поле Min Y введите -10, в поле Max Y — 10.
  9. Для сохранения всех настроек и расположения рабочих окон нажмите кнопку с изображением дискеты или выберите пункт меню File | Save.
  10. Вернитесь к вкладкам Chart. Выберите пункт меню Serial | Connect. Плата Arduino перезагрузится и начнется прорисовка графиков (рис. 5.3). Если этого не произошло, проверьте настройку номера и скорости порта, а также настройки рабочих окон.

5-3

Рис. 5.3. Рабочее окно программы FlexiPlot с демонстрационными графиками

exclamation При большой нагрузке на процессор компьютера может искажаться прорисовка графиков. В ответственных случаях лучше не запускать на компьютере одновременно с FlexiPlot какие-либо ресурсоемкие программы.

Дополнительные настройки рабочего окна графика

Вы можете также задать следующие дополнительные настройки:

  • Date Format — формат меток реального времени по оси X (часы:минуты:секунды). Можно оставить только нужную метку или полностью убрать метки времени;
  • Auto Filling — автоматическая заливка цветом областей под кривой графика;
  • Auto Fill Opacity — интенсивность цвета заливки. По умолчанию — 20%.

Встроенный терминал

В программе имеется встроенный терминал последовательного порта, доступный в меню Serial | Terminal. Это обычный терминал, который позволяет отправлять символы и шестнадцатеричные числа в плату Arduino и отображать поступающие данные. Опция Filter Plotting Packets отсекает пакеты данных и пропускает только символы, не входящие в пакеты. Эта опция позволяет отправлять в графопостроитель отладочные сообщения в интервале между пакетами данных.

Рисование столбчатых диаграмм

FlexiPlot может в режиме реального времени рисовать наглядные столбчатые диаграммы по данным, поступающим от платы контроллера Arduino. Каждый новый пакет полностью обновляет диаграмму.

Формат пакетов данных для диаграммы представлен в двух вариантах: с автоматическим выбором цвета столбцов и с явным указанием цвета.

Пример пакета данных с автоматическим выбором цвета имеет следующий вид:

{P0|Night;Morning;Day;Evening|Inside|12 15 17 14|Outside|8 15 23 19}

Сначала, как обычно идет индекс (имя) рабочего окна. Далее через точку с запятой задаются имена групп столбцов. Их может быть сколь угодно много. В нашем примере это четыре группы: ночь, утро, день и вечер. Допустим, мы измеряем температуру внутри помещения (Inside) и снаружи (Outside) четыре раза в сутки (то есть получаем по четыре группы значений для каждого типа замеров). Соответственно, после названия величины типа замера в пакете следуют четыре значения, разделенные пробелами. Затем идет название следующей величины и ее значения. Этот шаблон повторяется нужное количество раз.

В строке пакета нельзя использовать кириллицу и специальные символы.

Воспользуемся встроенным инструментом отладки FlexiPlot — Packet Injector — который позволяет имитировать получение пакетов через последовательный порт. Благодаря этому инструменту мы можем экспериментировать с содержимым пакетов и вариантами прорисовки диаграммы без программирования контроллера Arduino.

  1. Выберите пункт меню Graph | Add Bar Graph — чтобы открыть новое окно рисования столбчатых диаграмм.
  2. Выберите пункт меню Tools | Debug Tools — чтобы запустить инструмент отладки. Введите в поле Packet пример пакета данных c автоматическим выбором цвета и нажмите клавишу <Enter>. В рабочем окне должна появиться диаграмма (рис. 5.4). Если ничего не произошло, проверьте правильность ввода пакета данных. Чтобы повторить отправку пакета, выделите нужную строку в поле History.
  3. Перейдите на вкладку Settings в рабочем окне. В вашем распоряжении богатый выбор настроек внешнего вида диаграммы:
  • Name of X Axis и Name Of Y Axis — подписи осей координат. Можно использовать кириллицу;
  • Bar Chart Type — выбор типа диаграммы: обычная (Normal), с наложением столбцов (Stacked), с наложением в процентах (Percent), горизонтальная (Horizontal), горизонтальная с наложением (Horizontal Stacked), горизонтальная в процентах (Horizontal Percent);
  • Animation — анимация при прорисовке диаграммы: без анимации (No Animation), анимация осевой разметки (Grid/Axis Animation), анимация столбцов (Series Animation), анимация всех элементов (All Animations);
  • Theme — выбор темы оформления диаграммы;
  • Anti-Aliasing — сглаживание изображения;
  • Legend — настройка отображения, расположения и шрифта текста легенды диаграммы;
  • Labels — настройка отображения и расположения текстовых меток на диаграмме. По умолчанию числовое значение величины (@value) отображается в середине столбца;
  • Scaling — управление автоматическим масштабированием. Если диапазон значений известен заранее, можно задать минимальное и максимальное значение в полях Min и Max.

5-4

Рис. 5.4. Пример построения столбчатой диаграммы из четырех групп с автовыбором цвета

Попробуйте менять параметры настроек и наблюдайте за изменениями на вкладке Chart. Выберите вариант настройки, который вам больше нравится.

Цвет столбцов в формате R,G,B можно указать непосредственно в пакете. Для этого после названия величины надо вставить в пакет значение цвета:

{P0|Night;Morning;Day;Evening|Inside|255,0,0|12 15 17 14|Outside|0,255,0|8 15 23 19}

В этом примере параметр Inside будет отображен красными столбцами, а параметр Outside — зелеными.

Динамические диаграммы

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

Загрузите в плату Arduino скетч примера из листинга 5.4.

Листинг 5.4. Пример отображения динамической диаграммы в FlexiPlot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int i, j;
void setup() {
Serial.begin(115200);
}
 
void loop() {
for (i = 0; i &lt; 255; i = i + 5)
{
j = 255 - i;
Serial.println((String)"{P0|S|d1|" + i + ",0," + j +"|" + i + "|d2|0,255,0|" + j + "}");
delay(100);
}
 
for (int i = 255; i &gt; 0; i = i - 5)
{
j = 255 - i;
Serial.println((String)"{P0|S|d1|" + i + ",0," + j +"|" + i + "|d2|0,255,0|" + j + "}");
delay(100);
}
}

В этом скетче мы рисуем диаграмму из двух столбцов, высота которых плавно изменяется в противоположных направлениях от 0 до 255 и обратно. При этом цвет первого столбца плавно меняется в зависимости от текущего значения параметра. Эффект достигается подстановкой переменных значений в компонент цвета в пакете данных.

В настройках графика отключите анимацию, отображение легенды и автомасштабирование. Задайте диапазон значений Min/Max от 0 до 300. Попробуйте менять тип диаграммы Bar Chart Type и выберите наиболее подходящий для ваших задач.

Опубликовано

Графопостроитель Serial Port Plotter

По материалам книги В. Яценкова «Здоровье, спорт и окружающая среда в проектах Arduino» (глава 5. «Визуализация данных»)

Здоровье

Программа Serial Port Plotter не требует установки. Исполняемый файл для операционных систем Windows и Linux можно скачать по адресу https://github.com/CieNTi/serial_port_plotter/releases. На момент подготовки книги была доступна версия 1.3.0 от 8 сентября 2018 г. Извлеките каталог с файлами из архива и сохраните в любом удобном месте. Автоматическая проверка обновлений в программе пока не предусмотрена, поэтому я рекомендую регулярно проверять наличие новых версий.

Формат пакета данных немного отличается от формата встроенного плоттера Arduino: пакет обязательно должен начинаться с символа $ и заканчиваться символом ;, значения внутри пакета разделяются пробелами, символ перевода строки не нужен.

Каждому значению соответствует свой канал данных, к которому привязан график. Причем новый канал может появиться в пакете данных в любой момент — программа это распознает и начнет рисовать еще один график. Программа не ограничивает количество каналов, но для окраски линий графика доступен только циклически повторяющийся набор из 14-ти цветов.

Загрузите в плату Arduino скетч из листинга 5.2 (это слегка доработанный скетч из листинга 5.1).

Листинг 5.2. Пример работы с графопостроителем Serial Port Plotter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define DEG_TO_RAD 0.01745329
void setup() {
Serial.begin(115200);
}
 
void loop() {
for (float angle = 0; angle &lt; 360; angle++)
{
<strong>Serial.print("$");</strong>
Serial.print(angle/100);
Serial.print(" ");
Serial.print(sin(DEG_TO_RAD * angle)*10);
Serial.print(" ");
Serial.print(cos(DEG_TO_RAD * angle));
<strong>Serial.print(";");</strong>
delay(10);
}
}

Запустите программу. В меню PORT CONTROLS (слева от панели графопостроителя) выберите номер порта, к которому подключена плата и задайте скорость 115200. Нажмите кнопку с изображением треугольника ► в верхней строке меню, чтобы подключиться к порту и запустить отрисовку графика (рис. 5.2).

5-2

Рис. 5.2. Окно программы Serial Port Plotter (из-за ограничений типографской технологии рисунок дан в негативе)

Если линии графика не умещаются в панели, или, наоборот, график отображается слишком мелко, нажмите кнопку Autoscale Yaxis (автоматический масштаб по оси Y) — график будет автоматически отмасштабирован к размерам окна. Масштаб по оси X можно изменять вращением колесика мыши.

Если параметры сигнала известны заранее, или требуется ручная корректировка масштаба, воспользуйтесь панелью настройки PLOT CONTROLS.

Видимость линий графика можно выключать и включать двойным щелчком на имени канала в левой панели. Если вы забыли, какие каналы выключены, можно вернуть их все на экран нажатием кнопки Reset All Visible.

Под панелью графопостроителя расположено окно текстового терминала, в котором отображается поток входных данных. Терминал можно скрыть кнопкой Hide TextBox.

Легенда графика (подписи к линиям) расположена в правом верхнем углу. Подписи можно редактировать двойным щелчком на имени канала в легенде. Разрешено использовать символы кириллицы.

Все поступающие данные сохраняются в буфере до тех пор, пока хватает памяти компьютера. Благодаря этому? график можно «прокрутить» обратно, просто протаскивая мышью вправо. Это очень удобная опция для детального изучения графика в определенном интервале времени. Данные из буфера можно сохранить в CSV-файл, если нажать значок с изображением листа бумаги в верхнем меню.

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

Опубликовано

Arduino плюс Excel — сбор и хранение данных

По материалам книги В. Яценкова «Здоровье, спорт и окружающая среда в проектах Arduino» (глава 5. «Визуализация данных»)

Здоровье

Несмотря на широкое распространение облачных технологий и развитие систем обработки данных, в научных исследованиях и на производстве до сих пор часто применяется сбор, хранение и обмен данными в виде файлов Microsoft Excel. Если контроллер Arduino или другой прибор подключен к компьютеру через последовательный порт, можно без труда организовать автоматическое заполнение таблицы Excel, причем с поддержкой различных команд со стороны контроллера: заполнение ячеек, чтение ячеек, выбор рабочего листа таблицы, прокрутка листа и многое другое.

Компания Parallax Software разработала специальное расширение (plugin) PLX-DAQ для автоматического заполнения таблиц Excel данными, которые поступают от приборов через последовательный порт. Несколько лет назад официальная поддержка этого расширения была прекращена. Но энтузиасты платформы Arduino не просто продолжили его поддержку, а выпустили в 2016 году новую версию расширения, которая совместима с последними 64-битовыми версиями MS Office и Windows 10.

На официальном форуме Arduino создана специальная тема, посвященная этому расширению. Она расположена по адресу http://forum.arduino.cc/index.php?topic=437398.0. В первое сообщение темы разработчик регулярно добавляет ссылки на самую свежую версию расширения. На момент работы над книгой была доступна версия PLX-DAQ 2.11.

Расширение не требует установки и представляет собой файл Excel с присоединенным макросом на языке VBA (Visual Basic for Applications). Пользователь открывает файл, разрешает выполнение макросов и открывает последовательный порт, через который поступают данные из контроллера Arduino.

Строка сообщения Arduino содержит команды и данные. Макрос расширения считывает строку из последовательного порта, выполняет команды и сохраняет данные в ячейки таблицы. Макрос может отправить данные из таблицы Excel в Arduino в ответ на запрос контроллера.

Установка расширения на компьютер

Скачайте архив с самой новой версией расширения. Распакуйте его в удобное место. Архив состоит из следующих файлов:

  • PLX-DAQ-v2.11.xlsm — исходный шаблон файла Excel с макросом. Вы можете скопировать этот файл в другой каталог и переименовать или сохранить под другим именем;
  • PLX-DAQ-v2-DefaultSketch.ino — демонстрационный скетч Arduino, который содержит почти все возможные команды;
  • Beginners Guide to PLX DAQ v2 (rev1).doc — руководство пользователя;
  • PLX-DAQ-v2-AutoGrapher-RandomValue.ino — демонстрационный скетч с генератором случайных чисел и рисованием графика в реальном времени;
  • PLX-DAQ-v2-AutoGrapher-RandomValue.xlsm — файл Excel с примером данных для демонстрационного скетча.

Запуск расширения

Откройте файл шаблона. Для запуска расширения необходимо разрешить выполнение макросов (рис. 5.5). Нажмите кнопку Параметры и в открывшемся окне настроек выберите опцию Разрешить это содержимое. Если макрос не запустился автоматически, нажмите кнопку с надписью Open PLX DAQ UI в верхней части шаблона.

exclamation Готовый файл Excel c встроенным макросом PLX-DAQ (файл DustSensorTest.xlsm) можно найти в сопровождающем книгу электронном архиве (см. приложение 1). https://bhv.ru/product/zdorove-sport-i-okruzhayushhaya-sreda-v-proektah-arduino/

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

5-5

Рис. 5.5. Запрос системы безопасности на разрешение запуска макросов

Рабочее окно и органы управления

После запуска макроса нажмите на кнопку Display direct debug, чтобы открыть поле, в которое выводятся поступающие данные и команды (рис. 5.6).

5-6

Рис. 5.6. Окно макроса PLX-DAQ

  • Port — номер порта, к которому подключен контроллер Arduino;
  • Baud — скорость соединения, бод;
  • Connect — установить соединение с портом;
  • Pause logging / Resume logging — приостановить запись данных;
  • Reset Timer — сбросить таймер макроса. Таймер используется для подстановки меток времени в таблицу и измерения продолжительности работы макроса Excel;
  • Clear Columns — удаляет все данные из столбцов таблицы. Заголовки столбцов сохраняются;
  • Display / Hide direct debug — показывает или прячет текстовое поле в правой части окна. В текстовом поле отображаются поступающие команды;
  • Sheet name to post to — отображает список доступных листов текущей книги Excel. Данные будут сохраняться в лист, который выбран в списке. В документе такой лист обозначен опцией ActiveSheet. После добавления, удаления или переименования листов обязательно нажмите кнопку Load для обновления списка;
  • Controller Messages — отображает последнее сообщение, поступившее от контроллера. Обычно сообщения меняются очень часто, поэтому их удобнее наблюдать в окне Direct Debug Window;
  • Reset on Connect — обычно при подключении к порту происходит автоматический сброс контроллера. Эта опция позволяет отключить автоматический сброс, если нельзя прерывать работу контроллера;
  • Custom Checkbox 1/2/3 — пользовательские опции для управления работой контроллера. Arduino может задать подписи к флажкам в окне макроса, читать состояние флажков и выполнять определенные действия в зависимости от их наличия;
  • Log incoming data? — запись входящего потока данных от контроллера в окно отладки. Уберите этот флажок, если возникают проблемы с быстродействием макроса;
  • Log outgoing data? — запись исходящего потока данных из макроса в контроллер. Уберите этот флажок, если возникают проблемы с быстродействием макроса;
  • Log system messages? — запись системной информации Excel (например, сообщений об ошибках). Уберите этот флажок, если возникают проблемы с быстродействием макроса;
  • Add timestamp? — добавление метки времени к каждой записи лога. Полезно для отладки;
  • кнопка => — увеличивает размер окна отладки;
  • кнопка <= — уменьшает размер окна отладки;
  • Clear — удаляет все записи в окне отладки.
exclamation Не перемещайте окно макроса во время записи данных. Это может привести к сбою работы Excel и потере данных.

Формат строки данных Arduino

Строка команд выводится в порт командой Serial.println(). Для правильного обмена данными между Arduino и макросом расширения строка должна иметь строго определенный формат. Вот пример стандартной строки:

Serial.println( (String) “DATA,DATE,TIME,” + millis() );

Команды строки данных можно условно разделить на основные группы:

  • настройка и передача данных — команды для форматирования листа и передачи данных;
  • специальные команды и управление — команды для переключения между листами и использования управляющих полей Custom Checkbox для Arduino;
  • рабочая книга Excel — команды для управления процессом записи данных или сохранения рабочей книги;
  • прочие команды — дополнительные команды, которые не имеют важного прикладного значения.

Рассмотрим подробнее эти группы команд.

Команды настройки и передачи данных

  • CLEARSHEET — полностью очищает рабочий лист (включая загловки столбцов!). Эта команда должна быть первой в любом скетче.

Пример: Serial.println(“CLEARSHEET”);

  • CLEARDATA — очищает только данные (начиная со второй строки таблицы).

Пример: Serial.println(“CLEARDATA”);

  • LABEL — устанавливает заголовки столбцов в первой строке таблицы.

Пример: Serial.println(“LABEL, Temperature, Humidity, Lightness”);

  • DATA — самая главная и важная команда. Служит для передачи данных из Arduino в активный лист книги Excel. Вы можете передавать произвольные данные, но должны разделить данные запятыми и обеспечить совпадение количества столбцов данных и количества заголовков.

Зарезервированные слова DATE, TIME и TIMER распознаются макросом и заменяются на соответствующие значения: слово DATE — на текущую системную дату компьютера (например, 15.09.2018), слово TIME — на текущее системное время (например, 15:32:17), слово TIMER — на продолжительность текущего сеанса работы макроса в секундах (например, 1458).

В строку можно добавить ключевое слово AUTOSCROLL_XX. Распознав это слово, макрос автоматически прокручивает текущий лист так, чтобы в нижней части таблицы всегда были пустые строки. Число XX указывает, сколько строк с данными следуют выше последней строки с данными, — например, AUTOSCROLL_20.

Специальные команды и управление

  • CELL,SET — вводит произвольное значение в указанную ячейку таблицы. Можно работать как с активным листом (ActiveSheet), так и с любым другим листом.

Пример для активного листа: Serial.println(“CELL,SET,C9,myValue”);

Эта команда вводит значение myValue в ячейку С9 активного листа.

Пример для произвольного листа:

Serial.println(“CELL,SET, ONSHEET,mySheet,C,9,myValue”);

Эта команда вводит значение myValue в ячейку C9 листа с названием mySheet.

exclamation Внимание!При высоких скоростях обмена могут возникнуть проблемы с обработкой команды SET — макрос не будет успевать ее выполнить. В таком случае уменьшите скорость передачи данных или введите небольшую задержку перед командой. Обычно достаточно задержки в диапазоне 3–100 мс (например, delay(10)).
  • CELL,GET — извлекает данные из указанной ячейки и передает их в Arduino. Например, можно заранее сохранить в таблицу последовательность значений температуры и времени, а термостат на основе Arduino будет поочередно считывать значения и выдерживать указанную температуру в течение заданного промежутка времени. Аналогичным образом можно управлять различными технологическими процессами — от координатного станка до инкубатора.
exclamation Контроллер Arduino должен не только отправить команду запроса, но и прочитать строку ответа. Тип данных ответа может быть Integer (целое число) или String (строка). Вы должны быть уверены, что макрос отправит именно строку, если Arduino ждет строку, и целое число, если Arduino ждет число.Используйте для чтения ответа одну из следующих команд:

Serial.readStringUntil(10);

Serial.readStringUntil(10).toInt();

Serial.readStringUntil(10).toFloat();

Число 10 в коде ASCII означает конец строки, поэтому следует использовать только это число.

Пример кода Arduino:

int myData;

Serial.println(“CELL,GET,C9”); // команда чтения из ячейки C9

myData = Serial.readStringUntil(10).toInt(); // получение ответа

Пример чтения содержимого ячейки C9 из произвольного листа mySheet:

Serial.println(“CELL,GET,FROMSHEET,mySheet,C,9”);

exclamation Внимание!При высоких скоростях обмена могут возникнуть проблемы с обработкой команды GET — макрос не будет успевать ее выполнить. В таком случае уменьшите скорость передачи данных или введите небольшую задержку перед командой. Обычно достаточно задержки в диапазоне 3–100 мс (например, delay(10)).
  • ROW — вы можете явно задать значение указателя строки, с которой будете работать. Например, когда записаны 20 строк данных, вы можете сбросить указатель до значения 2 и начать сначала заполнение строк.

Примеры команд:

Serial.println(“ROW,SET,2”);

Serial.println(“ROW,GET”);

int myRow = Serial.readStringUntil(10).toInt();

  • CUSTOMBOX1 / CUSTOMBOX2 / CUSTOMBOX3 — вы можете задать подпись к опции, снять или установить флажок и прочитать состояние опции (булево значение false / true).

Примеры:

Serial.println(“CUSTOMBOX1,LABEL,LED Light”);

Serial.println(“CUSTOMBOX1,GET”);

boolean myV=CheckValue = Serial.readStringUntil(10).toInt();

  • CLEARRANGE — очищает заданный диапазон строк (range) активного листа.

Пример: Serial.println(“CLEARRANGE,B,10,D,20”);

  • RESETTIMER — сбрасывает счетчик продолжительности работы расширения.

Пример: Serial.println(“RESETTIMER”);

Рабочая книга Excel

  • PAUSELOGGING / RESUMELOGGING / STOPLOGGING — пауза записи данных / возобновление записи / прекращение записи. Разумеется, расширение продолжит «слушать» и выполнять поступающие команды, даже если запись данных в ячейки приостановлена или прекращена.

Пример: Serial.println(“PAUSELOGGING”);

  • SAVEWORKBOOK — сохраняет рабочую книгу Excel под текущим именем. Команда полезна, если вы записываете данные в течение длительного времени и хотите периодически сохранять файл с данными.
  • SAVEWORKBOOKAS — сохраняет рабочую книгу Excel под заданным именем. По умолчанию новый файл сохраняется в тот же каталог, где находился исходный файл, но вы можете задать новый каталог в строке имени файла.

Пример сохранения в текущий каталог:

Serial.println(“SAVEWORKBOOKAS,MyNewWorkbookName”);

Пример сохранения в подкаталог с именем mySubfolder:

Serial.println(“SAVEWORKBOOKAS,mySubfolder\Workbookname”);

  • FORCEEXCELQUIT — опасная команда! Немедленно прекращает работу Excel! Обязательно сохраните рабочую книгу перед отправкой этой команды.

Пример: Serial.println(“FORCEEXCELQUIT”);

Прочие команды

  • BEEP — всего лишь заставляет компьютер издать короткий звуковой сигнал встроенным звукоизлучателем материнской платы или корпуса. Полезно, если надо привлечь внимание пользователя, когда достигнуто определенное значение величины, которую вы измеряете.

Пример: Serial.println(“BEEP”);

  • MSG — помещает заданный текст в метку сообщения Controller Message в окне расширения.

Пример: Serial.println(“MSG,Put your text here”);

  • DONE — принудительно передает содержимое буфера последовательного порта со стороны Excel.
  • GETRANDOM — передает случайное число из Excel в Arduino. Это полезная команда, потому что Arduino не может самостоятельно генерировать случайные числа. Функции random() в Arduino требуется инициализация генератора случайных чисел начальным значением при помощи функции randomSeed(value). Если начальное значение будет повторяться, то и вся последовательность полученных псевдослучайных чисел тоже будет повторяться. Обычно генератор случайных чисел Arduino инициализируют случайным значением, прочитанным с «висящего в воздухе» аналогового входа. Но если все входы заняты, начальное значение можно получить из Excel.

Пример:

Serial.println(“GETRANDOM,-31313,32323”);

int rndseed = Serial.readStringUntil(10).toInt();

randomSeed(rndseed);

Serial.println( (String) “1st number: “ + random(0, 50));

Serial.println( (String) “2nd number: “ + random(0, 50));

Serial.println( (String) “3rd number: “ + random(0, 50));

Демонстрационный скетч PLX–DAQ

Демонстрационный скетч, приведенный в листинге 5.5, основан на коде скетча из комплекта поставки расширения PLX-DAQ v.2.11. Скетч содержит почти все доступные команды для работы с таблицей Excel.

Загрузите скетч в плату Arduino. Откройте исходный шаблон файла Excel из комплекта поставки расширения. В поле Port введите номер последовательного порта, к которому подключена плата. Остальные настройки не меняйте. Нажмите кнопку Display direct debug в окне расширения. Затем нажмите кнопку Connect. Если все работает правильно, контроллер перезагрузится, и в окне отладки побегут строки команд и служебных сообщений, а таблица будет заполняться значениями.

Обратите внимание, что изменились подписи к флажкам. Поставьте флажок Quit at 450. Как только значение счетчика скетча достигнет 450 (или уже превысило 450 на момент установки флажка) Excel сохранит файл под новым именем и прекратит работу.

Откройте сохраненный файл и посмотрите содержимое листов. Во втором листе с именем Further list должна быть заполнена ячейка G11.

Листинг 5.5. Пример работы с расширением PLX–DAQ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
int i = 0;
 
void setup() {
 
// последовательный порт на скорости 9600
Serial.begin(9600);
//Serial.println("CLEARDATA"); // очистка листа со строки 2
Serial.println("CLEARSHEET"); // очистка листа со строки 1
// определяем пять столбцов с именами "Date", "Time", "Timer", "Counter" и "millis"
Serial.println("LABEL,Date,Time,Timer,Counter,millis");
// задаем подписи к трем флажкам (только латинские символы)
Serial.println("CUSTOMBOX1,LABEL,Stop logging at 250?");
Serial.println("CUSTOMBOX2,LABEL,Resume log at 350?");
Serial.println("CUSTOMBOX3,LABEL,Quit at 450?");
// ставим флажки в первое и второе поля
Serial.println("CUSTOMBOX1,SET,1");
Serial.println("CUSTOMBOX2,SET,1");
Serial.println("CUSTOMBOX3,SET,0");
}
 
void loop() {
// выводим в таблицу данные и команду прокрутки
Serial.println( (String) "DATA,DATE,TIME,TIMER," + i++ + "," + millis() + ",AUTOSCROLL_20" );
// альтернативный способ вывода строки по частям
/* Serial.print("DATA,DATE,TIME,TIMER,");
Serial.print(i++);
Serial.print(",");
Serial.println(millis());
Serial.print(",");
Serial.println("SCROLLDATA_20"); */
// стираем некоторые ячейки (прямоугольник от B10 до D20)
if (i == 100)
Serial.println("ClearRange,B,10,D,20");
// звуковой сигнал, если i==150
if (i == 150)
Serial.println("BEEP");
// читаем целое число из ячейки E4
// в листе с заданным именем если i==200
if (i == 200)
{
// запрашиваем данные из листа
Serial.println("CELL,GET,FROMSHEET,Further sheet,E,4");
// короткий вариант для чтения из текущего листа
// Serial.println("CELL,GET,E4");
// получаем ответ Excel
 
int readvalue = Serial.readStringUntil(10).toInt();
// Выводим значение в окно отладки
Serial.println( (String) "Value of cell E4 is: " + readvalue);
}
 
// проверяем значение CUSTOMBOX1
// если флажок установлен, приостанавливаем запись
if (i == 250)
{
Serial.println("CUSTOMBOX1,GET");
int stoplogging = Serial.readStringUntil(10).toInt();
// выводим сообщение в окно отладки
Serial.println( (String) "Value of stoplogging/checkbox is: " + stoplogging);
if (stoplogging)
Serial.println("PAUSELOGGING");
}
// запрашиваем случайное число из компьютера если i==300
if (i == 300)
{
 
Serial.println("GETRANDOM,-4321,12345");
 
// случайное число от -4321 до 12345
 
int rndseed = Serial.readStringUntil(10).toInt();
 
// выводим сообщение в окно отладки
Serial.println( (String) "Got random value '" + rndseed + "' from Excel" );
}
// теперь возвобновляем запись если i==350 и стоит флажок CUSTOMBOX2
if (i == 350)
{
Serial.println("CUSTOMBOX2,GET");
int resumelogging = Serial.readStringUntil(10).toInt();
if (resumelogging)
Serial.println("RESUMELOGGING");
}
// запись в заданную ячейку G10 текущего листа
// и ячейку G11 произвольного листа
if (i == 400)
{
 
// активный лист по умолчанию
Serial.println("CELL,SET,G10,400 test 1 string");
// лист с именем "Further sheet"
Serial.println("CELL,SET,ONSHEET,Further sheet,G,11,400 test 2");
}
 
// если i&gt;=450 и установлен флажок CUSTOMBOX3
// сохраняем файл под другим именем и закрываем Excel
if (i &gt;= 450)
 
{
Serial.println("CUSTOMBOX3,GET");
if (Serial.readStringUntil(10).toInt()) {
Serial.println("SAVEWORKBOOKAS,450-Lines-File");
Serial.println("FORCEEXCELQUIT");
}
else
Serial.println("No forced Excel quit requested!");
}
}