Обновить
23
0

Пользователь

Отправить сообщение

STM32, C++ и FreeRTOS. Разработка с нуля. Часть 4 (Прерывания, UART и недоHART)

Время на прочтение29 мин
Охват и читатели23K

Ведение


Попав в отпуске в город на Неве и посетив множество красивых мест, я все таки, вечерами за чашкой пива, разбирался с UARTом. Тем более, что я купил неплохие наушники Fisher FA011, к которым пришлось прикупить USB SOUND BLASTER X-FI HD и хотел послушать музыку.
Предыдущие статьи вначале переехали на Geektime потом я обратно их перегнал, даже и не знаю, куда теперь их деть :)
Но так на всякий случай они тут:
STM32, C++ и FreeRTOS. Разработка с нуля. Часть 1
STM32, C++ и FreeRTOS. Разработка с нуля. Часть 2 и
STM32, C++ и FreeRTOS. Разработка с нуля. Часть 3 (LCD и Экраны)

UART


После детального изучения микроконтроллера, мне казалось, что все просто. Настройка и тестовая посылка байта в порт прошла без задоринки, все работало как часы, и тут я решил использовать прерывания. Нужно было сделать так, чтобы обработчик прерывания был статическим методом класса. И IAR в руководстве на компилятор, так и писал:
Special function types can be used for static member functions. For example, in the
following example, the function handler is declared as an interrupt function:
class Device
{
 static __irq void handler();
};

Но вот незадача, для Cortex M такой способ не подходит и
On ARM Cortex-M, an interrupt service routine enters and returns in the same way as a
normal function, which means no special keywords are required. Thus, the keywords
__irq, __fiq, and __nested are not available when you compile for ARM Cortex-M.

These exception function names are defined in cstartup_M.c and cstartup_M.s.
They are referred to by the library exception vector code:
NMI_Handler
HardFault_Handler
MemManage_Handler
BusFault_Handler

The vector table is implemented as an array. It should always have the name
__vector_table,

