MultiWii

OK-40
dROb:

Но в целом - недурно.

Спасибо, ссылку исправил.

Можно ли на этой платке использовать режим Care Free и что для этого нужно!

mataor
Olegsi:

у меня винда 64-разрядная , NET framework 2.0 не хочет ставить, а без него эта софтина не хочет работать.

у меня 7-ка 64 разрядная, все работает отлично - просто ставте то что на гуглокоде вместе с вингуи лежит

Sevick

Скорее в разных версиях processing разная кривость Serial… Но лень…

devv
OK-40:

Можно ли на этой платке использовать режим Care Free и что для этого нужно!

Да. Нужен рабочий и откалиброванный компас (HMC5883L Magnetometer)

OK-40
devv:

Да. Нужен рабочий и откалиброванный компас (HMC5883L Magnetometer)

Не совсем понимаю, что значит нужен? Разве его нет на плате?

Features:
• SMD component design with Atmega328P
• ITG3205 Triple Axis Gyro
• BMA180 Accelerometer
• BMP085 Barometer
• HMC5883L Magnetometer
• Servo output for camera pitch and roll control
• Separate 3.3v regulated power supply for the sensors
• On board logic level converter

devv

В курсе что он там есть.
Но китайцы они такие. Были случаи когда что то из элементов на контроллерах для коптеров не работало как задумывалось и планировалось.
Еще компас может работать (из за особенностей ваше конструкции/рамы) плохо (наводки от силовой части и т.д.).

OK-40
devv:

Но китайцы они такие. Были случаи когда что то из элементов на контроллерах для коптеров не работало как задумывалось и планировалось.

Вот оно как… Может быть, Евгений, и не в тему, но прошу посоветовать платку Wii (дешево и сердито), для новичка в коптероводстве с отсутствием (хотя бы в первое время) танцев вокруг нее. А то чем больше читаешь ветки, тем наваристее каша в голове 😃

devv

Нормальный у вас вариант. Адекватная цена. Всё есть
Берите.

Flutter

Абсолютно поддерживаю. Но все-равно, разбираться придется долго. Это не то. что. купил и полетел. НО результат того стоит.
Что-то я не в ту тему. Имелось в видуdx.com/…/crius-all-in-one-pro-v1-0-multiwii-megapi…

Gene

Требуется консультация человека, разбирающегося в программировании…

Занимаюсь разработкой очередного подвеса для камеры со степмоторами вместо сервомашинок, использующего мультивий SE в качестве собственных мозгов. Механическая часть практически доведена, степперы работают прекрасно (при 200 шагах на оборот и микростеппинге 1/16 получается такое разрешение и такая скорость, что сервы плачут от зависти). В связи с кардинально изменившейся функциональностью платы, код пытаюсь написать практически с нуля, но с использованием готовых библиотек для общения с MPU6050 по шине I2C (ибо являюсь дремучим чайником в смысле понимания и использования серийных протоколов).

Уперся в скорость получения данных с MPU 6050. Требуется получать СЫРЫЕ данные с гироскопов и акселей, всего по двум осям (x,y). По моим подсчетам, скорость сэмплирования с использованием вот этого скетча, который сразу получает данные с гир и акселей по всем трем осям, получается чуть больше 500 раз в секунду. Если читать данные отдельно с гироскопов и отдельно с акселей, скорость получается примерно 900hz, но это усложняет цикл и сбивает тайминги. Что я ни делал, какие параметры ни менял через библиотеку, изменений скорости не заметил никаких. По данным производителя, MPU 6050 способен отдавать данные со скоростью 8000hz для гироскопов и 1000hz для акселей. Можно ли хотя бы приблизиться к таким цифрам, если да, то как? Начинаю подозревать, что затык в стандартной ардуиновской библиотеке Wire, но не уверен. Кто-нибудь может подсказать, куда копать?

P.S. Идеально было бы посмотреть на какой-нибудь простой кусок кода, выдающий данные быстрее…

mahowik
Gene:

Требуется консультация человека, разбирающегося в программировании…

Занимаюсь разработкой очередного подвеса для камеры со степмоторами вместо сервомашинок, использующего мультивий SE в качестве собственных мозгов. Механическая часть практически доведена, степперы работают прекрасно (при 200 шагах на оборот и микростеппинге 1/16 получается такое разрешение и такая скорость, что сервы плачут от зависти). В связи с кардинально изменившейся функциональностью платы, код пытаюсь написать практически с нуля, но с использованием готовых библиотек для общения с MPU6050 по шине I2C (ибо являюсь дремучим чайником в смысле понимания и использования серийных протоколов).

Уперся в скорость получения данных с MPU 6050. Требуется получать СЫРЫЕ данные с гироскопов и акселей, всего по двум осям (x,y). По моим подсчетам, скорость сэмплирования с использованием вот этого скетча, который сразу получает данные с гир и акселей по всем трем осям, получается чуть больше 500 раз в секунду. Если читать данные отдельно с гироскопов и отдельно с акселей, скорость получается примерно 900hz, но это усложняет цикл и сбивает тайминги. Что я ни делал, какие параметры ни менял через библиотеку, изменений скорости не заметил никаких. По данным производителя, MPU 6050 способен отдавать данные со скоростью 8000hz для гироскопов и 1000hz для акселей. Можно ли хотя бы приблизиться к таким цифрам, если да, то как? Начинаю подозревать, что затык в стандартной ардуиновской библиотеке Wire, но не уверен. Кто-нибудь может подсказать, куда копать?

P.S. Идеально было бы посмотреть на какой-нибудь простой кусок кода, выдающий данные быстрее…

Эксперименты всегда хорошо, но реально для достойной стабилизации самплинг в 200-300гц с головой и для защиты от вибраций на гиру нч фильтр внутренний 42гц ставится… драйвер для 6050 и иму можно взять из сор сов вия соот-но…

Radio

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

Приметил плату, есть аналоги олион, в чем разница ? Тут писалось про Atmega2560, она не универсальна ?

kedrikov
Radio:

Посоветуйте пожалуйста продвинутые мозги, ищу замену назе, что бы жпс был + много функций

Это только закрытые проекты,кто ж вам исходники даст.

Radio:

Приметил плату, есть аналоги олион, в чем разница ?

Дешево и сердито обычный мультивий и думаю давно уже за вас все разработали и продвинули энтузиасты 😃 такие как Саша (mahowik) за что ему респект огромный

Radio:

есть аналоги олион, в чем разница

Вот на этом наверно ваш интузиазм закончится 😃
Начинайте отсюда

Gene
mahowik:

Эксперименты всегда хорошо, но реально для достойной стабилизации самплинг в 200-300гц с головой и для защиты от вибраций на гиру нч фильтр внутренний 42гц ставится…

НЧ фильтр работает, это проверено… Скорость сэмплирования желательно сделать больше именно из-за количества степов, это сильно упростит код и упростит настройку драйвера степпера – иначе для скорости придется постоянно переключать степпинг, а это чревато вибрациями. Я его отладил именно для 1/16, и это потребовало даже некоторой перепайки. Ну по крайней мере было бы ОЧЕНЬ желательно увеличить сэмплинг. С обычными сервами такой проблемы конечно даже не возникло бы, но со степперами другое дело…

драйвер для 6050 и иму можно взять из сор сов вия соот-но…

Так вроде бы там эта же библиотека и используется, нет? Александр, Вы специалист, Вы можете сказать, с какой примерно частотой производится сэмплирование в стандартном софте мультивия? Если с такой же, как у меня так может и копать не нужно…

mahowik
Gene:

с какой примерно частотой производится сэмплирование в стандартном софте мультивия?

примерно через 2-5мс, в зависимости от навески… т.е. 200-500гц…

Gene
mahowik:

примерно через 2-5мс, в зависимости от навески… т.е. 200-500гц…

Получается столько же, значит, смысла копать нет. Попробую в таком случае обойти библиотеку и читать нужные данные непосредственно из регистров…

