Простое управление коллекторным двигателем с помощью МК

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

Всем категорическое здравствуйте!

Есть проект, для которого необходимо простейшее управление коллекторным моторчиком 12V с энкодером на микроконтроллере:
- нажатие кнопки "Вперед" - вращение на полных оборотах, по часовой стрелке, на протяжении 30 сек. И пока поступают импульсы с энкодера;
- нажатие кнопки "Назад" - вращение на полных оборотах против часовой стрелки, на протяжении 30 сек. И пока поступают импульсы с энкодера;
- если в течении 2 сек. энкодер выдал меньше 50 импульсов (т. е. мотор провернул рычаг до упора) - стоп.
Вот и все. Программированием МК я не занимался, язык Си или Ассемблер - не знаю. Строить это на ардуино принципиально не хочу.
Решил, что с такой "мега сложной" задачей справлюсь с помощью гугля и своих скромных познаний в элетротехнике, но что то пошло не так...
Я разобрался как посчитать импульсы с энкодера таймером ТС1 на МК ATMega8 и остановить двигатель по заданному числу импульсов: сконфигурировал ТС1 на внешний источник тактирования, установил прерывание по совпадению, снимаю импульсы с входа Т1 счетчика, сравниваю с регистром ОСR1A (5000 импульсов) и при совпадении останавливаю двигатель подав лог. "0" на выход OC1A счетчика, который в свою очередь управляет драйвером L298.
Но вот как сделать, что бы мотор останавливать при падении импульсов до заданного числа да еще на протяжении заданного времени никак понять не могу. Подскажите кому не лень как в принципе можно решить эту "мега задачу"?
Всем откликнувшимся - категорическое Спасибо!
Реклама
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение Мурик »

Другим таймером считайте время и если в течении заданного времени нет ни одного импульса, то останавливайте мотор.
Реклама
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

[uquote="Мурик",url="/forum/viewtopic.php?p=3331039#p3331039"]Другим таймером считайте время и если в течении заданного времени нет ни одного импульса, то останавливайте мотор.[/uquote]
Можно пример конструкции на Си? Как посчитать отрезок времени другим таймером я понимаю, но как указать МК сравнивать каждые 2 сек. количество импульсов с заданным и если оно меньше 50 импульсов НА ПРОТЯЖЕНИИ ДВУХ СЕКУНД - останавливать мотор - не пойму....
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение Ivanoff-iv »

по прерыванию таймера (скажем 4 раза в секунду) сравниваешь состояние твоего счетного таймера с ячейкой массива на 8 элементов если разница меньше 50 - выключаешь мотор, если больше - записываешь состояние в ячейку и переключаешся на следующую ячейку массива, к этой ячейке он вернётся какраз через 2 сек (только первые 8 замеров всегда считай набравшими 50, это надо чтобы первые 2 секунды выдержать, пока счетчик наполнится).
так ходя по кругу счетчик точнее отмерит эти 2 секунды, можно, конечно не заморачиваться и заглядывать в счетчик раз в 2 секунды, но тогда работа мотора в заклиненном состоянии может дойти почти до 4сек (если заклинит в начале цикла измерения, но, уже набрав 50 отсчетов)

Добавлено after 1 minute 33 seconds:
чтобы считать импульсы можно один из таймеров настроить в режим счетчика внешних импульсов или используя внешнее прерывание инкрементировать переменную-счетчик программно
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение Мурик »

Запоминайте текущее число импульсов в переменной, ждите 2 секунды и сравнивайте текущее число импульсов с тем что ранее было сохранено в переменной. Если значения одинаковы, то новых импульсов не было.
Реклама
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

