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

Обратите внимание, что необходимо объединить контакты 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;
}
Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!