Создание собственной системы стабилизации

SergDoc

pios_board совсем разные создаётся чувство что про i2c совсем забыли, есть указание что переключить FLEXIPORT, а как работать оно должно -бог его знает…
разница:
ветка next

case HWSETTINGS_CC_FLEXIPORT_I2C:
#if defined(PIOS_INCLUDE_I2C)
		{
			if (PIOS_I2C_Init(&pios_i2c_flexi_adapter_id, &pios_i2c_flexi_adapter_cfg)) {
				PIOS_Assert(0);
			}
		}
#endif	/* PIOS_INCLUDE_I2C */
		break;

и sambas/mag_baro_testapp

/*
 * I2C Adapters
 */

void PIOS_I2C_main_adapter_ev_irq_handler(void);
void PIOS_I2C_main_adapter_er_irq_handler(void);
void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_ev_irq_handler")));
void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_er_irq_handler")));

static const struct pios_i2c_adapter_cfg pios_i2c_main_adapter_cfg = {
  .regs = I2C2,
  .init = {
    .I2C_Mode                = I2C_Mode_I2C,
    .I2C_OwnAddress1         = 0,
    .I2C_Ack                 = I2C_Ack_Enable,
    .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit,
    .I2C_DutyCycle           = I2C_DutyCycle_2,
    .I2C_ClockSpeed          = 200000,	/* bits/s */
  },
  .transfer_timeout_ms = 50,
  .scl = {
    .gpio = GPIOB,
    .init = {
      .GPIO_Pin   = GPIO_Pin_10,
      .GPIO_Speed = GPIO_Speed_10MHz,
      .GPIO_Mode  = GPIO_Mode_AF_OD,
    },
  },
  .sda = {
    .gpio = GPIOB,
    .init = {
      .GPIO_Pin   = GPIO_Pin_11,
      .GPIO_Speed = GPIO_Speed_10MHz,
      .GPIO_Mode  = GPIO_Mode_AF_OD,
    },
  },
  .event = {
    .handler = NULL,
    .flags   = 0,		/* FIXME: check this */
    .init = {
      .NVIC_IRQChannel                   = I2C2_EV_IRQn,
      .NVIC_IRQChannelPreemptionPriority = 1,
      .NVIC_IRQChannelSubPriority        = 4,
      .NVIC_IRQChannelCmd                = ENABLE,
    },
  },
  .error = {
    .handler = NULL,
    .flags   = 0,		/* FIXME: check this */
    .init = {
      .NVIC_IRQChannel                   = I2C2_ER_IRQn,
      .NVIC_IRQChannelPreemptionPriority = 1,
      .NVIC_IRQChannelSubPriority        = 3,
      .NVIC_IRQChannelCmd                = ENABLE,
    },
  },
};

uint32_t pios_i2c_main_adapter_id;
void PIOS_I2C_main_adapter_ev_irq_handler(void)
{
  /* Call into the generic code to handle the IRQ for this specific device */
  PIOS_I2C_EV_IRQ_Handler(pios_i2c_main_adapter_id);
}

void PIOS_I2C_main_adapter_er_irq_handler(void)
{
  /* Call into the generic code to handle the IRQ for this specific device */
  PIOS_I2C_ER_IRQ_Handler(pios_i2c_main_adapter_id);
}

#endif /* PIOS_INCLUDE_I2C */

ну и так далее
файлы
pios_i2c.h
pios_i2c.c
pios_i2c_priv.h

одинаковые с веткой NEXT (ну если несчитать ремапинга)

в Makefile тоже ничего сверхестественного нет, я опять в тупике 😦

SergDoc

Листая - читая, понял что в CC на данный момент функция i2c вообще упразнена, яко-бы может быть - когда-нибудь, в REVO вроде как i2c работает и по идее полностью такая-же как и должна быть в CC, но к сожалению я пока не в состоянии выдернуть из одного и вставить в другое без кучи ошибок, буду экспериментировать…

TimAU
SergDoc:

в REVO вроде как i2c

Я не специалистЪ но краем уха слышал что в рево STM32F4, а он вроде как с i2c лучше дружит чем m3

HikeR

Naze32 на F103 со всеми датчиками по I2C работает, так что проблема не в процессоре.

SergDoc

