В смысле не на одном датчике: Берём первый hmc5883l подключаем n контакт к земле адрес изменился на единичку меньше, другой магнитометр подключаем как обычно питание и sda scl и всё (адрес остался как был по умолчанию), третий подключаем n контакт к питанию (например 3.3v). Так на моём hmc5983l т.к. они схожи думаю и на hmc5883l должна быть анология.
датчики в разных модулях. Ни чего не понял.... Вы мне проговорили о 3-х датчиках.., А каким образом подключить 4 или к примеру 6 модулей... Им надо присвоить разные адреса... На примере трех вроде понятно.... а более?
Естественно а иначе зачем всё это? ХЗ может ещё есть функция изменения адреса, я знаю только как подключить 3 модуля а зачем мне больше?
Добрый день, вроде разобрался с модулем HMC5883L, а именно как подключить несколько штук к одной ардуинке. Соответственно замахиваюсь на модуль MPU 9250 и спрашииваю, а эти модули возможно подключать в нескольких количествах путем изменения адреса устройства? (возможно ли изменить адрес модуля?) Или остаются пути, такие как мультиплексер, несколько ардуинок и связь их в сеть, и освоенный мной способ изменения пинов SDA, SCL на шинеI2C?
Пришло две штучки MPU 9250,понимаю, что к одно плате можно подключить двумя способами . первыи по SPI., второи со специальнои библиотеки которая меняет пины для sda и scl. (второ способ я вроде как уже освоил) подключение по SPI- в целом ясна , но как управлятся с пином назначения того или иного порта - пока до конца не понял.. Что легче? И да планирую использовать предоставленныи код (измерения углов крена, тангажа, рысканья). Какои способ предпочтительнее? Такои и начну (продолжу) осваивать...
Это уж вам видней какой вам ближе (понятнее) тот и пробуйте SPI более скоростная шина предпочтительна за счёт меньших задержек при чтении/записи (+ при использовании 32бит плат можно считать сразу 16бит данных ) но придётся переписать код, с I2C всё проще я бы наверно его и выбрал т.к. мне было-бы лень что-то менять.
Вот теперь вопрос... подключить по I2C (к примеру 3 шт MPU 9250) - это хозяиство влезит на мини мегу? Т.к. если на три модуля, считаи код надо задублировать трижды... К стати там тоже надо менять..... и много... т.к. библиотека Wire - там не используется... все Wire переписывал на myWire1, myWire2 и т.д. сколько модулеи смотря... Но это ладно - я ж с этимразобрался и мне понятно что и как надо менять...Останется вопрос влезит ли Ваш код для трех модулеи. В недолеком будущем я пытался в Uno один засунуть, он не влез.... Влезет ли три на мини мегу?
Компьютеры и посей день были бы со шкаф размером еслиб все так рассуждали. А как у вас на компьютере могут быть абсолютно разные детали но вы же не переписываете ОС? Тем более там 3 одинаковых модуля программа должна опрашивать их последовательно либо по прерываниям но если вычислений много и время оно занимает больше чем частота ответов модуля можно с этим и не замачиваться ( это я к тому что у меня на меге 2560 частота фильтра была 145Гц в то время как датчик мог 250Гц соответственно смысла в прерываниях тут нет ).
Это Вы мне технологию SPI описали, а не по технологии I2C... Вот пример кода (рабочии) на подключение нескольких (двух) HMC5883L. Как видно что б менять пины подключения I2C,надо считаи два раза "код считывания прописать...). Т.е. все же получается надо осваивать SPI.. Или влезит код(с определениями углов) на 3 модуля по технологии I2C? Код (C++): #include <SoftwareWire.h> #define addr 0x0D //I2C Address for The HMC5883 SoftwareWire myWire1(4, 5); //4 sda and 5 scl SoftwareWire myWire2(6, 7); //6 sda and 7 scl const int knopka1=8; // кнопка №1 const int knopka2=9; // кнопка №2 int val=0; unsigned long L=250; int xx1; int yy1; int zz1; int xx2; int yy2; int zz2; static int mx1; static int my1; static int mz1; static int mx2; static int my2; static int mz2; void setup() { pinMode(knopka1, INPUT_PULLUP); pinMode(knopka2, INPUT_PULLUP); Serial.begin(9600); myWire1.begin(); myWire2.begin(); myWire1.beginTransmission(addr); //start talking myWire1.write(0x0B); // Tell the HMC5883 to Continuously Measure myWire1.write(0x01); // Set the Register myWire1.endTransmission(); myWire1.beginTransmission(addr); //start talking myWire1.write(0x09); // Tell the HMC5883 to Continuously Measure myWire1.write(0x1D); // Set the Register myWire1.endTransmission(); myWire2.beginTransmission(addr); //start talking myWire2.write(0x0B); // Tell the HMC5883 to Continuously Measure myWire2.write(0x01); // Set the Register myWire2.endTransmission(); myWire2.beginTransmission(addr); //start talking myWire2.write(0x09); // Tell the HMC5883 to Continuously Measure myWire2.write(0x1D); // Set the Register myWire2.endTransmission(); } void loop() { if(digitalRead(knopka1)==LOW) //проверка включена ли кнопка №1 { //Начало первого блока кода для чтения 1 датчика int x1, y1, z1; //triple axis data //Tell the HMC what regist to begin writing data into myWire1.beginTransmission(addr); myWire1.write((uint8_t)0x00); //start with register 3. myWire1.endTransmission(); //Read the data.. 2 bytes for each axis.. 6 total bytes myWire1.requestFrom(addr, 6); if (6 <= myWire1.available()) { x1 = myWire1.read(); //MSB x x1 |= myWire1.read() << 8; //LSB x z1 = myWire1.read(); //MSB z z1 |= myWire1.read() << 8; //LSB z y1 = myWire1.read(); //MSB y y1 |= myWire1.read() << 8; //LSB y } xx1=(mx1-x1)/L; mx1=x1; yy1=(my1-y1)/L; my1=y1; zz1=(mz1-z1)/L; mz1=z1; //Начало второго блока кода для чтения 2 датчика int x2, y2, z2; //triple axis data //Tell the HMC what regist to begin writing data into myWire2.beginTransmission(addr); myWire2.write((uint8_t)0x00); //start with register 3. myWire2.endTransmission(); //Read the data.. 2 bytes for each axis.. 6 total bytes myWire2.requestFrom(addr, 6); if (6 <= myWire2.available()) { x2 = myWire2.read(); //MSB x x2 |= myWire2.read() << 8; //LSB x z2 = myWire2.read(); //MSB z z2 |= myWire2.read() << 8; //LSB z y2 = myWire2.read(); //MSB y y2 |= myWire2.read() << 8; //LSB y } xx2=(mx2-x2)/L; mx2=x2; yy2=(my2-y2)/L; my2=y2; zz2=(mz2-z2)/L; mz2=z2; // Печать в порт Serial.print("E"); Serial.print(x1); Serial.print(","); Serial.print(y1); Serial.print(","); Serial.print(z1); Serial.print(","); Serial.print(xx1); Serial.print(","); Serial.print(yy1); Serial.print(","); Serial.print(zz1); //Serial.print(","); //Serial.print(x2); //Serial.print(","); //Serial.print(y2); //Serial.print(","); //Serial.print(z2); //Serial.print(","); //Serial.print(xx2); //Serial.print(","); //Serial.print(yy2); //Serial.print(","); //Serial.print(zz2); Serial.print("\n"); delay(L); } else { if(digitalRead(knopka2)==LOW) // нажали кнопочку #2 { val++; // прибавляем к переменной 1 при каждой смене цикла. delay(200); //небольшая защита от "дребезга" контактов кнопки if(val>=5) { Serial.print("REPER"); //Serial.print(val); val=0; // обнулили переменную delay(1000);//пауза } else { // ничего не делаем... } } else { val=0; // обнулили переменную } } }
Добрыи вечер, пытаюсь адаптировать код подключения двух MPU 9250.... с помощью библиотеки SoftwareWire.h иными словами заменяю пины Wire на другие SoftwareWire.h Код (C++): #include <SoftwareWire.h> SoftwareWire myWire1(4, 5); //4 sda and 5 scl SoftwareWire myWire2(6, 7); //6 sda and 7 scl Если сравнить данныи процесс с подключением двух HMC5883L (код выше в топике)(а там все понятно я можно сказать сам все сделал при помощи небольшои консультации), то возникает вопрос.. Необходимо все переменные продублировать? Иными словами SoftwareWire myWire1(4, 5); и прописать всю программу и SoftwareWire myWire2(6, 7); и прописать всю программу второи раз с дублированными переменными? В моеи программе есть константы #define потом массивы enum восьмибитные переменные uint8_t дествия void getMres() void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data) void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data) void transformation(float uncalibrated_values[3]) void setup() void loop() Соответственно далее деbствия... Так где надо менять? И дублировать переменные...? Код (C++): #include <Wire.h> #define MPU9250_ADDRESS 0x68 #define MAG_ADDRESS 0xC #define AK8963_ADDRESS 0xC #define AK8963_ST1 0x02 #define GYRO_FULL_SCALE_250_DPS 0x00 #define GYRO_FULL_SCALE_500_DPS 0x08 #define GYRO_FULL_SCALE_1000_DPS 0x10 #define GYRO_FULL_SCALE_2000_DPS 0x18 #define ACC_FULL_SCALE_2_G 0x00 #define ACC_FULL_SCALE_4_G 0x08 #define ACC_FULL_SCALE_8_G 0x10 #define ACC_FULL_SCALE_16_G 0x18 #define Pi 3,1415926 #define WHO_AM_I_MPU9250 0x75 enum Mscale { MFS_14BITS = 0, // 0.6 mG per LSB MFS_16BITS // 0.15 mG per LSB }; uint8_t Mmode = 0x06; uint8_t Mscale = MFS_16BITS; float aRes, gRes, mRes; float X ; float Y ; float Z ; void getMres() { switch (Mscale) { // Possible magnetometer scales (and their register bit settings) are: // 14 bit resolution (0) and 16 bit resolution (1) case MFS_14BITS: mRes = 10.*4912./8190.; // Proper scale to return milliGauss break; case MFS_16BITS: mRes = 10.*4912./32760.0; // Proper scale to return milliGauss break; } } // This function read Nbytes bytes from I2C device at address Address. // Put read bytes starting at register Register in the Data array. void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data) { // Set register address Wire.beginTransmission(Address); Wire.write(Register); Wire.endTransmission(false); // Read Nbytes Wire.requestFrom(Address, Nbytes); uint8_t index=0; while (Wire.available()) Data[index++]=Wire.read(); } // Write a byte (Data) in device (Address) at register (Register) void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data) { // Set register address Wire.beginTransmission(Address); Wire.write(Register); Wire.write(Data); Wire.endTransmission(); } float xv, yv, zv; //calibrated_values[3] is the global array where the calibrated data will be placed //calibrated_values[3]: [0]=Xc, [1]=Yc, [2]=Zc float calibrated_values[3]; //transformation(float uncalibrated_values[3]) is the function of the magnetometer data correction //uncalibrated_values[3] is the array of the non calibrated magnetometer data //uncalibrated_values[3]: [0]=Xnc, [1]=Ync, [2]=Znc void transformation(float uncalibrated_values[3]) { //calibration_matrix[3][3] is the transformation matrix //replace M11, M12,..,M33 with your transformation matrix data double calibration_matrix[3][3] = { {2195.878755, -32.093680, 6.147725},// Матрица пока не верная но уже работает! {-32.093680, 2372.162687, -7.654780}, {6.147725, -7.654780, 2407.630918} }; //bias[3] is the bias //replace Bx, By, Bz with your bias data double bias[3] = { 0.189463, -0.176225, 0.127606 }; //calculation for (int i=0; i<3; ++i) uncalibrated_values[i] = uncalibrated_values[i] - bias[i]; float result[3] = {0, 0, 0}; for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) result[i] += calibration_matrix[i][j] * uncalibrated_values[j]; for (int i=0; i<3; ++i) calibrated_values[i] = result[i]; } //vector_length_stabilasation() - is the function of the magnetometer vector length stabilasation (stabilisation of the sphere radius) float scaler; boolean scaler_flag = false; float normal_vector_length; void vector_length_stabilasation(){ //calculate the normal vector length if (scaler_flag == false) { getHeading(); normal_vector_length = sqrt(calibrated_values[0]*calibrated_values[0] + calibrated_values[1]*calibrated_values[1] + calibrated_values[2]*calibrated_values[2]); scaler_flag = true; } //calculate the current scaler scaler = normal_vector_length/sqrt(calibrated_values[0]*calibrated_values[0] + calibrated_values[1]*calibrated_values[1] + calibrated_values[2]*calibrated_values[2]); //apply the current scaler to the calibrated coordinates (global array calibrated_values) calibrated_values[0] = calibrated_values[0]*scaler; calibrated_values[1] = calibrated_values[1]*scaler; calibrated_values[2] = calibrated_values[2]*scaler; } // Initializations void setup() { // Arduino initializations Wire.begin(); Serial.begin(115200); // Configure gyroscope range I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_2000_DPS); // Configure accelerometers range I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_16_G); // Set by pass mode for the magnetometers I2CwriteByte(MPU9250_ADDRESS,0x37,0x02); // Request first magnetometer single measurement I2CwriteByte(MAG_ADDRESS,0x0A,Mscale << 4 | Mmode );//Mscale << 4 | Mmode } long int cpt=0; // Main loop, read and display data void loop() { // _______________ // ::: Counter ::: // Display data counter //Serial.print (cpt++,DEC); //Serial.print ("\t"); // ____________________________________ // ::: accelerometer and gyroscope ::: // Read accelerometer and gyroscope uint8_t Buf[14]; I2Cread(MPU9250_ADDRESS,0x3B,14,Buf); // Create 16 bits values from 8 bits data // Accelerometer int16_t ax=-(Buf[0]<<8 | Buf[1]); int16_t ay=-(Buf[2]<<8 | Buf[3]); int16_t az=Buf[4]<<8 | Buf[5]; // Gyroscope int16_t gx=-(Buf[8]<<8 | Buf[9]); int16_t gy=-(Buf[10]<<8 | Buf[11]); int16_t gz=Buf[12]<<8 | Buf[13]; // Display values //Accelerometer //Serial.print ("Значения акселерометра"); //Serial.print ("\t"); //Serial.print (ax,DEC); //Serial.print ("\t"); //Serial.print (ay,DEC); //Serial.print ("\t"); //Serial.print (az,DEC); //Serial.print ("\t"); //Gyroscope //Serial.print ("Значения гироскопа"); //Serial.print ("\t"); //Serial.print (gx,DEC); //Serial.print ("\t"); //Serial.print (gy,DEC); //Serial.print ("\t"); //Serial.print (gz,DEC); //Serial.print ("\t"); // _____________________ // ::: Magnetometer ::: //Read register Status 1 and wait for the DRDY: Data Ready //uint8_t ST1; //do //{ // I2Cread(MAG_ADDRESS,0x02,1,&ST1); //} // while (!(ST1&0x01)); if(readByte(MAG_ADDRESS, 0x02)& 0x01); { // Read magnetometer data uint8_t Mag[7]; //readBytes(AK8963_ADDRESS, 0x03, 7, &Mag[0]); I2Cread(MAG_ADDRESS,0x03,7,&Mag[0]); uint8_t c = Mag[6]; if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data // Create 16 bits values from 8 bits data // Magnetometer int16_t mx=-(Mag[3]<<8 | Mag[2]); int16_t my=-(Mag[1]<<8 | Mag[0]); int16_t mz=-(Mag[5]<<8 | Mag[4]); X = mx; Y = my; Z = mz; //float values_from_magnetometer[3]; // getHeading(); // values_from_magnetometer[0] = xv; //values_from_magnetometer[1] = yv; //values_from_magnetometer[2] = zv; //transformation(values_from_magnetometer); //vector_length_stabilasation(); //Serial.flush(); //Serial.print(calibrated_values[0]); //Serial.print(","); // Serial.print(calibrated_values[1]); //Serial.print(","); //Serial.print(calibrated_values[2]); // Serial.println(); // delay(100); // Magnetometer //Serial.print ("Значения магнитометра"); //Serial.print ("\t"); Serial.print (X ,DEC); Serial.print ("\t"); Serial.println (Y ,DEC); Serial.println ("\t"); Serial.print (Z ,DEC); Serial.print ("\t"); Serial.print ( Mscale << 4 | Mmode ,DEC); Serial.print ("\t"); // Serial.print (mx,DEC); //Serial.print ("\t"); //Serial.println (my ,DEC); //Serial.println ("\t"); //Serial.print (mz,DEC); //Serial.print ("\t"); } } // End of line //Serial.println(""); delay(100); } uint8_t readByte(uint8_t address, uint8_t subAddress) { uint8_t data; // `data` will store the register data Wire.beginTransmission(address); // Initialize the Tx buffer Wire.write(subAddress); // Put slave register address in Tx buffer Wire.endTransmission(false); // Send the Tx buffer, but send a restart to keep connection alive Wire.requestFrom(address, (uint8_t) 1); // Read one byte from slave register address data = Wire.read(); // Fill Rx buffer with result return data; // Return data read from slave register } void getHeading() { xv = X; yv = Y; zv = Z; }
Листая древние темы вдруг наткнулся, так и что получилось? Я последнее сообщение тогда в личку писал за стабилизатор ( механический ) но ответа не было. Недавно сам решил попробовать магнитометр в качестве металл детектора говно, чувствительность даж в сравнении с самодельной катушкой не о чём т.е. на земле в траве он видит и там где оч много металла но на 30см найти трубу уже не реально.