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

Датчик уровня жидкости

По материалам руководства к набору “Умный дом на базе Arduino. Большой набор + КНИГА

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

Внешний вид, назначение контактов

S6-1-уровень воды

Рис. S6.1. Датчик уровня воды (глубины)

Основные характеристики

Наименование Значение
Зона обнаружения, мм 16 ÷ 40
Напряжение питания, В 3,3 ÷ 5
Ток потребления, мА 20
Размеры, мм 62×20×8
Рабочая температура, °С 10 ÷ 30

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

S6-2-уровень воды

Рис. S6.2. Схема подключения датчика уровня жидкости

Программный код

Листинг S6.1. Измерения уровня жидкости

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
#define aPin A0 // пин для подключения аналогового выхода датчика
 
int avalue=0; //переменная
 
int levels[3]={600,500,400}; // значение уровней
 
void setup(){
 
pinMode(aPin, INPUT); // настройка аналогового пина на вход
 
Serial.begin(9600); // инициализация последовательного порта
 
}
 
void loop(){
 
// получение значения с аналогового вывода датчика
 
avalue=analogRead(aPin);
 
// вывод значения в монитор последовательного порта Arduino
 
Serial.print("avalue=");
 
Serial.print(avalue);
 
if (avalue>=levels[0]) Serial.println("->MAX");
 
if ((avalue>levels[2])&&(avalue<levels[0])) Serial.println("->NORM");
 
if (avalue<=levels[2]) Serial.println("->MIN");
 
// пауза перед следующим получением значения 1000 мс
 
delay(1000);
 
}

Результаты измерений

Значение аналоговых сигналов на аналоговом входе Arduino вы можете определить экспериментальным путем. Они могут оказаться такими, как показано на рис. S6.3.

2-06-3-уровень воды

Рис. S6.3. Экспериментальные значения аналоговых сигналов для разных уровней погружения

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

Датчик пламени YG1006

По материалам руководства к набору “Умный дом на базе Arduino. Большой набор + КНИГА

Датчик пламени позволяет фиксировать наличие инфракрасного излучения (открытого пламени) в диапазоне волн 760 ÷ 1100 нм в прямой видимости на расстоянии до 1 м (рис. S4.1).

4-01-flame

Рис. S4.1. Принцип действия ИК-датчика пламени YG1006

Основные характеристики

Наименование Значение
Дальность обнаружения пламени, см 20 ÷ 100
Угол обнаружения пламени, град 60
Длина волны, нм 760 ÷ 1100
Пиковая длина волны, нм 940
Напряжение питания, В 3 ÷ 5,5
Потребляемый ток не более, мА 15
Размеры (длина × ширина), мм 36×16

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

При подключении датчика только к цифровому выходу (D0) фиксируется лишь факт наличия пламени. А при подключении к аналоговому выходу (A0) можно оценить и яркость пламени.

2-04-2-flame

Рис. S4.2. Подключение датчика пламени

Программный код

Листинг S4.1. Подключение датчика пламени

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
#define ledPin 13 //номер пина встроенного светодиода
 
#define flameDigitalPin 10 //номер пина цифрового входа датчика
 
#define flameAnalogPin A0 //номер пина аналогового входа датчика
 
int valueDigital ; // переменная для цифрового значения
 
float valueAnalog; //переменная для аналогового значения
 
 
 
void setup ()
 
{
 
pinMode (ledPin, OUTPUT) ;
 
pinMode (flameDigitalPin, INPUT) ;
 
pinMode (flameAnalogPin, INPUT) ;
 
Serial.begin(9600);
 
}
 
 
 
void loop ()
 
{
 
valueAnalog = analogRead(flameAnalogPin);
 
//вывод аналогового значения в монитор порта
 
Serial.println(valueAnalog);
 
//чтение цифрового значения
 
valueDigital = digitalRead (flameDigitalPin) ;
 
if (valueDigital == HIGH) //когда на цифровом входе высокий уровень,
 
//светодиод горит
 
{
 
digitalWrite (ledPin, HIGH);
 
Serial.println("FLAME!");
 
}
 
else
 
{
 
digitalWrite (ledPin, LOW);
 
Serial.println("no flame");
 
}
 
delay(1000);
 
}

Результат

Рис. S4.3. Результаты фиксации пламени

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

Датчик звука KY-037