А у меня пока без изменений, шина неработает, ещё пока компилировал станцию положил платку около кулера - гиры поплыли мама негорюй, разонравилась мне уже эта схема, реально где купить MPU-6000?

SergDoc

У 6050 нет SPI и логика запитывается от 1.8 В, а я хочу SPI…

igor_v_t
SergDoc:

У 6050 нет SPI и логика запитывается от 1.8 В, а я хочу SPI…

Это логично, но MPU6000 нашел я только в США с рассылкой по США и Канаде. Поэтому до появления MPU6000 и MPU9150 может играться с гироскопами STM ? У STM тоже будет девятиосевая микросхема. И у них она заявлена по 3,1 ам. руб. в партии 1000 шт. В принципе любые гироскопы нормально летают.

SergDoc

LSM330DL - но смущает одно - у гиры и акселя раздельные шины и если по SPI то дофига получается дорожек разводить, а i2c я уже рисовал но пока чёт нерешаюсь делать…

igor_v_t
SergDoc:

LSM330DL - но смущает одно - у гиры и акселя раздельные шины и если по SPI то дофига получается дорожек разводить, а i2c я уже рисовал но пока чёт нерешаюсь делать…

Да в принципе все это с SPI имеет смысл если повышать скорость считывания данных. При 200 Гц можно и I2C обойтись и по большому счету и 32 разряда не надо. Я на мультиВие упражнялся, так проблем особых нет. Мы тут какую то макетницу рисуем и будем делать . Посему могу выложить, когда чертежик будет и в принципе готовые платки тож будут заводские , но все это не очень быстро. Поскольку работать иногда надо.

HikeR

аксели в СС на 3.2кГц работают (6-7 чтений с усреднением за цикл). переводить алгоритм на 200Гц — слишком много где порыться придется.

igor_v_t:

У STM тоже будет девятиосевая микросхема. И у них она заявлена по 3,1 ам. руб.

если вы про INEMO-M1, то она заявлена в 30-40 баксов.

igor_v_t
HikeR:

если вы про INEMO-M1, то она заявлена в 30-40 баксов.

Не я про LSM333 .INEMO-M1 она с процессором а потом мне непонятно что делать. Обработку всю этот процессор потянет, а для вывода на моторы еще один ставить?

HikeR:

аксели в СС на 3.2кГц работают (6-7 чтений с усреднением за цикл). переводить алгоритм на 200Гц — слишком много где порыться придется.

По СС мнение у меня такое - с такими датчиками не стоило огород городить. Не стоят они того. По опыту играясь с MPU 6000 неправильно в программе подключил аксели и не заметил поначалу, так как гироскопы без них справлялись. С другой стороны что ни делай с акселерометрами на МультиВии ничего хорошего не получается. Поэтому усложнять алгоритмы смысл имеет при нормальных датчиках. А основная идея перехода у меня на 32 разряда - это нелинейное управление.

HikeR
igor_v_t:

Обработку всю этот процессор потянет, а для вывода на моторы еще один ставить?

ессно, это ведь прямая замена всяких 9DOF модулей без необходимости лишней обвязки. к ней так и просятся парочка дополнительных датчиков, если откроют исходники.

igor_v_t:

с такими датчиками не стоило огород городить

не, я имел ввиду то, что СС весь “погряз” в рилтайме. чтобы изменить частоту опроса датчиков нужно перелопатить все связанные таймауты, иначе вместо опроса плата будет слать только варнинги.
насколько я помню, OpenPilot единственный открытый проект завязанные на RTOS, отсюда и трудности.

SergDoc

А я чего-то недоганяю, удаляю папку build компилирую всё заново а изменений никаких, в часности уменьшил скорость i2c поправил коэффициент для своих гир , а он непоменялся

igor_v_t:

Не я про LSM333

ну почему они каждому датчику собственную шину прикручивают?

Drinker
Sir_Alex:

Я где то читал, что есть некоторые грабли у F103 процов с i2c шиной и эти грабли поправили в F4. Так что, как вариант сразу этот проц закладывать в новых проектах. Хотя кто то тут писал про свой проект построения своего софта и долгое отлавливания багов с i2c шиной, но поделится чем то полезным человек не захотел…

Нету у кортекса проблем с и2ц

igor_v_t
HikeR:

не, я имел ввиду то, что СС весь “погряз” в рилтайме. чтобы изменить частоту опроса датчиков нужно перелопатить все связанные таймауты, иначе вместо опроса плата будет слать только варнинги. насколько я помню, OpenPilot единственный открытый проект завязанные на RTOS, отсюда и трудности.

Ну в этом я пока не понимаю.
Я на Атмеге игрался с этим и понимаю так, что если повышение частоты опроса не уменьшает ошибку интегрирования не имеет смысла ее повышать частоту опроса гироскопа. То же с акселем. В MPU 6000 есть ФНЧ. И вполне может быть что повышение частоты эффекта просто не даст.
На MS5611 я эффект получил при повышении частоты до 100 Гц. Дальнейшее усреднение баро дает красивую картину. И смысла фильтровать с акселерометром нет.
При этом на плате МультиВии (SE) с Гудлака фильтрация баро с акселерометром эффекта не дала по причине медленного акселерометра.

SergDoc:

ну почему они каждому датчику собственную шину прикручивают?

А может люди не мучатся а суют два кристала в один корпус?

SergDoc

Я вобщем решил пока так - гибрид КК и СС пока останется как есть(через 2 недели будут новые движки -опробую), заказал LSM330DL сделаю что-то на подобии NAZE32…

rual
SergDoc:

почему они каждому датчику собственную шину прикручивают?

тут нет никакой проблемы, у меня одна шина, SCK, MISO, MOSI параллельно , CS и RDY индивидуально подключены. Чтение через ПДП, выбор кристала переключает диспетчер СПИ, он же выбирает обработчик данных (дус\аксель) по окончании ПДП.
Однозначно победить и2ц не смог, изредка вылетают ошибки.
код такой

/* ----------------- запрос обмена по I2C через перерывание -------------------------*/
void IMU_ReqI2C_Trans(uint8_t adr, uint8_t iadr, uint8_t cnt )
{
uint16_t time = micros();
IMU_I2C_ClrAllErr();
I2C_ClearFlag(I2C_IMU,I2C_FLAG_AF|I2C_FLAG_ARLO|I2C_FLAG_BERR);

/* ожидаем освобождения интерфейса */
while(I2C_GetFlagStatus(I2C_IMU, I2C_FLAG_BUSY)){
if (((micros()-time)&0xfff) > IMU_I2C_MAXTIM){
IMU_I2C_SetErr(LBSY);
return;
}
}
/* предварительная настройка переменных */
imu_i2c_dev_adr = adr;
imu_i2c_buf[0] = iadr;
imu_i2c_cnt = cnt;
imu_i2c_inx = 0;
I2C_AcknowledgeConfig(I2C_IMU, ENABLE);
/* передаем состояние START */
I2C_GenerateSTART(I2C_IMU, ENABLE);
}
/* обработчик прерывания по событиям и буферу и2ц ИНС
внутренний адрес размещаем в buf[0]*/
void I2C1_ISR(void)
{
switch(I2C_GetLastEvent(I2C_IMU)&(~I2C_FLAG_BTF))
{
case I2C_EVENT_MASTER_MODE_SELECT: /* EV5 */
if ((imu_i2c_inx == 0)/* передаём вынутренний адрес */
||(imu_i2c_dev_adr&0x01 == 0)) /* режим передачи */
I2C_Send7bitAddress(I2C_IMU,imu_i2c_dev_adr,I2C_Direction_Transmitter);
else /* запуск чтения после повторного старта */
I2C_Send7bitAddress(I2C_IMU,imu_i2c_dev_adr,I2C_Direction_Receiver);
break;
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: /* EV6 */
case I2C_EVENT_MASTER_BYTE_TRANSMITTING: /* EV8 */
case I2C_EVENT_MASTER_BYTE_TRANSMITTED: /* EV8_2 */
if ((imu_i2c_inx == 1)&&(imu_i2c_dev_adr&0x01 != 0))
/* повторный старт для чтения */
I2C_GenerateSTART(I2C_IMU, ENABLE);
else { /* либо продолжаем писать */
if (imu_i2c_inx < imu_i2c_cnt+1)
/* передаём следующий байт */
I2C_SendData(I2C_IMU,imu_i2c_buf[imu_i2c_inx++]);
else /* передача буфера завершена */
I2C_GenerateSTOP(I2C_IMU, ENABLE);
}
break;

case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: /* EV6 */
case (uint32_t)(I2C_FLAG_BUSY|I2C_FLAG_MSL): /* состояние после сброса флага ADDR */
if (imu_i2c_cnt == 1) /* принимаем всего один байт */
I2C_AcknowledgeConfig(I2C_IMU, DISABLE);
break;

case I2C_EVENT_MASTER_BYTE_RECEIVED: /* EV7 */
if (imu_i2c_inx > imu_i2c_cnt) /* завершили чтение */
I2C_GenerateSTOP(I2C_IMU, ENABLE);
else {/* продолжаем чтение */
imu_i2c_buf[imu_i2c_inx++] = I2C_ReceiveData(I2C_IMU);
if (imu_i2c_inx == imu_i2c_cnt) /* будем принимать последний байт */
I2C_AcknowledgeConfig(I2C_IMU, DISABLE);
}
break;
default: /* не понятное состояние == ошибка интерфейса */
IMU_I2C_SetErr(IFERR);
I2C_GenerateSTOP(I2C_IMU, ENABLE);
I2C_SendData(I2C_IMU,I2C_GetLastEvent(I2C_IMU));
break;
}
/* проверим выход указателя за пределы буфера */
if (imu_i2c_inx > sizeof imu_i2c_buf)
{
imu_i2c_inx = sizeof imu_i2c_buf;
IMU_I2C_SetErr(OVBUF);
}

/* здесь вызов метода-заполнителя данных объекта ИНС */
switch(imu_i2c_dev_adr){
/* чтение магнитометра */
case MAG_I2C_DEV_ADR|0x01: MagmDataRdy(); break;
}
}
rual

