Хочу сделать так, чтобы две ардуинки одновременно замеряли дистанцию до преграды с помощью УЗ-дальномера.
Как я это вижу:
Дуина-master(Mega2560) замеряет расстояние до преграды и отправляет единицу(которая лежит в переменной sygnal) на Дуину-slave(Uno) и та замеряет расстояние, после чего ответ посылает первой, а та выводит его через Serial на компьютер.
Код дуины-мастера:
01 | #include <EasyTransfer.h> |
05 | struct SEND_DATA_STRUCTURE |
10 | struct RECEIVE_DATA_STRUCTURE |
15 | SEND_DATA_STRUCTURE data2; |
16 | RECEIVE_DATA_STRUCTURE data; |
28 | ET2.begin(details(data2), &Serial1); |
29 | ET.begin(details(data), &Serial1); |
31 | pinMode(sputnic_T_1, OUTPUT); |
32 | pinMode(sputnic_E_1, INPUT); |
37 | digitalWrite(sputnic_T_1, HIGH); |
39 | digitalWrite(sputnic_T_1, LOW); |
40 | tim1=pulseIn(sputnic_E_1, HIGH); |
53 | Serial .print( "tim1: " ); |
54 | Serial .print(tim1, 6); |
57 | Serial .print( "tim2: " ); |
58 | Serial .print(tim2, 6); |
Код дуины-слейва:
01 | #include <EasyTransfer.h> |
05 | struct RECEIVE_DATA_STRUCTURE |
10 | struct SEND_DATA_STRUCTURE |
15 | RECEIVE_DATA_STRUCTURE data2; |
16 | SEND_DATA_STRUCTURE data; |
27 | ET2.begin(details(data2), & Serial ); |
28 | ET.begin(details(data), & Serial ); |
30 | pinMode(sputnic_T_2, OUTPUT); |
31 | pinMode(sputnic_E_2, INPUT); |
38 | digitalWrite(sputnic_T_2, HIGH); |
40 | digitalWrite(sputnic_T_2, LOW); |
42 | tim2=pulseIn(sputnic_E_2, HIGH); |
Что работает:
если убрать проверку прихода информации(т.е. if(ET2.receiveData())) на обоих дуинках и просто разместить там ET2.receiveData(); то вторая дуинка успешно присылает данные на первую, а та выводит их на экран. Беда в том, что данные с них поступают с жутким рассинхроном. Если же вернуть проверку наличия входящего сигнала через if, то на компьютер мне вообще ничего не приходит. Из этого делаю вывод, что либо я делаю что-то не так, либо банально не уходит/не доходит сигнал. Второе вряд ли - занимаюсь проверкой своего кода, но так ничего подозрительного и не нашел.
Буду очень благодарен за помощь!
столкнулся на днях с такой же проблемой при обмене mini с DUE. Так вот, грабли оказались вот в чем.
1
struct
RECEIVE_DATA_STRUCTURE{unsigned
long
RXCommandC; unsigned
long
RXDataC; unsigned
long
RXExtrasC; unsigned
int
ToNode; };
вроде одна и та же строка. НО как оказалось на платке "мини", эта строка занимает в памяти 4+4+4+2 = 16 байт. эта же строка в DUE занимает 4+4+4+4 = 16 байт. почему я так и не понял. долно не думал, ибо лень :) сделал на обоих так
1
struct
RECEIVE_DATA_STRUCTURE{unsigned
long
RXCommandC; unsigned
long
RXDataC; unsigned
long
RXExtrasC; unsigned
long
ToNode; };
и на обоих получается 4+4+4+4 = 16 байт. а зачем это всё? а затем, что библиотека EasyTransfer сверяет длинну полученного пакета и длину объявленого struct. В самом файле EasyTransfer.cpp эта проверка выглядит так.
1
rx_len = _stream->read();
2
//make sure the binary structs on both Arduinos are the same size.
3
if
(rx_len != size){
4
rx_len = 0;
5
return
false
;
можно конечно убрать эту проверку, но мне показалось это не правильным.
Хм, я слышал, что int имеет разное значение в 16 и 32 битных системах, но не думал, что это касается ардуино)
Т.е. Вы предлагаете привести объем всех переменных к более крупному, либо отключить проверку?
Спасибо, сейчас попробую. Не исключаю, что так оно и будет, ведь с float'ной переменной передача/прием работает. Кстати, как Вы поняли, что int на этих платах занимает разное число байт?
Кстати, как Вы поняли, что int на этих платах занимает разное число байт?
http://arduino.cc/en/Reference/Int#.UwdibuOqmfA
Особо не вдавался в ваш код в первом посте, но что сразу бросатеся в глаза - Serial1.begin(9600); Что мешает поставит скорость передачи больше?
Сигнал синхронизации можно передать через любой свободный pin, а не гонять по сериал int. Получится так: мастер сделал измерение, выставил синхросигнал на пине, слэйв по прерыванию словил синхросигнал, сделал измерение и предал измерение мастеру. Логику с синхросигналом проработать только.
А зачем такая система - двух измерений на разных устройствах, интересно?
Огромное спасибо, pmaster!
Дело действительно было в int'е. Поменял на float и заработало. Но почему-то значение расстояния(tim2), которое я получаю с Uno, равно значению sygnal, которое я на неё же подаю с Mega. Ума не приложу, чем это вызвано.
Garry, я рассматривал такой вариант, но он мне казался костылем и я рассчитывал обойтись без него. Более высокую скорость пока не пытался ставить :)
Просто провожу опыты, в которых используются УЗ-замеры для регистрации очень быстрых движений различных объектов(не со скоростью полета пули, но всё же). Для этого нужно несколько УЗ-дальномеров(в ближайшие дни перейду с Serial на I2C, чтобы работать с гораздо большим количество датчиков). В будущем эти статистические данные будт применяться в более крупном проекте.
Я сам не понимал, пока не стал разбирать всё библиотеку, выводя все данные в терминал. тут то и заметил, что длинна пакетов разная. Поменял тип переменной и заработало. а зачем передавать float ? unsigned long не устраивает?
Здорово, что Вы проделали эту работу!
Устраивает, просто остальные переменные в этом же типе данных храню и решил опробовать не отходя от традиции. Код теперь выглядит так:
Uno(Slave) -
01
#include <EasyTransfer.h>
02
03
EasyTransfer ET, ET2;
04
05
struct
RECEIVE_DATA_STRUCTURE
06
{
07
float
signal;
08
};
09
10
struct
SEND_DATA_STRUCTURE
11
{
12
float
tim2;
13
};
14
15
RECEIVE_DATA_STRUCTURE data2;
16
SEND_DATA_STRUCTURE data;
17
18
#define sputnic_T_2 5
19
#define sputnic_E_2 4
20
21
float
tim2;
22
23
void
setup
()
24
{
25
Serial
.begin(115200);
26
27
ET2.begin(details(data2), &
Serial
);
28
ET.begin(details(data), &
Serial
);
29
30
pinMode(sputnic_T_2, OUTPUT);
31
pinMode(sputnic_E_2, INPUT);
32
}
33
34
void
loop
()
35
{
36
if
(ET2.receiveData())
37
{
38
digitalWrite(sputnic_T_2, HIGH);
39
delayMicroseconds(10);
40
digitalWrite(sputnic_T_2, LOW);
41
42
tim2=pulseIn(sputnic_E_2, HIGH);
43
44
delay(250);
45
46
data.tim2 = tim2;
47
48
ET.sendData();
49
}
50
}
Mega(Master) -
01
#include <EasyTransfer.h>
02
03
EasyTransfer ET, ET2;
04
05
struct
SEND_DATA_STRUCTURE
06
{
07
float
signal;
08
};
09
10
struct
RECEIVE_DATA_STRUCTURE
11
{
12
float
tim2;
13
};
14
15
SEND_DATA_STRUCTURE data2;
16
RECEIVE_DATA_STRUCTURE data;
17
18
#define sputnic_T_1 3
19
#define sputnic_E_1 2
20
21
float
tim1, tim2;
22
23
void
setup
()
24
{
25
Serial
.begin(9600);
26
Serial1.begin(115200);
27
28
ET2.begin(details(data2), &Serial1);
29
ET.begin(details(data), &Serial1);
30
31
pinMode(sputnic_T_1, OUTPUT);
32
pinMode(sputnic_E_1, INPUT);
33
}
34
35
void
loop
()
36
{
37
digitalWrite(sputnic_T_1, HIGH);
38
delayMicroseconds(10);
39
digitalWrite(sputnic_T_1, LOW);
40
41
tim1=pulseIn(sputnic_E_1, HIGH);
42
43
delay(250);
44
45
data2.signal = 5;
46
47
ET2.sendData();
48
49
if
(ET.receiveData())
50
{
51
tim2 = data.tim2;
52
53
Serial
.println(
" "
);
54
Serial
.print(
"tim1: "
);
55
Serial
.print(tim1, 0);
56
Serial
.println(
" "
);
57
58
Serial
.print(
"tim2: "
);
59
Serial
.print(tim2, 0);
60
Serial
.println(
" "
);
61
62
delay(250);
63
}
64
}
Ума не приложу, почему пятерка, которую я отсылаю на Uno возвращается мне на Mega вместо значения tim2.
Нашел свой косяк: забыл подключить общую линию заземления. Как только добавил - заработало как надо :)