Программное сопряжение оптического энкодера и шаговика

serega_k

✩✩✩✩✩✩✩
4 Ноя 2018
26
0
Здравствуйте!

Помогите написать скеч для управления шаговым двигателем (подключенным к ардуино мега через L298N) с помощью оптического энкодера и энкодерной ленты.
Есть отдельные скечи для энкодера и для шаговика, но вот их совместить не получается.

Цель такая: двигаю энкодер по ленте вправо - шаговик крутит в одну сторону,
двигаю энкодер по ленте влево - шаговик крутит в другую сторону.

Также хочется учесть в скече изменении количества импульсов на один шаг.

PS: Есть подобный скеч для вышеперечисленной цели, но собранной на драйвере DRV8825 (у меня он не работает)
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
@serega_k, Stepper.h написана так, что все процессорное время пока мотор не повернется на заданный угол будет занято.
*Недавно мозговал, как заставить два мотора крутится одновременно. Придумал))))*
 

serega_k

✩✩✩✩✩✩✩
4 Ноя 2018
26
0
Так отдельно библиотека то работает! В одном из моих приборов с ее помощью был реализован замысел! А здесь нужно использовать прерывания, а у меня с этим туговато!
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
@serega_k, библиотека работает. Но нельзя считать значение пока крутится мотор на заданный шаг и нельзя изменить этот шаг пока он в процессе выполнения.
К примеру свою задачу я решил просто. Нужно было крутить два мотора на n шагов. Я сделал цикл от 0 до n-1 с одним шагом. Моторы крутятся хоть и по очереди, но происходит это настолько быстро,что это не заметно.
Я это к чему, то что при использовании прерываний ты теряешь точность. А шаговик это типо точный инструмент и теряется смысл его использования.
 

serega_k

✩✩✩✩✩✩✩
4 Ноя 2018
26
0
Ну так алгоритм такой: на энкодерной ленте насечки; сам энкодер считывает насечки и получаются импульсы; предположим 5 импульсов это 1 шаг шаговика! Вот это я и хочу реализовать!
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
@serega_k, а какой триггер на начало работы шаговика?
Поясню. Пять насечек = 1 шаг. ты двигаешь энкодер через пять насечек - шаговик делает один шаг. Пока шаг выполняется то что ты двигаешь энкодер ардуино не понимает.
 

serega_k

✩✩✩✩✩✩✩
4 Ноя 2018
26
0
Я не силен в програмировании а тем более в терминах! Не знаю что такое триггер!
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
@serega_k, как должна понять ардуино сколько ей делать шагов? что должно заставить передать значение количества пройденых насечек на команду выполнения поворота шаговика? Какое условие?
 

serega_k

✩✩✩✩✩✩✩
4 Ноя 2018
26
0
Я так понимаю что ардуино считывает импульсы (шаговик находится в покое) и хранит в какой то ячейке. Как только набралось 5 импульсов ардуино дает команду драйверу сделать 1 шаг и сбрасывает эту ячейку!
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
@serega_k, ну как напишете, так и будет работать.
Ок, предположим что логика работает так как вы описали. Тогда:
В переменную заносим кол-во считанных импульсов с энкодера. Если оно равно пяти, то даём команду на вращение шаговику и обнуляем переменную. Пока шаговик крутит, следующие импульсы с энкодера не считываются. Соответственно теряется точность.
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
@serega_k, зачем тогда вообще в этой схеме энкодер? Он может крутится и по нажатию кнопки с таким же успехом.
Объясни чё ты вообще хочешь сделать, какая принципиальная задача, мож чё поскажу.
 

serega_k

✩✩✩✩✩✩✩
4 Ноя 2018
26
0
вот его прорамма

// Пины для входа с энкодера

#define ENC_A_PIN 2

#define ENC_B_PIN 3

// Чтение значения с энкодера
#define ENC_A ((PIND & (1 << ENC_A_PIN)) > 0)
#define ENC_B ((PIND & (1 << ENC_B_PIN)) > 0)

// Пины STEP/DIR
#define STEP_PIN 13
#define DIR_PIN 12

// Отправка данных в порты STEP/DIR
#define STEP(V) (PORTB = V ? PORTB | (1 << (STEP_PIN-8)) : PORTB & (~(1<<(STEP_PIN-8))))
#define DIR(V) (PORTB = V ? PORTB | (1 << (DIR_PIN-8)) : PORTB & (~(1<<(DIR_PIN-8))))

