Віримо в перемогу ЗСУ!
Працюємо з 09:00 до 18: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 разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Концевик с колесом для 3D принтера или CNC ramps 1.4

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

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

50.19грн.

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

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

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

83.82грн.

Датчик цвета TCS230

Датчик цвета TCS230

Датчик определения цвета основан на микросборке TCS230, которая представляет из себя матрицу фо..

114.20грн.

Радиатор для транзистора 21х15х10мм

Радиатор для транзистора 21х15х10мм

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

13.03грн.

Переменный резистор 1 кОм

Переменный резистор 1 кОм

Переменный резистор или потенциометрСопротивление 1 кОмМощность 0,5 ВтТип BЛинейная характеристикаТа..

20.60грн.