От Arduino к Arduino с использованием последовательного интерфейса

Обмен данными между двумя платами Arduino - очень полезная фича для многих проектов.

Например, можно чтобы одна плата Arduino управляла моторами, а вторая использовалась для подключения сенсоров и передачи управляющих сигналов на первый микроконтроллер. Реализовать обмен данными между двумя Arduino можно с использованием с помощью последовательного (serial) интерфейса. Для этого будут использоваться контакты RX и TX.

Схема подключения

На рисунке ниже показана схема подключения двух контроллеров Arduino. На схеме показаны две платы Arduino Uno, но можно использовать и Arduino Mega, если использовать соответствующие контакты RX и TX.

Схема подключения двух Arduino

Обратите внимание, что необходимо объединить контакты Gnd.

В противном случае, обмен данными происходить не будет! При подключении контакт TX подключается к RX, а RX - к TX.

Особенности программы

При использовании серийного интерфейса, данные передаются в байтах. Эти байты считываются вторым Arduino по одному. Если мы передаем символы, преобразовать их в байты не проблема. Но если мы передаем и символы и цифровые значения, данные могут интерпретироваться некорректно, так как число и символ могут принимать одинаковые значения в байтах. Кроме того, числа могут не поместиться в один байт... Самое простое решение этой проблемы - не передавать символы и числа одновременно.

Простой скетч

Можно настроить передачу данных между двумя Arduino с использованием примера Physical Pixel.

Загрузите скетч Physical Pixel, который можно найти в Arduino IDE в папке: File >> Examples >> Communication, на ваш Arduino.

На вторую плату Arduino загрузите следующий скетч:

void setup() {

Serial.begin(9600);

}

void loop() {

Serial.print('H');

delay(500);

Serial.print('L');

delay(500);

}

Когда код начинает работать, светодиод на 13 пине Arduino должен загораться и тухнуть с частотой 0.5 Гц. Для того, чтобы удостоверится в работоспособности скетча, можете изменить значение задержки (delay).

Символ 'H' в приведенном выше скетче зажигает светодиод, а символ 'L' отвечает за отключение светодиода. Можно расширить этот список символов для выполнения других действий.

Но этот код недостаточно гибкий и для решения более комплексных и сложных задач может не подойти.

Расширенный скетч

Есть второй вариант скетча для передачи данных от одного Arduino к другому. Для этого все данные с Arduino, который передает информацию, преобразовываются в символы. Вторая плата Arduino считывает поступающие данные тоже в символах. На практике данные, конечно, передаются в байтах, но наш Arduino отлично справляется с конвертацией символов в байты и обратно.

Скетч для Arduino, передающего данные

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

// скетч для Arduino, который передает данные

char str[4];

void setup() {

Serial.begin(9600);

}

void loop() {

int value=1234; // будет гораздо веселее, если это будут данные с какого-то сенсора

itoa(value, str, 10); // преобразует данные в массив символов

Serial.write(str, 4);

}

Скетч для Arduino, принимающего данные

Второй микроконтроллер Arduino получит массив данных в байтах и начнет их интерпретировать. Скетч для платы-ресивера приведен ниже.

// скетч для Arduino, который принимает данные

char str[4];

void setup() {

Serial.begin(9600);

Serial1.begin(9600);

}

void loop() {

int i=0;

if (Serial1.available()) {

delay(100);

while(Serial1.available() && i<4) {

str[i++] = Serial1.read();

}

str[i++]='\0';

}

if(i>0) {

Serial.println(str,4);

}

}

В программе, которая приведена выше, есть один недостаток. В результате мы будем получать массив символов, а не чисел...

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

void CharToFloat(char* chars, double* value, int count) {

int i=0, l=0;

float multiplier;

float front =0.0, behind =0.0;

value = 0.0;

// перед точкой

while(chars[i]!='.' && i<count) {

i++;

if (chars[i]=='.') {

int q=i;

for(int j=i; j>0; j--) {

multiplier=1;

for(int k=q; k>1; k--) {

multiplier *= 10;

}

front+=(chars[l]-'0')*multiplier;

l++;

q--;

}

l++;

}

}

int n=i;

// после точки

while(chars[n]!='\0' && i<count) {

n++;

if (chars[n]=='\0') {

int q=n, l=n-1;

for(int j=n-1; j>i; j--) {

multiplier=1;

for(int k=q-(i+2); k>=0; k--) {

multiplier = 0.1*multiplier;

}

behind+=(chars[l]-'0')*multiplier;

l--;

q--;

}

}

}

value[0]=front;

value[1]=behind;

}

Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!