Здраствуйте. Помогите пожалуйста разобраться начинающему самоучке. Хотел разобраться в управлении ШД. Не могу пока понять как корректно управлять ШД через МК.
Если просто дергать через таймер ногу 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);
}
}