Михась
-
Постов
370 -
Зарегистрирован
-
Посещение
Сообщения, опубликованные Михась
-
-
Усиливаем переменку ОУ, далее на МК с АЦП, который тянет мегагерц. АЦП кладет в ОЗУ через ДМА. Через ДМА же передаем по SPI на 8 или 16 мегабит. Среда передачи по SPI - POF (что-то подобное AFBR-2624Z). Будут два волокна - одно для клока, второе для данных. Питание этой изолированной части - можно от батарейки.
На приемной части - МК с двумя SPI для приема. Передача на ПК по вкусу - можно через USB например.
-
Опубликовано · Изменено пользователем Михась · Пожаловаться
Только авиамодельный двигатель и к нему колхозить генератор через редуктор. Или использовать в качестве безредукторного генератора высокоскоростной двигатель с постоянными магнитами.
Если нужен мощный - то смотреть на парамоторы.
- 1
-
Сугубое ИМХО - импульсный метод, две катушки. На одну высоковольтный импульс, на другой смотрим отклик. На первый взгляд реально. Но характеристики маловероятно что кто-то подскажет, нужно экспериментировать. Давно делал макет импульсного промышленного МД, но там все осталось на уровне макета, заказчик отвалился. Только катушка была побольше и кусочки металла побольше.
-
Опубликовано · Изменено пользователем Михась · Пожаловаться
А какой еще продукт в пластиковой трубе, кроме частички металла? С какой максимальной скоростью может двигаться частичка металла?
-
-
Вроде в свое время на управляющие входы дисплея ставили конденсаторы и даже несколько помогало. Сколько уже не помню.
-
Опубликовано · Изменено пользователем Михась · Пожаловаться
Делал выделение производной от бародатчика. Для сравнения один и тот-же поток данных прогонял через Калмана и Альфа-Бета фильтры параллельно и сравнивал графики. В общем результат был одинаковый, когда подогнал эмпирически коэффициенты, но Калман получился процентов не 10 побыстрее. В общем, чужой опыт тут скорее всего не поможет.
-
20 hours ago, A.V.Avtomat said:
Откуда же это вычерпнул топикстартер?
Мопед не мой. Ссылку на конкретное изделие выкладывать не буду. Написал просто как казус.
-
-
Опубликовано · Изменено пользователем Михась · Пожаловаться
Попался в описании к расходомеру такой метод повышения устойчивости к помехам
-
3 hours ago, MrYuran said:
Опять же, какая вероятность, что отверстие...
Пф. У нас в офисе что-то прикручивали к стене и попали в горизонтальный провод. Бахнуло, вскрыли проводку, соединили.
Приняли решение перенести дюбели на 10 сантиметров выше. Первый нормально, второй опять бахнул. Оказалось провод шел не по горизонтали а немного с наклоном вверх.
-
Небаитесь, это надолго. Вангую что все перейдем на RISC-V во всяких модификациях. Китайцы на них сейчас делают МК дуром.
-
Опубликовано · Изменено пользователем Михась · Пожаловаться
Ну и тогда про стандарты - TFTP в базе не умеет удалять файлы, на сколько я вспомнил. А при маленьком объеме файловой системы это уже очень важно. Можно обойти заливкой специального командного файла, который содержит имя удаляемого файла. Но это уже будет нестандартная надстройка над TFTP.
И еще надо подумать, что бутлоадер помимо стека TCP/IP потянет за собой файловую систему.
-
54 minutes ago, makc said:
Уже лучше, когда в последний раз к ним смотрел ничего этого ещё не было. Правда там тоже полно ляпов, достаточно крупных. Сначала пишут MIK32:
Всякого такого и у Миландра хватало. Как обычно кто-то пишет, а вычитать свежим взглядом некому. Есть еще метод - надо выводить документ с вотермаркой DRAFT. И кто найдет косяк, пусть пишет на почту - получит бесплатную девборду.
-
1 hour ago, makc said:
Начать хотя бы с того, что у Миландра на них хотя бы есть спецификации. С белыми пятнами, местами кривые, но есть и можно заниматься разработкой. А где такие спецификации в открытом доступе на АМУР? Куцая Wiki и все? 🫢
Вот https://mikron.ru/products/iot/mk32-amur/#!/tab/672102497-3
-
В К1986ВЕ1FI, К1986ВЕ1GI кстати 100 мегабитный PHY!
-
Когда уже сделают просто аппаратный контроллер скалярного ПЧ, чтобы просто записать частоту и читать флаги аварий/состояний.
-
Интересно, сколько будет выход годных?
-
Щикарно. GPT chat писал?
-
Это библиотечная функция.
void ADC_StartOfConversion(ADC_TypeDef* ADCx)
{
ADCx->CR |= (uint32_t)ADC_CR_ADSTART;
}В общем, проблема, как я думаю, не в DMA. Будем смотреть дальше, может в скаде. Потому как просто сдвиг, это понятно. А сдвиг по кольцу - это уже не понятно.
Остальной код - это про другое.
-
48 minutes ago, Arlleex said:
Почему adc_raw не volatile?
DMA-то да, перезапускать не надо. Вот только АЦП может после N преобразований скинуть бит активации и ждать следующего "пинка". Я не вдавался в подробности исходника ТС, возможно у него так (полагаться на простыни SPL/HAL не хочу).
На сколько помню, так и есть.
-
Спасибо за замечания. Будем изживать недостатки.
-
Опубликовано · Изменено пользователем haker_fox
К названию темы добавил модель МК. Длинный код спрятал под спойлер. · Пожаловатьсясобственно на одном из приборов, с которого длительно пишется информация в скаду, проявился дефект.
Прибор имеет 8 каналов АЦП (STM32F030), которые преобразовывают напряжение в температуру. Произошел сбой порядка чтения температур на один канал, т.е данные со второго канала попали в первый и т.д.
Грешу на сбой DMA, т.к. все остальные преобразования производятся последовательным вызовом одной функции без статических переменных. После сброса прибора показания нормализовались, до этого он не выключался примерно несколько месяцев.
Ситуация очень нехорошая, т.к. температуры все не сильно отличаются и как такой сбой диагностировать для меня полная загадка.
***********************************************************
Версия с DMA не подходит, т.к. в массив температур в этом случае попали бы коды температуры процессора и ИОН!
**********************************************************
Spoiler/*---------------------------------------------------------------------------- * Name: 12ADC.с * Purpose: * Note(s): *---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #include "stm32f0xx_conf.h" #include "stm32f0xx.h" #include "stm32f0xx_it.h" #include "12ADC.h" //-------- Работа с АЦП -------------------------------------------------------- // ДМА кладет первый отсчет регулярного канала в 1 ячейку, // видимо есть неочищенные флаги при запуске // 8 - на отсчеты adcin A0-A7 // 2 - VREF + internal TermoDat #define SIZEADCBUFF (8+2) // размер буфера данных АЦП #define ADC1_DR_Address ((uint32_t)0x40012440) #define CODE_FULL 4095 // АЦП 12 бит // local static uint16_t adc_raw[SIZEADCBUFF]; static volatile bool endconversion; /******************************************************************************* * Режим АЦП, когда данные по нескольким каналам передаются через DMA напрямую в ОЗУ * АЦП запускается по команде ADC_StartOfConversion(ADC1); * Генерируется прерывание обработчика массива Parameter: * Return: Тактирование - 14 мгц от внутр. RC генератора HSI14 14М/239 = 58577 Гц - частота семплирования для одного канала (17.1uS) Для 10 каналов результат будет с частотой 5857 Гц или каждые 170uS При времени семплирования 239.5 периодов входное сопротивление 50 килоом *******************************************************************************/ void ADC12_init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | \ GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | \ GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOA, &GPIO_InitStructure); /* DMA1 channel1 configuration ----------------------------------------------*/ DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adc_raw; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = (SIZEADCBUFF); DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); // Включим прерывание от ДМА по окончанию передачи блока DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); // весь блок NVIC_EnableIRQ(DMA1_Channel1_IRQn); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular); ADC_DMACmd(ADC1, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 2; //наименьшему число соответствует больший приоритет NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward; ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channel configuration */ ADC_ChannelConfig(ADC1, ADC_Channel_0, ADC_SampleTime_239_5Cycles); // PA0 ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_239_5Cycles); // PA1 ADC_ChannelConfig(ADC1, ADC_Channel_2, ADC_SampleTime_239_5Cycles); // PA2 ADC_ChannelConfig(ADC1, ADC_Channel_3, ADC_SampleTime_239_5Cycles); // PA3 ADC_ChannelConfig(ADC1, ADC_Channel_4, ADC_SampleTime_239_5Cycles); // PA4 ADC_ChannelConfig(ADC1, ADC_Channel_5, ADC_SampleTime_239_5Cycles); // PA5 ADC_ChannelConfig(ADC1, ADC_Channel_6, ADC_SampleTime_239_5Cycles); // PA6 ADC_ChannelConfig(ADC1, ADC_Channel_7, ADC_SampleTime_239_5Cycles); // PA7 ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor, ADC_SampleTime_239_5Cycles); ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint, ADC_SampleTime_239_5Cycles); ADC_TempSensorCmd(ENABLE); // температурный датчик ADC_VrefintCmd(ENABLE); // ИОН ADC_GetCalibrationFactor(ADC1); ADC_Cmd(ADC1, ENABLE); ADC_StartOfConversion(ADC1); ADC_DMACmd(ADC1, ENABLE); // Далее АЦП будет работать в автоматическом режиме // готовые данные по DMA складывать в массив в ОЗУ. } static uint16_t flash_read(uint32_t address) { return (*(__IO uint16_t*) address); } /******************************************************************************* * Измерение напряжения питания AVCC * Parameter: Код с канала внутреннего ИОН (можно отфильтровать) * Return: Напряжение питания АЦП AVCC в мВ *******************************************************************************/ static int16_t get_AVCC(uint16_t Vrefint_code) { // Читаем корректировочный код VREF при 3.3В из FLASH uint16_t VREF_CAL = flash_read(0x1FFFF7BA); uint16_t AVCC = (VREF_CAL * 3300) / Vrefint_code; return AVCC; } /******************************************************************************* * Преобразование кода канала в напряжение после делителя Parameter: Return: напряжение в милливольтах *******************************************************************************/ static uint16_t get_vCn(uint16_t cn_code, int16_t avcc) { uint32_t voltage = ((uint32_t)cn_code * avcc) / CODE_FULL; // напряжение в мВ без делителя return (uint16_t)voltage; } /******************************************************************************* * Измерение температуры на сенсоре CPU Parameter: код канала температуры, значение питания АЦП в милливольтах Return: температура в градусах цельсия *******************************************************************************/ //#define TEMP110_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7C2)) //#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7B8)) //#define VDD_CALIB ((uint16_t) (330)) // для F030 измерения при 3.3В //static int16_t get_temperatureCPU_051(int16_t code_temper, int32_t AVCC) //{ // int32_t temperature = ((code_temper * (AVCC / 10) / VDD_CALIB) - (int32_t)(*TEMP30_CAL_ADDR)); // temperature = temperature * (int32_t)(110 - 30); // temperature = temperature / (int32_t)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR); // temperature = temperature + 30; // return (int16_t)temperature; //} /* Temperature sensor calibration value address */ #define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7B8)) // сохраненный результат в кодах АЦП при 30грС #define VDD_CALIB (3300) // в милливольтах #define AVG_SLOPE (4300) // в экземпле 5336 в даташите 4300 //AVG_SLOPE in ADC conversion step (@3.3V)/°C multiplied by 1000 for precision on the division static int16_t get_temperatureCPU_030(int16_t code_temper, int32_t AVCC) { int32_t temperature = ((uint32_t) *TEMP30_CAL_ADDR - ((uint32_t)code_temper * AVCC) / VDD_CALIB) * 1000; temperature = (temperature / AVG_SLOPE) + 30; return (int16_t)temperature; } /******************************************************************************* * Получение всех параметров из кода АЦП * Parameter: напряжение канала в милливольтах температура кристалла в градусах напряжение на CPU в милливольтах * Return: *******************************************************************************/ void meas_analog12(int32_t * Cn0_voltage, int32_t * Cn1_voltage, int32_t * Cn2_voltage, int32_t * Cn3_voltage, int32_t * Cn4_voltage, int32_t * Cn5_voltage, int32_t * Cn6_voltage, int32_t * Cn7_voltage, int16_t * CPU_temp, int16_t * avccCPU) { if(endconversion == true) { // вычисляем напряжение питания контроллера uint16_t U_AVCC = get_AVCC(adc_raw[0]); // измеряем напряжение *Cn0_voltage = get_vCn(adc_raw[1], U_AVCC); *Cn1_voltage = get_vCn(adc_raw[2], U_AVCC); *Cn2_voltage = get_vCn(adc_raw[3], U_AVCC); *Cn3_voltage = get_vCn(adc_raw[4], U_AVCC); *Cn4_voltage = get_vCn(adc_raw[5], U_AVCC); *Cn5_voltage = get_vCn(adc_raw[6], U_AVCC); *Cn6_voltage = get_vCn(adc_raw[7], U_AVCC); *Cn7_voltage = get_vCn(adc_raw[8], U_AVCC); *CPU_temp = get_temperatureCPU_030(adc_raw[9], U_AVCC); *avccCPU = U_AVCC; endconversion = false; } else { *Cn0_voltage = 0; *Cn1_voltage = 0; *Cn2_voltage = 0; *Cn3_voltage = 0; *Cn4_voltage = 0; *Cn5_voltage = 0; *Cn6_voltage = 0; *Cn7_voltage = 0; *CPU_temp = 0; *avccCPU = 0; } ADC_StartOfConversion(ADC1); } /*---------------------------------------------------------------------------- Обработчик прерывания от DMA - АЦП по окончании передачи блока *---------------------------------------------------------------------------*/ void DMA1_Channel1_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC1)) { endconversion = true; DMA_ClearITPendingBit(DMA1_IT_TC1); } } //-------------------------------------------------------------------------------
-
On 9/22/2023 at 6:45 PM, x893 said:
Есть примеры готовых изделий ?
Аналог их анализатора применяется в медицине. По сути там картридж- бумажка пропитанная специфическим реагентом, меняющим окраску. В коробочке стоит тупая веб-камера, передает в ПО, которая анализирует изменение окраски, пишет в базу результаты и печатает отчет. Продается государству за сотни тысяч.
performance risc-v
в RISC-V
Опубликовано · Изменено пользователем Михась · Пожаловаться
Сначала надо понять, что есть целое семейство ядер RISC-V. Самое младшее - совсем дохлое, нет даже аппаратного умножения.
Вот например, какие варианты предлагает WCH
http://joxi.ru/82QolW6S4npwJr