[uquote="Мурик",url="/forum/viewtopic.php?p=3331054#p3331054"]Запоминайте текущее число импульсов в переменной, ждите 2 секунды и сравнивайте текущее число импульсов с тем что ранее было сохранено в переменной. Если значения одинаковы, то новых импульсов не было.[/uquote]
ВО! Спасибо, суть понял! Только мне нужно сравнивать с тем значением что было 2 сек. назад: если оно увеличилось меньше чем на 50 импульсов - стоп, если больше чем на 50 импульсов - продолжать работу 30 сек. или 5000 импульсов. ибо мотор с редуктором и в заклиненном состоянии как нибудь да шевелиться будет, выдавая енкодеру эти самые несколько импульсов. Но это уже простая математика.
Пошел искать синтаксис для реализации на Си. Нужно еще разобраться с delay. Я так понимаю он полностью останавливает программу на время задержки. Как правильно "ждать" эти 2 сек. нужно еще разобраться... Так же еще не уяснил как задать время работы 30 сек.
Спасибо за помощь!
Реклама
city77
Открыл глаза
Сообщения: 53
Зарегистрирован: Чт дек 28, 2017 23:07:31

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение city77 »

есть такая штука - прерывания, а просто ждать - не вариант
Аватара пользователя
AndyBig
Грызет канифоль
Сообщения: 250
Зарегистрирован: Ср янв 17, 2018 13:09:14

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение AndyBig »

Может лучше не количество импульсов оценивать, а время между ними? 50 импульсов за 2 секунды - это 40 миллисекунд между передними (или задними) фронтами импульсов. Как время между очередными 2 импульсами превысило 80 миллисекунд - стоп.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15575
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение BOB51 »

Пару релюшек и концевички (можно геркон или мелкосхемку магниточуствительную).
Ежли алгоритм "туда-сюда до упора" вполне достаточно.
8)
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение pyzhman »

[uquote="dds7sdd",url="/forum/viewtopic.php?p=3331023#p3331023"]...5000 импульсов...[/uquote]
Что это за число?
Docendo discimus
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

Блин, что я делаю не так?
int b;
int a;
unsigned char takt = 0;
ISR (TIMER2_OVF_vect)
{
a=TCNT1;
takt++;
if (takt>=31) {b=TCNT1;
if (a==b) {/*TCCR1A &= ~(1 << FOC1A)*/PORTD = (1 << PD4);}}
}
int main(void)
{
TIMSK |= (1<< TOIE2);
TCCR2 |= (1<< CS22)|(1<< CS20);
TCCR1A = 0b01011000;
TCCR1B = 0b00000111;
TIMSK = (1 << OCIE1A);
sei();
while(1) {

}
return 0;
}
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение a5021 »

Первое, что вы делаете не так -- это обращаетесь в обработчике прерывания к переменным, которые к таким обращениям не предрасположены. Я имею ввиду, что переменные не имеют в объявлении модификатора volatile.
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

В общем сделал я вот так:
ISR (TIMER2_OVF_vect)
{
a=TCNT0;
takt++;
if (takt==40) {b=TCNT0;}
if (takt==45) {if (b==a){PORTD &= ~(1 << PD6)&&~(1 << PD7);} takt=0;}
}


Теперь при заклинивании мотора (рычаг доходит до крайнего положения) идет команда СТОП.
Но в проекте мотор с редуктором и при заклинивании его ротор будет делать незначительные движения за счет люфта шестерней редуктора, зазоров соединений с рычага и т. п..
То есть енкодер всегда будет выдавать некое (небольшое) значение даже при заклиненном моторе.
Не могу придумать как осуществлять команду СТОП, если количество импульсов на Т0, за промежуток времени (2 сек), не превышает к примеру там 20, 50, 100 (в зависимости от енкодера и частоты вращения мотора).
Уже пробовал a-b<20 и т. п. ничего не выходит...
Подскажите плз как реализовать.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение Ivanoff-iv »

вот у тебя Т1 ведёт счёт времени
настрой Т0 на отсчет временнЫх интервалов (получи прерывание с определённой частотой)
в прерывании:

Код: Выделить всё

static unsigned int LastMeas;
if ((TCNT1-LastMeas)<50) {Остановка мотора};
LastMeas=TCNT1;
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3341106#p3341106"]вот у тебя Т1 ведёт счёт времени
настрой Т0 на отсчет временнЫх интервалов (получи прерывание с определённой частотой)
в прерывании:

Код: Выделить всё

static unsigned int LastMeas;
if ((TCNT1-LastMeas)<50) {Остановка мотора};
LastMeas=TCNT1;
[/uquote]
Так я так и делаю, только у меня T0 считает импульсы энкодера, а Т2 ведет отсчет времени.
Полный код:

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