Датчик звука, как следует из названия, предназначен для обнаружения звука (фиксирует появление громкого звука). На рис. S8.1 показаны наиболее широко применяемые в проектах Arduino датчики звука.

Внешний вид, назначение контактов

8_01-звук

Рис. S8.1. Применяемые в проектах Arduino датчики звука

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

Работая с датчиком звука, можно использовать как цифровой, так и аналоговый его выходы (рис. S8.2). Аналоговый выход выдает значение сигнала микрофона, а цифровой выход передает 1, если сигнал превысит пороговое значение, и 0 в противном случае. Пороговое значение можно настроить с помощью потенциометра, расположенного на плате датчика. Можно подключить одновременно и два выхода (например, для настройки порогового значения).

2-08-2-звук

Рис. S8.2. Схема подключения датчика звука

Программный код

Листинг S1.8. Измерение громкости с помощью датчика звука

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
#define soundAnalogPin A0 // пин, к которому аналоговый выход
 
#define soundDigitalPin 4 // пин, к которому цифровой выход
 
int analogVal=0; // Объявляем переменные для хранения значений
 
int digitalVal=0; //с датчика и задаем ее начальное значение 0
 
void setup()
 
{
 
Serial.begin(9600); // Открываем монитор порта
 
pinMode(soundAnalogPin, INPUT);//Настройка аналогового пина на вход
 
pinMode(soundDigitalPin, INPUT);// Настройка цифрового пина на вход
 
}
 
void loop()
 
{
 
//присваиваем переменной аналоговое значение
 
analogVal =analogRead(soundAnalogPin);
 
//присваиваем переменной цифровое значение
 
digitalVal=digitalRead(soundDigitalPin);
 
//Выводим полученныес датчика значения
 
Serial.print("Sound value A0: "); //
 
Serial.print(analogVal,DEC);
 
Serial.print(" D0: ");
 
Serial.println(digitalVal,DEC);
 
 
 
delay(100); //задаем паузу
 
}

Результат

2-08-3-звук

Рис. S8.3. Фиксация хлопка в ладоши на мониторе последовательного порта

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

Датчик газа MQ-135

По материалам руководства к набору “Умный дом на базе Arduino. Большой набор + КНИГА

Датчик газа MQ-135 предназначен для измерения наличия в окружающем воздухе вредных примесей газа. В качестве чувствительного элемента в датчике служит пластина диоксида олова (Sn02), который имеет низкую проводимость в чистом воздухе. Когда датчик оказывается в среде с парами токсичных газов, его проводимость возрастает. Датчик MQ-135 очень чувствителен к аммиаку, сульфидам, парам бензола и алкоголя, СО2 и идеально подходит для мониторинга дыма и других вредных примесей в воздухе. На рис. S7.1 показано изменение сопротивления датчика в зависимости от концентрации различных газов в окружающем воздухе в миллионных долях (от общего объема газа).

Внешний вид, назначение контактов

7-01-MQ135

Рис. S7.1. Изменение сопротивления датчика в зависимости от концентрации различных газов в окружающем воздухе

Основные характеристики

Наименование Значение
Напряжение питания, В 5
Потребляемый ток, мА 160
Рабочая температура, °С 10 ÷ 45
Относительная влажность, % менее 95
Концентрация кислорода в воздухе (стандартная), % 21
Стандартная температура измерения, °С 20
Влажность, % 65
Диапазон измерений аммиак: 10 ppm ÷ 300 ppm

бензин: 10 ppm ÷ 1000 ppm

этиловый спирт: 10 ppm ÷ 300 ppm

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

7-02-MQ135

Рис. S7.2. Подключение датчика газа

Программный код

Листинг S7.1. Измерение концентрации газов с помощью датчика MQ-135

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
#define MQPin A0 //пин, к которому подключен датчик газа
 
#define ledPin 13 //пин встроенного светодиода
 
int sensorValue = 0; //переменная для хранения значений
 
void setup() {
 
Serial.begin(9600);
 
pinMode(ledPin, OUTPUT);
 
Serial.println("MQ135 Test" ); //Посылаем текст в монитор порта
 
}
 
