Блок на STM32F103C8 ARM (Скетч, описание, фото)

Тема в разделе "Лабораторные блоки питания", создана пользователем sashokc, 25 июн 2018.

  1. sashokc

    sashokc Новый пользователь

    Приветствую.

    Все началось с того, что при определенных действиях сгорела Arduino Nano, подручными средствами восстановить не удалось.

    В магазинах своего города нужной ардуинки не нашлось, но нашлась интересная Системная плата STM32F103C8T6 ARM по функционалу и периферии она на много превосходит atmega328.

    Трудности которые я себе представлял за ранее:

    1) 3,3 В логика. Решение в виде двунаправленного конвертора уровней на транзисторах.
    2) Большее количество ног. Решение - распаянный на макетной плате переходник.
    3) Отсуствие встроенного UART - USB конвертера для соединения с ПК. Решение - прошивка загрузчика, емулирование сом порта, благо все придумано и написано до меня, работает отлично!
    4) Отсутствие EEPROM. Решение использовать внутреннюю память вместо EEPROM. У нее правда жизненный цикл 10000 перезаписей всего, но здесь эти переменные не меняются по этому все гуд...

    Плюсы, которые я обрисовал себе за ранее:

    1) 16-ти битный аппаратный ШИМ, pwmWrite(*); может принимать значение 0..65535, против убогих 0..255
    2) Быстрый 12-ти битный АЦП, analogRead(*); будет возвращать 0..4095 против 0..1023, что в первом случае ведёт к более точным измерениям;

    Забегу вперед: На деле плюсы действительно заметны.

    Купил платку, принялся за работу:

    Распаял переходник. Выходы почти все один в один с оригинальной схемой, на данном этапе трудностей 0. Так же на переходнике распаял 7805CV.

    Принялся за прошивку. На освоение IDE и написание прошивки с нуля для STM32 времени не было, решил подружить STM с Arduino IDE. Очень хорошая статейка по данному вопросу на хабре: https://habr.com/post/395577/

    Изменение в оригинальной прошивке:

    1) Отредактировал пределы PWM.
    2) Отредактировал наименование выводов.
    3) Сменил некоторые функции analogWrite() => pwmWrite()
    4) Режим работы PWM пина pinMode(pwm, OUTPUT); => pinMode(pwm, PWM);
    5) Закомментировал на мой взгляд не нужные части кода.

    Что хотелось бы реализовать:

    1) Конвертор уровней, я так и не стал делать, транзистор Q2 не открывается на полную, из за этого макс. напряжение всего 14В из 24В.
    2) Исправление бага с дисплеем, при манипулировании энкодером переодически начинают бегать символы, приходится перегружать. - думаю достаточно перевести на I2C.
    3) Дописать функции разрядки/зарядки аккумуляторов и сохранение значений емкости.
    4) Возможно применить встроенный RTC. Кто то на форуме об этом задумывался http://forum.start.net.ua/threads/vnedrenie-chasov-i-termometra-v-lbp.25/

    Скетч: https://github.com/SaNToS/arduinolps

    Тему дополню позже скетч опубликую.
     

    Вложения:

    Последнее редактирование: 3 июл 2018
    Bondar, Oleg_D и Gupic нравится это.
  2. Oleg_D

    Oleg_D Интересующийся

    Большое спасибо за идею и переделанный скетч под stm32. Копаясь в этом скетче заметил, что Вы не до конца изменили строку
    float Uout = analogRead(PA1) * ((5.0 + Ucorr) / 1023.0) * 5.0; //узнаем напряжение на выходе
    , где 1023 надо бы заменить на 4095, у stm32 ведь больше разрядность. И логическая единица у stm32 вроде 3.3 вольт.
    В итоге наверно так будет правильнее :
    float Uout = analogRead(PA1) * ((3.3+ Ucorr) / 4095.0) * 3.3;
    И точность чтения данных вырастет. В строке :
    if(ceil(level)!=255) pwmWrite(pwm, ceil(level)); //подаем нужный сигнал на ШИМ выход (кроме 255, так как там какая-то лажа!!!) также меняем 255 на 4095. А может там уже и нет лажы. Надо проверять.
    Поправьте если ошибаюсь, я только начинающий.
    По поводу :
    "1) Конвертор уровней, я так и не стал делать, транзистор Q2 не открывается на полную, из за этого макс. напряжение всего 14В из 24В."
    На выходе PWM, при номинальном питании от 3. 3В, максимально возможное напряжение будет 3.3, то есть логическая единица. При питании от 5в, максимум 3.6в. Подозреваю что не дотягивает до задуманных 5в, как у ардуино .
    Пробовали поднять усиление с помощью подбора резистора R6, по схеме 2.3? То есть чтобы при изменении" напряжения " PWM от 0-3. 6 вольт, выходное напряжение менялось во всем диапазоне. Я только собираюсь собрать данный блок питания и проверить пока нет возможности . А идея stm32 очень заинтересовала. Если получится побороть этот недуг, то разведу плату сразу под этот контроллер.
    Кстати, от 5в как себя чувствует контроллер, не греется?
     
    Последнее редактирование: 6 июл 2018
  3. sashokc

    sashokc Новый пользователь

    И в правду не досмотрел. У себя уже исправил.

    Лажи действительно нет.

    Я думаю подобрать можно, но не пробовал пока..

    Контроллер не греется, потому как на плате присутствует стабилизатор 3,3 в http://prntscr.com/k3ngrf

    Поправил скетч + добавил предустановленные параметра по нажатию кнопки энкодера
     
    Последнее редактирование: 7 июл 2018
    yatsuk нравится это.
  4. Oleg_D

    Oleg_D Интересующийся

    Тогда " if(ceil(level)!=255)" можно удалить из скетча.
    Разобрался в сути работы замера напряжения.
    Цитата: "12-разрядный АЦП с опорным напряжением 3,3 В преобразует аналоговые сигналы от 0 до 3,3 В в диапазон цифровых значений от 0 до 4095 единиц". В схеме 2.3 делитель напряжения на R11 - R12 уменьшает напряжение в 5 раз до приемлемых ардуино 5В. То есть при питании 24В на вход МК через R14 поступит U=24/5=4.8В, что не превышает 5В.Но Ардуино видит это напряжение в своих попугаях,то есть переведет это в (4.8/5)*1023=982 единиц. В скетче мы видим обратный перевод в Вольты с умножением на коэффициент делителя, равный 5: float Uout = analogRead(PA1) * ((5.0 + Ucorr) / 1023.0) * 5.0. Теперь, что получит STM32? Это будет вне диапазона чтения МК, равный 3.3В и = 4095 попугаев. Если не менять скетч, то при 24В МК вернет максимально 3.3/5*24=15.84В. То есть надо изменить сопротивления в делителе так, чтобы при максимальном напряжении на вход МК поступало не более 3.3В. Коэффициент делителя при этом будет 24В/3.3В=7.27.. Так как это значение в дальнейшем надо будет использовать в скетче, давайте округлим его до 7.3 , тогда на делителе 24/ 7.3 =3.2877В, неплохо. Используя стандартные номиналы , R11 можно взять 4.7кОм, R12 - 680 Ом, R20 остается тот же.
    В скетче преобразование примет вид: float Uout = analogRead(PA1) * ((3.3 + Ucorr) / 4095.0) * 7.3 . Подстроечником R20 добиваемся верного отображения напряжения, при этом на делителе, не принимая во внимание падение, должно быть около 3.2877В . Таким образом можно расчитать делитель под любые , имеющиеся в наличии номиналы, помня что напряжение, идущее на R14, не должно превышать 3.3В.

    По поводу измерения силы тока, строка float Iout = analogRead(PA0) / 100.00; // узнаем ток в нагрузке
    Падение напряжения на шунте 0.1 Ом при токе 1A составит U=I*R=0.1В. Попугаи делятся на 100 и получаем ток. Отсюда напряжение на R13, соответствующее силе тока 1А будет для ардуино 5/1023*100=0.488758. Для STM32 будет 3.3/4095*100 =0.080586...То есть разница будет 0.488758/0.080586=6.0665 раз. Этот расчет для того, чтобы понять насколько нужно изменить делитель в скетче, чтобы не менять схему. Выражение для силы тока примет вид: float Iout = analogRead(PA0) / 606.65; То есть для тока в 1А МК читает на R13 все те же 0.488758 В , но разделив на 606 получит I=((0.488758/3.3)*4095)/606 = 1А. Если хотите, используйте в скетче делитель 600, просто чуть-чуть надо будет переменником R8 скорректировать показания Амперметра. Тогда в схеме 2.3 надпись I control (U=Iout*0.48875...) примет вид: U= Iout*3.3/4095*600, I control (U=Iout*0.48351...) При этом максимальная измеренная сила тока будет 3.3/0.48351=6.82А
     
    Последнее редактирование: 8 июл 2018
    Bondar и yatsuk нравится это.
  5. sashokc

    sashokc Новый пользователь

    Гениально :) Проверю на практике отпишусь...

    Что то не похоже.... :)
     
  6. Oleg_D

    Oleg_D Интересующийся

    Будем признателены :)
    Мои детали ещё в пути.
     
  7. witt84

    witt84 Новый пользователь

    Что-то тема затихла..
     
  8. Oleg_D

    Oleg_D Интересующийся

    Из моих опытов могу добавить, что напряжения на ШИМ не хватает для прямого регулирования оборотов интеловского кулера. Тогда как атмега 328 регулирует, при изменении ШИМ сигнала. Это для меня небольшой минус. Хотя может потому что у stm шим другой частоты. Надо будет частоту ещё замерить. При одинаковых скетчах, во всяком случае, не хочет.
    На счёт схемы. Я бы рекомендовал всё таки использовать внешний dac, типа mcp4725. Линейность и скорость регулировки вырастет. Толку от 16 бит шим, если показания считываются 12бит. Либо в коде применить оверсемплинг до 16 бит, или хотя бы до 14. В результате такого дисбаланса МК никогда не находится в равновесии, и то и дело, то поднимает, то отпускает шим, производя лишние итерации, внося дополнительные шумы. При 12бит входе и 12 бит выходе хотя бы прыгания не будет. Конечно и шаг регулировки напряжения в меню надо точно подстроить под шаг шим(если не в меню, то хотя бы в коде) . 12 бит достаточно для большинства задач.
    Касательно самого МК. Так как я собираю абсолютно изолированную вычислительную часть схемы, а это предполагает использование различных библиотек и модулей. На данном МК могут быть проблемы с совместимостью. Комплектующие все уже в наличии. Но у меня немного изменились хотелки)). Данную схему на stm, без изоляции МК, соберу чуть позже, естественно с улучшениями. Но пока это не приоритетная задача. Сейчас ковыряю 328, т. к. всё равно будут внешние dac и adc. В голове уже все работает, чётко представляю всю схему, осталось перенести в lay и ino. Скетч переделывать долго. Проще даже написать новый . Также будет 2 энкодера, отдельно для V и А. Кнопка включения, программно-аппаратная. Автоматический контроль и индикация температуры. Улучшения в системе защиты и предупреждения КЗ. Фильтры по питанию, опорники. Я в свое удовольствие, не торопясь.
     
    Последнее редактирование: 5 ноя 2018
  9. Oleg_D

    Oleg_D Интересующийся

    По скетчу.
    Наверно я чего-то не понимаю, но зачем уменьшать ШИМ менее чем на единицу при точной регулировке:
    "
    //узнаем запас разницу между током в нагрузке и установленным током
    float raz = (Iout - Ioutmax);
    if(raz>0.3) //очень сильно превышено (ток больше заданного более чем на 0,3А)
    {
    level = level - raz * 20; //резко понижаем ШИМ
    }else{
    if(raz>0.05) //сильно превышено (ток больше заданного более чем на 0,1А)
    {
    level = level - raz * 5; //понижаем ШИМ
    }else{
    if(raz>0.00) level = level - raz * 2; //немного превышен (0.1 - 0.01А) понижаем плавно
    }"
    А потом все равно округлять до целого:
    if(ceil(level)!=255) analogWrite(pwm, ceil(level)); //подаем нужный сигнал"
    Может это было актуально при шим 255?

    Также, при том что у stm32 шим 65535 против 8192, то есть при использовании в скетче одинаковых коэффициентов регулировки , в этом случае регулировка (тобишь скорость реакции в целом) будет происходить в 8! раз медленнее, чем задумывалось на атмеге 328. Так как градаций больше, а шаг остался такой же.
     
    Последнее редактирование: 15 окт 2018
  10. Bondar

    Bondar Интересующийся

    Я думаю, для того чтобы не было "дребезжания" ну типа при каждом замере (цыкле) выход ШИМ не менялся на еденицу туда-назад. А просто сохранялись доли едениц для более плавной работы. И переключения не были такими частыми. ИМХО.
     
  11. Oleg_D

    Oleg_D Интересующийся

    Я специально привёл пример из кода, когда завышено. Самое нелепое творится именно здесь, когда if(raz>0.05), но меньше 0.2 Насколько мы в курсе, ceil() — округление вверх. В этом случае максимальное итоговое значение не превысит 1-цу. То есть отнимая ,скажем ,от 20( результат вычисления предыдущей итерации для шим - целое число) 0.9, получим 19.1. Которое потом округляется опять до 20. Топчемся на месте. А выражение :
    if(raz>0.00) level = level - raz * 2; вообще не имеет смысла, так как опять топчемся на месте.
    Короче, множители надо менять.
     

Поделиться этой страницей