void setup() {
intSetup();
driveSetup();
}

void driveSetup(){
pinMode(STEP_PIN, OUTPUT);
STEP(0);

pinMode(DIR_PIN, OUTPUT);
DIR(0);
}

volatile boolean A, B;

void intSetup(){
pinMode(ENC_A_PIN, INPUT);
A = ENC_A;
attachInterrupt(0, onEncoderChannelA, CHANGE);

pinMode(ENC_B_PIN, INPUT);
B = ENC_B;
attachInterrupt(1, onEncoderChannelB, CHANGE);
}

volatile unsigned long pulses = 0;
volatile boolean gotDir = false;
volatile boolean cw = false;

unsigned long pps = 2; // pulses per step

void loop() {

if(pulses >= pps){
pulses = 0;
STEP(1);
delayMicroseconds(10);
STEP(0);
}

if(gotDir){
DIR(!cw);
gotDir = false;
}
}

void onEncoderChannelA(){

A = ENC_A;

if((A && B) || (!A && !B)){
if(!cw) gotDir = true;
cw = true;
}else{
if(cw) gotDir = true;
cw = false;
}

pulses ++;
}

void onEncoderChannelB(){

B = ENC_B;

if((B && A) || (!B && !A)){
if(cw) gotDir = true;
cw = false;
}else{
if(!cw) gotDir = true;
cw = true;
}

pulses ++;
}
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
вот его прорамма

// Пины для входа с энкодера

#define ENC_A_PIN 2

#define ENC_B_PIN 3

// Чтение значения с энкодера
#define ENC_A ((PIND & (1 << ENC_A_PIN)) > 0)
#define ENC_B ((PIND & (1 << ENC_B_PIN)) > 0)

// Пины STEP/DIR
#define STEP_PIN 13
#define DIR_PIN 12

// Отправка данных в порты STEP/DIR
#define STEP(V) (PORTB = V ? PORTB | (1 << (STEP_PIN-8)) : PORTB & (~(1<<(STEP_PIN-8))))
#define DIR(V) (PORTB = V ? PORTB | (1 << (DIR_PIN-8)) : PORTB & (~(1<<(DIR_PIN-8))))

void setup() {
intSetup();
driveSetup();
}

void driveSetup(){
pinMode(STEP_PIN, OUTPUT);
STEP(0);

pinMode(DIR_PIN, OUTPUT);
DIR(0);
}

volatile boolean A, B;

void intSetup(){
pinMode(ENC_A_PIN, INPUT);
A = ENC_A;
attachInterrupt(0, onEncoderChannelA, CHANGE);

pinMode(ENC_B_PIN, INPUT);
B = ENC_B;
attachInterrupt(1, onEncoderChannelB, CHANGE);
}

volatile unsigned long pulses = 0;
volatile boolean gotDir = false;
volatile boolean cw = false;

unsigned long pps = 2; // pulses per step

void loop() {

if(pulses >= pps){
pulses = 0;
STEP(1);
delayMicroseconds(10);
STEP(0);
}

if(gotDir){
DIR(!cw);
gotDir = false;
}
}

void onEncoderChannelA(){

A = ENC_A;

if((A && B) || (!A && !B)){
if(!cw) gotDir = true;
cw = true;
}else{
if(cw) gotDir = true;
cw = false;
}

pulses ++;
}

void onEncoderChannelB(){

B = ENC_B;

if((B && A) || (!B && !A)){
if(cw) gotDir = true;
cw = false;
}else{
if(!cw) gotDir = true;
cw = true;
}

pulses ++;
}
по моему это кусок программы. не вижу какие библиотеки он подключает.
 

serega_k

✩✩✩✩✩✩✩
4 Ноя 2018
26
0
Да, компилируется!
Шаговик дергается в разные стороны и вроде как энкодер воспринимает, но толком не работает!
 

KOHb

★✩✩✩✩✩✩
25 Окт 2018
119
10
@serega_k, тьфу блин, чёж вы меня путаете со Stepper.h ?))))))
Используйте DRV8825 (В любом магазине радиодеталей по цене двух банок охота крепкая) и всё у вас заработает.

С его кодом позже разберусь)