void loop() {
 
// Считываем значения с датчика
 
sensorValue = analogRead(MQPin);
 
if (sensorValue >= 400)
 
// и, если превышен заданный порог,
 
{
 
digitalWrite(ledPin, HIGH); // то включаем светодиод,
 
}
 
else // а если нет…
 
{
 
digitalWrite(ledPin, LOW); // то выключаем
 
}
 
Serial.print("MQ135 value= " );
 
// Для отслеживания данных с датчиков
 
// транслируем их в монитор порта
 
Serial.println(sensorValue);
 
delay(1000);
 
}

Результат

2-07-4-MQ135

Рис. S7.4. Результаты измерений

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

Датчик влажности почвы YL-38

По материалам руководства к набору “Умный дом на базе Arduino. Большой набор + КНИГА

Модуль датчика состоит из двух частей: контактного щупа и датчика YL-38 (рис. S5.1), в комплекте также идут провода для подключения. Между двумя электродами щупа создается небольшое напряжение. Если почва сухая, то сопротивление большое, а ток небольшой. Если земля увлажняется (например, поливом), то сопротивление уменьшается, а ток немного увеличивается (рис. S5.2).

Внешний вид, назначение контактов

2-05-1-влажность почвы

Рис. S5.1. Датчик влажности почвы YL-38

5-02-влажность почвы

Рис. S5.2. Принцип работы датчика влажности почвы

В качестве датчика влажности почвы можно использовать два оцинкованных гвоздя и проволоку, как показано на рис. S5.3. Когда почва увлажнится сопротивление между гвоздями уменьшится.

2-05-4-влажность почвы

Рис. S5.3. Использование гвоздей в качестве датчика влажности почвы

Основные характеристики

Наименование Значение
Рабочее напряжение, В 3 ÷ 5
Ток потребления, мА 15
Напряжение цифрового выхода, В 3 ÷ 5
Напряжение аналогового выхода, В 0 ÷ 5

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

2-05-2-влажность почвы

Рис. S5.4. Подключение датчика измерения влажности почвы

Программный код

Листинг S5.1. Подключение датчика влажности почвы

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define sensorPin A0 //номер пина влажности почвы
 
int sensorValue = 0; //переменная значения влажности
 
void setup() {
 
Serial.begin(9600);
 
}
 
void loop() {
 
sensorValue = analogRead(sensorPin);
 
Serial.println(sensorValue);
 
delay(100);
 
}

В процессе эксплуатации контактный щуп окисляется, и это происходит достаточно быстро. Чтобы окисление проходило медленнее, можно подключить питание датчика на цифровой вход Arduino и подавать напряжение только на время измерения (см. https://mxjournal.ru/blog/1319). В нашем примере контакт питания от модуля влажности (VCC) следует соединить на плате Arduino Uno не с пином 5V, а с цифровым пином — например, D8 (на рис. S5.4 показано пунктиром). В этом случае код может быть переписан следующим образом (листинг S5.2) — мы вводим переменную timing, в которой будет храниться количество миллисекунд. По умолчанию значение переменной равно 0. В основной части программы проверяем условие: если количество миллисекунд с запуска микроконтроллера минус число, записанное в переменную timing, больше, чем записано в переменную interval (в минутах), то выполняется функция get_sensor().

Листинг S5.2. Измерение влажности почвы с интервалом

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
#define sensorPin A0 //номер аналогового пина влажности почвы
 
#define powerPin 8 //номер пина питания датчика влажности почвы
 
int sensorValue = 0; //переменная значения влажности
 
unsigned long timing = 0; //переменная для хранения точки отсчета
 
int interval=60; //интервал измерений в минутах
 
void setup() {
 
Serial.begin(9600);
 
pinMode (powerPin, OUTPUT); // питание датчика влажности
 
digitalWrite (powerPin, LOW);
 
digitalWrite (13, LOW);
 
}
 
void loop() {
 
if (abs(millis() - timing)/1000 > interval*60) { //один раз в час
 
get_sensor(); // снимаем показания датчика влажности почвы
 
timing = millis();
 
}
 
}
 
void get_sensor() {
 
digitalWrite (powerPin, HIGH); //включаем датчик влажности
 
digitalWrite (13, HIGH); //включаем датчик влажности
 
delay (3000);
 
sensorValue = analogRead(A0); //получение значения влажности с
 
//аналогового вывода датчика
 
Serial.println(sensorValue); //конролируем влажность на
 
//Мониторе порта
 
delay(100);
 
digitalWrite (powerPin, LOW); //выключаем датчик влажности
 
}
Опубликовано

Графопостроитель 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!");
}
}
Опубликовано

