Jump to content
Alexander Weide

Помощь с кодом. Управление 3-мя шаговыми двигателями

Recommended Posts

Доброе время суток !!!

В программировании новичок по этому и спрашиваю ... 

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

Что нужно выполнить контроллеру:

Основная программа :

Задаются параметры для каждого двигателя персонально (скорость и направление вращения )

Двигатель №1  - Постоянно работает

Двигатель №2 - Изменяет направление движения при срабатывании концевиков  

Двигатель №3 - Изменяет направление движения при срабатывании концевиков 

Прерывания 

На каждый двигатель есть 4 кнопки ( вперед/назад/скорость+/скорость - )

Они нужны для подстройки скоростей двигателей и когда нужно в  ускорении работы или смены направления.

Было бы не плохо что бы после отключения питания все значения оставались в памяти.

Использовал процессор Atmega32. Код программы который я сделал на данный момент ниже. Также прикрепил електрическую схему, и печатную плату. Всем спасибо за помощь =)

 

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define VD5 PORTA
#define VD4 PORTB

int S1=350;    
int S2=450;    
int S3=550;    


int main(void)

{
    PORTA = 0b00000000;
    DDRA =     0b11111111;
    
    PORTB = 0b11110000;
    DDRB =    0b00001111;
    
    PORTC = 0b11111111;
    DDRC =    0b00000000;
    
    PORTD = 0b11111111;
    DDRD =    0b00000000;
    

sei(); //разрешаем глобальные прерывания
            
    unsigned char butcount=0;
    

    
    void delay (int ms)
    {
        for (;ms;ms--)
        _delay_us(0.1);
    }
    void right_M1 (void) //Функция поворота ротора дигателя М1  вправо
    {
        VD4 = 0b00000011; // шаг 1
        delay(S1);
        VD4 = 0b00000110; // шаг 2
        delay(S1);
        VD4 = 0b00001100; // шаг 3
        delay(S1);
        VD4 = 0b00001001; // шаг 4
        delay(S1);
    }
    void left_M1 (void) //Функция поворота ротора дигателя М1  влево
    {
        VD4 = 0b00001001; // реверс шаг 1
        delay(S1);
        VD4 = 0b00001100; // реверс шаг 2
        delay(S1);
        VD4 = 0b00000110; // реверс шаг 3
        delay(S1);
        VD4 = 0b00000011; // реверс шаг 4
        delay(S1);
    }
    void right_M2 (void) //Функция поворота ротора дигателя М2  вправо
    {
        VD5 = 0b00000011; // шаг 1
        delay(S2);
        VD5 = 0b00000110; // шаг 2
        delay(S2);
        VD5 = 0b00001100; // шаг 3
        delay(S2);
        VD5 = 0b00001001; // шаг 4
        delay(S2);
    }
    void left_M2 (void) //Функция поворота ротора дигателя М2  влево
    {
        VD5 = 0b00001001; // реверс шаг 1
        delay(S2);
        VD5 = 0b00001100; // реверс шаг 2
        delay(S2);
        VD5 = 0b00000110; // реверс шаг 3
        delay(S2);
        VD5 = 0b00000011; // реверс шаг 4
        delay(S2);
    }
    void right_M3 (void) //Функция поворота ротора дигателя М3  вправо
    {
        VD5 = 0b00110000; // шаг 1
        delay(S3);
        VD5 = 0b01100000; // шаг 2
        delay(S3);
        VD5 = 0b11000000; // шаг 3
        delay(S3);
        VD5 = 0b10010000; // шаг 4
        delay(S3);
    }
    void left_M3 (void) //Функция поворота ротора дигателя М3  влево
    {
        VD5 = 0b10010000; // реверс шаг 1
        delay(S3);
        VD5 = 0b11000000; // реверс шаг 2
        delay(S3);
        VD5 = 0b01100000; // реверс шаг 3
        delay(S3);
        VD5 = 0b00110000; // реверс шаг 4
        delay(S3);
    }
    
    while (1)

{
    
    // -------------------------------------------------------------------------------------------------                
        if (!(PINC&0b01000000))
        {
            if(butcount < 5)
            {
                butcount++;
            }
            else
            {
                while (1)
                {
                    right_M1 ();
                                        
                    if (!(PINC&0b00100000))
                    {
                        if(butcount<5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S1=S1+1;
                        }
                    }
                                        
                    if (!(PINC&0b00010000))
                    {
                        if(butcount < 5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S1=S1-1;
                        }
                    
                    }
                }
            }
        }
        
        
    if (!(PINC&0b10000000))
    {
        if(butcount < 5)
        {
            butcount++;
        }
        else
        {
            while (1)
            {
                
                left_M1 ();
                
                
                if (!(PINC&0b00100000))
                {
                    if(butcount < 5)
                    {
                        butcount++;
                    }
                    else
                    {
                        S1=S1+1;
                    }
                }
                
                
                if (!(PINC&0b00010000))
                {
                    if(butcount < 5)
                    {
                        butcount++;
                    }
                    else
                    {
                        
                        S1=S1-1;
                        
                    }
                }
            }
        }
    }
    
    
    
    // -------------------------------------------------------------------------------------------
        

    {
        if (!(PINC&0b00001000))
        {
            if(butcount < 5)
            {
                butcount++;
            }
            else
            {
                while (1)
                {
                    right_M2 ();
                    
                    if (!(PINC&0b00000010))
                    {
                        if(butcount<5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S2=S2+1;
                        }
                    }
                    
                    if (!(PINC&0b00000001))
                    {
                        if(butcount < 5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S2=S2-1;
                        }
                        
                    }
                }
            }
        }
        
        
        if (!(PINC&0b00000100))
        {
            if(butcount < 5)
            {
                butcount++;
            }
            else
            {
                while (1)
                {
                    
                    left_M2 ();
                    
                    
                    if (!(PINC&0b00000010))
                    {
                        if(butcount < 5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S2=S2+1;
                        }
                    }
                    
                    
                    if (!(PINC&0b00000001))
                    {
                        if(butcount < 5)
                        {
                            butcount++;
                        }
                        else
                        {    
                            S2=S2-1;    
                        }
                        }
                        }
                        }
                        }
        
    
    // ----------------------------------------------------------------------------------------
    {
        if (!(PIND&0b00010000))
        {
            if(butcount < 5)
            {
                butcount++;
            }
            else
            {
                while (1)
                {
                    right_M3 ();
                    
                    if (!(PIND&0b01000000))
                    {
                        if(butcount<5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S3=S3+1;
                        }
                    }
                    
                    if (!(PIND&0b10000000))
                    {
                        if(butcount < 5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S3=S3-1;
                        }
                        }
                        }
                        }
                        }        
        
        if (!(PIND&0b00100000))
        {
            if(butcount < 5)
            {
                butcount++;
            }
            else
            {
                while (1)
                {
                    left_M3 ();
                            
                    if (!(PIND&0b01000000))
                    {
                        if(butcount < 5)
                        {
                            butcount++;
                        }
                        else
                        {
                            S3=S3+1;
                        }
                    }
                    
                    if (!(PIND&0b10000000))
                    {
                        if(butcount < 5)
                        {
                            butcount++;
                        }
                        else
                        {
                                S3=S3-1;
                        }
                    }
                }
            }
        }
        
// -------------------------------------------------------------------------------------------
        }
        }
        }
}

 