mahowik

в Sensors.ino есть все что надо и I2C драйвер и драйвер mpu6050… все в одном и без либ 😉

Gene
mahowik:

в Sensors.ino есть все что надо и I2C драйвер и драйвер mpu6050… все в одном и без либ 😉

Возможно я тупой, но не смог разобраться в коде 😦 Один кусок кода тянет за собой другой, и так до бесконечности… до конца цепочки я добраться не смог. все что мне нужно – считать значение регистра…

mataor
Gene:

Скорость сэмплирования желательно сделать больше именно из-за количества степов, это сильно упростит код и упростит настройку драйвера степпера

возьмите хмегу - там аппаратная поддержка 2 шаговых/трехфазных моторов, да и цикл более шустрый получается

Gene:

но не смог разобраться в коде Один кусок кода тянет за собой другой, и так до бесконечности…

там весь код в шапке сенсор.ино, все остальное чего оно хочет - в основном переменные определенные в мультивий.ино и дефайны из деф.н и сонфиг.н

Gene
mataor:

возьмите хмегу - там аппаратная поддержка 2 шаговых/трехфазных моторов, да и цикл более шустрый получается

Возможно в след. версии 😃

там весь код в шапке сенсор.ино, все остальное чего оно хочет - в основном переменные определенные в мультивий.ино и дефайны из деф.н и сонфиг.н

Я как Остап Бендер, только он играл в шахматы, а я программирую второй раз в жизни 😃 Не для моего нетренированного мозга разбираться в этом. Код я воспринимаю и имею шанс понять, только когда вижу его целиком перед глазами. Когда он начинает разбегаться по всяческим инклюдам и дефайнам, пиши пропало, нить потеряна – могу только собезьянничать, не понимая что происходит на самом деле.

mataor

хм… ну вообще если нужно чисто и2с и получить 6 данных с датчиков то тебе нужно:

  1. определится с переменными, со знаками и направлениями
uint8_t rawADC[6];
static int16_t  gyroADC[3],accADC[3];
#define MPU6050_ADDRESS     0x68
#define MPU6050
#define ACC_ORIENTATION(Y, X, Z)  {accADC[ROLL]  = -Y; accADC[PITCH]  = -X; accADC[YAW]  =  Z;}
#define GYRO_ORIENTATION(Y, X, Z) {gyroADC[ROLL] =  X; gyroADC[PITCH] = -Y; gyroADC[YAW] = -Z;}
  1. взять основные ф-ции и2с
// ************************************************************************************************************
// I2C general functions
// ************************************************************************************************************

void i2c_init(void) {
  #if defined(INTERNAL_I2C_PULLUPS)
    I2C_PULLUPS_ENABLE
  #else
    I2C_PULLUPS_DISABLE
  #endif
  TWSR = 0;                                    // no prescaler => prescaler = 1
  TWBR = ((F_CPU / I2C_SPEED) - 16) / 2;   // change the I2C clock rate
  TWCR = 1<<TWEN;                              // enable twi module, no interrupt
}

void i2c_rep_start(uint8_t address) {
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN) ; // send REPEAT START condition
  waitTransmissionI2C();                       // wait until transmission completed
  TWDR = address;                              // send device address
  TWCR = (1<<TWINT) | (1<<TWEN);
  waitTransmissionI2C();                       // wail until transmission completed
}

void i2c_stop(void) {
  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
  //  while(TWCR & (1<<TWSTO));                // <- can produce a blocking state with some WMP clones
}

void i2c_write(uint8_t data ) {
  TWDR = data;                                 // send data to the previously addressed device
  TWCR = (1<<TWINT) | (1<<TWEN);
  waitTransmissionI2C();
}

uint8_t i2c_read(uint8_t ack) {
  TWCR = (1<<TWINT) | (1<<TWEN) | (ack? (1<<TWEA) : 0);
  waitTransmissionI2C();
  uint8_t r = TWDR;
  if (!ack) i2c_stop();
  return r;
}

