Обмен данными между двумя дуинками с помощью EasyTransfer
- Войдите на сайт для отправки комментариев
Хочу сделать так, чтобы две ардуинки одновременно замеряли дистанцию до преграды с помощью УЗ-дальномера.
Как я это вижу:
Дуина-master(Mega2560) замеряет расстояние до преграды и отправляет единицу(которая лежит в переменной sygnal) на Дуину-slave(Uno) и та замеряет расстояние, после чего ответ посылает первой, а та выводит его через Serial на компьютер.
Код дуины-мастера:
#include <EasyTransfer.h> EasyTransfer ET, ET2; struct SEND_DATA_STRUCTURE { int sygnal; }; struct RECEIVE_DATA_STRUCTURE { float tim2; }; SEND_DATA_STRUCTURE data2; RECEIVE_DATA_STRUCTURE data; #define sputnic_T_1 3 #define sputnic_E_1 2 float tim1, tim2; void setup() { Serial.begin(9600); Serial1.begin(9600); ET2.begin(details(data2), &Serial1); ET.begin(details(data), &Serial1); pinMode(sputnic_T_1, OUTPUT); pinMode(sputnic_E_1, INPUT); } void loop() { digitalWrite(sputnic_T_1, HIGH); delayMicroseconds(1); digitalWrite(sputnic_T_1, LOW); tim1=pulseIn(sputnic_E_1, HIGH); delay(250); data2.sygnal=1; ET2.sendData(); if(ET.receiveData()) { tim2 = data.tim2; Serial.println(" "); Serial.print("tim1: "); Serial.print(tim1, 6); Serial.println(" "); Serial.print("tim2: "); Serial.print(tim2, 6); Serial.println(" "); delay(250); } }
Код дуины-слейва:
#include <EasyTransfer.h> EasyTransfer ET, ET2; struct RECEIVE_DATA_STRUCTURE { int sygnal; }; struct SEND_DATA_STRUCTURE { float tim2; }; RECEIVE_DATA_STRUCTURE data2; SEND_DATA_STRUCTURE data; #define sputnic_T_2 5 #define sputnic_E_2 4 float tim2; void setup() { Serial.begin(9600); ET2.begin(details(data2), &Serial); ET.begin(details(data), &Serial); pinMode(sputnic_T_2, OUTPUT); pinMode(sputnic_E_2, INPUT); } void loop() { if(ET2.receiveData()) { digitalWrite(sputnic_T_2, HIGH); delayMicroseconds(1); digitalWrite(sputnic_T_2, LOW); tim2=pulseIn(sputnic_E_2, HIGH); data.tim2 = tim2; ET.sendData(); delay(250); } }
Что работает:
если убрать проверку прихода информации(т.е. if(ET2.receiveData())) на обоих дуинках и просто разместить там ET2.receiveData(); то вторая дуинка успешно присылает данные на первую, а та выводит их на экран. Беда в том, что данные с них поступают с жутким рассинхроном. Если же вернуть проверку наличия входящего сигнала через if, то на компьютер мне вообще ничего не приходит. Из этого делаю вывод, что либо я делаю что-то не так, либо банально не уходит/не доходит сигнал. Второе вряд ли - занимаюсь проверкой своего кода, но так ничего подозрительного и не нашел.
Буду очень благодарен за помощь!
столкнулся на днях с такой же проблемой при обмене mini с DUE. Так вот, грабли оказались вот в чем.
вроде одна и та же строка. НО как оказалось на платке "мини", эта строка занимает в памяти 4+4+4+2 = 16 байт. эта же строка в DUE занимает 4+4+4+4 = 16 байт. почему я так и не понял. долно не думал, ибо лень :) сделал на обоих так
и на обоих получается 4+4+4+4 = 16 байт. а зачем это всё? а затем, что библиотека EasyTransfer сверяет длинну полученного пакета и длину объявленого struct. В самом файле EasyTransfer.cpp эта проверка выглядит так.
можно конечно убрать эту проверку, но мне показалось это не правильным.
Хм, я слышал, что 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) -
Mega(Master) -
Ума не приложу, почему пятерка, которую я отсылаю на Uno возвращается мне на Mega вместо значения tim2.
Нашел свой косяк: забыл подключить общую линию заземления. Как только добавил - заработало как надо :)