Arduino Zero (ATSAMD21G) - I2C - непрерывный поток неверных данных

Я столкнулся со странным поведением при выполнении тестов на 2-полосную передачу между 2 Arduino Zero (ATSAMD21G), одним ведущим и одним ведомым. Неправильные данные постоянно передаются в обоих направлениях. Ожидаемые данные также передаются между ними. Я должен отфильтровать полученные данные, чтобы поймать их (строка 41 в коде ведущего и 33 в ведомом).

Я использую стандартные библиотеки проводов (разные для 2 плат), а также "I2C_readAnything"Ника Гэммона.

Код магистра

Код раба

Я думаю, что этот непрерывный поток не позволяет освободить автобус. Возможно, это то, что делает невозможным общение со вторым мастером (и, возможно, вызывает мою предыдущую проблему).

Я также попробовал свой код между Mega 2560 (ведомый) и нулем (ведущий). Поддельные данные на этот раз отправляются только в одну сторону (только от Нуля до Мега).

Есть ли какой-то конкретный код, который нужно добавить для правильной отправки данных с плат ATSAMD? Это ошибка в библиотеке проводов SAMD?

Мне также пришлось добавить задержку в 1 мс после отправки данных от Мастера. Иначе это не прошло бы. Разве это не должно обрабатываться ATSAMD или библиотекой проводов?

, 👍1


2 ответа


0

Начните с одного байта, с очень маленького скетча, с ведущим и ведомым устройством на частоте 100 кГц. Когда это будет работать на 100% надежно, вы можете попытаться перенести структуру.

Подчиненная функция RequestEvent всегда должна возвращать действительные данные, а не каждые две секунды. Глобальные переменные, которые используются в receiveEvent или requestEvent и в цикле (), должны быть "изменчивыми". Отключите прерывания в цикле() при чтении или записи глобальной изменчивой структуры.

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

Вы можете добавить дополнительные тесты, например, проверить возвращаемое значение Wire.endTransmissing, проверить параметр "Сколько", проверить фактическое число, возвращаемое Wire.request.

,

Я упростил код для тестирования с помощью однобайтовой 2-полосной передачи при частоте 100 кГц, используя летучие вещества в событиях, как вы советовали. Я все еще вижу то же самое поведение (после открытия монитора на обоих, конечно). Передача только в одну сторону работает правильно. Добавление дополнительных тестов звучит для меня так, что это только скроет, что поддельные данные текут между устройствами (как фильтрация, которую я сделал в своем первоначальном коде). Я должен избегать отключения прерываний, потому что мое окончательное приложение полагается на них (управление ПИД-двигателем и считывание энкодера...), @kb_

Результат на ведомом устройстве: -Arduino подключен ... y y m y y _BOS_ ... (должен получить только "m"; такое же поведение на стороне мастера) [Мастер](http://tinyurl.com/hm2nsfc) / [Рабыня](http://tinyurl.com/zyder4a]) / [Только один путь, Мастер](http://tinyurl.com/hq47p9v), @kb_

Я выяснил, что не сработало в упрощенном тесте. Миллисекундная задержка в requestEvent приводила к таймауту. Вместо этого я поместил эту задержку перед requestFrom в мастер. Я должен проверить параметр "howMany" в receiveEvent, чтобы он не путал входящие данные с requestEvent. На мой взгляд, это должно быть обработано wire library. [Исправлено code](https://github.com/kb-/Arduino-I2C-2way-anydata/commit/88d35b78301265cacf743e1f00232c59bbe0aadc), @kb_


1

В кодексе было несколько проблем.

receiveEventна стороне ведомого устройства содержал таймер миллисекундного состояния, который определял время ожидания. Я переместил таймер на главную сторону, прежде чем вызвать Wire.requestFrom.

receiveEvent, на стороне подчиненного, также путал реальные данные с входящим запросом. Я добавил оператор if для сравнения размера данных receiveEvent с ожидаемым размером. Половина данных была неверной без этого фильтра (в идеале это должно обрабатываться в библиотеке проводов).

Я установил глобальные переменные, используемые в событиях, как изменчивые. Код тоже работает и без этого.

исправлен Мастер-код

исправлен ведомый код

,

Тактовая частота ведомого I2C составляет 100 кГц, ведущего-800 кГц. Начните с самых обычных настроек, то есть и Мастера на 100 кГц. Возвращаемые значения не проверяются в Мастере. Я думаю, что в этой ситуации вы должны их проверить. В ведомом устройстве вы можете проверить howMany и увеличить счетчик ошибок, если он неверен. Шина I2C не является отказоустойчивой, это означает, что она всегда должна работать на 100%. Если он ненадежен, вы должны его исправить. Какой длины провода ? Когда вы подключаете плату 3,3 В через I2C к плате 5 В, вы использовали переключатель уровня ? Вы подключили GND обеих плат ?, @Jot

Вы имеете в виду оставшиеся неправильные данные, которые я отфильтровываю, проверяя, сколько их там не должно быть? Когда я тестирую его, как вы советуете, я вижу, что это половина receiveEvent (больше не непрерывный поток, так что это достаточно хорошо, шина освобождается после каждой транзакции, так что multimaster теперь тоже работает). Вот почему я думаю, что это путает requestEvent с данными. Я пойму больше, как только получу свой логический анализатор., @kb_

Мастер устанавливает скорость шины I2C. Код ведомого устройства не содержит настройки скорости. 800 кГц отлично работает между 48 МГц Nano, но слишком много с Mega. Длина проводов составляет менее 1 м. Я использую сдвиг уровня между Нано и Мега. Все на том же GND. Я добавлю тест на содержание данных в свою окончательную заявку для дополнительной безопасности., @kb_

Мне все равно, работал ли 800 кГц в прошлом. Вы должны исправить ряд проблем, поэтому было бы разумно вернуться к 100 кГц. Если все работает нормально, вы можете попробовать более высокие тактовые частоты. Но вы еще не там. Связь I2C должна работать на 100%, а не на 99%. Когда howMany-это только половина receiveEvent okay, то ваша связь I2C работает на 50%. Вы должны исправить проблемы, чтобы сделать это на 100%. Начните с использования тактовой частоты I2C по умолчанию 100 кГц и проверьте возвращаемые значения в мастере. Может быть, вы также могли бы сохранить howMany в переменной, когда она была неправильной, и распечатать эту переменную., @Jot

То же самое при частоте 100 кГц. howMany = 0 для половины receiveEvent. Для них Wire.read возвращает -1, что означает отсутствие данных., @kb_

Спасибо за тестирование. Это очень странно. Обычно это может быть вызвано только столкновением в многомастерной шине. howMany - это количество допустимых байтов, ожидающих в буфере. Когда вы читаете больше, чем количество допустимых байтов, Wire.read возвращает -1. У меня кончились идеи. Это все еще может быть аппаратная проблема, у вас есть подтягивающие резисторы ? Мое лучшее предположение заключается в том, что это проблема в проволочной библиотеке для Нуля. Я могу найти ряд проблем с Wire library для Arduino Zero / Feather M0 / Arduino M0 (все ATSAMD21G)., @Jot

Я сделал еще несколько тестов. Подтягивания есть, около 2 Ком. Я сделал первый тест с 10 передачами, без howMany. Данные были случайно неправильными в серийном отпечатке, но все хорошо на логическом анализаторе! [код и result](https://github.com/kb-/Arduino-I2C-2way-anydata/tree/cb5ea4863f77e6eb323db0bbd84c01d5734e1fd9) Затем я сделал еще один тест с 10000 передачами, с howMany. Любая одиночная передача была хороша как в последовательной печати, так и в логическом анализаторе. [код и result](https://github.com/kb-/Arduino-I2C-2way-anydata/tree/b8525944b4ef0c0166e8c4d66c1b1bcf2adbd2cb). Меня смущает 1-й результат!, @kb_

Для меня это означает, что проводная библиотека иногда запускает receiveEvent, когда нет никаких входящих данных. Это не большая проблема, так как в шине нет неправильных данных или столкновений., @kb_

Вам нужно протестировать его на частоте 100 кГц. Если вы можете сделать то же самое на частоте 100 кГц, то я предлагаю предположить, что это ошибка в библиотеке, и вы должны обойти ее. Возможно, receiveEvent иногда случайно вызывается, когда транзакция I2C только началась. Когда Мастер запрашивает данные, Мастер должен отправить NAK в конце, но это не так. Я читал, что при записи регистра в ведомое устройство с последующим чтением этого регистра иногда требуется короткая задержка (1 мс) между Wire.endTransmission и Wire.requestFrom. Это означает, что уже есть три вещи, которые нужно улучшить для библиотеки проводов SAMD21., @Jot

Он ведет себя так же на частоте 100 кГц. Я вижу НАКА только в конце чтения, перед остановкой с логическим анализатором. Обходной путь howMany позволил осуществить передачу со 100% успехом. Спасибо за все ваши советы. Добавление других предложенных вами тестов плюс повторные попытки при столкновениях позволило использовать код для 2-полосной передачи с несколькими мастерами., @kb_