Працюємо з 09:00 до 19:00 Пн-Пт
Київ біля ТЦ Квадрат бул.Перова

Всем пользователям контроллеров Arduino известно, что можно передавать данные через аппаратный порт UART контроллера, а так же при помощи любых дискретных входов-выходов программным UART портом. По сути для соединения двух контроллеров между собой нам понадобятся 2 ... 3 провода. По двум проводам будет связь только в одну сторону, а по трём в обе стороны.

Так вот, мы можем в один контроллер записать например вот такой кусок программы

// Подключаем библиотеку Software Serial
#include <SoftwareSerial.h>

// Объявляем задействованные дискретные каналы контроллера для связи
SoftwareSerial outSerial(5, 6); // RX, TX

float i1=40.04;
float i2=5.08;
float i3=-200.03;
String str;
unsigned long previousMillis = 0; 
const long interval =2000;  //периодичность отправки данных в порт другому контроллеру

void setup(){

Serial.begin(9600); // Обычная скорость передачи данных аппаратного UART порта (используем для проверки получения данных от другого контроллера)

outSerial.begin(9600); //скорость обмена программного порта
}

void loop(){
unsigned long currentMillis = millis();
//с заданной периодичностью пишем в программный порт
//другому контроллеру Arduino три постоянно изменяющихся числа float
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    str = "<";
    i1 = i1+0.1;
    str += i1;
    str += ";";
    i2 = i2+0.1;
    str += i2;
    str += ";";
    i3 = i3+0.1;
    str += i3;
    str += ">";
    outSerial.println(str); //здесь отправка типо <3.54;56.17;-140.34>
  }

//здесь отправляем все полученные от соседнего контроллера данные в аппаратный UART в монитор порта
if (outSerial.available()) {
    Serial.write(outSerial.read());
  }
}

Соединим два контроллера Arduino Nano R3 согласно следующей не хитрой схемы


Во второй контроллер запишем программу с небольшими изменениями. Мы в ней изменим стартовые величины флоатов, чтобы они явно отличались от данных с первого Nano. А так же поменяем местами дискретные пины к которым привязан программный UART.

// Подключаем библиотеку Software Serial
#include <SoftwareSerial.h>

// Объявляем задействованные дискретные каналы контроллера для связи
SoftwareSerial outSerial(6, 5); // RX, TX

float i1=240.04;
float i2=1005.08;
float i3=-4200.03;
String str;
unsigned long previousMillis = 0; 
const long interval =2000;  //периодичность отправки данных в порт другому контроллеру

void setup(){

Serial.begin(9600); // Обычная скорость передачи данных аппаратного UART порта (используем для проверки получения данных от другого контроллера)

outSerial.begin(9600); //скорость обмена программного порта
}

void loop(){
unsigned long currentMillis = millis();
//с заданной периодичностью пишем в программный порт
//другому контроллеру Arduino три постоянно изменяющихся числа float
  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    str = "<";
    i1 = i1+0.1;
    str += i1;
    str += ";";
    i2 = i2+0.1;
    str += i2;
    str += ";";
    i3 = i3+0.1;
    str += i3;
    str += ">";
    outSerial.println(str); //здесь отправка типо <3.54;56.17;-140.34>
  }

//здесь отправляем все полученные от соседнего контроллера данные в аппаратный UART в монитор порта
if (outSerial.available()) {
    Serial.write(outSerial.read());
  }
}

Теперь один Arduino нужно будет запитать отдельно без нашего компа, а другой подключить к компу. И в мониторе порта будем получать следующие строки с периодичностью в 2 секунды:

<240.64;1005.68;-4199.43>

<240.74;1005.78;-4199.33>

<240.84;1005.88;-4199.23>

Всё красиво и душевно. Каждый из двух контроллеров покажет нам свои способности одновременной передачи и приема данных, но пока рано танцевать чечётку от радости. Дело в том, что полученные данные только в мониторе порта похожи на заветные данные, а на самом деле это просто массив байтов, с которым трудно дальше работать и выделить из него полезные составляющие.
Поискав на сайте ардуино, я нашол на первый взгляд грубоватый метод выделения из байтов необходимую текстовую, вещественную и целочисленную информацию. Попробовав его в деле, мне стало ясно, что это довольно классный пример получения, обработки и парсинга данных для нашей задачи обмена полезными данными.
Следующий код для Arduino контроллеров позволяет получить из отправленной строки вида <HelloWorld, 12, 24.57> три переменные, разделенные наперед заданным символом ",", каждую своего определенного типа: строка char, целое число int и вещественное число float. Так же в этом примере код проверяет наличие начального символа "<" строки данных и завершающего символа ">"

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];    // временный массив используется во время парсинга

      // переменные для хранения полученных данных
char messageFromPC[numChars] = {0}; //текстовые данные
int integerFromPC = 0; //целочисленные данные
float floatFromPC = 0.0;  //вещественные данные

boolean newData = false;

//============

void setup() {
    Serial.begin(9600);
    Serial.println("Этот пример ожидает три значенияданных - текст, целое число и число с плавающей запятой");
    Serial.println("Передавайте данные с другого контроллера в таком виде <HelloWorld, 12, 24.7>  ");
    Serial.println();
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
        parseData();
        showParsedData();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // завершаем строку
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // разделение данных на составляющие части

    char * strtokIndx; // это используется функцией strtok() как индекс

    strtokIndx = strtok(tempChars,",");      // получаем значение первой переменной - строку
    strcpy(messageFromPC, strtokIndx); //записываем её в переменную messageFromPC
 
    strtokIndx = strtok(NULL, ","); // продолжаем с последнего индекса
    integerFromPC = atoi(strtokIndx);     // конвертируем эту составляющую в integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // преобразовываем этот кусок текста в float

}

//============

void showParsedData() {
    Serial.print("Message ");
    Serial.println(messageFromPC);
    Serial.print("Integer ");
    Serial.println(integerFromPC);
    Serial.print("Float ");
    Serial.println(floatFromPC);
}

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

Пойду штудировать дальше. Всем большой привет от geekmatic!

<< Проекты << Все товары >> Статьи, уроки >>

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Универсальная плата под микросхемы SOP20, SSOP20

Универсальная плата под микросхемы SOP20, SSOP20

Универсальная монтажная плата, позволяет проводить монтаж различных микросхем с поверхностным монтаж..

11.49грн.

Датчик напряжения сети 220В

Датчик напряжения сети 220В

Гальванически изолированный датчик наличия напряжения в сети 220ВНапряжение питания логики 3 ... 5 В..

63.21грн.

Orange PI автозапуск браузера на весь экран при включении

Orange PI автозапуск браузера на весь экран при включении

Вступительное слово Основная идея проекта - отображение содержимого нашего сайта на экране телевизо..

Фольгированный текстолит двухсторонний 75х100мм

Фольгированный текстолит двухсторонний 75х100мм

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

44.74грн.

Муфта на двигатель 3x5x25мм

Муфта на двигатель 3x5x25мм

Данная муфта служит переходником между валами 3 мм и 5 мм. Тоесть имеет с одной стороны отверстие ди..

40.21грн.