volatile int b;
volatile int a;
volatile int takt = 0;
////////////////////////////////////////////////ПРЕРЫВАНИЯ ПО ТАЙМЕРУ №2/////////////////////////////////////////////
ISR (TIMER2_OVF_vect)
{
a=TCNT0;
takt++;
if (takt==40) {b=TCNT0;}
if (takt==45) {if (b==a){PORTD &= ~(1 << PD6)&&~(1 << PD7);} takt=0;}
}

int main(void)
{

//////////////////////////////////КОНФИГУРАЦИЯ ПОРТОВ/////////////////////////////////////////////////////////////

////////Порт В
DDRB = 0b00000110; //порты PB1 и PB2 установлены как выход.
////////Порт С
DDRC = 0x00; //все порты C установлены как входы.
PORTC = 0xFF; //подтягивающие резисторы на входы порта С.
////////Порт D
DDRD = 0b11000000;//порт PD6, PD7 установлены как выход.


//////////////////////////////////ТАЙМЕРЫ////////////////////////////////////////////////////////////////////////

////////Таймер №0 (захват импульсов с экодера)
TCCR0 |= (1 << CS02)|(1 << CS01)|(1 << CS00);//Внешний источник тактирования по растущему фронту на T0.
////////Таймер №2 (счет задержки)
TIMSK |= (1<< TOIE2);//установка прерывания по переполнению
TCCR2 |= (1<< CS22)|(1<< CS20)|(1<< CS21);//предделитель тактов на 1024.
sei();

while(1)
{
//////////////////////////////////КНОПКИ////////////////////////////////////////////////////////////////////////
////////Кнопки управления двигателем
//SW1
if ((PINC&(1 << PC0))==0)
{PORTD = (1 << PD6);}

//SW2
if ((PINC&(1 << PC1))==0)
{
PORTD = (1 << PD7);
}

}
return 0;
}

Вот только если дописать строчку (красным)
ISR (TIMER2_OVF_vect)
{
a=TCNT0;
takt++;
if (takt==40) {b=TCNT0;}
if (takt==45) {if (b==a){PORTD &= ~(1 << PD6)&&~(1 << PD7);}}

if (takt==50) {if (a-b<20) {PORTD &= ~(1 << PD6)&&~(1 << PD7);} takt=0;}}
}
То происходит произвольная, через периоды, остановка мотора...
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение Ivanoff-iv »

1) если у тебя на заклиненном моторе может набраться 50 импульсов, то при работе мотора размеров таймера т0 не хватит - он на второй круг пойдёт с описанными тобой последствиями: либо используй Т1 либо сокращай время замера (так, чтобы при остановленном моторе импульса 3 - 4 было за время замера)
2) както странно ты засекаешь импульсы - 40 прерываний ждёшь, потом в течении 10 - замеряешь (точка отсчета засекается на 40 такте, а сравнение на 50м).
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3341181#p3341181"]1) если у тебя на заклиненном моторе может набраться 50 импульсов, то при работе мотора размеров таймера т0 не хватит - он на второй круг пойдёт с описанными тобой последствиями: либо используй Т1 либо сокращай время замера (так, чтобы при остановленном моторе импульса 3 - 4 было за время замера)
2) както странно ты засекаешь импульсы - 40 прерываний ждёшь, потом в течении 10 - замеряешь (точка отсчета засекается на 40 такте, а сравнение на 50м).[/uquote]

1. Точно так же ведет себя, если поставить и 10 импульсов и 5... Все зависит от частоты вращения мотора и скорости переполнения Т0. Я так понимаю, что здесь нужно математически высчитывать, или, скорее всего использовать другой подход.
2. Если проводить сравнение на 40 такте, то там же происходит запись значения из TCNT0 в переменную b и в этот же момент , будет происходить прерывание, так как на 40 такте значения а и b будут равны.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение Ivanoff-iv »

1) нет, не так, почему бездействует 40 тактов? почему не записываешь в переменную a сразу после сравнения? примерно так

Код: Выделить всё