выкладываю остатки, если вдруг затруднения возникнут

/// это в загловочном файле макросы для фиксации ошибок и2с
typedef enum _IMU_ERR{
LBSY = 0, /* длительная занятость */
OVBUF, /* выход за пределы буфера */
IFERR, /* ошибка интерфейса */
ACKF /* нет ответа ведомого */
}IMU_ERR;
#define IMU_I2C_MAXTIM 250*8 /* макс. занятость интерфейса в микросек. */
#define IMU_I2C_SetErr(Err) {imu_i2c_err|= (1<<Err);}
#define IMU_I2C_ClrErr(Err) {imu_i2c_err&= ~(1<<Err);}
#define IMU_I2C_ClrAllErr() {imu_i2c_err = 0;}
#define IMU_I2C_GetErr() (imu_i2c_err)

typedef enum _IMU_ERR{
LBSY = 0, /* длительная занятость */
OVBUF, /* выход за пределы буфера */
IFERR, /* ошибка интерфейса */
ACKF /* нет ответа ведомого */
}IMU_ERR;
#define IMU_I2C_MAXTIM 250*8 /* макс. занятость интерфейса в микросек. */
#define IMU_I2C_SetErr(Err) {imu_i2c_err|= (1<<Err);}
#define IMU_I2C_ClrErr(Err) {imu_i2c_err&= ~(1<<Err);}
#define IMU_I2C_ClrAllErr() {imu_i2c_err = 0;}
#define IMU_I2C_GetErr() (imu_i2c_err)

/// инициализация и2ц
/* настойка и2ц ИНС */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
/* Configure I2C1 pins: PB6->SCL and PB7->SDA */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);

I2C_DeInit(I2C_IMU);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_16_9;
I2C_InitStructure.I2C_OwnAddress1 = 1;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000; /* 100kHz */
I2C_Cmd(I2C_IMU, ENABLE);
I2C_Init(I2C_IMU, &I2C_InitStructure);
/* настройка прерывания И2Ц ИНС */
NVIC_EnableIRQ(I2C1_ER_IRQn);
NVIC_EnableIRQ(I2C1_EV_IRQn);
NVIC_SetPriority(I2C1_EV_IRQn, 5);
/* разрешаем прерывание от и2ц */
I2C_ITConfig(I2C_IMU, I2C_IT_EVT|I2C_IT_BUF|I2C_IT_ERR, ENABLE);

всё это обращается к стандартным перефирийным библиотекам