Или по простому, ваш обработчик прерывания должен иметь такое же имя, какое он имеет в таблице векторов определенной в startup файле. Это делается с помощью специального ключевого слова — слабой ссылки __weak (в ассемблере PUBWEAK), которая означает, что данное определение будет использоваться до тех пора, пока не найдется хотя бы одно совпадающее по написанию без ключевого слова __week. Ну т.е., если вы определите функцию с точно таким же именем без этой директивы, то компилятро будет использовать это определение, а если не определите, то которое помечено __weak.
Понятное дело, что я не могу в файл startup_stm32l1xx_md.s или startup_stm32l1xx_md.с вставить С++ имя статического метода типа cUart::USART2_IRQHandler(), ассемблер его просто не поймет.
А просто «USART2_IRQHandler» не совпадает с определением «cUart::USART2_IRQHandler()».
Можно использовать extern «C» { void USART2_IRQHandler(void) {...}}, но это означает, что я тут буду делать вставки из Си, что мне совсем не надо, и вообще доступа из такой функции к атрибутам моего класса, например буферу — не будет, и надо будет городить кучу некрасивого кода :).
Поэтому, я решил пойти другим путем и создать файл startup_stm32l1xx_md.cpp. Поиск в интернете обнаружил, что точно такая же проблема была у некоторых людей Вот например
В общем идея заключается в следующем: Объявляем в startup_stm32l1xx_md.cpp классы со статическими методами (которые и будут являться обработчиками прерываний), создаем таблицу __vector_table, где на каждом из векторов прерываний стоит указатель на эти статические методы. Дальше делаем __weak определение каждого метода
И теперь когда в коде компилятор видет реализацию void cUart1::handler(), он не задумываясь берет её. Конечно же при этом ваши классы и методы должны называться точь в точь так, как они определены в startup_stm32l1xx_md.cpp.
Нужно еще не забыть про функции FreeRtos: vPortSVCHandler, xPortPendSVHandler, xPortSysTickHandler и поставить их на нужное прерывание и вуаля — все работает:
startup_stm32l1xx_md.cpp
#pragma language = extended
#pragma segment = "CSTACK"
extern "C" void __iar_program_start( void );
extern "C" void vPortSVCHandler(void);
extern "C" void xPortPendSVHandler(void);
extern "C" void xPortSysTickHandler(void);
class cNMI
{
public:
    static void handler(void);
};
class cHardFault
{
public:
    static void handler(void);
};
class cMemManage
{
public:
    static void handler(void);
};
class cBusFault
{
public:
    static void handler(void);
};
class cUsageFault
{
public:
    static void handler(void);
};
class cDebugMon
{
public:
    static void handler(void);
};
class cWindowWatchdog
{
public:
    static void handler(void);    
};
class cPvd
{
public:
    static void handler(void);    
};
class cTamperTimeStamp
{
public:
    static void handler(void);    
};
class cRtcWakeup
{
public:
    static void handler(void);    
};
class cFlash
{
public:
    static void handler(void);    
};
class cRcc
{
public:
    static void handler(void);    
};
class cExti
{
public:
    static void line0Handler(void);
    static void line1Handler(void);
    static void line2Handler(void);
    static void line3Handler(void);
    static void line4Handler(void);
    static void line9Handler(void);
    static void line15_10Handler(void);
};
class cDma
{
public:
    static void channellHandler(void);    
    static void channel2Handler(void);    
    static void channel3Handler(void);    
    static void channel4Handler(void);    
    static void channel5Handler(void);    
    static void channel6Handler(void);    
    static void channel7Handler(void);    
};
class cAdc
{
public:
    static void handler(void);    
};
class cDac
{
public:
    static void handler(void);    
};
class cUsb
{
public:
    static void highPriorityHandler(void);    
    static void lowPriorityHandler(void);
    static void fsWakeupHandler(void);
};
class cComp
{
public:
    static void handler(void);    
};
class cLcdDriver
{
public:
    static void handler(void);    
};
class cTim9
{
public:
    static void handler(void);    
};
class cTim2
{
public:
    static void handler(void);    
};
class cTim3
{
public:
    static void handler(void);    
};
class cTim4
{
public:
    static void handler(void);    
};
class cTim10
{
public:
    static void handler(void);    
};
class cTim6
{
public:
    static void handler(void);    
};
class cTim7
{
public:
    static void handler(void);    
};
class cTim11
{
public:
    static void handler(void);    
};
class cI2C1
{
public:
    static void eventHandler(void);
    static void errorHandler(void);
};
class cI2C2
{
public:
    static void eventHandler(void);
    static void errorHandler(void);
};
class cSpi1
{
public:
    static void handler(void);    
};
class cSpi2
{
public:
    static void handler(void);    
};
class cUart1
{
public:
    static void handler(void);    
};
class cUart2
{
public:
    static void handler(void);    
};
class cUart3
{
public:
    static void handler(void);    
};
class cRtcAlarm
{
public:
    static void handler(void);    
};
typedef void( *intfunc )( void );
typedef union { intfunc __fun; void * __ptr; } intvec_elem;
// The vector table is normally located at address 0.
// When debugging in RAM, it can be located in RAM, aligned to at least 2^6.
// If you need to define interrupt service routines,
// make a copy of this file and include it in your project.
// The name "__vector_table" has special meaning for C-SPY:
// it is where the SP start value is found, and the NVIC vector
// table register (VTOR) is initialized to this address if != 0.
#pragma location = ".intvec"
extern "C" const intvec_elem __vector_table[] =
{
  { .__ptr = __sfe( "CSTACK" ) },
  __iar_program_start,

  cNMI::handler,
  cHardFault::handler,
  cMemManage::handler,
  cBusFault::handler,
  cUsageFault::handler,
  0,
  0,
  0,
  0,
  vPortSVCHandler,             //функции freeRTOS не трогать!
  cDebugMon::handler,
  0,
  xPortPendSVHandler,          //функции freeRTOS не трогать!
  xPortSysTickHandler,         //функции freeRTOS не трогать!
  //External Interrupts
  cWindowWatchdog::handler,    //Window Watchdog
  cPvd::handler,               //PVD through EXTI Line detect
  cTamperTimeStamp::handler,   //Tamper and Time Stamp
  cRtcWakeup::handler,         //RTC Wakeup
  cFlash::handler,             //FLASH
  cRcc::handler,               //RCC
  cExti::line0Handler,         //EXTI Line 0
  cExti::line1Handler,         //EXTI Line 1
  cExti::line2Handler,         //EXTI Line 2
  cExti::line3Handler,         //EXTI Line 3
  cExti::line4Handler,         //EXTI Line 4
  cDma::channellHandler,       //DMA1 Channel 1
  cDma::channel2Handler,       //DMA1 Channel 2
  cDma::channel3Handler,       //DMA1 Channel 3
  cDma::channel4Handler,       //DMA1 Channel 4
  cDma::channel5Handler,       //DMA1 Channel 5
  cDma::channel6Handler,       //DMA1 Channel 6
  cDma::channel7Handler,       //DMA1 Channel 7
  cAdc::handler,               //ADC1
  cUsb::highPriorityHandler,   //USB High Priority
  cUsb::lowPriorityHandler,    //USB Low  Priority
  cDac::handler,               //DAC
  cComp::handler,              //COMP through EXTI Line
  cExti::line9Handler,         //EXTI Line 9..5
  cLcdDriver::handler,         //LCD
  cTim9::handler,               //TIM9
  cTim10::handler,             //TIM10
  cTim11::handler,             //TIM11
  cTim2::handler,             //TIM2
  cTim3::handler,              //TIM3
  cTim4::handler,              //TIM4
  cI2C1::eventHandler,         //I2C1 Event
  cI2C1::errorHandler,         //I2C1 Error
  cI2C2::eventHandler,         //I2C2 Event
  cI2C2::errorHandler,         //I2C2 Error
  cSpi1::handler,              //SPI1
  cSpi2::handler,              //SPI2
  cUart1::handler,             //USART1
  cUart2::handler,             //USART2
  cUart3::handler,             //USART3
  cExti::line15_10Handler,     //EXTI Line 15..10
  cRtcAlarm::handler,          //RTC Alarm through EXTI Line
  cUsb::fsWakeupHandler,       //USB FS Wakeup from suspend
  cTim6::handler,              //TIM6
  cTim7::handler                //TIM7
};
__weak void cNMI::handler()          { while (1) {} }
__weak void cHardFault::handler()    { while (1) {} }
__weak void cMemManage::handler()    { while (1) {} }
__weak void cBusFault::handler()     { while (1) {} }
__weak void cUsageFault::handler()   { while (1) {} }
__weak void cDebugMon::handler()     { while (1) {} }
__weak void cWindowWatchdog::handler()  { while (1) {} }
__weak void cPvd::handler()             { while (1) {} }
__weak void cTamperTimeStamp::handler() { while (1) {} }
__weak void cRtcWakeup::handler()       { while (1) {} }
__weak void cFlash::handler()           { while (1) {} }
__weak void cRcc::handler()             { while (1) {} }
__weak void cExti::line0Handler()       { while (1) {} }
__weak void cExti::line1Handler()       { while (1) {} }
__weak void cExti::line2Handler()       { while (1) {} }
__weak void cExti::line3Handler()       { while (1) {} }
__weak void cExti::line4Handler()       { while (1) {} }
__weak void cExti::line9Handler()       { while (1) {} }
__weak void cExti::line15_10Handler()   { while (1) {} }
__weak void cDma::channellHandler()     { while (1) {} }
__weak void cDma::channel2Handler()     { while (1) {} }
__weak void cDma::channel3Handler()     { while (1) {} }
__weak void cDma::channel4Handler()     { while (1) {} }
__weak void cDma::channel5Handler()     { while (1) {} }
__weak void cDma::channel6Handler()     { while (1) {} }
__weak void cDma::channel7Handler()     { while (1) {} }
__weak void cAdc::handler()             { while (1) {} }
__weak void cUsb::fsWakeupHandler()     { while (1) {} }
__weak void cUsb::highPriorityHandler() { while (1) {} }
__weak void cUsb::lowPriorityHandler()  { while (1) {} }
__weak void cDac::handler()             { while (1) {} }
__weak void cComp::handler()            { while (1) {} }
__weak void cLcdDriver::handler()       { while (1) {} }
__weak void cTim2::handler()            { while (1) {} }
__weak void cTim3::handler()            { while (1) {} }
__weak void cTim4::handler()            { while (1) {} }
__weak void cTim6::handler()            { while (1) {} }
__weak void cTim7::handler()            { while (1) {} }
__weak void cTim9::handler()            { while (1) {} }
__weak void cTim10::handler()           { while (1) {} }
__weak void cTim11::handler()           { while (1) {} }
__weak void cI2C1::errorHandler()       { while (1) {} }
__weak void cI2C1::eventHandler()       { while (1) {} }
__weak void cI2C2::errorHandler()       { while (1) {} }
__weak void cI2C2::eventHandler()       { while (1) {} }
__weak void cSpi1::handler()            { while (1) {} }
__weak void cSpi2::handler()            { while (1) {} }
__weak void cUart1::handler()           { while (1) {} }
__weak void cUart2::handler()           { while (1) {} }
__weak void cUart3::handler()           { while (1) {} }
__weak void cRtcAlarm::handler()        { while (1) {} }
extern "C" void __cmain( void );
extern "C" __weak void __iar_init_core( void );
extern "C" __weak void __iar_init_vfp( void );

