Обмен данными между двумя дуинками с помощью EasyTransfer

Daemon2017
Offline
Зарегистрирован: 08.10.2013

Хочу сделать так, чтобы две ардуинки одновременно замеряли дистанцию до преграды с помощью УЗ-дальномера. 

Как я это вижу: 

Дуина-master(Mega2560) замеряет расстояние до преграды и отправляет единицу(которая лежит в переменной sygnal) на Дуину-slave(Uno) и та замеряет расстояние, после чего ответ посылает первой, а та выводит его через Serial на компьютер. 

Код дуины-мастера:

01#include <EasyTransfer.h>
02 
03EasyTransfer ET, ET2;
04 
05struct SEND_DATA_STRUCTURE
06{
07  int sygnal;
08};
09 
10struct RECEIVE_DATA_STRUCTURE
11{
12  float tim2;
13};
14 
15SEND_DATA_STRUCTURE data2;
16RECEIVE_DATA_STRUCTURE data;
17 
18#define sputnic_T_1 3
19#define sputnic_E_1 2
20 
21float tim1, tim2;
22 
23void setup()
24{
25  Serial.begin(9600);
26  Serial1.begin(9600);
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 
35void loop()
36{     
37  digitalWrite(sputnic_T_1, HIGH);
38  delayMicroseconds(1);
39  digitalWrite(sputnic_T_1, LOW);
40  tim1=pulseIn(sputnic_E_1, HIGH); 
41   
42  delay(250); 
43   
44  data2.sygnal=1;
45   
46  ET2.sendData();
47        
48  if(ET.receiveData())
49  {  
50  tim2 = data.tim2;
51     
52  Serial.println(" "); 
53  Serial.print("tim1: ");
54  Serial.print(tim1, 6);
55  Serial.println(" ");
56   
57  Serial.print("tim2: ");
58  Serial.print(tim2, 6);
59  Serial.println(" "); 
60 
61  delay(250); 
62  }
63}

Код дуины-слейва:

01#include <EasyTransfer.h>
02 
03EasyTransfer ET, ET2;
04 
05struct RECEIVE_DATA_STRUCTURE
06{
07  int sygnal;
08};
09 
10struct SEND_DATA_STRUCTURE
11{
12  float tim2;
13};
14 
15RECEIVE_DATA_STRUCTURE data2;
16SEND_DATA_STRUCTURE data;
17 
18#define sputnic_T_2 5
19#define sputnic_E_2 4
20 
21float tim2;
22 
23void setup()
24{
25  Serial.begin(9600);
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 
34void loop()
35{       
36  if(ET2.receiveData())
37  
38  digitalWrite(sputnic_T_2, HIGH);  
39  delayMicroseconds(1);
40  digitalWrite(sputnic_T_2, LOW);
41   
42  tim2=pulseIn(sputnic_E_2, HIGH); 
43  
44  data.tim2 = tim2;
45     
46  ET.sendData();
47 
48  delay(250); 
49  }
50}

Что работает:

если убрать проверку прихода информации(т.е. if(ET2.receiveData())) на обоих дуинках и просто разместить там ET2.receiveData(); то вторая дуинка успешно присылает данные на первую, а та выводит их на экран. Беда в том, что данные с них поступают с жутким рассинхроном. Если же вернуть проверку наличия входящего сигнала через if, то на компьютер мне вообще ничего не приходит. Из этого делаю вывод, что либо я делаю что-то не так, либо банально не уходит/не доходит сигнал. Второе вряд ли - занимаюсь проверкой своего кода, но так ничего подозрительного и не нашел.

Буду очень благодарен за помощь!

pmaster
Offline
Зарегистрирован: 23.05.2011

столкнулся на днях с такой же проблемой при обмене mini с DUE. Так вот, грабли оказались вот в чем. 

1struct 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 байт. почему я так и не понял. долно не думал, ибо лень :) сделал на обоих так 

1struct RECEIVE_DATA_STRUCTURE{unsigned long RXCommandC; unsigned long RXDataC; unsigned long RXExtrasC; unsigned long ToNode; };

и на обоих получается 4+4+4+4 = 16 байт. а зачем это всё? а затем, что библиотека EasyTransfer сверяет длинну полученного пакета и длину объявленого struct. В самом файле EasyTransfer.cpp эта проверка выглядит так.