Последовательный обмен данными с использованием двух протоколов последовательной связи: TTL Serial и USB

По материалам книги Т.Иго «Умные вещи: Arduino, датчики и сети для связи устройств: Пер. с англ. 3-е изд.»  (глава 2 «Простейшая сеть»)

Умные вещи: Arduino

Устанавливаем соединение: нижние уровни

Мы уже знакомы с одним примером последовательного обмена данными — между микроконтроллером и персональным компьютером. В частности, в главе 1 мы подключили микроконтроллерный модуль к персональному компьютеру через порт USB. Это подключение является примером асинхронного последовательного обмена данными с использованием двух протоколов последовательной связи: TTL Serial и USB.

Первый из них — это протокол, понимаемый микроконтроллером, и называется он последовательный ТТЛ (TTL[1] Serial). Этот протокол можно разделить на следующие концептуальные уровни:

  • Физический. Определяет контакты, используемые контроллером для обмена данными. В модуле Arduino данные принимаются на контакт, обозначенный RX (от Receive, прием), а передаются с контакта, обозначенного TX (от Transmit, передача).
  • Электрический. Определяет напряжения для представления битов данных. В некоторых микроконтроллерах применяется напряжение 3,3 В, в других — 5 В.
  • Логический. Высокий уровень напряжения (3,3 или 5 В) представляет логическое значение 1, а низкий (0 В) — логическое значение 0.
  • Уровень данных. Обмен данными обычно осуществляется со скоростью 9600 битов в секунду. Для представления одного символа требуется один байт, который содержит 8 битов данных, а также стартовый и стоповый биты (которые мы никогда не будем использовать).
  • Уровень приложений. На этом уровне мы отправляем один байт от ПК на микроконтроллер, который обрабатывает его и возвращает один байт на ПК.

Но это еще не все. Импульсы напряжения не идут на ПК напрямую. Сначала они поступают на TTL/USB микросхему на плате, которая преобразовывает последовательные TTL-сигналы в последовательные USB-сигналы. На некоторых микроконтроллерных платах — например, на Arduino Uno, преобразователь USB сигналов в сигналы ТТЛ реализован в виде отдельной микросхемы. На других же — например, на MKR1000 и Arduino 101, эта функциональность встроена в микросхему микроконтроллера.

Обработка преобразованных в формат USB сигналов осуществляется с использованием соответствующего протокола USB[2], который во многом отличается от протокола последовательного обмена TTL. Он разбивается на следующие концептуальные уровни:

  • Физический. Шина USB состоит из двух проводов для передачи данных: Data+ и Data– и двух проводов питания (+5 В и общего).
  • Электрический. Сигнал на линии Data– всегда противоположен сигналу на линии Data+, в результате чего сумма напряжений этих сигналов всегда равна нулю. Эта особенность используется приемником для проверки на наличие ошибок электрического сигнала — для этого он складывает напряжения обеих этих линий. Если полученная сумма не равна нулю, приемник отбрасывает такой сигнал.
  • Логический. Логическое значение 1 представляется сигналом напряжения +5 В (на линии Data+) или –5 В (на линии Data–), а логическое значение 0 — сигналом напряжения 0 В.
  • Уровень данных. Уровень данных модели протокола USB более сложный, чем соответствующий уровень протокола последовательного обмена ТТЛ. В USB скорость обмена данными может достигать 480 мегабит в секунду. Один символ представляется одним байтом, который содержит 8 битов данных, а также стартовый и стоповый биты. Несколько устройств USB под управлением ПК могут использовать для обмена данными одну и ту же пару проводов (набор проводов для обмена сигналами называется шиной). Поскольку к одной шине может быть подсоединено несколько устройств, операционная система присваивает каждому из этих устройств однозначный адрес и обеспечивает обмен данными между каждым подсоединенным к шине устройством и его соответствующим приложением на компьютере.
  • Уровень приложений. На уровне приложения преобразователь USB/TTL-Serial на плате Arduino отправляет операционной системе компьютера несколько байтов, чтобы идентифицировать себя. Операционная система использует эти байты для того, чтобы сопоставить плату с программой ее драйвера, который другие программы могут использовать для обмена данными с этим устройством.