#pragma required=__vector_table
void __iar_program_start( void )
{
  __iar_init_core();
  __iar_init_vfp();
  __cmain();
}


image

Читать дальше →

Новые нейронные сети или моделирование работы нервной системы

Время на прочтение6 мин
Охват и читатели26K
image

Привет, Geektimes! Хочу представить свои наработки в исследовании в области искусственного интеллекта.
Читать дальше →

Путешествие в микромир

Время на прочтение8 мин
Охват и читатели59K
В предыдущей статье мы говорили о числах-гигантах. Можно сказать, что мы совершили путешествие к бесконечности, а когда подошли к Числу Грэма, то лично у меня создалось ощущение, что вот еще чуть-чуть – и мы прикоснемся к ней рукой. Сегодня я предлагаю вам еще одно путешествие. На этот раз в микромир – мир малых объектов. Настолько малых, что среди всех тех, которые мы рассмотрим, песчинка будет самой крупной. Сразу скажу, что эта статья не о физике. Мы не будем говорить о квантовых эффектах, принципе неопределенности и теории струн. Я не физик (впрочем, я думаю, что вы поняли это и на основании моего предыдущего текста). Это статья о цифрах, масштабах и красоте. Добро пожаловать.
Читать дальше →

Как спасти залитый ноутбук и минимизировать стоимость возможного ремонта?

