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

ATMega + DRV8825 + ШД. Вопрос =)


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

Здраствуйте. Помогите пожалуйста разобраться начинающему самоучке. Хотел разобраться в управлении ШД. Не могу пока понять как корректно управлять ШД через МК.

Если просто дергать через таймер ногу STEP драйвера то в принцепе двигатель оживает. Направление так же меняется без проблем.

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

Возможно есть какой то иной способ управления? Подскажите пожалуйста. 

Заранее спасибо. 

Прилагаю код. Не весь функционал я еще прописал, хочется решить проблему.

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

Старт стоп для двигателя. Направление двигателя. И регулировка скорости двигатателя. Все.

Использовал ATMega16 потому что пока есть она. Хочу переделать потом на Mega8.

#define F_CPU 12000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

int MotorSpeed = 0;
int MotorWork = 0;
unsigned int OverflowsRemainMotorWork = 0;

//Переменные для энкодера
enum { State0, StateA, StateB, StateAB }; //состояния энкодера
static char EncPrev;      //предыдущее состояние энкодера
static char EncPrevPrev;  //пред-предыдущее состояние энкодера

unsigned char R1=0, R2=0, R3=0;

unsigned int OverflowsRemainStartButton = 0;
int StartSet = 0;
int StartButtonPressed = 0;

unsigned int OverflowsRemainLeftButton = 0;
int LeftSet = 0;
int LeftButtonPressed = 0;

unsigned int OverflowsRemainRightButton = 0;
int RightSet = 0;
int RightButtonPressed = 0;

//=========================================Энкодеры=================================================
void Encoder_Init(void)
{
    DDRC  &= ~(1<<PC3) | ~(1<<PC4); //настройка портов на ввод
    PORTC |= (1<<PC3) |  (1<<PC4);    //включение подтягивающих резисторов
    EncPrev = State0;       //инициализация предыдущего состояния
    EncPrevPrev = State0;   //инициализация пред-предыдущего состояния
}

void To_Do_Step_Up()
{
    MotorSpeed++;
    if (MotorSpeed>=100) MotorSpeed = 100;
}

void To_Do_Step_Dn()
{
    MotorSpeed--;
    if (MotorSpeed<=0) MotorSpeed = 0;
}

void Encoder(void)
{
    char EncCur = 0;
    if(!(PINC&(0b00001000))) EncCur  = StateA; //опрос фазы 1 энкодера
    if(!(PINC&(0b00010000))) EncCur |= StateB; //опрос фазы 2 энкодера
    if(EncCur != EncPrev)             //если состояние изменилось,
    {
        if(EncPrev == StateAB &&        //если предыдущее состояние StateAB
        EncCur != EncPrevPrev )      //и текущее и пред-предыдущее не равны,
        {
            if(EncCur == StateB)          //если текущее состояние StateB,
            To_Do_Step_Up();            //шаг вверх
            else                          //иначе
            To_Do_Step_Dn();            //шаг вниз
        }
        EncPrevPrev = EncPrev;          //сохранение пред-предыдущего состояния
        EncPrev = EncCur;               //сохранение предыдущего состояния
    }
}

//=========================================SPI=================================================

void SPI_init(void)
{
    DDRB |= ((1<<PORTB4)|(1<<PORTB5)|(1<<PORTB7)); //ножки SPI на выход
    PORTB &= ~((1<<PORTB4)|(1<<PORTB5)|(1<<PORTB7)); //низкий уровень
    SPCR |= ((1<<SPE)|(1<<MSTR));//включим шину, объ¤вим ведущим
}

//=========================================Таймеры=================================================

void timer0_ini(void)
{
    // Установка предделителя /256
    TCCR0 = (1 << CS02);
    // Обнуляем счетчик таймера 0
    TCNT0 = 0;
    // Разрешение прерывания таймера 0 по переполнению
    TIMSK |= (1 << TOIE0);
}

void timer1_ini(void)
{
    TCCR1A |= 0;
    TCCR1B |= (1<<CS11) | (1<<WGM12);    // Делитель: Clk/64
    TIMSK |= (1 << OCIE1B);    // Прерывание при переполнении: Вкл.
    OCR1B = 100; // границы скрости 6 - 255
    TCNT1 = 0;    // Предустановленное значение: 0
}

