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

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


Alexander Weide

Рекомендуемые сообщения

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

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

Нужно осуществить управление 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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

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

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

Изменено пользователем Falconist
Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

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

 

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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обр/мин

 

 

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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]);


}

 

 

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

Изменено пользователем ARV

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

Ссылка на комментарий
Поделиться на другие сайты

Только что, BARS_ сказал:

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

ну да.

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...