uint8_t i2c_readAck() {
  return i2c_read(1);
}

uint8_t i2c_readNak(void) {
  return i2c_read(0);
}

void waitTransmissionI2C() {
  uint16_t count = 255;
  while (!(TWCR & (1<<TWINT))) {
    count--;
    if (count==0) {              //we are in a blocking state => we don't insist
      TWCR = 0;                  //and we force a reset on TWINT register
      neutralizeTime = micros(); //we take a timestamp here to neutralize the value during a short delay
      i2c_errors_count++;
      break;
    }
  }
}

size_t i2c_read_to_buf(uint8_t add, void *buf, size_t size) {
  i2c_rep_start((add<<1) | 1);	// I2C read direction
  size_t bytes_read = 0;
  uint8_t *b = (uint8_t*)buf;
  while (size--) {
    /* acknowledge all but the final byte */
    *b++ = i2c_read(size > 0);
    /* TODO catch I2C errors here and abort */
    bytes_read++;
  }
  return bytes_read;
}

size_t i2c_read_reg_to_buf(uint8_t add, uint8_t reg, void *buf, size_t size) {
  i2c_rep_start(add<<1); // I2C write direction
  i2c_write(reg);        // register selection
  return i2c_read_to_buf(add, buf, size);
}

/* transform a series of bytes from big endian to little
   endian and vice versa. */
void swap_endianness(void *buf, size_t size) {
  /* we swap in-place, so we only have to
  * place _one_ element on a temporary tray
  */
  uint8_t tray;
  uint8_t *from;
  uint8_t *to;
  /* keep swapping until the pointers have assed each other */
  for (from = (uint8_t*)buf, to = &from; from < to; from++, to--) {
    tray = *from;
    *from = *to;
    *to = tray;
  }
}

void i2c_getSixRawADC(uint8_t add, uint8_t reg) {
  i2c_read_reg_to_buf(add, reg, &rawADC, 6);
}

void i2c_writeReg(uint8_t add, uint8_t reg, uint8_t val) {
  i2c_rep_start(add<<1); // I2C write direction
  i2c_write(reg);        // register selection
  i2c_write(val);        // value to write in register
  i2c_stop();
}

uint8_t i2c_readReg(uint8_t add, uint8_t reg) {
  uint8_t val;
  i2c_read_reg_to_buf(add, reg, &val, 1);
  return val;
}
  1. получить данные по акселю и гире
// ************************************************************************************************************
// I2C Gyroscope and Accelerometer MPU6050
// ************************************************************************************************************
#if defined(MPU6050)

void Gyro_init() {
  TWBR = ((F_CPU / 400000L) - 16) / 2; // change the I2C clock rate to 400kHz
  i2c_writeReg(MPU6050_ADDRESS, 0x6B, 0x80);             //PWR_MGMT_1    -- DEVICE_RESET 1
  delay(5);
  i2c_writeReg(MPU6050_ADDRESS, 0x6B, 0x03);             //PWR_MGMT_1    -- SLEEP 0; CYCLE 0; TEMP_DIS 0; CLKSEL 3 (PLL with Z Gyro reference)
  i2c_writeReg(MPU6050_ADDRESS, 0x1A, MPU6050_DLPF_CFG); //CONFIG        -- EXT_SYNC_SET 0 (disable input pin for data sync) ; default DLPF_CFG = 0 => ACC bandwidth = 260Hz  GYRO bandwidth = 256Hz)
  i2c_writeReg(MPU6050_ADDRESS, 0x1B, 0x18);             //GYRO_CONFIG   -- FS_SEL = 3: Full scale set to 2000 deg/sec
  // enable I2C bypass for AUX I2C
  #if defined(MAG)
    i2c_writeReg(MPU6050_ADDRESS, 0x37, 0x02);           //INT_PIN_CFG   -- INT_LEVEL=0 ; INT_OPEN=0 ; LATCH_INT_EN=0 ; INT_RD_CLEAR=0 ; FSYNC_INT_LEVEL=0 ; FSYNC_INT_EN=0 ; I2C_BYPASS_EN=1 ; CLKOUT_EN=0
  #endif
}