void timer2_ini(void)
{
    TCCR2 |= (1<<WGM21); // устанавливаем режим СТС (сброс по совпадению)
    TIMSK |= (1<<OCIE2);    //устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR2
    OCR2 = 255; //записываем в регистр число 255 для сравнения
    TCCR2 |= (1<<CS20) | (1<<CS22);//установим делитель 128.
}


//=========================================Индикатор=================================================

void segchar (unsigned char seg)
{
    switch(seg)
    {
        case 1: SPDR = 0b00010100; break;
        case 2: SPDR = 0b11001101; break;
        case 3: SPDR = 0b01011101; break;
        case 4: SPDR = 0b00011110; break;
        case 5: SPDR = 0b01011011; break;
        case 6: SPDR = 0b11011011; break;
        case 7: SPDR = 0b00010101; break;
        case 8: SPDR = 0b11011111; break;
        case 9: SPDR = 0b01011111; break;
        case 0: SPDR = 0b11010111; break;
        case 10: SPDR = 0b001000000;  break; // Точка
        case 11: SPDR = 0b000000000;  break; // Пустота
        case 12: SPDR = 0b010001011; break; // F
    }
}

void ledprint(unsigned int number)
{
    if (MotorSpeed > 0)
    {
        R1 = number%10;
        if (number < 10) R2 = 11;
        else R2 = number%100/10;
        if (number < 100) R3 = 11;
        else R3 = number%1000/100;
    }
    else
    {
        R1 = 12;
        R2 = 12;
        R3 = 0;
    }
}

//=========================================Обработчик таймера=================================================

ISR (TIMER0_OVF_vect)
{
    OverflowsRemainStartButton++;
    OverflowsRemainLeftButton++;
    OverflowsRemainRightButton++;
}

ISR (TIMER1_COMPB_vect)
{
    OverflowsRemainMotorWork++;
}

unsigned char n_count=0;

ISR (TIMER2_COMP_vect)
{
    if(n_count==0)
    {
        SPDR = 0b11111101;
        while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
        segchar(R1);
        while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
        //сгенерируем отрицательный фронт для записи в STORAGE REGISTER
        PORTB |= (1<<PORTB4); //высокий уровень
        PORTB &= ~(1<<PORTB4); //низкий уровень
    }
    if(n_count==1)
    {
        SPDR = 0b11111011;
        while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
        segchar(R2);
        while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
        //сгенерируем отрицательный фронт для записи в STORAGE REGISTER
        PORTB |= (1<<PORTB4); //высокий уровень
        PORTB &= ~(1<<PORTB4); //низкий уровень
    }
    if(n_count==2)
    {
        SPDR = 0b11110111;
        while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
        segchar(R3);
        while(!(SPSR & (1<<SPIF)));//подождем пока данные передадутся
        //сгенерируем отрицательный фронт дл¤ записи в STORAGE REGISTER
        PORTB |= (1<<PORTB4); //высокий уровень
        PORTB &= ~(1<<PORTB4); //низкий уровень
    }
    n_count++;
    if (n_count>2) n_count=0;
}

//=========================================drv8825=================================================
void DRV8825_ini()
{
    DDRD |= (1<<PD0) | (1<<PD1) | (1<<PD2); // Enable Step Dir
    PORTD |= (1<<PD0) | (0<<PD1) | (1<<PD2); // Enable Step Dir
}

//=========================================Кнопки=================================================
void button_ini()
{
    DDRC &= ~(1<<PC0) | ~(1<<PC1) | ~(1<<PC2); // Enable Step Dir
    PORTC |= (1<<PC0) | (1<<PC1) | (1<<PC2); // Enable Step Dir
}

//=========================================Светодиоды кнопок=================================================
void led_ini()
{
    DDRC |= (1<<PA0) | (1<<PA1) | (1<<PA2); // Enable Step Dir
    PORTC &= ~(1<<PA0) | ~(1<<PA1) | ~(1<<PA2); // Enable Step Dir
}

//=========================================Обработчик кнопок=================================================

void StartButton()
{
    if (!(PINC&0b00000010))
    {    TCCR0 |= (1 << CS02);
        TCNT0 = 0;
        if (OverflowsRemainStartButton > 10)
        {
            TCCR0 &= ~(1 << CS02);
            OverflowsRemainStartButton = 0;
            if (!(PINC&0b00000010))
            {
                if (StartButtonPressed == 0)
                {
                    if (StartSet == 0) StartSet = 1;
                    else
                    {
                        StartSet = 0;
                        RightSet = 0;
                        LeftSet = 0;
                    }
                }
                StartButtonPressed = 1;
            }
        }
    }
    else StartButtonPressed = 0;

}


