Визуализация данных в виде графика — SFMonitor

С помощью Ардуино можно легко собирать данные с самых разных датчиков. Можно, к примеру, измерить температуру, скорость ветра и влажность воздуха на улице. А если добавим к этому списку МЭМС барометр и датчик освещенности, получим настоящую погодную станцию у себя во дворе. Но что делать с огромной массой полученных данных? Как проанализировать накопленные массивы чисел?

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

Барометры BMP085, BMP180 и MS5611

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

На этом уроке мы поговорим еще про один инструмент для визуализации — приложение SFMonitor. Это монитор последовательного порта с открытыми исходными кодами, который я разработал пару лет назад для работы над системой стабилизации беспилотников. В основе SFMonitor лежит проект Eli Bendersky написанный на языке python и библиотеки PyQt. Монитор позволяет строить сразу несколько графиков, используя для передачи данных библиотеку SerialFlow. Обо всем этом я расскажу далее.

Строим простой график в SFMonitor

Для того, чтобы построить в SFMonitor самый простой тип графика, потребуется несложная программа, которая будет отправлять в COM-порт показания какого-нибудь датчика. Для примера используем фоторезистор, подключенный к аналоговому порту Ардуино.

const int adc1Pin = A0;
int val = 0;

void setup(){
    Serial.begin(115200);
    pinMode(adc1Pin, INPUT);
}

void loop(){
    val = analogRead(adc1Pin);
    val = map(val, 0, 1023, 0, 255);
    Serial.write(val);
    delay(20);
}

Важно отметить, что мы будем передавать всего один байт за раз, а это число от 0 до 255. АЦП же нам дает число от 0 до 1023. Мы используем функцию map, чтобы нормировать результат АЦП в 1 байт.

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

Теперь включим монитор и настроим параметры. Первое, что нужно будет выбрать — это тип графика. В выпадающем меню выбираем «Простой».

Настройка SFMonitor. Формат данных

Затем настраиваем формат данных в пакете. Для этого зайдем в пункт меню «Данные/Настройка потоков».

Настройка SFMonitor. Графики

На вкладке «Общие» выбираем размер чисел в пакете — 1 байт.

sfmonitor_settings_common

Переходим на вкладку «Поток №1» и ставим галку «Беззнаковые значения». Это означает, что мы будем принимать строго положительные числа от 0 до 255.

sfmonitor_settings_flow1

Теперь выбираем COM-порт Ардуино и скорость передачи данных.

Настройка SFMonitor. Выбор порта
sfmonitor_port

Наконец, запускаем монитор и наблюдаем график.

Настройка SFMonitor. Простой график из COM-порта Ардуино

Пакетная передача данных

Что делать, если нам нужно строить график по шкале от 0 до 1024? или еще больше, от -1 000 000 до 1 000 000. А еще интересно, как сразу передавать данные с двух, или с трех датчиков? Нужен другой способ передачи данных. Способ, при котором данные складываются в некий виртуальный пакет в заданном порядке, затем отправляются адресату, который разворачивает пакет. Собственно, такой метод передачи данных и называют пакетным. На основе пакетов работает весь интернет и большинство промышленных линий связи.

В SFMonitor для пакетной передачи используется библиотека SerialFlow. Эта библиотека позволяет задать формат пакета и предоставляет функции для упаковки данных в пакет и для их распаковки обратно.

Напишем программу для Ардуино, которая будет передавать показания акселерометра ADXL345 для всех трех осей в диапазоне от -32768 до 32767.

#include <SerialFlow.h>
#include <ADXL345.h>

ADXL345 accelerometer;
SerialFlow rd(&Serial); // RX, TX

Vector araw;

void setup() {
    rd.setPacketFormat(2, 3, 0);
    rd.begin(115200);
 
    accelerometer.begin();
    accelerometer.setRange(ADXL345_RANGE_2G);
}

void loop() {
    araw = accelerometer.readRaw();
    rd.setPacketValue( araw.XAxis );
    rd.setPacketValue( araw.YAxis );
    rd.setPacketValue( araw.ZAxis );
    rd.sendPacket();
}

Чтобы SFMonitor смог отобразить три графика настроим следующие параметры:

  • Формат данных — выбираем v(t);
  • Потоки — ставим галку для всех трех;
  • Размер значения в пакете — 2 байта;
  • Беззнаковые значения — ставим для всех трех потоков.

После запуска монитора получим такие вот три графика:

Настройка SFMonitor. Данные акселерометра из COM-порта Ардуино

Построение графиков в Arduino IDE

Начиная с версии 1.6.6 в среде Arduino IDE появилось штатное средство для построения графиков. Немного изменим программу, чтобы Ардуино смогла корректно передавать данные с акселерометра для встроенного монитора.

#include <ADXL345.h>

ADXL345 accelerometer;
Vector araw;

