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

Xenia

Модератор FTP
  • Постов

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

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

    2

Xenia стал победителем дня 18 марта 2023

Xenia имел наиболее популярный контент!

Репутация

31 Очень хороший

Информация о Xenia

  • Звание
    Гуру
    Гуру
  • День рождения 2 июня

Контакты

  • ICQ
    Array

Информация

  • Город
    Array

Посетители профиля

15 081 просмотр профиля
  1. Виновата - килогерцы с мегагерцами спутала.
  2. Возможно, что я отстала от жизни :), но по моим представлениям 1000 SPS (а тем более 4000 SPS) не совместимо с требованием иметь разрешение в 20-24 разряда. Высокоразрядные АЦП, как правило, относятся к типу "сигма-дельта", чья высокая разрядность базирутся на принципе интегрирования входного сигнала на всем протяжении периода измерения. Именно благодаря такому усреднению удается уменьшить уровень шума и тем самым повысить число значащих бит в результате. Но по мере того, как мы увеличиваем частоту оцифровки данных, период измерения сокращается и эффект от усреднения всё меньше дает пользы. Оттого и разрешение с ростом частоты сэмплирования неизбежно уменьшается. Поэтому, на мой взгляд, при частоте сэмплирования свыше 1 МГц стоило бы использовать обычный SAR и смириться с разрядностью 16 бит.
  3. STM32F411 и I2C

    Через Transmit и Receive у меня тоже не получалось читать датчики, но для этой цели хорошо подошла функция: HAL_I2C_Mem_Read( &hi2c1, devAddress << 1, regAddress, 1, pData, 2, I2C_TIMEOUT10); куда сразу закладываем номер регистра данных - regAddress и адрес буфера на 2 байта, куда надо прочесть данные - pData. Т.е. всё делает одна эта функция. В вашем случае это будет выглядеть так: HAL_I2C_Mem_Read( &hi2c1, I2C_ACL_ADRESS << 1, rgMgnAdress, 1, &rgMgnData, 2, I2C_TIMEOUT10); Внимание! в качестве rgMgnAdress следует класть число (в вашем случае 0x4F), а не адрес памяти, где оно лежит! Вероятно в этом ваша ошибка. HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  4. Это у меня восприятие такое - заменить плату или прошивку кажется мне легким делом (особенно, если прошивку сама писала, а плата и драйвер не интегрированы в одно целое). Тогда как что-то делать с железом кажется мне непосильным трудом, а предложение добавить "синхронизирующий вал" вгоняет в ужас 🙂.
  5. Золотые слова :). Судя по картинке, двигатели там относительно маломощные (на вид Nema17), а для таких есть дешевые драйверы на ток до 2А. У меня, например, стоят A4988 на каждый двигатель (у меня их 4 штуки). Лот из 5-ти штук на Aliexpress за $1 когда-то покупала. Ныне, когда 3D-принтеры широко распространены, драйверы для них достать очень легко.
  6. А чем это плохо? Или вы, когда в следующий раз станок включите, ожидаете, что шаговый двигатель останется на том же шаге, на котором вы его в прошлый раз выключили? А если при включении станка вы свой двигатель позиционируете, гоняя до ближайшего концевого выключателя, то вам должно быть безразлично, в каком положении остался двигатель в прошлый раз. Почему бы тогда вам ни поставить второй концевой выключатель, а этот раз на максимум?
  7. Вместо пинга я пользуюсь программой NMAP (https://nmap.org), которой сканирую всю сетку. К сожалению, при подключении моей платы к роутеру новый IP-узел не появляется.
  8. Все равно не работает... А может быть DHCP не надо отключать? Пусть роутер присвоит свой IP - тогда уж сеть у компьютера и платы с гарантией будет одинаковой, раз уж они в один и тот же роутер воткнуты. Или это плохая идея? P.S. И вообще для меня было бы большим облегчением увидеть своими глазами исходники рабочего проекта, написанного на HAL (CubeMХ) в конфигурации "DP83848+RMII". Без RTOS. В репозитории (\Repository\STM32Cube_FW_F4_V1.28.0\Projects\) уже искала, но там только под MII есть примеры, тогда как у меня на плате DP83848 кормит отдельный генератор на 50 МГц (именно генератор, а не резонатор). А раз так то я вынуждена режим RMII использовать. Это было бы для меня наиболее эффективной помощью, т.к. у меня не хватает наглости просить участников нашей конференции, чтобы они искали ошибки в моем программном коде.
  9. Из ваших объяснений не поняла, в каком месте надо выставить IP и какой. Но больше всего я боюсь, что, перенастроив ПК на связь с платой, я лишусь интернета. На эту мысль меня наводит тот факт, что на ПК DHCP у меня включен, а на плате выключен. Именно такой совет мне был дан: А пока DHCP на вкладке CubeMX не выключишь, статический IP адрес он ввести не дает. Вот оно как у меня: Тогда как в настройках ПК ситуация выглядит так:
  10. Однако не заработало оно у меня... Однако я задам вопрос не о возможных причинах этого (тем более, что их может быть очень много), а о том, как этот пинг проверять. Пока что я просто соединила пач-кордом Ethernet-гнездо на плате с Ethernet-гнездом на материнской плате компьютера. Результат таков: компьютер крутит колесико (у меня Win7) в поисках интернет-сети, но так ее и не находит. Оно и понятно, т.к. моя плата предоставить выход в интернет не может. А поскольку сети компьютер не находит, то я и не могу поглядеть , какие TCP/IP-адреса в ней есть. Сперва я подумала, что в программе у меня ошибка и поэтому вместо самодельно-запрограммированной платы поставила другую плату (иной конструкции), где какая-то заводская прошивка для Ethernet уже была. Но результат получила точно такой же. От этого и закралась у меня мысль, что может быть я платный Ethernet неправильно проверяю? Вдруг компьютер надо как-то иначе настраивать, чтобы он такую плату в своем окружении увидел?
  11. Покупала себе под шаговые двигатели вот такую плату: https://aliexpress.ru/item/1005004770273121.html на ней STM32G407 стоит. А раньше использовала MKS-GEN V1.4 на контроллере ATmega2560. Обе платы рассчитаны на управление шаговыми двигателями на 3D-принтере. До тока 2А хватает наплатных драйверов, а при больших токах надо использовать внешние. Код прошивки брала оттуда же - https://github.com/MarlinFirmware/Marlin/ но перед компиляцией вносила в него свои поправки. Оно так и положено, поскольку 3D-принтеры у всех разные.
  12. Что-то стоит 🙂 . Согласилась. Впрочем решение своей проблемы я кажется нашла - это именно та функция, что стояла внутри while'ов. Она достаточно надежно определяет, когда шина I2C лишается подтяжки: __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) Причем работает она максимально быстро, т.к. представляет собой дефайн, который при флаге I2C_FLAG_BUSY тождественен проверке бита: SR2.BUSY например, так: if ((I2C1->SR2 & I2C_SR2_BUSY) != 0) { читать и писать нельзя, зависнет! } Уже испытала: при обеих подтяжках (SCL и SDA) SR2.BUSY = 0, а если хотя бы от одной из них оторвать подтяжку, то SR2.BUSY > 0. Правда после возвращения подтяжки на место, в ноль она возвращаться не хочет, но после "взбадривания" на ноль возвращается.
  13. Потому что в данном случае "зависание" является не каким-то событием, наступление которого можно отследить трассировкой, а похоже, что является бесконечным циклом, по которому можно ходить трассировщиком бесконечно долго. Но есть и короткие циклы типа: while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); из которых не выходит никогда. И таких мест в этом файле 19 штук. Вот что нашел поиск по команде find: ---------- STM32F1XX_HAL_I2C.C while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status) while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
  14. Именно так и сделала - заменила I2C-ключи на управляемые уровнем, вот такие: https://wiki.iarduino.ru/page/silovoy-klyuch-trema-modul/ Но такого рода исправление касается только "критического блока", где переключение клапанов происходит часто (потому и вероятность сбоя там выше). Однако есть там один датчик, который только по I2C способен работать. И если он вызовет зависание контроллера, то и "критическому блоку" тоже каюк, т.к. контроллер у них один и тот же.
  15. Про это я читала раньше, но суть этой заметки в целом сводится к детализации реализации совета, который сама компания ST дала в Errara ("STM32F10xx8 and STM32F10xxB silicon limitations"). На мой взгляд этот способ плохой, т.к. он занимает много времени и срабатывает не всегда. По этому поводу я уже проводила собственные исследования и изобрела лучший способ :), который работает более надежно и к тому же гораздо более простой. Однако в той статье описана борьба с другой проблемой - той, когда статус BUSY выдается ошибочно, в то время как с подтяжками на линиях I2C всё в порядке. Т.е. это отнюдь не моя проблема, поскольку там на операциях чтения и передачи контроллер не зависает, а честно выдает ошибку HAL_BUSY. Поэтому в том случае действительно возможен алгоритм, основанный на принятии мер , "взбадривающих" I2C, после того, как транзакция окончилась неудачей. Тогда как у меня проблема иная - неудачная транзакция приводит к зависанию с последующим ресетом по WаtchDog. Т.е. мне нечего лечить, т.к. наступает полный пипец. К этому стоит добавить, что мой контроллер по I2C-шине управляет силовыми ключами, вот такими (на ток 10А): https://wiki.iarduino.ru/page/power-key-4n-i2c-datasheet/ А те, в свою очередь, переключают клапана на линиях, по которым перекачиваются "агрессивные" жидкости. Это, так называемый, "градиент низкого давления", когда клапаны поочередно пропускают жидкость из двух бутылей/ёмкостей, выдерживая нужное время для каждой фазы, для того, чтобы после смесителя получилась нужная концентрация. Абстрактный пример: качаем 4 секунды спирт из первой бутыли, а потом 6 секунд - воду из второй бутыли. И так в бесконечном цикле. В результате после смесителя получаем 40%-ный (по объему) спирт. И это должно надежно работать даже ночью. А теперь представим, что мой контроллер, который не только управляет клапанами, но и контролирует результат их работы по расходомеру, внезапно завис? Я со всеми неожиданностями знаю способы борьбы, но зависание контроллера это кранты.
×
×
  • Создать...