void LeftButton()
{
    if (!(PINC&0b00000001))
    {    TCCR0 |= (1 << CS02);
        TCNT0 = 0;
        if (OverflowsRemainLeftButton > 10)
        {
            TCCR0 &= ~(1 << CS02);
            OverflowsRemainLeftButton = 0;
            if (!(PINC&0b00000001))
            {
                if (LeftButtonPressed == 0)
                {
                    if (LeftSet == 0) LeftSet = 1;
                    else LeftSet = 0;
                }
                LeftButtonPressed = 1;
            }
        }
    }
    else LeftButtonPressed = 0;

}

void RightButton()
{
    if (!(PINC&0b00000100))
    {    TCCR0 |= (1 << CS02);;
        TCNT0 = 0;
        if (OverflowsRemainRightButton > 10)
        {
            TCCR0 &= ~(1 << CS02);
            OverflowsRemainRightButton = 0;
            if (!(PINC&0b00000100))
            {
                if (RightButtonPressed == 0)
                {
                    if (RightSet == 0) RightSet = 1;
                    else RightSet = 0;
                }
                RightButtonPressed = 1;
            }
        }
    }
    else RightButtonPressed = 0;

}

void StartButtonProg()
{
    if (StartSet==1)
    {
        if (LeftSet == 1 || RightSet== 1)
        {
            PORTA |= (1<<PA1); //Включаем лед
            PORTD &= ~(1<<PD0);    //Включаем DRV8825
            MotorWork = 1;
        }
    }
    if (StartSet == 0)
    {
        PORTA &= ~(1<<PA1); //Выключаем лед
        PORTD |= (1<<PD0); //Выключаем DRV8825
        MotorWork = 0;
    }
}

void LeftButtonProg()
{
    if (LeftSet==1)
    {
        PORTA |= (1<<PA0); //Включаем лед
    }
    else
    {
        PORTA &= ~(1<<PA0);
    }
}

void RightButtonProg()
{
    if (RightSet==1)
    {
        PORTA |= (1<<PA2); //Включаем лед
    }
    else
    {
        PORTA &= ~(1<<PA2);
    }
}

void Motor()
{
    if (LeftSet == 1 || RightSet== 1)
    {
        if (MotorWork == 1)
        {
            if (OverflowsRemainMotorWork == 1)
            {
                OverflowsRemainMotorWork = 0;
                if (LeftSet == 1)   PORTD |= (1<<PD2);
                if (RightSet == 1)    PORTD &= ~(1<<PD2);
                PORTD ^= (1<<PD1);
                TCNT1 = 0;
            }
        }
    }
}


int main(void)
{
    timer0_ini();
    timer1_ini();
    timer2_ini();
    Encoder_Init();
    button_ini();
    DRV8825_ini();
    led_ini();
    SPI_init();
    sei();
    
    while (1)
    {
        StartButton();
        LeftButton();
        RightButton();
        StartButtonProg();
        LeftButtonProg();
        RightButtonProg();
        Encoder();
        Motor();
        ledprint(MotorSpeed);
    }
}

 

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

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Отказывайтесь от delay в пользу millis, для управления шаговым используйте библиотеку AccelStepper

Никогда СЮДА не нажимай!!!

надоело из каждого вытаскивать информацию, поэтому:

А ПОДРОБНЕЕ? ГДЕ ФОТО? ГДЕ СХЕМА? ЧТО ЗНАЕШЬ? ЧТО УМЕЕШЬ?

мощные выходные транзисторы перегорают, предохраняя от перегорания плавкие предохранители....

Школа учит читать и писать, институт - пользоваться справочниками и искать ответы

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

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

15 минут назад, sanbi4 сказал:

Отказывайтесь от delay в пользу millis, для управления шаговым используйте библиотеку AccelStepper

Я ж не на ардуино делаю. Откуда у меня millis и библиотеки.

На самом деле я разобрался уже. 

Формирование ШИМ сигнала нужно делать отдельно от общей программы. Я сделал через таймер1 с корректировкой частоты.  Теперь влияния общей программы на работу двигателя нет. 

Своими словами излагаю как понимаю (любитель от слова совсем).

Осталось разобраться со значениями ICR1 и OCR1 в данном режиме. Пока выставил примерно ( в попугаях) значения. Все работает. Может найду где точнее считаются 

 

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

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

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

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

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

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

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

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

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

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

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

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

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