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

Перемикач мініатюрний на плату 2 групи контактів

Мініатюрний перемикач для встановлення на друковану плату.Має дві групи перемикаючих контактівГабари..

4.57грн.

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

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

Використовується для передачі та редукції обертаючого моменту від двигуна до вісі 8 ммКількість зубц..

19.54грн.

Стійка латунна М3 висотою 15мм шестикутник мама-мама

Стійка латунна М3 висотою 15мм шестикутник мама-мама

Латунна стійка мама-мама з різьбою М3 та шестикутним зовнішнім перетиномЗастосовується при конструюв..

7.37грн.

Вентилятор для Orange PI товщиною 10мм

Вентилятор для Orange PI товщиною 10мм

Вентилятор для охолодження процесора міні-комп'ютера Orange PI або Raspberry PIПрацює дуже тихоЖивле..

40.28грн.

SG90 9g міні серво мотор

SG90 9g міні серво мотор

Міні серво мотор для підключення до контролерівПластмасовий редуктор.Робоча температура - 30 ....

48.76грн.