Все это управление прозрачно для пользователя, так как контроллер USB компьютера передает ему только те байты, которые предназначены для него. Микросхема преобразователя USB/TTL-Serial на плате Arduino представляет себя операционной системе компьютера в качестве последовательного порта и отправляет данные через разъем USB с выбранной пользователем скоростью (9600 битов в секунду — как в примере из главы 1).

 

Кабель-переходник USB/TTL-Serial компании FTDI

 

Рис. 2.4. Кабель-переходник USB/TTL-Serial компании FTDI

Распиновка разъема TTL

Рис. 2.5. Распиновка разъема TTL кабеля USB/TTL-Serial компании FTDI. Кроме линий передачи, приема и питания он также имеет линии для аппаратного управления обменом данных: RTS (Request-to-send, запрос на передачу) и CTS (Clear-to-send, готовность к передаче). Некоторые устройства используют эти линии для управления потоком последовательных данных

Есть и еще один протокол — если вы используете микроконтроллерный модуль BASIC Stamp или другой микроконтроллерный модуль с интерфейсом иным, чем USB, он, скорее всего, оснащен 9-контактным разъемом для подключения к компьютеру или к адаптеру USB/RS-232 (распиновка разъемов USB и RS-232 показана на рис. 2.6). Этот разъем называется DB-9 или D-sub-9 и является стандартным разъемом для другого последовательного протокола: RS-232. Протокол RS-232 был стандартом для последовательного интерфейса компьютеров до протокола USB и все еще встречается на некоторых специализированных периферийных устройствах. Этот протокол состоит из следующих концептуальных уровней:

  • Физический. Данные в разъеме RS-232компьютера принимаются на контакт 2, а передаются с контакта 3. Контакт 5 — «земля».
  • Электрический. Данные в стандарте RS-232 передаются двумя уровнями напряжения: от +3 В до +25 В и от –3 В до –25 В.
  • Логический. Высокий уровень напряжения (от +3 В до +25 В) представляет логическое значение 0, а низкий (от –3 В до –25 В) — логическое значение 1. Как можно видеть, эта схема построена на основе отрицательной (или инвертированной) логики.
  • Уровень данных. Такой же, как и в протоколе TTL, — 8-битовый байт данных с дополнительными стартовым и стоповымбитами.

Распиновка разъемов: USB и RS-232

Рис. 2.6. Распиновка разъемов: USB и RS-232

 

Спрашивается, как же подключать некоторые микроконтроллеры — например, BASIC Stamp, непосредственно к последовательному порту RS-232? Поскольку микроконтроллеры обычно не могут создавать отрицательные напряжения, для преобразования выходных сигналов ТТЛ микроконтроллера в уровни RS-232 обычно используется отдельная специальная микросхема. Протокол RS-232 намного проще, чем протокол USB, но, к сожалению, он, по большому счету, сильно устарел. Большинство современных микроконтроллеров оснащены встроенным преобразователем USB/TTL-Serial.

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

Преобразователи USB/Serial

Большинство современных электронных модулей, с которыми вам придется иметь дело, будут, скорей всего, оснащены каким-либо последовательным интерфейсом для взаимодействия с микроконтроллерами. Самым распространенным из таких интерфейсов является последовательный TTL-интерфейс — TTL-Serial. Например, большинство модулей системы GPS[5] (с одним из которых мы познакомимся в главе 8) оснащены интерфейсом TTL-Serial.  Для любого, кто интересуется созданием современных электронных устройств, преобразователь USB/TTL-Serial станет одним из самых необходимых инструментов.

На рынке доступен ряд микросхем преобразователя USB/Serial. Одной из наиболее популярных является микросхема FT232RL, изготавливаемая уже упомянутой ранее компанией FTDI. Но основе этой микросхемы компания делает кабель-переходник, другие компании также используют эту микросхему для изготовления плат-преобразователей. Кабель-переходник компании FTDI (см. рис. 2.4) приобрел такую популярность, что его распиновка (см. рис. 2.5) была принята в качестве де-факто стандарта на рынке любительской электроники  и используется во многих устройствах.

Кроме кабеля-преобразователя компании FTDI, преобразовательные платы изготавливают такие компании как Adafruit, SparkFun, Parallax и ряд других. Микросхемой FT232RL также оснащаются многие устройства, включая адаптеры XBee компании Digi и платы-клоны Arduino RedBoard компании SparkFun.