1rx_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;

можно конечно убрать эту проверку, но мне показалось это не правильным.

 

Daemon2017
Offline
Зарегистрирован: 08.10.2013

Хм, я слышал, что int имеет разное значение в 16 и 32 битных системах, но не думал, что это касается ардуино)

Т.е. Вы предлагаете привести объем всех переменных к более крупному, либо отключить проверку?

Спасибо, сейчас попробую. Не исключаю, что так оно и будет, ведь с float'ной переменной передача/прием работает. Кстати, как Вы поняли, что int на этих платах занимает разное число байт?

Garry
Garry аватар
Offline
Зарегистрирован: 07.04.2012

Daemon2017 пишет:

Кстати, как Вы поняли, что int на этих платах занимает разное число байт?

http://arduino.cc/en/Reference/Int#.UwdibuOqmfA

Особо не вдавался в ваш код в первом посте, но что сразу бросатеся в глаза - Serial1.begin(9600); Что мешает поставит скорость передачи больше?

Garry
Garry аватар
Offline
Зарегистрирован: 07.04.2012

Сигнал синхронизации можно передать через любой свободный pin, а не гонять по сериал int. Получится так: мастер сделал измерение, выставил синхросигнал на пине, слэйв по прерыванию словил синхросигнал, сделал измерение и предал измерение мастеру. Логику с синхросигналом проработать только.

А зачем такая система - двух измерений на разных устройствах, интересно?

Daemon2017
Offline
Зарегистрирован: 08.10.2013

Огромное спасибо, pmaster!

Дело действительно было в int'е. Поменял на float и заработало. Но почему-то значение расстояния(tim2), которое я получаю с Uno, равно значению sygnal, которое я на неё же подаю с Mega. Ума не приложу, чем это вызвано.

Daemon2017
Offline
Зарегистрирован: 08.10.2013

Garry, я рассматривал такой вариант, но он мне казался костылем и я рассчитывал обойтись без него. Более высокую скорость пока не пытался ставить :)

Просто провожу опыты, в которых используются УЗ-замеры для регистрации очень быстрых движений различных объектов(не со скоростью полета пули, но всё же). Для этого нужно несколько УЗ-дальномеров(в ближайшие дни перейду с Serial на I2C, чтобы работать с гораздо большим количество датчиков). В будущем эти статистические данные будт применяться в более крупном проекте. 

pmaster
Offline
Зарегистрирован: 23.05.2011

Я сам не понимал, пока не стал разбирать всё библиотеку, выводя все данные в терминал. тут то и заметил, что длинна пакетов разная. Поменял тип переменной и заработало. а зачем передавать float ? unsigned long не устраивает?

Daemon2017
Offline
Зарегистрирован: 08.10.2013

Здорово, что Вы проделали эту работу!

Устраивает, просто остальные переменные в этом же типе данных храню и решил опробовать не отходя от традиции. Код теперь выглядит так:

Uno(Slave) -

01#include <EasyTransfer.h>
02 
03EasyTransfer ET, ET2;
04 
05struct RECEIVE_DATA_STRUCTURE
06{
07  float signal;
08};
09 
10struct SEND_DATA_STRUCTURE
11{
12  float tim2;
13};
14 
15RECEIVE_DATA_STRUCTURE data2;
16SEND_DATA_STRUCTURE data;
17 
18#define sputnic_T_2 5
19#define sputnic_E_2 4
20 
21float tim2;
22 
23void 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 
34void 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 
03EasyTransfer ET, ET2;
04 
05struct SEND_DATA_STRUCTURE
06{
07  float signal;
08};
09 
10struct RECEIVE_DATA_STRUCTURE
11{
12  float tim2;
13};
14 
15SEND_DATA_STRUCTURE data2;
16RECEIVE_DATA_STRUCTURE data;
17 
18#define sputnic_T_1 3
19#define sputnic_E_1 2
20 
21float tim1, tim2;
22 
23void 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 
35void 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. 

Daemon2017
Offline
Зарегистрирован: 08.10.2013

Нашел свой косяк: забыл подключить общую линию заземления. Как только добавил - заработало как надо :)