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

Литиевые батарейки Fanso для систем телеметрии и дистанционного контроля

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

Подробнее

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
                     

Приглашаем на вебинар Решения для построения ультразвуковых счетчиков жидкостей и газов на базе MSP430

Компэл совместно с Texas Instruments 23 октября 2019 приглашают на вебинар, посвященный системам-на-кристалле для построения ультразвуковых расходомеров жидкостей и газов на базе ядра MSP430. Вебинар проводит Йоханн Ципперер – эксперт по ультразвуковым технологиям, непосредственно участвовавший в создании данного решения. На вебинаре компания Texas Instruments представит однокристальное решение, позволяющее создавать точные недорогие счетчики жидкостей и газов.

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

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

  • Сообщения

    • Ну зачем же так строго! Сегодня сделал ревизию своему старичку M830BZ MASTECH. Контакты на переключателе как новые. Он в паре с UT70B трудиться уже около 10 лет. Заменил подстроечный резистор VR1 200 Ом на многообротный, и настроил прибор по мультиметру UT70B. На всех диапазонах измерений точность практически идеальная. Те, старенькие 830 не теперешний ширпотреб. Единственное, так это пришлось по колдовать с резисторами делителя на пределе 200 Ма. Нижние пределы конечно показывают полный хаос, но эти микро амперы мне и не нужны. В чём была причина так и не понял. Контакты в отличном состоянии, несмотря на приличный возраст прибора. Почистил контакты ластиком, протёр спиртом, смазал вазелином. Так что не нужно спешить выбрасывать то что ещё может поработать. И так всю страну завалили отходами! Даёшь вторичное использование мультиметров! Резисторы там стоят толстенькие полосатые бочёнки. А за 2-3 бакса такой сегодня не купишь. Разве что только название похожее. Ведь даже качество пластика у него не очень плохого качества. Есть с чем сравнивать - лежат ещё 5 штук разных годов выпуска. А вчера переделывал для сына свежекупленный 830, встраивал повышайку и зарядку для лития. Так там вообще не пластик а полителен какой то. Любая техника чем старее тем была качественней. Пусть тот же самый Китай. Интересно будет лет через 10 почитать темы про ремонт мультиметров. Я не думаю, что будет бурное обсуждение приборов купленных в наши дни. Они просто не переживут этот срок. 
    • А нафига сгоревшие светодиоды выпаивать? Оторвать кусачками да и делов то. Вот интересно было бы посмотреть как это реализовано, наверно лампы сильно перегревались. 
    • Проверить цепь, по которой проходит сигнал на динамик. Если, конечно , под словами "разговорный динамик" не скрывается микрофон.
    • исправленная печатка и схема - здесь  
    • Отказал разговорный динамик. Заменил, оказалось зря, всё так-же осталось. Специалистов по близости нет. Одни предлагают выкинуть, другие перепрошить. Подскажите, что можно сделать?
    • скину свой касяк - исправленная печатка и схема - кто собирал -обратите внимание на шоттки в печатке и резистор в базе транзистора - его нужно добавить - извиняюсь) спешу вечно. все проверенно. автошим 494.lay6
    • Линейка, бесспорно, тоже нужна! Для плоскостных измерений, приносит удобство. А сверло, мечик или плашку линейкой уже не измерить. Тогда на помощь приходит штангенциркуль и таблица в помощь. Для хорошего мастера не помешает иметь и то и другое. Перелистывать страницы справочника - это тоже потеря времени. А так, глянул в таблицу и сразу получил ответ соответствия. И не надо считать деления на линейке. Это преимущество особенно ярко выражено, если величина перевода не кратная. Полезные таблицы, вообще желательно распечатать на принтере, наклеить на жёсткую картонку и магнитиком прихватить возле рабочего стола. Например: нужно реставрировать предохранитель, глянул в эту таблицу, и за считанные минуты запаял требуемый волосок калиброванного провода для данного тока. Помимо этой таблицы, желательно повесить и таблицу с ESR параметрами. Для ремонтника и не только она не будет лишней.
  • Покупай!

×
×
  • Create New...