Працюємо з 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 разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Реле 220В с колодкой

Реле 220В с колодкой

Реле с двумя группами переключающихся контактов с клеммной колодкойКатушка реле рассчитана на 220 ВМ..

78.36грн.

Шестерня для зубчатого ремня на 36 зубьев под ось 8 мм

Шестерня для зубчатого ремня на 36 зубьев под ось 8 мм

Используется для передачи и редукции крутящего момента от двигателя до оси 8 ммКоличество зубьев 36 ..

52.94грн.

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

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

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

42.83грн.

Шаговый двигатель 28BYJ-48 с модулем драйвера

Шаговый двигатель 28BYJ-48 с модулем драйвера

Количество фаз 4Рабочее напряжение 5 ВКоэффициент изменения скорости 1/64Угол поворота минимальный&n..

66.36грн.

Концевик с колесом для 3D принтера или CNC ramps 1.4

Концевик с колесом для 3D принтера или CNC ramps 1.4

Концевой выключатель для установки на 3D-принтер или CNC-станок системы ramps 1.4В комплекте ка..

33.26грн.