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

Вебинар STM32G0 – новый лидер бюджетных 32-битных микроконтроллеров от STMicroelectronics

Компания Компэл приглашает вас 25 сентября принять участие в вебинаре, который посвящен новому семейству микроконтроллеров STM32G0. Вебинар рассчитан на технических специалистов и тех, кто хорошо знаком с семейством STM32. На вебинаре будут освоены современные методы тестирования производительности микроконтроллеров на примере самых бюджетных 32-битных семейств общего назначения STM32G0 и STM32F0 и проведено их подробное сравнение.

Подробнее

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
Posted (edited)

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

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

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

Edited by Falconist

Share this post


Link to post
Share on other sites
                     

Литиевые батарейки Fanso в беспроводных датчиках пожарно-охранной сигнализации

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

Подробнее...

это и так понятно... у тубя частота МК стоит 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.

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 такта

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
Posted (edited)

Я дико извиняюсь, что лезу, куда не просят... Но мне кажется, что управлять полными шагами тремя движками по силам любому 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...

  • Сообщения

    • А других у нас не купить. Эти самые дорогие, по 175 за штуку. Остальные хуже. Давно брал для УМ на 1875 подешевле, так они при завинчивании обломались под корешок, силумин.
    • Дурина, при загрузке в неё соответствующего ПО, тоже может программатором.  Но основная проблема всей темы вовсе не в программаторе.
    • @finn32 ,выходные терминалы эти оставишь?
    • Повёлся на мощность Она у этого пылесоса действительно большая, ~2,2 -2,5квт. Из которых эффективная на всасывание в районе 700вт. То есть пылесосит он действительно не плохо)) Да так собственно и хочу поступить) стоил бы фильтр до 3тр, то ещё куда не шло бы. А так, 5тр + доставка, мне жалко отдавать за кусок пластика с бумагой. Учитывая что например за подобную сумму можно купить целый пылесос) Прошлый пылесос (нилфиск) был как раз с мешками, проблема была в том, что к нему было не найти мешков и приходилось ножницами дорабатывать посадочную картонку, в принципе это не проблема была, у него потом просто двигатель клинанул, проработал он у меня долго, больше 7 лет. Вот после него захотелось мощный пылесос, но без пакетов)))
    • Название темы уже забавное. "Сквозной ток" однотактного генератора - надо записать в тетрадку.
    • Так об этом пишут уже десятки лет, зачем покупать "мерседес" если будете возить навоз на дачу. Хотите полный эксперимент отключите совсем датчик и увидите насколько хватит этого пылесоса раз не хотите менять фильтр.
    • На второй картинке 50 Гц на выходе. На печатке ЛБП ошибок не нашел. А сколько вольт на +моста? А какая ёмкость на выходе ЛБП. Осциллограммы питания +12 и -12 ОУ. С БП отключить цепь Z, ей нужен КС162. Пригодность КС182 зависит от напряжения на С6 в БП, если у тебя напряжения в БП больше на 2-3 вольта, чем написано на схеме, то КС182 может и подойдет. Последние наброски печаток и схема. Их не собирал, надо проверять. https://forum.cxem.net/applications/core/interface/file/attachment.php?id=647843   ЛБП 44.3.N.lay6
×
×
  • Create New...