Эта микросхема удобна тем, что она может обрабатывать последовательные TTL-сигналы разных напряжений:  5 В и 3,3 В. Компания SparkFun изготавливает отдельные версии плат для каждого напряжения,  а у платы FTDI Friend компании Adafruit на тыльной стороне предусмотрен ряд перемычек, перепаивая которые можно менять рабочее напряжение контактов для приема и передачи последовательных сигналов. Кроме того, эта плата также способна работать с уровнями напряжения сигналов RS-232. Для работы с RS-232 предназначена  и адаптерная плата компании Parallax, оснащенная к тому же разъемом DB-9.

Использование адаптера USB/TTL-Serial не представляет собой ничего сложного. Контакт передачи (TX) этого адаптера подсоединяется к контакту приема (RX) устройства и наоборот. Общий («земляной») контакт платы подключается к соответствующему контакту устройства, а при питании устройства от адаптерной платы контакт питания VCC платы подключается к контакту питания устройства. Прежде чем запитывать устройство от адаптера, необходимо убедиться в том, что устройство может работать на уровне напряжения, подаваемого адаптером. Напряжение питания большинства адаптеров USB/TTL-Serial составляет 5 В, что может повредить устройства с питанием 3,3 В. В главе 1 мы узнали, как с помощью адаптера USB/TTL-Serial компании FTDI подключиться через монитор порта к плате Raspberry Pi (см. рис. 1.17). Но в том случае плата микроконтроллера не запитывалась от адаптерной платы.

Чтобы использовать с компьютером любой из адаптеров USB/Serial, на компьютер нужно установить драйверы микросхемы этого адаптера. Качество работы адаптера USB/TTL-Serial во многом зависит от качества его драйвера. Драйверы более дешевых адаптеров обычно совместимы с более узким диапазоном платформ. Поэтому имеет смысл немного переплатить, но приобрести устройство с доступными, качественными и многоплатформенными драйверами. В этом отношении особенно выделяется компания FTDI —драйверы от этой компании всегда вовремя обновляются для поддержки текущих версий Windows, macOS и различных дистрибутивов Linux.

Но кроме компании FTDI, адаптеры USB/TTL-Serial изготавливаются и другими компаниями —  например, компаниями Prolific (адаптер PL2303), Silicon Labs (адаптер CP2102), Jiangsu Heng Qin (адаптер CP340) и другими. Драйверы для упомянутых адаптерных плат этих компаний можно загрузить со следующих веб-сайтов:

  • ftdichip.com/FTDrivers.htm (FTDI);
  • silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx (Silicon Labs);
  • prolific.com.tw/US/Show-Product.aspx?pcid=41 (Prolific);
  • wch.cn/download/CH341SER_ZIP.html (Jiangsu Heng Qin).

В плате Arduino Uno в качестве адаптера USB/TTL-Serial используется микроконтроллер общего назначения Atmel 16U2, запрограммированный под эту задачу. Для этого адаптера не требуются драйверы под macOS и Linux, а драйверы USB для Windows устанавливаются автоматически установщиком Windows. Исходный код адаптера USB/TTL-Serial для Arduino Uno можно загрузить из каталога hardware/arduino/avr/firmwares/atmegaxxu2 репозитория https://github.com/arduino, а дополнительную информацию о конструкциях устройств USB вы найдете на веб-сайте www.usb.org/developers/usbfaq.

При использовании адаптера USB/TTL-Serial для программирования микроконтроллера вам, вероятно, нужно будет также задействовать выводы CTS (clear-to-send, готовность к передаче) и RTS (request-to-send, запрос на передачу). Большинство микроконтроллеров, полагающихся на адаптеры USB/TTL-Serial, — такие, как адаптерная плата Huzzah! на микросхеме ESP8266 компании Adafruit или плата ESP8266 Thing компании SparkFun, оснащены контактами для этих выводов, так что вам не нужно беспокоиться об этом. Дополнительную информацию по использованию адаптеров USB/TTL-Serial для программирования микроконтроллеров ищите в руководстве по программированию вашей платы.

Использование платы Arduino в качестве адаптера USB/TTL-Serial

Если у вас нет под рукой отдельного адаптера USB/TTL-Serial, вместо него можно воспользоваться совместимой с Arduino платой, запрограммировав ее должным образом.