Безымянный.png

схема.pdf

Share this post


Link to post
Share on other sites

а это вообще работает?

может как-то так "тыц" надо делать ? а то у вас пока шагает один ШД другие тупо заторможены.

Share this post


Link to post
Share on other sites

Да работает. Только все двигатели по отдельности. 

Какую первую кнопку нажмешь тот двигатель и будет работать. 

По сути тела основной программы нет, так это в основном как мне кажется только управление кнопок. Да и то без прерываний они работают по принципу какая кнопка первая та и заняла весь мп. 

Share this post


Link to post
Share on other sites

Вебинар "Разбор новых уникальных модулей FMAC и CORDIC в микроконтроллерах общего назначения STM32G4" (15.07.2020)

Компания КОМПЭЛ приглашает вас принять участие в вебинаре 15.07.2020, посвященном новому семейству микроконтроллеров общего назначения – STM32G4. Вебинар рассчитан на технических специалистов и тех, кто знаком с основами цифровой обработки сигналов. Мы разберем алгоритм работы CORDIC, а также рассмотрим пример создания цифрового фильтра на базе FMAC.

Зарегистрироваться на вебинар

18 часов назад, Alexander Weide сказал:

Только все двигатели по отдельности. 

Какую первую кнопку нажмешь тот двигатель и будет работать. 

а как должно быть?

и это, эта функция

#define F_CPU 8000000UL
#include <util/delay.h>

    void delay (int ms)
    {
        for (;ms;ms--)
        _delay_us(0.1);
    }

не работает, точнее выдает совсем не то, что от нее ожидалось...

Share this post


Link to post
Share on other sites
                     

