Ви не увійшли.
Сторінки 1
Пару месяцев назад я уже выкладывал в своем блоге и сообществе программы для работы с энкодером. Пост назывался «энкодер это просто». Недостатком тех программ было использование задержек для программного подавления дребезга контактов. В обычных устройствах такие задержки вполне приемлемы и не сказываются на качестве выполняемых задач. Но бывают задачи, когда использование задержек непозволительная роскошь, даже если это и не пресловутый delay().
И вот недавно случилось мне заниматься написанием программы для стенда по настройке топливной аппаратуры дизельных двигателей. В программе кроме тахометра, счетчика заданного количества оборотов, кнопок, индикации и т.п. нужно было еще обрабатывать данные с восьми энкодеров. Использование абсолютных энкодеров (ru.wikipedia.org/wiki/Датчик_угла_поворота) проект не предусматривал, поэтому пришлось мучиться с инкрементальными.
Первым делом нужно было избавиться от каких-либо задержек в обработке сигналов. После некоторого «мучения» получился вот такой код.
Сохранить в Альбом
Несмотря на свою краткость, эта программа вполне успешно справляется со своей задачей.
Можете её использовать в проектах для регулировок, в паяльных станциях, усилителях и т.п.
Но мне нужно было увеличить точность отслеживания перемещения, нужно было реагировать на каждый бит информации.
Как принято говорить, «допилив» программу, получил желаемую точность.
Аппетит приходит во время еды, и на определенном этапе разработки было принято решение обрабатывать каждый энкодер своим контроллером. Использовать ATmega или ATtiny85 (это было в наличии) у которых на борту имеется UART, показалось как-то расточительно.
Выбор пал на ATtiny13… если бы я знал какой это мазохизм то наверное … Впрочем не будем об этом.
В сети есть немного информации по программному UART для ATtiny13, я за основу взял этот листинг.
pastebin.com/NBFMq1C6
Немного его доработал, добавил необходимые обработчики и получил такой себе псевдо абсолютный энкодер. Теперь все восемь энкодеров можно подключить на одну шину и не бояться, что основная программа пропустит какое-то изменение угла.
Неактивний
Краткость сестра таланта. У всех современных микроконтроллеров есть функция прерывания по изменению входного состояния портов, у ATTiny тоже. Использовать ее для автомата энкодера было бы лучшим решением. А фильтр подавления дребезга, на мой взгляд, все-таки желателен, для предотвращения ложных сигналов перемещения, который имеет смысл дрожания вала.
прерывания используются для UARTa ...
Неактивний
Вы прогрупповые ....
А зачем вообще если все нормально реализовано и без них...
В предыдущем посте я выкладывал скетчи с прерыванеием... значимого отличия в работе не обнаружено.
По поводу фильтра - двух конденсаторов хватает за глаза...
Неактивний
Можно по всякому, и опросом тоже, это не очень принципиально. Лишь бы требуемым параметрам удовлетворить. Есть даже аппаратная поддержка таймерами, для больших скоростей. А RC фильтр на логическом входе - опасная вещь, нужен триггер шмидта.
По поводу этого не знаю.
Сталкивался только с описаниями (тесты в реале) эффективности RC фильтров.
Хотя действительно в некоторых микросхемах на входах для энкодеров аппаратно стоят ТШ.
Неактивний
boolean compare, triger, inc_cw, nc_cww;
byte division,division_CW,division_CWW, backlash_CW, backlash_CWW, backlash;
int counter_lcd , calibre_lcd;
// настройка вннешнего прерывания INT0 и INT1.
//INT0 PD2. Mode: Falling Edge. INT1 PD2. Mode: Rising Edge.
EICRA = (1<<ISC11) | (1<<ISC10) | (1<<ISC01) | (0<<ISC00);
EIMSK = (1<<INT1) | (1<<INT0);
EIFR = (1<<INTF1) | (1<<INTF0);
PCICR = (0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);
//======================================================================
if((digitalRead(10) == 0)&&(triger == 0)) //compare.
{
temp++;
if(temp == 0xff)
{
if(counter_lcd < calibre_lcd) //motor_cww.
{
compare = 0;
PORTD |= (1<<5); //on motor cw.
while(compare == 0)
{
}
PORTD &= ~(1<<5); //off motor.
PORTB |= (1<<4); //on braking.
braking = 0x3300; //13056 time braking.
triger = 1; //set triger.
goto compare_end;
}
if(counter_lcd > calibre_lcd) //motor_cww.
{
compare = 0;
PORTD |= (1<<4);//on motor cww.
while(compare == 0)
{
}
PORTD &= ~(1<<4); //off motor.
PORTB |= (1<<4); //on braking.
braking = 0x3300; //13056 time braking.
triger = 1; //set triger.
}
}
}
compare_end:
ISR(INT0_vect)//INT0 PD2. Mode: Falling Edge. обработка прерываний с деление и люфтом INT0 and INT1 - ON
{
cli();
if((inc_cw == 1)&&(digitalRead(3) == 0))// энкодер++.
{
if(backlash_CW == backlash)//выбор люфта вперед.
{
if(division_CW == division) //деление входных импульсов.
{
counter_lcd++;
if(compare == 1)
{
if(counter_lcd == calibre_lcd)
{
PORTD &= ~(1<<5);
compare = 1;
}
}
division_CW = 0;
goto out_int_A;
}
division_CW++;
goto out_int_A;
}
backlash_CW++;
backlash_CWW = 0;
division_CWW = 0;
goto out_int_A;
}
if((inc_cww == 1)&&(digitalRead(3) == 1))//энкодер--.
{
if(backlash_CWW == backlash)//выбор люфта назад.
{
if(division_CWW == division)//деление входных импульсов.
{
counter_lcd--;
if(compare == 1)
{
if(counter_lcd == calibre_lcd)
{
PORTD &= ~(1<<4);
compare = 1;
}
}
division_CWW = 0;
goto out_int_A;
}
division_CWW++;
goto out_int_A;
}
backlash_CWW++;
backlash_CW = 0;
division_CW = 0;
}
out_int_A:
inc_cw = 0;
inc_cww = 0;
sei();
}
//==================================================================
//ISR(INT1_vect)//INT1 PD2. Mode: Rising Edge.
{
cli();
if(digitalRead(2) == 0){inc_cw = 1; inc_cww = 0; goto out_int_B;}//энкодер++.
if(digitalRead(2) == 1){inc_cww = 1; inc_cw = 0; goto out_int_B;}//энкодер--.
out_int_B:
sei();
}
//====================================================================
Вот мой код обработке энкодера, смысл в том что есть переменная calibre_lcd к значению которой крутится двигатель. В первом прерывании задаются направление энкодера в нулевом отсчёт. В коде есть выборка люфта и деление входных импульсов от энкодера.
Проблема такова, не срабатывает вот этот код, двигатель крутится постоянно. Я убирал люфт и деление, проблема остаётся значит дело не в них???
if(compare == 1)
{
if(counter_lcd == calibre_lcd)
{ PORTD &= ~(1<<5); // или PORTD &= ~(1<<4);
compare = 1;
}
}
Остання редакція goodspeedmen (2017-06-08 15:42:36)
Неактивний
Вот мой код обработке энкодера, смысл в том что есть переменная calibre_lcd к значению которой крутится двигатель. В первом прерывании задаются направление энкодера в нулевом отсчёт. В коде есть выборка люфта и деление входных импульсов от энкодера.
Проблема такова, не срабатывает вот этот код, двигатель крутится постоянно. Я убирал люфт и деление, проблема остаётся значит дело не в них???
Вставьте код по правилам форума....
Неактивний
Сторінки 1