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

Радиатор алюминиевый 40х40х20 мм

Радиатор алюминиевый без наклейки.Используется для охлаждения греющихся элементов электронной констр..

63.90грн.

Переходник питания с кроны на Arduino

Переходник питания с кроны на Arduino

Переходник питания с батарейки крона на разъем  5,5х2,1ммПодходит для питания плат контрол..

13.11грн.

Arduino UNO как осциллограф

Arduino UNO как осциллограф

Простой осциллограф своими руками без паяльникаОсциллографы бывают дорогие или очень дорогие. Как же..

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

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

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

75.65грн.

Модуль усилителя 2 х 3 Вт

Модуль усилителя 2 х 3 Вт

Миниатюрный стерео усилитель звуковой частоты класса D на основе микросхемы PAM8403Мощность 2 х..

22.09грн.