Новые контроллеры VIPerPLUS для ИП – видео и материалы вебинара STMicroelectronics

Видеозапись и материалы вебинара ST о семействе AC/DC регуляторов VIPerPLUS производства компании STMicroelectronics. Инженерами ST было детально рассмотрено новое семейство микросхем VIPerPLUS со встроенным транзистором, их возможности и топологии применения. Продемонстрировано испытание из лаборатории ST в Праге и моделирование в среде E-DesignSuite.

Подробнее

Это функция  которую я применяю для увеличения или уменьшения времени задержки. То есть управление скоростью двигателя Точно не знаю правильно ли но работает.

Если по пытаться  включить 3 двигателя одновременно то они как то странно одинаково крутятся ( не так как по отдельности ). Даже если заданные разные временные задержки   S1 S2 S3. Пока не понимаю почему.

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

Edited by Falconist

Share this post


Link to post
Share on other sites
                     

Конденсаторы ECWFG от Panasonic: теперь и для высоковольтных применений

Компания Panasonic анонсировала существенное расширение серии пленочных конденсаторов ECWFG: на сегодняшний день диапазон рабочих напряжений серии составляет 630…1100 В (DC). Серия ECWFG поддерживает уникальную функцию микропредохранителей.

Подробнее

это и так понятно... у тубя частота МК стоит 8МГц , один машинный цикл выполняется за 0,125мкс

_delay_us(0.1) это макрос который частоту МК умножает на заданную задержку и получает количество маш.циклов

те этот макрос уже не может сформировать задержку в 0,1мкс, цикл for()  віполняется за 8-15маш.циклов , те длительность одного цикла состовляет 1,25..1,875мкс

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

у этого МК нет ресурсов и быстродействия, что бы нормально управлять тремя ШД паралельно без дополнительной обвязки , на вскидку  максимум что можно выжать это параллельную работу на скоростях до 30..40обр/мин

 

Share this post


Link to post
Share on other sites

А почему бы не взять тот МК, где управление движками реализовано аппаратными модулями?..

Share this post


Link to post
Share on other sites

А зачем, если и у AVR'ок хватит быстродействия?

Допустим, у ШД 200 шагов на оборот (вообще-то, это довольно много) и скорость 6000 об/мин (100 об/с). Получается 20`000 шагов в секунду. То есть 400 тактов на шаг при 8 МГц частоты.

Запас, конечно, небольшой, но на задачу ТСа быстродействия вполне хватит. Тем более если ставить более типичные шаговики, шагов на 20.


Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Share this post


Link to post
Share on other sites
34 минуты назад, COKPOWEHEU сказал:

Допустим, у ШД 200 шагов на оборот (вообще-то, это довольно много) и скорость 6000 об/мин (100 об/с). Получается 20`000 шагов в секунду. То есть 400 тактов на шаг при 8 МГц частоты. 

о как...   только не 6000 вы до такой скорости  шаговик вряд ли не раскрутите, а вот до 1500 вполне реально. 

1500обр/мин = 25обр/сек = 5000имп/сек . длительность одного импульса 200мкс = 1600маш.цикл

считаем все тоже самое для 1499обр/мин = 24.98(3)обр/сек= 4996,(6)имп/сек длительность импульса 200.1334мкс = 1601маш.цикл

разница 0,1334мкс при тактовой 8МГц маш.цикл=0,125мкс , те крутить ШД точно с шагом 1обр/мин ужо не получицо  будет погрешность , сформировать такую длительность можно 16-ти битным таймером.  Для трех ШД таких нужно три , у 32й всего один.  чем будите формировать длительность импульсов? софтово? тогда шаг получицо уже не 0,125мкс, а в лучшем случае 50-100мкс и получите регулирование ШД как раз до 30-50обр/мин

 

 

Share this post


Link to post
Share on other sites

А точно ТСу нужна регулировка с точностью 0,07% ? Учитывая, что индикация не упомянута, точность установки вряд ли нужна выше 5%.

Даже для моего примера это 21 такт разницы (6000 против 5700 дают 20000 против 19000 шагов/сек, то есть 400 против 421 такта). Опять же запаса нет, но не безнадежно.

В более реалистичном варианте - 1500 об/мин (25 об/сек) и 24 шага -> 600 шагов/сек, точность 5%:

1500 об/мин -> 600 шагов/сек -> 13333 такта

1425 об/мин -> 570 шагов/сек -> 14035 тактов

разница аж 702 такта


Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Share this post


Link to post
Share on other sites
29.07.2019 в 21:36, Alexander Weide сказал:

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

для этого нужно функции поворота ШД вывернуть наизнанку и код поместить или в основной цикл или вызывать по таймеру

типа так:

const char step[]={
      0b00000011,
      0b00000110,
      0b00001100,
      0b00001001};
      

while(1)
{
if (count_motor1<speed_motor1)
   {
      count_motor1++;  
   }  
   else
     {
       count_motor1=0;
       if(flag_revers_M1)
          {step_motor1--;}
          else
          {step_motor1++;}
        step_motor1 &= 3;
     }

if (count_motor2<speed_motor2)
   {
      count_motor2++;  
   }  
   else
     {
       count_motor2=0;
       if(flag_revers_M2)
          {step_motor2--;}
          else
          {step_motor2++;}
        step_motor2 &= 3;
     }


PORTB = ((step[step_motor1])<<4)|(step[step_motor2]);


}

 

 

Share this post


Link to post
Share on other sites

Я дико извиняюсь, что лезу, куда не просят... Но мне кажется, что управлять полными шагами тремя движками по силам любому AVR c большим запасом! Во всяком случае, у меня дома валяются обломки настоящего плоттера Roland, в котором плата управления двумя ШД основана на классическом MCS51, который в самом идеальном случае способен за секунду на 2 миллиона однотактных команд (среднее количество тактов на команду у него больше 1,5). AVR в "базовом" варианте примерно в 12 раз производительнее - неужели этой разницы не хватит на третий движок?!

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

По аналогичному принципу делаются музыкальные полифонические синтезаторы - сам делал 7-канальный. Думаю, для ШД тоже пойдет. Скажем, выдача новых комбинаций на ШД с частотой 8000 Гц - это сколько оборотов максимум? Для AVR это вообще не проблема, имхо. Да и 16000 представляется не сильно большой проблемой...

P.S. Даже на счет трех массивов я перегнул - и одного хватит.

Edited by ARV

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites

не надо там мелкая дискретность задания скорости вообще.

ни какой ШД высокую скорость не развить не сможет.

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

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

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

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

занимался я для собственного удовольствия управлением ШД. и делал я это на ATMega8, и даже на внутреннем RC генераторе 1 МГц - вполне хватило производительности. и нет никакой необходимости лезть на 8 МГц или выше.

два двигателя у меня шли одновременно от двух таймеров - таймера1 и таймера2 в режиме СТС. время каждого таймера соответствовало 1 шагу.

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

а вы тут взялись частоту высокую брать, такты считать - глупости это...

при разгоне и торможении в прерывании таймера вычислялось новое время шага и записывалось в регистр TCCR таймера.

после достижения заданной скорости просто перезаписывалось то же самое время шага.

можно для третьего двигателя задействовать таймер0, но хлопот чуть больше из-за вычисления дополнительного числа до переполнения таймера.


Мудрость приходит вместе с импотенцией...

Share this post


Link to post
Share on other sites

еще добавлю к сказанному.

у меня на частоте 1 МГц не только таймеры успевают делать расчет времени шага, но еще в главном цикле и экран 1602 работает, кнопки работают и интерфейс с компом работает. на всё хватает времени, и еще остается время до начала следующего главного цикла.


Мудрость приходит вместе с импотенцией...

Share this post


Link to post
Share on other sites

А в чем смысл 1 МГц? Просто показать, что так можно?

Share this post


Link to post
Share on other sites

а ты разве ничего не понял из прочтения темы?

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

я разве непонятно выражаюсь?


Мудрость приходит вместе с импотенцией...

Share this post


Link to post
Share on other sites

Вполне понятно. Хотя я вообще не понимаю, зачем до сих пор используются AVR МК. По стоимости они давно не в выигрыше. За те же деньги продаются ARM МК, где есть куча аппаратных фишек и не надо морочить голову с программными извращениями.

Share this post


Link to post
Share on other sites
Только что, BARS_ сказал:

За те же деньги продаются ARM МК

А накопленные запасы предлагаете выбросить?


Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Share this post


Link to post
Share on other sites

ну да.

купленное - выбросить, и за такие же деньги купить новое...


Мудрость приходит вместе с импотенцией...

Share this post


Link to post
Share on other sites

... новое, огромное, мощное... И сделать на нём какую-нибудь мигалку, для которой хватило бы выброшенного 8-ми лапого МК.

@BARS_ , каждому своё. И каждой задаче соответственно своя реализация.

PS: Не начинайте очередной холивар, на тему "Что лучше .... ?".

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...