void setup() {
    Serial.begin(115200);
    accelerometer.begin();
    accelerometer.setRange(ADXL345_RANGE_16G);
}

void loop() {
    araw = accelerometer.readRaw();
    Serial.println( araw.XAxis );
    delay(20);
}

Используем обычный println. Загружаем программу на Ардуино и запускаем встроенный монитор через меню «Инструменты/ Плоттер по последовательному соединению». Результат ниже.

aplot_sflow_accel

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

Заключение

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

В будущих версиях планируется режим отображения трехмерных данных, который удобно использовать для визуализации данных инклинометра. И напоминаю, приложение SFMonitor полностью открытое, и мы приветствуем любую помощь по доработке!

Ресурсы


Изменено:

Визуализация данных в виде графика — SFMonitor: 22 комментария

  1. Вроде все настроил и подключил датчик температуры, запустил программку. Датчик температуры через Serial показывает 4-5 градуса Цельсия, а график упорно выводит 10. Не пойму в чем дело.

  2. Все неплохо и толково.Но вот не могу понять как сами датчики к ардуино подключать к каким выводам.Питание пожалуй понятно а остальное?Прошу разжуйте этот вопрос.

  3. скажите пожалуйста как подключить датчик температуры ds18bd20
    Arduino uno R3

  4. Подскажите пожалуйста, как записать команду (формирования и отправки пакета ? ) двух переменных X и Y, чтобы строить график по этим двум координатам в реальном времени.

  5. Олег, доброго здоровья и огромное спасибо за SFMonitor. Пожалуйста, помогите вывести графики температура-время от двух модулей max6675 с термопарами, в диапазоне от 10 до 400 градусов Цельсия, за период в 10-15 минут. Это общедоступный проект на форуме Амперки, на mega2560 & tft lcd 320*480, для настройки коэффициентов PID хочется видеть график на большом экране. Спасибо.

  6. Здравствуйте.
    Очень не хватает четвертого потока данных 🙁
    Подскажите, может планируется обновление программы с добавлением потоков данных???

    • Иван, вообще конечно проект я забросил, ведь в Arduino IDE появился встроенный плоттер графиков. Там и 4 графика наверное можно нарисовать. Даже не знаю, есть ли смысл теперь развивать SerialFlow.

  7. Приветствую!
    Хочу сказать спасибо за вашу программу, аналогов пока не находил. То что нужно для графического вывода данных ком-порта.
    Но есть небольшая проблема: я работаю с stm32 и не получается адекватно вывести хотя бы один график..
    В ком-порт я шлю следующий пакет, состоящий из байт, исходя из вашей справки:
    0x12, Data1.1, Data1.2, 0x10, Data2.1, Data2.2, 0x13 — не работает…
    в дата1 и дата2 я ставлю 16-разрядные переменные(естественно разделяю их на две 8-разрядные), и тупо инкрементирую, тем самым получая счетчик от 0 до 65535, программа выводит только 1й поток, где переменная y всегда = 20(хотя должна рости до 2х байт, x-меняется(время). второй поток отображается просто точкой в начале координат. Эти данные валяться из ком-порта именно по такому протоколу как я написал, проверял в других мониторах последовательного порта(с которыми постоянно работаю).
    Так же не влияет ставлю или нет разделитель(0x10) у себя в протоколе и/или в вашей программе.
    Методом тыка получилось получить адекватные графики, только когда две переменные data1 и data2 были 8-разрядные и без разделителя.
    Но для моих задач нужно как минимум 2 графика с 16-разрядными переменными, для отладки..
    Вы не могли бы глянуть еще раз протокол приема данных по ком-порту в Вашей программе? может я чего не так шлю в нее….

  8. uint8_t _UART_TxDataBuf[7] = {0x12, //Start byte
    0x00, //
    0x00, //
    0x10, //Separate
    0x00, //
    0x00, //
    0x13}; //Stop byte

    while(1) {
    i++; //тип uint16_t
    j++; //тип uint16_t
    _UART_TxDataBuf[2] = (uint8_t)i; //мл.байт1
    _UART_TxDataBuf[1] = (uint8_t)(i >> 8); //ст.байт1
    _UART_TxDataBuf[5] = (uint8_t)j; //мл.байт2
    _UART_TxDataBuf[4] = (uint8_t)(j >> 8); //ст.байт2
    HAL_UART_Transmit(&huart1, _UART_TxDataBuf, sizeof(_UART_TxDataBuf), 1000);
    HAL_Delay(100);
    }

  9. Привет.
    Написал давно подобную вещь, но пользователей мало, видать мало кто знает.
    Ради продвижения оставлю ссылку:
    https://github.com/Tyill/SVisual

    Присоединяйтесь к разработке.

  10. Можете, пожалуйста подсказать как можно визуализировать такой график на телефон через блютуз модуль? Буду очень признателен, прост новичек в етом деле))

Добавить комментарий для Станислав Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

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