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

Трансформатор тока 0-20А

Трансформатор тока предназначен для измерения силы переменного тока, протекающего через провод. Для ..

65.00грн.

Модуль блока питания 5В 1А

Модуль блока питания 5В 1А

Плата модуля импульсного блока питания 5В 1АВходное переменное напряжение 85 ... 265 В 50/60 ГцРазме..

60.08грн.

Модуль блока питания 5В 700мА

Модуль блока питания 5В 700мА

Миниатюрный безкорпусный трансформаторный блок питания для любительских проектов.Входное напряжение ..

46.44грн.

Модуль часов реального времени DS3231SN + батарейка

Модуль часов реального времени DS3231SN + батарейка

Батарейка входит в комплектМодуль часов реального времени для различных плат микроконтроллеровХаракт..

52.77грн.

Кабель сигнальный 4х0,22мм² экранированный медный

Кабель сигнальный 4х0,22мм² экранированный медный

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

6.09грн.