Подскажите пожалуйста, как считать данные с одинаковых датчиков MPU6050, в количестве N штук? (N>1). С одним датчиком по шине I2C все понятно, примеров куча, а вот с N одинаковыми датчиками - не нашел. Желательно код! Заранее благодарен!
У MPU6050 есть только один адресный вход, это значит на шине может быть максимум две микросхемы. Т.е. на одной i2c только два MPU6050. Варианты: - взять MPU6000. У нее SPI. - сделать програмный i2c. Понадобится (N+1)/2 шин
Написал код для двух устройств. С одного устройства получаем данные по 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); }
Зависания не будет, это из принципа работы SPI. SPI по сути - это сдвиговый регистр. Тактовый сигнал говорит что ведомому надо принять очередной бит, по окончании тактового сигнала, ведущее устройство не "ждет" чего-то, а смотрит на состояние линии и приписывает очередной бит к принимаемому байту.
Еще один вопрос: Если обмен данными идет по принципу: Master <---> Slave, т.е. существуют только два устройства, которые обмениваются между собой по каналам MOSI и MISO. Канал SS у них один. Код (C++): int reg; digitalWrite(SS, LOW); SPI.transfer(reg); digitalWrite(SS, HIGH); как я тут узнаю, переменная reg была отправлена или получена? Может для кого-то это смешно, но я суть не могу уловить, в предыдущем посте я писал про transfer. Помогите понять!
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
Спасибо за хорошии ответы. Я понял, что в recv = SPI.transfer(send) одновременно я могу послать с Ардуино send и принять в Ардуино recv. Про трубу вообще молчу, гениальное объяснение. Спасибо еще раз, но хотел бы кое-что уточнить: MPU6000 или MPU6050 представляют собой датчики и гироскопа и акселерометра. Они могут передавать (гироскоп) большие значения, которые в один байт не влезут. Передача данных на шине SPI в Ардуино ограничено одним байтом? Есть ли выход из этого положения - передавать 2 байта по SPI? PS: Может быть MPU60x0 вообще не может передать значения более 1 байта?
Пока пин 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 от первого байта надо откинуть, т.к. устройство выталкивало данные еще не зная что за команда, а вот ответ со второго байта и есть считанные данные
Можно ли кусок кода на скетче, где затрагивается прием recv = SPI.transfer(send). Что-то бьюсь и никак не пойму! E меня тип возвращаемого значения recv - double. я так понимаю что я должен 9 раз вызвать recv = SPI.transfer(send), первый байт отбросить, а остальные объединить оператором &...? Пожалуйста небольшой примерчик кода, как использовать recv = SPI.transfer(send) для приема переменной типа double! Если double нельзя использовать, то другой многобайтовый прием через recv = SPI.transfer(send).
MPU6000 - Гироскоп + Акселерометр. Честно говоря, я не нашел что он выдает на SPI. По идее должен быть doublе. Если нет, тогда поправьте. Я подключал Тройка модули по I2C - там были double.
Отнюдь. Мы можем работать по i2c с одной из множества подключенных при условии, что на остальных адресный вход выставлен в 0. А то, что на другом адресе висит n-1 слейвов, никого не волнует- на нашем адресе только один отвечающий слейв. Потом перещелкиваем адресные входы и работаем со следующим и т.д. Только успевай переключать - бортовой вычислитель Mpu успевает все посчитать за 10 мс