ISR (TIMER2_OVF_vect){
takt++;
if (5<=takt) //длительность замера
  {
  b=TCNT0;
  if (4>(b-a)) PORTD &= ~(1 << PD6)&&~(1 << PD7); //количество импульсов
  a=TCNT0;
  takt=0;
  };
}
2) Т0 умеет считать только до 255, а Т1 и 65000 выдержит (есть разница? :) ) так что если есть возможность перейти на Т1 - это лучше сделать
3) померь частоту на энкодере работающего мотора чтобы знать, с какими скоростями имеем дело.
4) ты точно знаешь что все переменные у тебя понимаются как беззнаковые? а то при копировании при разных типах можно получить ерунду (и потом махать ею :) ) если используешь Т0, то сделай переменные а и b типа char.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
dds7sdd
Прорезались зубы
Сообщения: 207
Зарегистрирован: Чт дек 07, 2017 13:48:44

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение dds7sdd »

[uquote="Ivanoff-iv",url="/forum/viewtopic.php?p=3341453#p3341453"]1) нет, не так, почему бездействует 40 тактов? почему не записываешь в переменную a сразу после сравнения? примерно так

Код: Выделить всё

ISR (TIMER2_OVF_vect){
takt++;
if (5<=takt) //длительность замера
  {
  b=TCNT0;
  if (4>(b-a)) PORTD &= ~(1 << PD6)&&~(1 << PD7); //количество импульсов
  a=TCNT0;
  takt=0;
  };
}
2) Т0 умеет считать только до 255, а Т1 и 65000 выдержит (есть разница? :) ) так что если есть возможность перейти на Т1 - это лучше сделать
3) померь частоту на энкодере работающего мотора чтобы знать, с какими скоростями имеем дело.
4) ты точно знаешь что все переменные у тебя понимаются как беззнаковые? а то при копировании при разных типах можно получить ерунду (и потом махать ею :) ) если используешь Т0, то сделай переменные а и b типа char.[/uquote]

1. Они не бездействуют, это время задержки (1-2 сек) которую нужно выждать, перед отключением мотора. Алгоритм: сразу передаем значение TCNT0 переменной a; ждем 40 тактов (1-2 сек) - передаем значение TCNT0 переменной b (делаем это каждые 40 тактов); ждем еще 5 тактов и сравниваем переменные a и b - если равны - СТОП. Так вот если не ждать эти 5 доп. тактов, то при сравнении а будет всегда равняться b. Пять доп тактов это время сравнения, 40 тактов это время задержки между сравнениями. Твой пример не работает по этой причине.
2. Знаю про 8 битные и 16 битные таймеры. Но, если честно, не вижу разницы какой применять касательно данного примера. В проекте еще предусмотрен цикличный таймер c , LSD с меню, Bluetooth и ИК управление. Поэтому 16 битный таймер еще будет нужен. Правда можно взять другой МК.
3. Мотор будет примерно такой: https://ru.aliexpress.com/item/Best-Pri ... 2747006160
Выдавить из китайцев точную инфу по нему пока что сложно, на данном этапе мне это и не нужно. Я хочу изначально разобраться с принципом, что бы наработанный результат можно было применить потом к любому мотору с незначительными правками. В среднем, скорость вращения ротора мотора будет где то 2500 - 3500 об\мин. За оборот энкодер выдает порядка 20-50 импульсов.
4. Ок.
Решения пока не нашел...
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Простое управление коллекторным двигателем с помощью МК

Сообщение Ivanoff-iv »

тогда хотябы так:

Код: Выделить всё

ISR (TIMER2_OVF_vect)
{
takt++;
if (takt==40) {b=TCNT0;}
if (takt==50) 
  {
  a=TCNT0; 
  if (a-b<20) {PORTD &= ~(1 << PD6)&&~(1 << PD7);} 
  b=a;
  takt=40;
  }
}
ждет 40 тактов, берёт первую пробу, ещё через 10 берет вторую и сравнивает, следующее сравнение будет через 10 тактов
при запуске двигателя не забудь скинуть takt=0; чтобы обеспечить твои обязательные 2 секунды работы двигателя.

Добавлено after 7 minutes 11 seconds:
по приблизительным подсчетам при тактовой 8 МГц при рабочих оборотах переполнение Т0 может произойти уже на 3х тактах (а при меньшей тактовой частоте и раньше), поэтому вместо (takt==50) надо писать (takt==42)
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Ответить

Вернуться в «Разные вопросы по МК»