Время на прочтение10 мин
Охват и читатели358K
Одна из самых распространенных проблем, с которыми обращаются в сервисные центры владельцы лэптопов – пролитая на устройство жидкость. Само по себе событие из ряда вон выходящее и крайне неприятное, но… Доходы мастеров сервиса могли бы быть несколько скромнее, а число выживших после омовения устройств значительно больше, если бы пользователи были чуточку повнимательнее и вовремя познакомились с правилами первой неотложной помощи для своих электронных друзей.

О технике “искусственного дыхания” для ненароком залитого ноутбука, о том, как по возможности снизить затраты на вероятный ремонт и повысить шансы на полное восстановление устройства мы расскажем в нашей статье.

мануал по восстановлению залитого ноутбука
Читать дальше →

«Хозяин, напиши для нас приложение». Требуется разработчик софта и железа для дронов DJI

Время на прочтение9 мин
Охват и читатели33K

Китайцы начали «пылесосить» сначала Китай, а теперь и весь мир, чтобы найти гениальных разработчиков приложений для своих дронов.

В 2014, сразу после того как DJI (китайский Google в области дроностроения) представили пакет средств для разработки (SDK), прошла первая олимпиада по разработке софта для дронов. Победители получили 100 000 юаней (около 900 000 руб). О первых трех местах — под катом.

В 2015 стартовала вторая олимпиада для программистов уже со всего мира. Итоги ее мы узнаем в конце лета.