void Gyro_getADC () {
  i2c_getSixRawADC(MPU6050_ADDRESS, 0x43);
  GYRO_ORIENTATION( ((rawADC[0]<<8) | rawADC[1])/4 , // range: +/- 8192; +/- 2000 deg/sec
	            ((rawADC[2]<<8) | rawADC[3])/4 ,
	            ((rawADC[4]<<8) | rawADC[5])/4 );
  GYRO_Common();
}

void ACC_init () {
  i2c_writeReg(MPU6050_ADDRESS, 0x1C, 0x10);             //ACCEL_CONFIG  -- AFS_SEL=2 (Full Scale = +/-8G)  ; ACCELL_HPF=0   //note something is wrong in the spec.
  //note: something seems to be wrong in the spec here. With AFS=2 1G = 4096 but according to my measurement: 1G=2048 (and 2048/8 = 256)
  //confirmed here: 
  #if defined(FREEIMUv04)
    acc_1G = 255;
  #else
    acc_1G = 512;
  #endif

  #if defined(MPU6050_I2C_AUX_MASTER)
    //at this stage, the MAG is configured via the original MAG init function in I2C bypass mode
    //now we configure MPU as a I2C Master device to handle the MAG via the I2C AUX port (done here for HMC5883)
    i2c_writeReg(MPU6050_ADDRESS, 0x6A, 0b00100000);       //USER_CTRL     -- DMP_EN=0 ; FIFO_EN=0 ; I2C_MST_EN=1 (I2C master mode) ; I2C_IF_DIS=0 ; FIFO_RESET=0 ; I2C_MST_RESET=0 ; SIG_COND_RESET=0
    i2c_writeReg(MPU6050_ADDRESS, 0x37, 0x00);             //INT_PIN_CFG   -- INT_LEVEL=0 ; INT_OPEN=0 ; LATCH_INT_EN=0 ; INT_RD_CLEAR=0 ; FSYNC_INT_LEVEL=0 ; FSYNC_INT_EN=0 ; I2C_BYPASS_EN=0 ; CLKOUT_EN=0
    i2c_writeReg(MPU6050_ADDRESS, 0x24, 0x0D);             //I2C_MST_CTRL  -- MULT_MST_EN=0 ; WAIT_FOR_ES=0 ; SLV_3_FIFO_EN=0 ; I2C_MST_P_NSR=0 ; I2C_MST_CLK=13 (I2C slave speed bus = 400kHz)
    i2c_writeReg(MPU6050_ADDRESS, 0x25, 0x80|MAG_ADDRESS);//I2C_SLV0_ADDR -- I2C_SLV4_RW=1 (read operation) ; I2C_SLV4_ADDR=MAG_ADDRESS
    i2c_writeReg(MPU6050_ADDRESS, 0x26, MAG_DATA_REGISTER);//I2C_SLV0_REG  -- 6 data bytes of MAG are stored in 6 registers. First register address is MAG_DATA_REGISTER
    i2c_writeReg(MPU6050_ADDRESS, 0x27, 0x86);             //I2C_SLV0_CTRL -- I2C_SLV0_EN=1 ; I2C_SLV0_BYTE_SW=0 ; I2C_SLV0_REG_DIS=0 ; I2C_SLV0_GRP=0 ; I2C_SLV0_LEN=3 (3x2 bytes)
  #endif
}

void ACC_getADC () {
  i2c_getSixRawADC(MPU6050_ADDRESS, 0x3B);
  ACC_ORIENTATION( ((rawADC[0]<<8) | rawADC[1])/8 ,
                   ((rawADC[2]<<8) | rawADC[3])/8 ,
                   ((rawADC[4]<<8) | rawADC[5])/8 );
  ACC_Common();
}

GYRO_Common и ACC_Common ф-ции переделать под себя будет чуть геморойнее - они используют больше переменных из других файлов проэкта