Создание собственной системы стабилизации
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 тоже ничего сверхестественного нет, я опять в тупике 😦
Листая - читая, понял что в CC на данный момент функция i2c вообще упразнена, яко-бы может быть - когда-нибудь, в REVO вроде как i2c работает и по идее полностью такая-же как и должна быть в CC, но к сожалению я пока не в состоянии выдернуть из одного и вставить в другое без кучи ошибок, буду экспериментировать…
в REVO вроде как i2c
Я не специалистЪ но краем уха слышал что в рево STM32F4, а он вроде как с i2c лучше дружит чем m3
Naze32 на F103 со всеми датчиками по I2C работает, так что проблема не в процессоре.
А у меня пока без изменений, шина неработает, ещё пока компилировал станцию положил платку около кулера - гиры поплыли мама негорюй, разонравилась мне уже эта схема, реально где купить MPU-6000?
Тут например
www.csgshop.com/product.php?id_product=81
У 6050 нет SPI и логика запитывается от 1.8 В, а я хочу SPI…
У 6050 нет SPI и логика запитывается от 1.8 В, а я хочу SPI…
Это логично, но MPU6000 нашел я только в США с рассылкой по США и Канаде. Поэтому до появления MPU6000 и MPU9150 может играться с гироскопами STM ? У STM тоже будет девятиосевая микросхема. И у них она заявлена по 3,1 ам. руб. в партии 1000 шт. В принципе любые гироскопы нормально летают.
LSM330DL - но смущает одно - у гиры и акселя раздельные шины и если по SPI то дофига получается дорожек разводить, а i2c я уже рисовал но пока чёт нерешаюсь делать…
LSM330DL - но смущает одно - у гиры и акселя раздельные шины и если по SPI то дофига получается дорожек разводить, а i2c я уже рисовал но пока чёт нерешаюсь делать…
Да в принципе все это с SPI имеет смысл если повышать скорость считывания данных. При 200 Гц можно и I2C обойтись и по большому счету и 32 разряда не надо. Я на мультиВие упражнялся, так проблем особых нет. Мы тут какую то макетницу рисуем и будем делать . Посему могу выложить, когда чертежик будет и в принципе готовые платки тож будут заводские , но все это не очень быстро. Поскольку работать иногда надо.
аксели в СС на 3.2кГц работают (6-7 чтений с усреднением за цикл). переводить алгоритм на 200Гц — слишком много где порыться придется.
У STM тоже будет девятиосевая микросхема. И у них она заявлена по 3,1 ам. руб.
если вы про INEMO-M1, то она заявлена в 30-40 баксов.
если вы про INEMO-M1, то она заявлена в 30-40 баксов.
Не я про LSM333 .INEMO-M1 она с процессором а потом мне непонятно что делать. Обработку всю этот процессор потянет, а для вывода на моторы еще один ставить?
аксели в СС на 3.2кГц работают (6-7 чтений с усреднением за цикл). переводить алгоритм на 200Гц — слишком много где порыться придется.
По СС мнение у меня такое - с такими датчиками не стоило огород городить. Не стоят они того. По опыту играясь с MPU 6000 неправильно в программе подключил аксели и не заметил поначалу, так как гироскопы без них справлялись. С другой стороны что ни делай с акселерометрами на МультиВии ничего хорошего не получается. Поэтому усложнять алгоритмы смысл имеет при нормальных датчиках. А основная идея перехода у меня на 32 разряда - это нелинейное управление.
Обработку всю этот процессор потянет, а для вывода на моторы еще один ставить?
ессно, это ведь прямая замена всяких 9DOF модулей без необходимости лишней обвязки. к ней так и просятся парочка дополнительных датчиков, если откроют исходники.
с такими датчиками не стоило огород городить
не, я имел ввиду то, что СС весь “погряз” в рилтайме. чтобы изменить частоту опроса датчиков нужно перелопатить все связанные таймауты, иначе вместо опроса плата будет слать только варнинги.
насколько я помню, OpenPilot единственный открытый проект завязанные на RTOS, отсюда и трудности.
А я чего-то недоганяю, удаляю папку build компилирую всё заново а изменений никаких, в часности уменьшил скорость i2c поправил коэффициент для своих гир , а он непоменялся
Не я про LSM333
ну почему они каждому датчику собственную шину прикручивают?
Я где то читал, что есть некоторые грабли у F103 процов с i2c шиной и эти грабли поправили в F4. Так что, как вариант сразу этот проц закладывать в новых проектах. Хотя кто то тут писал про свой проект построения своего софта и долгое отлавливания багов с i2c шиной, но поделится чем то полезным человек не захотел…
Нету у кортекса проблем с и2ц
не, я имел ввиду то, что СС весь “погряз” в рилтайме. чтобы изменить частоту опроса датчиков нужно перелопатить все связанные таймауты, иначе вместо опроса плата будет слать только варнинги. насколько я помню, OpenPilot единственный открытый проект завязанные на RTOS, отсюда и трудности.
Ну в этом я пока не понимаю.
Я на Атмеге игрался с этим и понимаю так, что если повышение частоты опроса не уменьшает ошибку интегрирования не имеет смысла ее повышать частоту опроса гироскопа. То же с акселем. В MPU 6000 есть ФНЧ. И вполне может быть что повышение частоты эффекта просто не даст.
На MS5611 я эффект получил при повышении частоты до 100 Гц. Дальнейшее усреднение баро дает красивую картину. И смысла фильтровать с акселерометром нет.
При этом на плате МультиВии (SE) с Гудлака фильтрация баро с акселерометром эффекта не дала по причине медленного акселерометра.
ну почему они каждому датчику собственную шину прикручивают?
А может люди не мучатся а суют два кристала в один корпус?
Я вобщем решил пока так - гибрид КК и СС пока останется как есть(через 2 недели будут новые движки -опробую), заказал LSM330DL сделаю что-то на подобии NAZE32…
почему они каждому датчику собственную шину прикручивают?
тут нет никакой проблемы, у меня одна шина, 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;
}
}
офф-топ Ханты-Мансийск?
он самый )
выкладываю остатки, если вдруг затруднения возникнут
/// это в загловочном файле макросы для фиксации ошибок и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);
всё это обращается к стандартным перефирийным библиотекам