Есть несколько проектов, которые, используя SDK от DJI, выпустили очень востребованные и коммерчески успешные программы для дронов.

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

А может быть вы хотите сделать 3d-скан горы Маттерхорн (4478м)?

Всех желающих написать софт для страж-птицы, добро пожаловать под кат. Иначе это сделают китайцы.
Читать дальше →

Как провести лето с пользой, или чем занять детей на каникулах

Время на прочтение4 мин
Охват и читатели9.1K


Наверняка, многие хабрагиктаймсжители когда-то были детьми. Причём большинство было детьми советскими, кому-то даже довелось побывать пионером. А поднимите руки, сколько из вас были октябрятами? В докапиталистические времена наше социалистическое государство заботилось о летнем времяпрепровождении юных поколений своих граждан. Поэтому многие из нас провели несколько месяцев своей жизни в таких местах, как пионерские лагеря. В целом это были неплохие места, хотя конкретные реализации в рамках страны имели невероятный разброс качества: от деревянных бараков с разбитой инфраструктурой до прекрасных капитальных кирпичных корпусов, разбросанных по огромной благоустроенной территории. В течение летних месяцев сотни детей разных возрастов приезжали в пионерские лагеря, чтобы под чутким, якобы, надзором воспитателей и вожатых проводить досуг на природе.
Читать дальше →

Пошаговая видео-инструкция для новичков 3д печати, как настроить 3д принтер

Время на прочтение1 мин
Охват и читатели9.2K


Подготовил видео-инструкцию, о том как же настраивать такого дикого зверя, как слайсер для 3д принтера. Когда начинал свой путь в 3д печати, очень не хватало такого видео, исправляем ситуацию.

Приятного просмотра.

Читать дальше →

Азбука электронщика: увлекательная теория, занимательная практика и полезные решения для начинающих

Время на прочтение4 мин
Охват и читатели61K
Я слушаю и забываю,
я вижу и запоминаю,
я делаю и понимаю.
Конфуций

Замечали ли вы, что интерес к электронике, радиотехнике, конструированию радиоэлектронных приборов в последнее время заметно возрос?

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



Понимая это, Мастер Кит начал выпуск серии наборов «Азбука электронщика».
Читать дальше →

10 правил хорошего тона при описании багов

Время на прочтение6 мин
Охват и читатели222K
Здравствуйте, меня зовут Наталья, я инженер по тестированию компании Docsvision.
Иногда, когда я просматриваю ошибки, записанные новенькими (а иногда и старенькими) тестировщиками, рука машинально тянется к лицу. В голове возникает только одна мысль:



«Что? Что я сейчас прочитала?»

В интернете много информации о том, ЧТО обязательно должно присутствовать в баг-репорте. А я решила поделиться с вами своими мыслями о том, КАК нужно писать баг-репорт, чтобы было понятно, о чём вы пишете.
В первую очередь, я писала это для инженеров по тестированию и инженеров технической поддержки, которые передают нам баги, присланные заказчиками. Также моя статья может помочь сформировать описание возникшей проблемы при обращении пользователя в техподдержку: корректное описание позволяет без дополнительных вопросов быстрее обработать инцидент.
Вообще её может быть полезно почитать всем членам команды разработки ПО, которые фиксируют своё общение в багтрекинговой системе.
Читать дальше →

Советы для начинающих hardware-стартапов

Время на прочтение9 мин
Охват и читатели12K


Пока мы прилежно трудимся с паяльниками в руках, начинающие стартапы жалуются, что «железо» – это сложно, и это постепенно становится нормой. Наши товарищи, занимающиеся ПО, беспокоятся, что мы можем заварить их MacBook’и, если те пятый раз на дню упомянут многовариантное тестирование.

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

Вот несколько советов, которые мы подготовили.
Читать дальше →

Функциональный DDS rенератор на ПЛИС