В частности, для этой цели подойдут платы MKR1000 или Arduino 101. Обе платы используют одинаковые процессоры, оснащенные встроенными средствами работы с USB, и последовательные порты этих плат, отображаемые в мониторе порта, подключены непосредственно к процессору. Для обращения к выводам TX (передача) и RX (прием) платы обычно используется объект Serial1. Далее приводится скетч для реализации этой задачи. В нем вывод передачи USB перенаправляется на вывод приема (RX) платы, а вывод приема USB — на вывод передачи (TX) платы. Таким образом, любая микроконтроллерная плата на микроконтроллере со встроенными средствами работы с USB превращается в адаптер USB/TTL-Serial.

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
void setup() {
 
// инициализируем оба последовательные подключения:
Serial.begin(9600);  // USB
 
Serial1.begin(9600); // TTL
}
 
 
 
void loop() {
 
// считываем RX TTL, отправляем на USB:
 
if (Serial1.available()) {
 
char c = Serial1.read();
 
Serial.write(c);
 
}
 
 
 
// считываем USB, отправляем на TX TTL:
 
if (Serial.available()) {
 
char c = Serial.read();
 
Serial1.write(c);
 
}
 
}

Микроконтроллеры более старых плат — например, Arduino Uno, не имеют встроенных средств для работы с USB. Поэтому, чтобы позволить таким платам взаимодействовать с компьютером через порт USB, они оснащаются отдельной микросхемой адаптера USB/TTL-Serial. Выход передачи (TX) такого адаптера подсоединен к контакту приема (RX) микроконтроллера и наоборот. Это означает, что здесь можно обойти микроконтроллер и напрямую использовать плату Arduino в качестве адаптера USB/TTL-Serial. Для этого в микроконтроллер нужно загрузить скетч, который ничего не делает:

1
2
3
void setup() {}
 
void loop() {}

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

  • контакт приема внешнего устройства — к контакту RX (0) платы Arduino;
  • контакт передачи внешнего устройства — к контакту TX (1) платы Arduino.

Теперь наше устройство может обмениваться данными напрямую с адаптером USB/TTL-Serial платы Arduino, обходя микроконтроллер. Когда же снова нужно будет использовать микроконтроллер, просто отсоедините устройство и загрузите требуемый скетч.

 

 

[1] TTL, Transistor-Transistor Logic — транзисторно-транзисторная логика (ТТЛ).

[2] USB, Universal Serial Bus (protocol) — протокол универсальной последовательной шины.

[3] TTY, Teletype Unit — телетайпное устройство.

[4] CU, Сalling Unit — вызывающее устройство.

[5] GPS, Global Positioning System — система глобального позиционирования.[/vc_column_text]

USB — неисчерпаемый источник последовательных портов

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

Например, если к компьютеру подсоединить три модуля Arduino через USB-хаб, в операционной системе появится три новых последовательных порта. На машинах под Mac OS они будут отображаться примерно так:

/dev/cu.usbmodem1441

/dev/cu.usbmodem1461

/dev/cu.usbmodem1471

В системах POSIX, включая macOS, порты часто указываются дважды: один раз как /dev/tty.usbmodemXX и еще раз как /dev/cu.usbmodemXX. Эта особенность является пережитком эпохи телефонных модемов: порты TTY[3] служили для коммутации входящих звонков, а CU[4] — для исходящих. Для устройств USB/TTL-Serial, которые применяются в этой книге, тип используемого порта не имеет существенной важности.

На машинах под Windows эти порты будут отображаться, например, так: COM8, COM9, COM10.

Большинство современных микроконтроллерных плат оснащены встроенным модулем преобразователя USB/TTL-Serial. Для тех плат, которые не имеют встроенного преобразователя, на рынке предлагаются отдельные модули ценой порядка $15–20. Один из наиболее популярных таких преобразователей с разъемом для макетных плат, который удобно использовать для подсоединения устройств, оснащенных последовательным интерфейсом технологии TTL, выпускает компания FTDI (Future Technology Devices International), сайт которой находится по адресу www.ftdichip.com. Этот преобразователь можно прибрести в разделе макетных плат и кабелей магазинов фирм Maker SHED, SparkFun, Adafruit и многих других. Доступен он в двух версиях: 5 В и 3,3 В — любую из них можно использовать для всех проектов этой книги. Кабель-переходник USB/TTL-Serial компании FTDI показан на рис. 2.4, а распиновка его разъема TTL — на рис. 2.5.

