Raspberry PI 3 + OpenCV + Arduino UNO + ......(поледнее решение и вопрос в последнем сообщении)

Тема в разделе "Флудилка", создана пользователем Igor68, 21 ноя 2016.

  1. Un_ka

    Un_ka Гуру

    На картинке пиксели на карте размытые, значит имело место обработка. Сжатие происходит не уменьшением размера, а ужасно сложными алгоритмами.
    Насчёт пятна и карты, пока что имею это.
    Screenshot_2020-05-13-12-54-58.png
    Так, по-моему наглядней.
     
    Igor68 нравится это.
  2. Igor68

    Igor68 Гуру

    По поводу пятна: Согласно диаграммы направленности на определённой дистанции отраженный сигнал будет находиться в радиусе (я строил вручную по картинке из документации) от предполагаемой "идеальной" точки (пеленг и дистанция). Эти параметры передаются собственно программой sonar (на малине, которая получает дистанцию по I2C), которая передаёт эти данные(дистанция, тот самый определённый радиус) на сервер. Пеленг (состояние сервомашин) передаёт программа servoANDmotor(на этой же малине, которая по USB-SERIAL обменивается с ардуиной) на сервер. Программа xDmap на другой малине (сейчас для теста заменена на приложение в ноутбуке) принимает от сервера данные (пеленг, дистанция, радиус пятна), а так же формирует управление и передаёт это на сервер (параметры управления потом забирает программа servoANDmotor на первой малине). В связи с такой схемой у меня просто нет сил и времени делать наглядность в QT приложении на ноутбуке. Тем более что это только отработка правил, которые будут перенесены в программу xDmap на второй малине. А по ходу надо пилить ещё и сам сервер (ведь формат передаваемых данных и правила обмена так же меняются)
     
    Последнее редактирование: 28 май 2020
  3. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Есть ли у кого опыт вращения карты вокруг точки на ней? Рассматривал возможность вращения массива, но есть одно но... а именно поворот на 90 градусов нормально. Мне же надо вращать на любой угол. Смысл в том что при развороте машинки надо знать истинное положение разворота. Предполагаю после разворота вращать карту вокруг точки (положения на карте) и после нового сканирования привязаться к "определяющим" точкам на этой карте. Таким образом знать местоположение.
    Спасибо заранее!
     
  4. Un_ka

    Un_ka Гуру

    Дак полярные координаты в помощь. Не повёрнутая карта и повёрнутая карта должны быть в двух разных массивах, причём размер массива повёрнутой карты должен равняться диагонали не повёрнутой. Как искать определяющие точки я уже писал.
     
  5. Igor68

    Igor68 Гуру

    Спасибо за отклик! Полярные координаты сейчас пробую... думал есть что-то иное.
     
  6. Igor68

    Igor68 Гуру

    snapshot67.png
    Это после сканирования
    snapshot68.png
    Это после поворота на 45 гр.
    snapshot69.png
    Это поворот на - 45
    snapshot70.png
    Это поворот ещё на -45
    Вот функция (указывается карта и угол поворота):
    Код (C++):
    //вращение
    void MathRotate(DMAP1 *map1, int16_t angle)
    {
        DMAP1 mlmap;
        int16_t ang = 0;
        float dist;
        float x, y, xml, yml;
        //
        memset(&mlmap, 0, sizeof(DMAP1));
        while(ang < 360)
        {
            dist = 0.0;
            if(angle == 360) angle = 0;
            while(1)
            {
                x = dist * sin(angle * M_PI / 180.0) + _centrX;
                y = dist * sin((90 - angle) * M_PI / 180.0) + _centrY;
                xml = dist * sin(ang * M_PI / 180.0) + _centrX;
                yml = dist * sin((90 - ang) * M_PI / 180.0) + _centrY;
                if((x < 0) || (y < 0) || (xml < 0) || (yml < 0) ||
                (x > _szXDAarray) || (y > _szYDAarray) || (xml > _szXDAarray) || (yml > _szYDAarray))
                    break;
                mlmap.so[(int16_t)(xml)][(int16_t)(yml)] = map1->so[(int16_t)(x)][(int16_t)(y)];
                dist += 1.0;
            }
            angle++;
            ang++;
        }
        //
        memcpy(map1, &mlmap, sizeof(DMAP1));
    }
     
    Буду дальше пилить... надо научиться сравнивать... дабы определить угол. Вот бы ещё сначала выделять ключевые точки:confused:
     
    Последнее редактирование: 2 июн 2020
  7. Un_ka

    Un_ka Гуру

    То есть?
    При одном замере на 10 градусов у меня получилось вот это.
    Угол обзора 180°.
    Screenshot_2020-06-02-17-06-26-996_com.realvnc.viewer.android.jpg
    Screenshot_2020-06-02-17-11-48-244_com.realvnc.viewer.android.jpg
    Screenshot_2020-06-02-17-12-43-393_com.realvnc.viewer.android.jpg
    Думаю увеличить количество замеров до одного замера на 5 градусов. Белые круги это отображения касания на телефоне.
     
  8. Igor68

    Igor68 Гуру

    Вот уж не знаю что там у Вас за устройство(если оно сонар), если хотите уменьшить шаг до 5 градусов... В моём случае на дистанции в 234 см угол захвата (то самое пятно) 3,68 градусов, а при дистанции 51 см угол 14,19 градусов. Одним словом препятствие на этой дистанции может находиться в пределах этого пятна в любом его месте (на 51 см в пределах 14,19 градусов). Если я правильно выбрал методику расчёта. Я же не из-за болтовни говорил про диаграмму направленности. В моём случае шаг сканирования зависит от дистанции согласно диаграмме.
    Простите я на картинках совсем не понял что означает "отображение касания на телефоне"
     
    Последнее редактирование: 3 июн 2020
  9. Igor68

    Igor68 Гуру

    В моём случае каждый "пиксель" имеет вес. При сканировании если на месте пикселя есть что-то то его вес увеличивается на 15 иначе уменьшается на 15. Вес пикселя может быть 0...255. Каждый пиксель может менять вес при сканировании в диапазоне "пятна" (угла захвата по диаграмме направленности для измеренной дистанции). Так же следует учитывать что пятно не только по горизонтали, но и по вертикали. Сейчас пытаюсь строить не трёхмерную, а плоскую карту.
     
  10. Un_ka

    Un_ka Гуру

    Так как звук - волна. Я думаю можно попробовать сделать насадку на излучатель ультразвуковых волн, чтобы уменьшить размер пятна.
    Я использую HC-SR04.
    Вот его диаграмма направленности.
    10 дюймов= 25см.

    HC-SR04_polar_pattern.png
     
  11. Igor68

    Igor68 Гуру

    Если посмотреть пост этой темы:
    http://forum.amperka.ru/threads/raspberry-pi-3-opencv-arduino-uno-поледнее-решение-и-вопрос-в-последнем-сообщении.10001/page-10#post-114921
    Я использовал эти самые параметры.
    Если бы я был заинтересован в принципе действия сонара и рассмотрения волновых теорий, то не создавал этой темы.
    Я был намерен купить готовое изделие и применять. Сейчас занимаюсь возможностью применения данного изделия для ориентации, построения карты и пр.

    PS: к сожалению в шапку где только голосование я не могу выкладывать то что нужно включая модернизацию кода и результаты обсуждения.
     
  12. Igor68

    Igor68 Гуру

    вот как не гуд вышло! а именно: время от времени ардуина виснет... вот и морду машинка себе разбила. как? а вот так:
    - ардуина повисла.
    - малина продолжала подавать сигнал "все приводы в ноль"
    - повисшая ардуина не выдавала по I2C шилдам нулевое задание
    раньше (просто отладка) не обращал внимания. сбрасывал на плате (ардуина) кнопку "res", после чего работа полностью восстанавливалась. разбила об стену камеру... да нет не камеру, а прищепку крепления штатную. всё остаётся работоспособным. но не очень приятно... камера сейчас на двухстороннем скотче. пилю устойчивость работы ардуины. Думаю что бы применить. Пусть зараза перезапускается что ли. ну не руками нажимать же.
    Питание цепей ардуины от малины по USB-SERIAL. Малина ведь не висит. силовые цепи разделены от питания контроллера кроме общего(GND). тупо где перерезал дорожки, где навесным проводом. шилд "мультисерво" своими светодиодами показывает что всё отдельно при подачи питания автономно. хотя понимаю что контроллер без питания при подаче на силовые цепи не красиво. может надо какой программный вариант применить? знаю что код ардуины надо попилить... может и внешний сброс делать (при потере связи малина материт):
    Код (Text):
    receive ansver CMD16 error! ...dev: 1  addr: 64
    receive ansver CMD3 error! ...dev: 1  addr: 64
    receive ansver CMD16 error! ...dev: 1  addr: 48
    receive ansver CMD3 error! ...dev: 1  addr: 48
    receive ansver CMD16 error! ...dev: 1  addr: 64
    receive ansver CMD3 error! ...dev: 1  addr: 64
    receive ansver CMD16 error! ...dev: 1  addr: 48
    receive ansver CMD3 error! ...dev: 1  addr: 48
    receive ansver CMD16 error! ...dev: 1  addr: 64
    receive ansver CMD3 error! ...dev: 1  addr: 64
    receive ansver CMD16 error! ...dev: 1  addr: 48
    receive ansver CMD3 error! ...dev: 1  addr: 48
     
    В принципе всё штатно, кроме ардуины.
    После сброса ардуины (кнопка "res" всё восстанвливается)
     
    Последнее редактирование: 15 июн 2020
  13. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Вот имею (уже давно) малину B+ ещё первую. Она приклеена к роутеру двухсторонним скотчем и к нему же подключена по ETHERNET. Всё в порядке... на ней поднят вэб сервер Apache. Делаю страничку на ней для продолжения опытов.
    Вопрос в том, можно ли работать с двоичным дампом на PHP со стороны сервера и в JS на стороне браузера. Если можно то как?
    Или надо через JSON только. PHP со стороны сервера должен работать с бинарным файлом через /dev/shm и с ним же код на Си на этой же малине. Уж больно не хочется делать бестолковые преобразования. Все имеющиеся малины в сети работают в обмене по одной сети в бинарном режиме... хочу и эту подключить - а то только погода из интернета и прочее барахло.

    Жаль что если нельзя придётся делать JSON со стороны Си:confused:
    Спасибо заранее!
     
    Последнее редактирование: 14 мар 2021
  14. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Вот решил снова достать зверька - время пришло. Ну и докурить управление платой ComMotion, а именно чтение статуса по I2C. Если с ардуины посылаем шилду запрос статуса:
    Код (C++):
    //------ Status Request can be directed to MCU 1 or MCU 2 ----------------------------------------------------------

    void ComMotionStatus(byte mcu, byte request) // value for mcu must be 0 or 1. Each bit of the request byte is a separate request.
    {
      Wire.beginTransmission(COMMOTION_ADDR + COMMOTION_OFFS + mcu);  // Initialize I²C communications with ComMotion shield MCU 1 or 2
      Wire.write(6);                             // Specify that data packet is a status request
      Wire.write(request);                       // Each bit of the request byte returns a different status report
      Wire.endTransmission();                    // transmit data from I²C buffer to ComMotion shield
    }
    то тут всё понятно, шилд занимет два адреса I2C.
    И в шилде понятно с точки зрения приёма(хоть и надо покурить):
    Код (C++):
    //--- тут сначала в Setup() ---
        Wire.begin(address);                                                        // initialize I²C library and set slave address
        Wire.onReceive(I2C_Receive);                                                // define I²C slave receiver ISR
        Wire.onRequest(I2C_Send);                                                   // define I²C slave transmit ISR
        Wire.setTimeout(1L);                            // sets a timeout of 1mS for I²C.

    //а потом в функции
    void I2C_Receive(int bytes)            // received command as I²C slave    
    {
        for(byte i=0;i<bytes;i++)                                
            datapack[i]=Wire.read();    // transfer data from I²C buffer to datapack
     
        command=datapack[0];
        packsize=bytes;
        if(mode==1 && command<5)
        {
            mode=0;                // disable demo mode
            EEPROM.write(1,mode);
        }
     
       
          //------------------------------------------------------------ demo syncronization ---------------------------------------------------------
        if(command==15 && packsize==3)
        {
            EEPROM.write(0,datapack[1]);    // only update EEPROM if necessary
            EEPROM.write(1,datapack[2]);    // only update EEPROM if necessary
       
            demo=datapack[1];
            mode=datapack[2];
       
            command=255;
            return;
          }
     
        if(command==7 && packsize==3)  //============================= Demo Modes Angle Update ======================================================
        {
            angle=datapack[1]*256+datapack[2];
            Trigonometry();
            command=255;
            return;
        }
    }
    Но вот посылка шилдом ответа:
    Код (C++):
            byte returnaddress=master;                                               // return address is I²C master by default
            if((request&127) && mcu==0) returnaddress=address+1;                     // bit 7 indicates internal request - return to other processor
            if((request&127) && mcu==1) returnaddress=address-1;                     // bit 7 indicates internal request - return to other processor
       
            Wire.beginTransmission(returnaddress);
            Wire.write(sendpack,spsize);
            Wire.endTransmission();
            command=255;
    Меня загоняет в ступор... в плане того, что шилд не отвечает в запросе, а по некому адресу returnaddress. Это что ведущий должен иметь тоже адрес? Никак не привыкну к тому что I2C вовсе не I2C, а что-то иное. В чём я туплю?
    Вот тестовый код:
    Код (C++):
    if(CMCU == 0) {
            switch(cntresp) {
                case 0:    //
                    rdtype        = 0x08;
                    rdtypesz    = 6;
                    rds        = &rd[0];
                    ComMotionStatusRd(CMCU, rdtype, rds, rdtypesz);
                    break;
                default:
                    //cntresp = 0;
                    //rdtypesz    = 0x10;
                    break;
            }
            //ComMotionStatusRd(CMCU, rdtype, rds, rdtypesz);
            CMCU++;
        } else {
            switch(cntresp) {
                case 0:
                    rdtype         = 0x10;
                    rdtypesz    = 6;
                    rds        = &rd[6];
                    ComMotionStatusRd(CMCU, rdtype, rds, rdtypesz);
                    break;
                default:
                    //cntresp = 0;
                    break;
            }
            //ComMotionStatusRd(CMCU, rdtype, rds, rdtypesz);
            CMCU = 0;
        }
        Serial.print("00 ");Serial.print(rd[0]);Serial.print("\n");
        Serial.print("01 ");Serial.print(rd[1]);Serial.print("\n");
        Serial.print("02 ");Serial.print(rd[2]);Serial.print("\n");
        Serial.print("03 ");Serial.print(rd[3]);Serial.print("\n");
        Serial.print("04 ");Serial.print(rd[4]);Serial.print("\n");
        Serial.print("05 ");Serial.print(rd[5]);Serial.print("\n");
        Serial.print("------------\n");
        delay(1000);
    А это моя бестолковая тестовая функция приёма:
    Код (C++):
    void ComMotionStatusRd(byte mcu, byte request, byte* rd, byte sz)
    {
        int    cnt = 0;
        Wire.beginTransmission(COMMOTION_ADDR + COMMOTION_OFFS + mcu);  // Initialize I²C communications with ComMotion shield MCU 1 or 2
        Wire.write(6);                             // Specify that data packet is a status request
        Wire.write(request);                       // Each bit of the request byte returns a different status report
        //Wire.endTransmission();                    // transmit data from I²C buffer to ComMotion shield
        //
        //Wire.requestFrom(COMMOTION_ADDR + COMMOTION_OFFS + mcu, sz);
        //Wire.requestFrom(1, sz);
        while(cnt < sz) {
            (*(byte*)(rd + cnt)) = Wire.read();
            cnt++;
        }
        Wire.endTransmission();
    }
    Это просто тест и вот что принимаю:
    Код (C++):
    ------------
    00 255
    01 255
    02 255
    03 255
    04 255
    05 255
    ------------
    00 0
    01 0
    02 0
    03 0
    04 0
    05 0
    ------------
     
  15. Igor68

    Igor68 Гуру

    И что никто не делал запрос к ведомым по I2C, что бы получить ответ от него? Ведь тут I2C вовсе не I2C в прямом понимании. Сделали I2C по своему - с потолка! И никто нормально примера применения функций Wire не приведёт? Я не прошу готовый ответ...
    Этот пример относится к нормальному I2C:
    https://all-arduino.ru/arduino-dlya-nachinayushhih-urok-11-interfejs-i2c/
    В моём случае ведомый отвечает:
    Код (C++):
    Wire.beginTransmission(returnaddress);
            Wire.write(sendpack,spsize);
            Wire.endTransmission();
    То есть ведущий должен стать ведомым - returnaddress
    Лучше бы не уродовали I2C и не делали из него непонятно что.
     
    Последнее редактирование: 1 ноя 2021
  16. Un_ka

    Un_ka Гуру

    Та вроде можно обратится
    Код (C++):
    Wire.write(reg);
    и получить ответ. Или записать значение в регистр и получить ответ.
    Или и то и то, но вместо получения ответа считать данные с какого-то регистра.
     
  17. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Я так и обращаюсь, когда посылаю ведомому параметр/команду всё работает. Но мне надо подать команду ведомому вот этим:
    Код (C++):
    //------ Status Request can be directed to MCU 1 or MCU 2 ----------------------------------------------------------

    void ComMotionStatus(byte mcu, byte request) // value for mcu must be 0 or 1. Each bit of the request byte is a separate request.
    {
      Wire.beginTransmission(COMMOTION_ADDR + COMMOTION_OFFS + mcu);  // Initialize I²C communications with ComMotion shield MCU 1 or 2
      Wire.write(6);                             // Specify that data packet is a status request
      Wire.write(request);                       // Each bit of the request byte returns a different status report
      Wire.endTransmission();                    // transmit data from I²C buffer to ComMotion shield
    }
    А он (ведомый) отвечает этим:
    Код (C++):
    Wire.beginTransmission(returnaddress);
    Wire.write(sendpack,spsize);
    Wire.endTransmission();
    То есть он активирует передачу какому-то (наверное ведущему) адресу. А ведущий в это время должен бросить шину I2C, потому как он уже ведомый. Это не я придумал, это в исходниках ComMotion driver fo 4 motors Всё работает, но хочу читать показания от шилда которые реализованы в нём (ток каждого двигателя, напряжение питания для двигателей, значения энкодеров каждого двигателя). Вот и хочу к нему обратиться по I2C и судя по исходникам он отвечает. Так сигнал SCL должен быть от кого? И ведущий - он вовсе и совсем не ведущий? А I2C он точно I2C в этом случае? Или надо включать/выключать I2C в процессе работы?
     
  18. Igor68

    Igor68 Гуру

    Мне бы хватило такого... типа:
    1 - ведущий стартует I2C как ведущий и выполняет запрос и сразу активирует I2C как ведомый с неким адресом
    2 - ведомый получив запрос стартует I2C как ведущий и выдаёт ответ по некому адресу после чего переводит I2C как ведомый
    3 - настоящий ведущий получив ответ переключает I2C как ведущий для посылки нового запроса
    ...и так далее
    Вот такой пример я и хотел увидеть. Сразу говорю, что это не I2C как таковой.
    Спасибо!

    PS: сейчас хочу перепилить исходники ComMotion driver for 4 motors для контроля(управления) не по PWM, а по току каждого двигателя, что в принципе умеет данный шилд - а энкодеры в удобном для конструкции исполнении пока не подобрал. Шилд с 4-мя энкодерами работать умеет, надо только конфигурацию при старте указать. Ток каждого двигателя шилд так же измеряет.
     
  19. Igor68

    Igor68 Гуру

    Всё это в моём случае довольно кропотливо:
    1) снимаем с "бутерброда" Multisetvo
    2) устанавливаем джампер RST на плату ComMorion
    3) Переключаем переключатель MCU1 на плате ComMotion
    4) Подключаемся по WIFI по SSH (с ключом -X ) к малине 3 (она нижняя в "бутерброде")
    5) монтируем NFS диск на малину (где исходники) то же по WIFI
    6) запускаем Arduino IDE на малине и прошиваем MCU1 по "Upload Using Programmer" через Arduino UNO R3(следующая от малины в "бутерброде")
    7) Переключаем переключатель MCU2 на плате ComMotion
    8) Прошиваем MCU2 на плате ComMotion как в П.6.
    9) Устанавливаем переключатель MCU на плате ComMotion в нейтральное положение
    10) Прошиваем Arduino UNO R3 тестовой прошивкой
    11) Запускаем на малине тестовую программу для проверки
    Ради информацию - доступ ко всему затруднительный... и удобно прошивать только саму Arduino, но не шилды что на ней.
    Потому и спрашиваю про те вопросы на которые времени точно не хватает.
    В данном случае интересует именно опрос шилда по I2C, потому как в него писать параметры и команды проблем нет. Хотел опираясь на библиотеку Wire изменить кое что.
    - Есть передача в шилд и вопросов нет
    - Есть функция запроса получить параметр в количестве N байт, но нет в этом запросе имени(номера) параметра Использовать номер параметра в теле адреса шилда - выскакиваем в конфликт - шилд имеет два адреса, потому как на нём два MCU и каждый сидит на I2C... да ещё и DIP перекючатель выбирает адреса для обоих MCU в комплексе.

    PS: а Вы я так понял подумали что мне "курить" нет желания. Ведь вами обкатана эта Wire неужели не выбирали по адресу из устройства по адресу на шине? Я не применял нестандартный I2C - не скрываю.
     
  20. Igor68

    Igor68 Гуру

    сколько не ковырялся а это:
    Код (Text):
    CMCU:0  RS:6
    00 0
    01 255
    02 255
    03 255
    04 255
    05 255
    06 0
    07 255
    08 255
    09 255
    10 255
    11 255
    ------------
    CMCU:1  RS:6
    00 0
    01 255
    02 255
    03 255
    04 255
    05 255
    06 0
    07 255
    08 255
    09 255
    10 255
    11 255
    ------------
     
    тут идёт чтение то из одного устройства, то из другого с записью 6 принятых байт в один массив (в одном случае в адреса 0...5 в другом 6...12) - как видно не работает.
    И что только не делал... (по комментарию в коде видно что испытывал всякое):
    инициализация на ведущем:
    Код (C++):
        //Wire.begin ();                    // Required to support I2C communication
        Wire.begin(_Myaddress);            // initialize I²C library and set slave address
        Wire.onReceive(receiveEvent);           // register event
        //Wire.onRequest(I2C_Send);            // define I²C slave transmit ISR
         Wire.setTimeout(5L);                // sets a timeout of 5mS for I²C.
    и запрос к ведомому:
    Код (C++):
    byte ComMotionStatusRd(byte mcu, byte request, byte* rd, byte sz)
    {
        int    cnt = 0;
            byte    rs;
        //Wire.beginTransmission(COMMOTION_ADDR + COMMOTION_OFFS + mcu);  // Initialize I²C communications with ComMotion shield MCU 1 or 2
        //Wire.write(6);                             // Specify that data packet is a status request
        //Wire.write(request);                       // Each bit of the request byte returns a different status report
        //Wire.endTransmission();                    // transmit data from I²C buffer to ComMotion shield
        //
            //delay(10);
        Wire.requestFrom(COMMOTION_ADDR + COMMOTION_OFFS + mcu, sz);
            Wire.write(6);                             // Specify that data packet is a status request
        Wire.write(request);                       // Each bit of the request byte returns a different status report
        //Wire.requestFrom(1, sz);

            //rs = Wire.available();
        //while(cnt < rs) {
        //while(Wire.available()) {
        //    (*(byte*)(rd + cnt)) = Wire.read();
        //    cnt++;
        //}
        //Wire.endTransmission(); */
            while(cnt < datapackCnt) {
              (*(byte*)(rd + cnt)) = datapack[cnt];
              cnt++;
            }
            return cnt;
    }
    --НЕ забывайте про комментарии - это разные попытки.
    А ведомые между тем по исходникам отвечают этим:
    Код (C++):
            Wire.beginTransmission(returnaddress);
            Wire.write(sendpack,spsize);
            Wire.endTransmission();
    И что самое важное ведомые исполняют команды - моторы управляются. А вот параметры (значения АЦП и прочее) ведущий получить не может. Шина I2C реализован в шилдах изначально - оба (ComMotion driver for 4 motors и Multiservo) сидят на I2C. Сейчас Multiservo демонтирован дабы не отвлекать, да и читать с него ничего не надо.
    Курю библиотеку Wire думаю что может быть. Осциллографа нет, да если и был бы думаю туда в конструкцию не подлезть... да и глазам задница. Судя по принятым отчётам (сделал для отладки) байт 0 равен 0 наверное на шине SDA низкий уровень, а остальные 255... наверное уровень поднялся... а в это время ведущий по идее уже ведомый (исходя из кода передачи настоящего ведомого - он на время вроде становится ведущим). Глупая реализация I2C чем-то напоминает ISO7616-3 обмена для SIM карт в мобильниках и спутниковых ресиверах. В моём случае хотел просто реализовать функции чтения статуса моторов от шилда. Дальше, даже если ставить энкодеры ни моторы всё равно надо читать... в шилде работа с энкодерами реализована.