Время на прочтение11 мин
Охват и читатели79K
Недавно я увидел проект генератора сигналов на микроконтроллере AVR. Принцип генерации — DDS, на базе библиотеки Jesper максимальная частота — 65534 Гц (и до 8 МГц HS выход с меандром). И тут я подумал, что генератор — отличная задача, где ПЛИС сможет показать себя в лучшем виде. В качестве спортивного интереса я решил повторить проект на ПЛИС, при этом по срокам уложиться в два выходных дня, а параметры получить не строго определенные, а максимально возможные. Что из этого получилось, можно узнать под катом

Что получилось?

Идеальный путь внедрения статического анализатора кода

Время на прочтение20 мин
Охват и читатели6.9K
Apple II emulator for Windows
Одной из основных сложностей при использовании инструментов статического анализа является работа с ложными срабатываниями. Существует множество способов устранить ложные срабатывания, используя настройки анализатора или изменяя код. Я взял маленький проект Apple II emulator for Windows и покажу, как можно на практике работать с отчётом статического анализатора PVS-Studio. Покажу на примерах, как править ошибки и подавлять ложные срабатывания.
Читать дальше →

Метод конечных элементов на примере уравнения Пуассона

Время на прочтение2 мин
Охват и читатели39K
В данной статье мне хотелось бы изложить реализацию метода конечных элементов на примере уравнения Пуассона. Рассмотрим задачу:

image

с однородным краевым условием

image

где
image

image

image


Требуется найти функцию , решающую заданное уравнение.
Читать дальше →

Спасение утопающих — дело рук роботов

Время на прочтение4 мин
Охват и читатели6.4K


Современная робототехника сегодня разделена, по большому счёту, на четыре основные категории:

  • промышленные роботы, стационарные или перемещающиеся в пределах производственного помещения,
  • бытовые роботы (пока представлены, в основном, пылесосами),
  • военные роботы,
  • и роботы для развлечений.

Конечно, деление это весьма условное. Но все остальные категории пока находятся в состоянии разной степени зачаточности. Использование роботов имеет огромный потенциал во многих сферах деятельности. Но активное внедрение механических помощников пока сдерживается рядом факторов, и в первую очередь научно-техническими затруднениями. При этом одной из наиболее перспективных областей для роботизации является спасение людей в зонах крупных техногенных аварий и природных катастроф. Эта тема с годами становится всё актуальнее.
Читать дальше →

Радиоуправляемый катер на Arduino и радио модуле NRF24L01 из потолочной плитки

Время на прочтение2 мин
Охват и читатели62K
Хочу рассказать о моем увлечении радио моделями, в частности катерами.

Для управления моторами решил использовать ардуину и готовый пульт для квадрокоптеров. Данный пульт собран с использованием радио модуля NRF24L01, и к тому же один добрый человек раскодировал протокол.
Читать дальше →

Удобный лог не роскошь, а средство отладки, или как подключить dll при помощи h файла

Время на прочтение6 мин
Охват и читатели7.7K
image

ПроЛог


Не один программист, приступая к разработке приложения, не проходит мимо вопроса о логах. Вроде бы простой вопрос, но перебирая уже существующие варианты, понимаешь, что в каждом что-то неудобно: нет run-time отключения лога (только при компиляции), иногда нужно перенаправить лог в файл, иногда в communication port или еще куда-нибудь и т.д. и т.п. Писать полноценный вариант не хватает времени, а создавать наспех еще одну реализацию — рука не поднимается. И получается, как говорится, сапожник без сапог, даже еще хуже, ведь логи это инструмент разработки… А что если подойти к этому вопросу не спеша? Как разработчику мне бы хотелось видеть инструмент отладки таким:

  1. Легким и простым в использовании — чтобы можно было по умолчанию включить один h файл в проект и все заработало будь то старое или новое приложение.
  2. Расширяемым — чтобы добавив один h файл в проект, можно было нарастить функциональность настолько, насколько вам необходимо, не затрагивая при этом самого приложения (ведь часто приложение уже работает у клиента и трогать его не желательно).
  3. Конфигурируемым в полном объеме — разработчик в отличии от пользователя должен контролировать инструмент разработки в полной мере.

Читать дальше →

Генератор Федеративного Фильтра Калмана с использованием Генетических Алгоритмов

