Працюємо з 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) {
    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 размітка не підтримується! Використовуйте звичайтий текст.
    Погано           Добре
Датчик швидкості оптичний

Датчик швидкості оптичний

Модуль відкритої оптопари для вимірювання швидкості обертання.Також можна використовувати як оптични..

22.21грн.

Пінцет самозатискаючий вигнутий

Пінцет самозатискаючий вигнутий

Мультифункціональний пінцет з самозатиском та вигнутим кінцемДовжина 143 мм..

57.80грн.

Модуль гальванорозв'язки 4-канальний

Модуль гальванорозв'язки 4-канальний

Модуль захисту та гальванічної розв'язки 4-х дискретних входів контролера з гвинтовими клемниками. ..

72.71грн.

Модуль реле одноканальний 5В 10А

Модуль реле одноканальний 5В 10А

Одноканальный модуль реле для підключення напряму до дискретного виходу контролера. Світлодіодна інд..

25.98грн.

Світлодіод ультраяскравий 5мм

Світлодіод ультраяскравий 5мм

Над-яскравий світлодіод діаметром 5 мм Корпус прозорий в світлодіодів різного кольору світіння. Тоб..

1.51грн.