[/vc_column][/vc_row]
Опубликовано

Уровни согласования взаимодействия устройств

По материалам книги Т.Иго «Умные вещи: Arduino, датчики и сети для связи устройств: Пер. с англ. 3-е изд.»  (глава 2 «Простейшая сеть»)

Умные вещи: Arduino

Самая простая сеть — это соединение двух объектов один к одному. В этой главе подробно рассматривается двусторонняя связь, и начнем мы с характеристик, которые нужно оговорить прежде всего. Мы познакомимся с некоторыми логистическими элементами сетевой связи: протоколами данных, управлением потоками и адресацией. Эти теоретические понятия мы применим на практике, создав два устройства, реализующих примеры использования последовательной связи между микроконтроллером и персональным компьютером. Мы также рассмотрим модемную связь и узнаем, как заменить кабель, соединяющий микроконтроллер и компьютер, на приемопередатчики беспроводной связи Bluetooth. Наконец, мы научимся программировать микроконтроллеры низкого уровня с тем, чтобы распределять вычислительные потребности наших проектов между разными процессорами.

Уровни согласования

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

  • Физический. Каким образом вводы и выводы каждого устройства соединяются с другими? Сколько необходимо соединений между двумя устройствами для возможности обмена сообщениями?
  • Электрический. Какие уровни напряжения использовать для представления битов данных? 5 вольт? 3,3 В? Какое-либо другое напряжение?
  • Логический. Какую схему логики использовать — положительную или отрицательную? Схема, при которой высокий уровень напряжения представляет логическую 1, а низкий — логический 0, называется положительной, а когда значения уровней инвертированы: высокий уровень напряжения представляет логический 0, а низкий — логическую 1, — отрицательной.
  • Уровень данных. Как осуществляется синхронизация битов? Сколько битов считывается за раз: 8, 9, 10 или больше? Обозначаются ли группы битов в начале и в конце специальными битами?
  • Уровень приложений. Как организовываются группы битов для создания сообщений? Каков порядок обмена сообщениями для того, чтобы что-то сделать?

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

Какой бы сложной ни была бы сеть, никогда не забывайте о том, что связь между электронными устройствами — это всего лишь электрические импульсы. Устройства, осуществляющие обмен данными по последовательному каналу, соединены между собой электрически. Посылающее устройство изменяет уровень напряжения на соединяющей линии через согласованные интервалы времени, и каждый такой интервал представляет собой один бит данных. Чтобы отправить значение 0 или 1 очередного бита, отправитель меняет уровень напряжения, а получатель определяет уровень полученного сигнала: высокий он или низкий.

Отправитель и получатель могут согласовывать скорость отправки битов двумя способами (рис. 2.3). Скорость асинхронного последовательного обмена данными согласовывается между обеими сторонами обмена и синхронизируется (иногда говорят: тактируется) отправителем и получателем независимо друг от друга. А скорость синхронного последовательного обмена данными управляется отправителем, который подает постоянный сигнал синхронизации (тактирования) на отдельную линию (на рис. 2.3 показаны два интерфейса синхронного последовательного обмена: интерфейс SPI и интерфейс I2C). Синхронный последовательный обмен данными в основном применяется для связи между интегрированными схемами (например, между процессором компьютера и его микросхемами памяти). В этой главе рассматривается только асинхронный последовательный обмен данными, так как именно этот тип последовательной связи лежит в основе сетей, которым посвящена эта книга: от Ethernet-соединений по проводам до беспроводной радиосвязи.

Асинхронный обмен данными

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

Синхронный обмен данными (интерфейс SPI, Serial Peripheral Interface)

Синхронный обмен данными (интерфейс SPI, Serial Peripheral Interface): ведущее устройство подает  сигнал тактирования на ведомое устройство и инициирует обмен, подавая сигнал выбора схемы. Обмен данными происходит по смене уровня напряжения сигнала тактирования на обратное

Синхронный обмен данными (интерфейс I2C)

Синхронный обмен данными (интерфейс I2C): ведущее устройство подает сигнал тактирования на ведомое устройство, выбирая ведомое по его адресу. Обмен данными происходит по смене уровня напряжения сигнала тактирования на обратное

Рис. 2.3. Типы последовательной связи