Перейти к содержанию
    

amaora

Участник
  • Постов

    778
  • Зарегистрирован

  • Посещение

  • Победитель дней

    3

Сообщения, опубликованные amaora


  1. 9 hours ago, juvf said:

    а с какой цифры начинается много? лично для меня и 128 бит много. Нужно массив в 10 байт - выделяем 128. 👍 

    При использовании DMA обычно выравнивать надо и кэш отключать, размер становится больше. Да и 10 байт я бы и без DMA вероятно заменил на 16.

     

    3 hours ago, Arlleex said:

    Посмотрел цитаты великого цитируемого (с моими скромными комментами)

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

  2. 6 hours ago, MPetrovich said:

    Я правильно понимаю, что, подав на соответствующие фазы соответствующие величины постоянных напряжений (которые сформируются ШИМом нужного заполнения), я могу удерживать ротор двигателя в неподвижном  состоянии? Даже под нагрузкой (например - подвешен груз на лебедке)? 

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

  3. 1 hour ago, AlanSbor said:

    Расшифрую более подробно:  Нужна программа умеющая строить правильно графики такой размерности.

    То есть, нужна рисовалка графиков умеющая работать с длинными числами произвольной разрядности? И умеющая рисовать графики синусов на 10^2000 периодов (преобразовывать их в заливку прямоугольника 😆)?

    А памяти видимо не хватает для хранения всех точек графика?

    • Upvote 1
  4. 53 minutes ago, MPetrovich said:

    А эти проекции вектора на координаты являются двумя каким-либо фазами или чем-то ещё?

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

  5. On 4/10/2024 at 10:47 PM, MPetrovich said:

    Не понял что такое двухфазный вектор... 

    В прямоугольной системе координат, вектор из двух элементов.

     

    On 4/10/2024 at 10:47 PM, MPetrovich said:

    Я полагаю это метод управления двигателем по двум фазам, в то время, как третья на земле (нижний ключ фазы открыт). Я таким пользуюсь, но в скалярном режиме.

    Да, как на картинке. Вектор напряжения (межфазные напряжения) на выходе при этом остаётся тот же. Можно и к питанию аналогично прижиматься,  менять это прижатие вниз или вверх в зависимости от того через какие ключи ток больше, и другие варианты.

  6. On 4/9/2024 at 12:48 PM, MPetrovich said:

    Итак, насколько я смог понять, в процессе управления на стойках силовых ключей формируются векторы токов задающих направление магнитного поля в статоре и момент вращения ротора. Векторы тока в стойках формируются синусоидальными ШИМ-сигналами. В процессе вращения чередуются базовые векторы - в каждом секторе в 60гр. оперируют по два базовых вектора. Вот с этого места у меня начинается непонимание.

    Есть более простое (на мой вкус) объяснение.

    Представьте, что эти стойки моста являются управляемыми источниками напряжения. Про ШИМ пока можно даже не думать и принять за выходное напряжение среднее значение за период ШИМ. Один раз настраиваете синхронное формирование ШИМ для трёх каналов, и дальше работаете только с заданными напряжениями (заполнениями ШИМ) по трём каналам, ничего не думая о том в какой момент какие ключи включены а какие выключены.

    Преобразовать заданный двухфазный вектор в значения напряжений по трём каналам тоже проще в векторном виде, не надо рассматривать секторы и таблицы базисных векторов, не надо работать с угловыми величинами. Игры с минимизацией переключения достигаются прибавлением к значениям напряжения по всем каналам выбранной константы (тк. это не меняет заданный вектор), так чтобы например наименьшее значение всегда было 0 (то есть одна фаза оказывается с заполнением 0% фактически без ШИМ).

    Результат будет тот же, но проще и эффективнее, не знаю почему об этом мало пишут в литературе, наверно так проще только мне.

  7. 3 hours ago, EdgeAligned said:

    На STM32F103C8 невозможно сделать мостовое управление биполярным ШД - есть всего один таймер с тремя комплиментарными выходами - TIM1.   Без комплим.выходов вы не сделаете эффективного и безопасного управления мостами.

    Можно соединить начала двух обмоток ШД, тогда будет три вывода и управлять по трём каналам. Но будет потеря по доступному диапазону напряжения до уровня 1/sqrt(2).

  8. On 4/5/2024 at 11:31 AM, Zuse said:

    Вопрос: зачем измеряются все три тока?.. Ведь сумма токов равна нулю и достаточно измерить токи в двух фазах. 

    Если измерения сделаны по шунтам внизу, то начиная с некоторого значения заполнения близкого к 100% измерения становятся непригодными к использованию (время установления после переключения). Но из трёх каналов можно выбрать два в которых заполнение меньше порогового и измерения достаточно точные. Если бы были доступны лишь два канала измерения, то периодически могли бы складываться условия, что годное измерение только в одном канале. Такое происходит на максимальной скорости, когда дальнейший разгон упирается в напряжение питания.

    В дешёвых BLDC контроллерах часто вижу некачественную трассировку, из-за которой DC/DC сильно шумят на измерительные цепи. Во всех трёх каналах наблюдается случайный шум, но он коррелированный (почти одинаковый) по всем каналам. Наличие трёх каналов позволяет компенсировать (вычитать) шум при пересчёте тока из трёх фаз в две, пока по всем каналам выполняется условие по величине заполнения. В хорошо спроектированном контроллере комбинирование трёх каналов позволяет немного уменьшить случайную составляющую погрешности измерения тока.

    Для дополнительного контроля и диагностики тоже полезно иметь избыточность в измерениях.

     

  9. 28 minutes ago, A.V.Avtomat said:

    Не понял, в чём вопрос или сомнение?

    Узнать кто как решает подобную задачу.

     

    29 minutes ago, A.V.Avtomat said:

    Ничто не мешает в "мёртвый' период измерить сопротивление нагретой обмотки правильно

    Как именно?

  10. В начале расскажу как измерение делаю сейчас, а после жду отзывов и предложений. Двигатель допустим трехфазный PMSM, но это не сильно важно. Сопротивление обмоток статора порядка ~4 мОм и хочется измерять его с точностью не хуже 10-20%.

    Двигатель подключён к мосту из MOSFET ключей (Rdson ~ 0.8 мОм), доступны измерения тока и напряжения на всех фазных выводах. Используется симметричная ШИМ, а выборки значений тока делаются по центру периода, выборки напряжения чуть позже (+1 мкс). Частота ШИМ 28 кГц, разрешение таймера 2940. Величина DeadTime и минимального импульса около 200 нс, в зависимости от схемотехники конкретного контроллера от 70 до ~600 нс.

    Измерение сопротивления очевидно производится с помощью известного выражения Rs = U / I. Где, U - вычисляется исходя из напряжения звена постоянного тока и коэффициента заполнения модуляции, I - измеряется непосредственно. Основные погрешности возникают от того, что U известно не точно из-за подавления импульсов малой длительности и неопределённости во время DeadTime. Что делается для компенсации погрешности измерения U?

    1) Величина заполнения модуляции поднята по всем фазам на длительность минимального импульса, таким образом исключается нелинейность на малых значениях заполнения;

    2) Измерение делается на двух значения тока (20А и 5А) с помощью выражения Rs = (U1 - U0) / (I1 - I0), таким образом исключается постоянная составляющая в U, которая может появится из-за DeadTime;

    3) Используются измерения фазных напряжений для восстановления фактической длительности импульсов и компенсации погрешности из-за DeadTime. Схема аналогична интегрированию напряжения в течение периода модуляции, но в моем случае вместо интегратора используется аналоговый RC фильтр (с постоянной времени ~25 мкс) перед АЦП и цифровой КИХ после АЦП, который восстанавливает среднее за период напряжение по двум последовательным выборкам.

     

    Допустим напряжение звена постоянного тока 30в. Погрешность измерения Rs без этих компенсаций составила бы (200e-9 / 35e-6) * 30 (В) / (20 - 5) (А) ~ 11 мОм, что неприемлемо много. С компенсацией есть варианты, например когда, используется п.3 и не используется разница доходит до 3 мОм. То есть видимо, одних только п.1 и п.2 недостаточно, а на п.3 я не очень рассчитываю из-за того, что там делается самокалибровка коэффициентов FIR по результатам которой можно судить лишь о дифференциальной точности измерения среднего напряжения, но не по абсолютному значению. Другими словами, достаточно точный результат получается, только когда используются все три пункта.

    Точность оцениваю увеличивая ток (40А, 60А, ...) зондирования и уменьшая напряжение звена постоянного тока (15в), если оценка Rs при этом не уходит больше требуемых 10-20%, то считаю измерения достаточно точными. Эталона или средств измерения таким малых сопротивлений у меня нет.

     

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

     

  11. 1 hour ago, EdgeAligned said:

    Вот интересно. Отписавшиеся тут просто перепечатывают интернет-информацию. Ну а самостоятельно кто-либо на деле применял этот фильтр Калмана? Вот что бы не по описанному в инете, а на своем чисто натурном опыте в натуре?

    EKF - наблюдатель положения PMSM для бездатчикового управления;

    SRUKF (QR) - калибровка IMU;

     

    А так же экспериментальные реализации разных численных методов на тестовых задачах.

    • Upvote 1
  12. Наибольший интерес представляет оценивание неизвестных параметров недоступных для прямого измерения по измерениям других связанных с ними параметров. Для понимания я бы рекомендовал сначала ознакомится с Байесовским выводом и например фильтром частиц. А разные варианты фильтра Калмана являются удобным частным случаем при условии нормального распределения вероятностей.

  13. 1 hour ago, аксим-м said:

    Все что выше-это на оптике с раздельными источниками.Почему?...Да потому что надежность хреновая.Возможно еще какие-то

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

    прожигало все вплоть до мозгов

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

  14. Гамма коррекция может быть нужна например при рисовании графических примитивов со сглаживанием (antialiasing). На границах будут полутона и результат не всегда хорошо выглядит без подстройки гамма коррекции под конкретный дисплей.

  15. 4 minutes ago, EdgeAligned said:

    EXTIx по фронту для  определения момента смены направления

    В ODrive так делают. Но мне не нравится неопределённость, не знаю как часто будет происходить это прерывание, и приоритет ему надо дать высокий. В худшем случае на предельно высокой частоте издержки будут выше (на вход/выход из прерываний), чем если поллингом через DMA.

  16. Делаю обработку сигналов STEP/DIR или CW/CCW на stm32f4. Как я понял нет никакой возможности настроить таймер, так чтобы он считал импульсы STEP с учётом направления заданного уровнем DIR. Для CW/CCW можно задействовать два таймера в режиме счётчика внешних импульсов, но не сошлось по ногам (оба входа идут на один таймер), да и не важен этот режим если не работает STEP/DIR.

    Все, что удалось придумать это поллинг GPIO регистров с помощью DMA и дальнейший ручной анализ фронтов. Сейчас это отнимает около ~2.5 мкс (каждые 35 мкс) при частоте опроса 500 кГц. Как можно сделать лучше?

    Spoiler
    void STEP_mode_DMA()
    {
    	/* Enable clock.
    	 * */
    	RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
    	RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
    
    	hal.STEP_frequency = (hal.STEP_frequency < 50000) ? 50000
    		: (hal.STEP_frequency > CLOCK_TIM8_HZ) ? CLOCK_TIM8_HZ : hal.STEP_frequency;
    
    	TIM8->CR1 = 0;
    	TIM8->CR2 = 0;
    	TIM8->SMCR = 0;
    	TIM8->DIER = TIM_DIER_UDE;
    	TIM8->CCMR1 = 0;
    	TIM8->CCMR2 = 0;
    	TIM8->CCER = 0;
    	TIM8->CNT = 0;
    	TIM8->PSC = 0;
    	TIM8->ARR = CLOCK_TIM8_HZ / hal.STEP_frequency;
    	TIM8->CCR1 = 0;
    	TIM8->CCR2 = 0;
    	TIM8->CCR3 = 0;
    	TIM8->CCR4 = 0;
    
    	hal.STEP_frequency = CLOCK_TIM8_HZ / TIM8->ARR;
    
    #define XGPIO_GET_IDR(xGPIO)	(GPIOA_BASE + 0x0400U * XGPIO_GET_PORT(xGPIO) + 0x10U)
    
    	/* DMA on TIM8_UP.
    	 * */
    	DMA2_Stream1->CR = (7U << DMA_SxCR_CHSEL_Pos) | DMA_SxCR_PL_1
    		| (1U << DMA_SxCR_MSIZE_Pos) | (1U << DMA_SxCR_PSIZE_Pos)
    		| DMA_SxCR_MINC | DMA_SxCR_CIRC;
    	DMA2_Stream1->NDTR = STEP_DMA_MAX;
    	DMA2_Stream1->PAR = (uint32_t) XGPIO_GET_IDR(GPIO_STEP);
    	DMA2_Stream1->M0AR = (uint32_t) priv_STEP.dmabuf;
    	DMA2_Stream1->FCR = DMA_SxFCR_DMDIS;
    
    	priv_STEP.dma_rp = 0;
    
    	priv_STEP.wire_STEP = GPIO_get_STATE(GPIO_STEP);
    	priv_STEP.wire_DIR = GPIO_get_STATE(GPIO_DIR);
    
    	priv_STEP.NCNT = 32767;
    
    	/* Start TIM8.
    	 * */
    	TIM8->CR1 |= TIM_CR1_CEN;
    
    	/* Start DMA2.
    	 * */
    	DMA2_Stream1->CR |= DMA_SxCR_EN;
    
    	/* Enable STEP/DIR pins.
    	 * */
    	GPIO_set_mode_INPUT(GPIO_STEP);
    	GPIO_set_mode_INPUT(GPIO_DIR);
    
    	GPIO_set_mode_PULL_DOWN(GPIO_STEP);
    	GPIO_set_mode_PULL_DOWN(GPIO_DIR);
    }
    
    int STEP_get_POSITION()
    {
    	int		wp = (STEP_DMA_MAX - DMA2_Stream1->NDTR) & (STEP_DMA_MAX - 1);
    	int		rp = priv_STEP.dma_rp;
    
    #ifdef STM32F7
    	/* Invalidate D-Cache.
    	 * */
    	SCB_InvalidateDCacheByAddr((uint32_t *) priv_STEP.dmabuf,
    			sizeof(uint16_t) * STEP_DMA_MAX);
    #endif /* STM32F7 */
    
    #define XGPIO_GET_STATE(xGPIO, IDR)	((IDR & (1U << XGPIO_GET_N(xGPIO))) ? 1 : 0)
    
    	if (hal.STEP_mode == STEP_ON_STEP_DIR) {
    
    		while (likely(rp != wp)) {
    
    			uint16_t	IDR = priv_STEP.dmabuf[rp];
    			int		wire_STEP, wire_DIR;
    
    			wire_STEP = XGPIO_GET_STATE(GPIO_STEP, IDR);
    			wire_DIR = XGPIO_GET_STATE(GPIO_DIR, IDR);
    
    			if (unlikely(		priv_STEP.wire_STEP == 0
    						&& wire_STEP != 0)) {
    
    				if (wire_DIR != 0) {
    
    					priv_STEP.NCNT++;
    				}
    				else {
    					priv_STEP.NCNT--;
    				}
    			}
    
    			priv_STEP.wire_STEP = wire_STEP;
    			priv_STEP.wire_DIR = wire_DIR;
    
    			rp = (rp + 1) & (STEP_DMA_MAX - 1);
    		}
    	}
    	else if (hal.STEP_mode == STEP_ON_CW_CCW) {
    
    		while (likely(rp != wp)) {
    
    			uint16_t	IDR = priv_STEP.dmabuf[rp];
    			int		wire_CW, wire_CCW;
    
    			wire_CW = XGPIO_GET_STATE(GPIO_STEP, IDR);
    			wire_CCW = XGPIO_GET_STATE(GPIO_DIR, IDR);
    
    			if (unlikely(		priv_STEP.wire_STEP == 0
    						&& wire_CW != 0)) {
    
    				priv_STEP.NCNT++;
    			}
    
    			if (unlikely(		priv_STEP.wire_DIR == 0
    						&& wire_CCW != 0)) {
    
    				priv_STEP.NCNT--;
    			}
    
    			priv_STEP.wire_STEP = wire_CW;
    			priv_STEP.wire_DIR = wire_CCW;
    
    			rp = (rp + 1) & (STEP_DMA_MAX - 1);
    		}
    	}
    
    	priv_STEP.dma_rp = rp;
    
    	return priv_STEP.NCNT;
    }

     

     

×
×
  • Создать...