Время на прочтение18 мин
Охват и читатели25K
В рамках своей научной активности реализовал так называемый Федеративный Фильтр Калмана (Federated Kalman Filter). В этой статье рассказывается о том, что такое «Федеративный ФК», чем он отличается от обобщенного, а также описывается консольное приложение, реализующее данный фильтр и генетические алгоритмы для подбора параметров его математической модели. Приложение было реализовано с использованием TPL (Task Parallel Library), поэтому пост будет интересен не только специалистам по цифровой обработке сигналов.

UPD1: после прочтения двух недавних статей решил тоже присоединиться к эксперименту/исследованию/авантюре (называйте как хотите). В конце статьи добавил еще один опрос — "Стали бы Вы поощрать рублем такие узко специализированные статьи на Хабрахабре?".

Под катом описание и ссылка на сорцы

CH341A, USB-UART-конвертер и I2C/SPI-программатор за $5

Время на прочтение4 мин
Охват и читатели285K
Когда-то давным-давно я писал пару статей о широко известном в узких кругах чипе FTDI FT232H и различных его применениях. Всем хорош был FT232H для DIY, но и у него нашлось несколько недостатков — относительно неприятный для ручной пайки корпус LQFP48 (для истинных любителей хардкора есть еще вариант в QFN48, паяй — не хочу, DIHALT не даст соврать), цена за оригинальный чип от 250 рублей, вероятность проблем с драйверами на поддельных чипах и некоторая функциональная избыточность, к примеру, поддержка JTAG нужна далеко не всем.

Решение, как обычно, пришло из Поднебесной, в которой после нескольких лет тупого передирания творческой адаптации чужих чипов наконец выпустили свой собственный конвертер USB-TTL — WinChipHead CH341A в корпусе SOP-28 (не DIP, но тоже паяется без проблем).

Производство чипа было начато году приблизительно в 2006, но в поле моего зрения он попал только в 2014, когда I2C/SPI-программаторы на этом чипе наводнили европейский EBAY, причем продавцы предлагали цену от 3,5 евро вместе с доставкой, что при средней стоимости хорошего китайского программатора вроде MiniPro TL866A в 50 евро оказалось настолько заманчивым предложением, что устоять не получилось.

Если вам все еще интересно, что умеет этот китайский чип за 1$ и стоит ли платить больше, если не видно разницы — прошу под кат.
Читать дальше →

36 млн запросов в час, 10000+ постоянно работающих клиентов, на одном сервере, nginx+mysql

Время на прочтение5 мин
Охват и читатели117K
Сложилась ситуация, что участвую в проекте, который работает с достаточно большой нагрузкой. Как уже написал — 36 млн запросов в час. Я много чего прочитал и перепробовал за последний месяц, настраивая сервер; хотелось бы просто сжато и компактно выдать тезисно то, что работает хорошо в такой конфигурации.

Первое, что я заметил — множество советов как все настроить под большую нагрузку. Читайте их внимательно, обычно в тексте найдете, что речь про «высокую нагрузку» в 15-20 тысяч клиентов в сутки. У нас клиентов примерно миллион, активных, ежедневных.

У нас нет денег и мы все делаем за свой счет, поэтому экономим. Итог — весь миллион клиентов обслуживается на одном сервере, вот на таком — EX-60 на hetzner.
Читать дальше →

6 фраз которые могут изменить ваш подход к обслуживанию клиентов

Время на прочтение5 мин
Охват и читатели56K
Друзья, всем привет!

Мы продолжаем переводить и публиковать для вас лучшие материалы о поддержке клиентов. В данном материале речь пойдет о том, что использование определенных фраз может изменить восприятие информации вашими пользователями. «Словом можно убить, а можно вылечить человека» (с) — в отношении службы поддержки эта пословица особенно актуальна! Ниже приведены и разобраны шесть конкретных фраз, которые способны сделать ваших клиентов более счастливыми.



От переводчика: С оригинальной статьей вы можете ознакомиться по ссылке. Список ранее переведенных материалов доступен в конце поста. Приятного чтения, команда сервиса для поддержки клиентов Teamdesk.
Читать дальше →

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность