Подключение N-датчиков MPU6050

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем Mihay, 18 янв 2016.

  1. Mihay

    Mihay Гик

    Подскажите пожалуйста, как считать данные с одинаковых датчиков MPU6050, в количестве N штук? (N>1). С одним датчиком по шине I2C все понятно, примеров куча, а вот с N одинаковыми датчиками - не нашел. Желательно код! Заранее благодарен!
     
  2. ANV

    ANV Гуру

    У MPU6050 есть только один адресный вход, это значит на шине может быть максимум две микросхемы.
    Т.е. на одной i2c только два MPU6050. Варианты:
    - взять MPU6000. У нее SPI.
    - сделать програмный i2c. Понадобится (N+1)/2 шин
     
  3. Mihay

    Mihay Гик

    Про SPI слышал, но ничего не знаю толком. Как программировать на шине SPI? Хотя бы обзор?
     
  4. ANV

    ANV Гуру

  5. Mihay

    Mihay Гик

    Написал код для двух устройств. С одного устройства получаем данные по SPI, другому отправляем данные. Возникли два вопроса:
    1. В функции приема данных Slave -> Master: int recvSlave(void) - правильно ли я принимаю данные функцией: SPI.transfer(reg)? Меня терзают смутные сомнения: transfer - переводится как передача. В библиотеке SPI.h не нашел функции типа приема, похожее на слово receive.
    2. В функции loop() если данных от Slave не будет: int data = recvSlave(), то не зависнет ли ПО в этом месте? Если зависнет, как сделать ожидание в функции recvSlave(void)?
    Заранее благодарен!!!

    Код (C++):
    #include <SPI.h>

    int SS1 = 9;  // Master -> Slave
    int SS2 = 10; // Slave -> Master
    void setup()
    {
      // режимы PIN
      pinMode(SS1, OUTPUT);
      pinMode(SS2, OUTPUT);
      // инициализациz SPI
      SPI.begin();
    }

    // посылка данных Master -> Slave
    void sendSlave(int reg)
    {
      digitalWrite(SS1, LOW);
      SPI.transfer(reg);
      digitalWrite(SS1, HIGH);
    }

    // прием данных Slave -> Master
    int recvSlave(void)
    {
      int reg;
      digitalWrite(SS2, LOW);
      SPI.transfer(reg);
      digitalWrite(SS2, HIGH);
      return reg;
    }

    void loop()
    {
      int data = recvSlave(); // что будет если данных от устройства нет?
      sendSlave(data);
    }
     
  6. ANV

    ANV Гуру

    Зависания не будет, это из принципа работы SPI.
    SPI по сути - это сдвиговый регистр. Тактовый сигнал говорит что ведомому надо принять очередной бит, по окончании тактового сигнала, ведущее устройство не "ждет" чего-то, а смотрит на состояние линии и приписывает очередной бит к принимаемому байту.
     
  7. Mihay

    Mihay Гик

    Еще один вопрос: Если обмен данными идет по принципу: Master <---> Slave, т.е. существуют только два устройства, которые обмениваются между собой по каналам MOSI и MISO. Канал SS у них один.
    Код (C++):
    int reg;
    digitalWrite(SS, LOW);
    SPI.transfer(reg);
    digitalWrite(SS, HIGH);
     
    как я тут узнаю, переменная reg была отправлена или получена? Может для кого-то это смешно, но я суть не могу уловить, в предыдущем посте я писал про transfer. Помогите понять!
     
  8. ANV

    ANV Гуру

    SS у всех разный, этим пином выбирают с кем из slave сейчас будет общение. Общими являются MOSI и MISO. Выставлять два SS в low нельзя, т.к. оба ведомых переведут свой пин MISO из tri-state состояния (т.е. не low, не high, а болтающийся в воздухе) в активное. Если при этом один slave выставит свой MISO в low, а другой в high, то пины могут погореть, т.к. у одного ведомого открыт верхний ключ на 5 вольт, у другого нижний на землю и получается короткое замыкание через микросхемы.

    Теперь про reg и SPI.transfer
    Тут есть два момента: логика работы SPI и момент в языке Си
    Про SPI: представьте трубу длиной 8см и шарики сантиметровые белые и черные. Белый - ноль, черный - единица. Изначально, в трубе 8 шариков уже есть.
    Вы разложили с одной стороны свои шарики и заталкиваете их в трубу все 8 штук по одному при помощи SPI.transfer. Ваши в трубу закатываются, при этом из трубы с другой стороны шарики выталкиваются, причем внутри трубы они могли быть перекрашены. У вас вылезло 8 шариков - это принятые данные.
    Т.е. с точки зрения железа нет разницы между чтением и записью.

    По Си: в вашем примере вы переслали reg в SPI, но результат, который вернула функция SPI.transfer не сохранили. Если написать reg = SPI.transfer(reg); то вы передадите reg в SPI, а принятый результат вернется в reg
     
  9. Mihay

    Mihay Гик

    Спасибо за хорошии ответы. Я понял, что в recv = SPI.transfer(send) одновременно я могу послать с Ардуино send и принять в Ардуино recv. Про трубу вообще молчу, гениальное объяснение. Спасибо еще раз, но хотел бы кое-что уточнить:
    MPU6000 или MPU6050 представляют собой датчики и гироскопа и акселерометра. Они могут передавать (гироскоп) большие значения, которые в один байт не влезут. Передача данных на шине SPI в Ардуино ограничено одним байтом? Есть ли выход из этого положения - передавать 2 байта по SPI?
    PS: Может быть MPU60x0 вообще не может передать значения более 1 байта?
     
  10. ANV

    ANV Гуру

    Пока пин SS в low - это все одна транзакция по шине SPI.
    Т.е. выставили SS в low, послали команду, послали данные, вернули SS в HIGH

    стр 38: http://www.seeedstudio.com/wiki/images/b/b1/MPU6050.pdf
    Псевдопример (без учета какие там реально регистры):
    - запись в регистр 0x33h байт 0x44, для этого SS = low, посылаем 0x33, 0x44, SS = high
    - чтение из регистра 0x12: SS = low, посылаем 0x92, 0x00, SS = high тут при чтении первый байт 0x92, а не 0x12 потому что первй бит номера регистра должен быть 1, если это чтение. Второй байт может быть каким угодно, т.к. мы им просто выталкиваем данные. То что вернет SPI transfer от первого байта надо откинуть, т.к. устройство выталкивало данные еще не зная что за команда, а вот ответ со второго байта и есть считанные данные
     
  11. Mihay

    Mihay Гик

    Можно ли кусок кода на скетче, где затрагивается прием recv = SPI.transfer(send). Что-то бьюсь и никак не пойму! E меня тип возвращаемого значения recv - double. я так понимаю что я должен 9 раз вызвать recv = SPI.transfer(send), первый байт отбросить, а остальные объединить оператором &...? Пожалуйста небольшой примерчик кода, как использовать recv = SPI.transfer(send) для приема переменной типа double! Если double нельзя использовать, то другой многобайтовый прием через recv = SPI.transfer(send).
     
  12. ANV

    ANV Гуру

    А откуда у вас берется double? Регистр внешней микросхемы или другая Ардуина?
     
  13. Mihay

    Mihay Гик

    MPU6000 - Гироскоп + Акселерометр. Честно говоря, я не нашел что он выдает на SPI. По идее должен быть doublе. Если нет, тогда поправьте. Я подключал Тройка модули по I2C - там были double.
     
  14. ObelardO

    ObelardO Нерд

  15. Onkel

    Onkel Гуру

    Отнюдь. Мы можем работать по i2c с одной из множества подключенных при условии, что на остальных адресный вход выставлен в 0. А то, что на другом адресе висит n-1 слейвов, никого не волнует- на нашем адресе только один отвечающий слейв. Потом перещелкиваем адресные входы и работаем со следующим и т.д. Только успевай переключать - бортовой вычислитель Mpu успевает все посчитать за 10 мс