ura308

Отрицательный Отсчет-Реверсивный Счетчик На Энкодере

5 сообщений в этой теме

ura308    0

Подскажите как реализовать? реверсивный счетчик, энкодер крутит в сторону вычитания до нуля и счетчик останавливается-как сделать чтоб неостанавливалось дальше считало от нуля 1,2,3,...реверсивно

void fnBtEnc(void)

{

static uchar cButt;

static uchar cEnc;

//------------------

cButt=fnReadButt();

if(cButt)

{

lCnt=0;

fnCalc(lCnt);

}

//------------------

cEnc=Encoder_Exe();

if(cEnc != NULL_ENC)

{

switch(cEnc)

{

case PLUS_ENC:

lCnt+=1; // энкодер вправо

break;

case MINUS_ENC:

if(lCnt)lCnt-=1; //энкодер влево

break;

}

fnCalc(lCnt);

}

}

Поделиться сообщением


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

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Alex    484
и счетчик останавливается
В коде этого нет. Не понятно, из-за чего это у Вас происходит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ura308    0

Только начал осваивать "Си" для AVR

Архив с проектом в конце сообщения ( WinAvr 2010,симуляция Proteus 7.на семисегментниках )

Проект с радиокота http://radiokot.ru/f...hp?f=61&t=84965

Вариант с Lcd16х2 не рассматриваю - некомфортно,нечитабельно с расстояния! только на сегментных индикаторах!

Поставил дома на станок в качестве линейки,А он считает реверсивно только в одном направлении - если при резе дошел до "0" то при резе в другом направлении относительно "0" счет не происходит. Толку от него ровным счетом ноль!

У заводского на другой оси все в порядке! у него энкодер имеет выходы A ,B и Z-изменение направления.

У меня стоит обычный оптический 200 импульсов энкодер A и B выходы.

Нужно чтобы при изменении направления вращения энкодера относительно "0" (допустим после первого импульса ) -инверсировался опрос энкодера так, что бы счетчик считал как и считал ранее а минус высвечивался в зависимости он направления счета относительно "0"

Вывод на индикацию через 74HC595 чтобы освободить ножки для вывода "индикации - (Минус)"

Неплохо бы было и делитель добавить чтоб убрать погрешность (количество импульсов на 1мм)

Довести проект "до ума" Таких проектов в интернете просто нет!

Я думаю он многим будет полезен!

сам код опроса энкодера

:


//! Файл	 : button_enc.h
//!**************************************************
#include "button_enc.h"
#include "hard_config.h"
//----------------------------- Константы: -----------------------------------
enum { State0, StateA, StateB, StateAB }; //состояния энкодера
//----------------------------- Переменные: ----------------------------------
static char EncPrev;	 //предыдущее состояние энкодера
static char EncPrevPrev; //пред-предыдущее состояние энкодера
//----------------------- Инициализация энкодера: ----------------------------
void Encoder_Init(void)
{
EncPrev = State0;	 //инициализация предыдущего состояния
EncPrevPrev = State0; //инициализация пред-предыдущего состояния
PORTA=0xFF;
}
//------------------------- Обработка энкодера: ------------------------------
REZ_ENC Encoder_Exe(void)
{
char EncCur = 0;

char cRezEnc=NULL_ENC;

if(!Pin_ENC_F1) {EncCur = StateA;} //опрос фазы 1 энкодера
if(!Pin_ENC_F2) {EncCur |= StateB;} //опрос фазы 2 энкодера
if(EncCur != EncPrev)			 //если состояние изменилось,
{
if(EncPrev == StateAB &&	 //если предыдущее состояние StateAB
 EncCur != EncPrevPrev )	 //и текущее и пред-предыдущее не равны,
{
 if(EncCur == StateB) {cRezEnc= MINUS_ENC;}
 else{ cRezEnc=PLUS_ENC;}
}
//----------------------------------------------------------------------------------------------------------------
вот когда это дописал считает реверсивно!только в другом направлении вращения Но неправильно( начал пропускать импульсы)
а реверсивно в этом направлении вообще почти не считает ( на 200 импульсах в сек) а на 24 считает кое как
( в другом направлении когда считает импульсы не пропускает)
как автоматизировать процесс переключения между ними? в зависимости от направления вращения если на табло "0" или сброс в ноль
с какой переменной брать результат счетчика - или этот ноль?
что подправить чтоб импульсы не пропускал?
------------------------------------------------------------------------------------------------------------------//
else
if(EncPrev == StateAB && //если предыдущее состояние StateAB
EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
{
if(EncCur == StateB) {cRezEnc=PLUS_ENC;}
else{ cRezEnc= MINUS_ENC;}
}
//---------------------------------------------------------------------------------------------------------------------
EncPrevPrev = EncPrev;		 //сохранение пред-предыдущего состояния
EncPrev = EncCur;			 //сохранение предыдущего состояния
}
return cRezEnc;
}

главная функция;

//!**************************************************
//! Файл	 : main.c
//! Авторское право (с) :
//! Разработка	 : urry <urry1@rambler.ru>
//! Дата создания	 :
//! Описание
//!
//!**************************************************
#include "hard_config.h"
// определяем массив вывода и флаги
volatile sFlags_ strFlags;
volatile uchar cCalculate[DIGIT];
static unsigned long lCnt;
// определение используемых функций --------------
static void fnInit(void);
void fnBtEnc(void);
void fnLtoA(unsigned long tmp);
void fnCalc(unsigned long l);
//------------------------------------------------
//=========================================
int __attribute__((naked)) main (void)
//=========================================
{
fnInit();
for(;
{
if(strFlags.bTick)
{
strFlags.bTick=false;
fnBtEnc();
if(BITTST0(PINA,1))// пропадание напряжения !
{
fnEepSave(lCnt); // записываемся
off:
asm("wdr");
goto off;// до сброса питания ничего не делаем
}
} //end strFlags.bTick
asm("wdr");
}// end for
}// end main
//=========================================
//-----------------------------------------
static void fnInit(void)
{
DDRD=0;
DDRD|=(1<<R_1)|(1<<R_2)|(1<<R_3)|(1<<R_4)|(1<<R_5);
PORTD=0xFF;
DDRB=0xFF;
// Timer/Counter 0 initialization
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// External Interrupt(s) initialization
GIMSK=0x00;
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x80;
// Universal Serial Interface initialization
USICR=0x00;
// Analog Comparator initialization
ACSR=0x80;
asm("wdr");
wdt_enable(WDTO_1S);
lCnt=fnEepRead();
fnCalc(lCnt);
strFlags.bReady=1;
Encoder_Init();
//--------------------------------
sei();
}
//------------------------------------
void fnBtEnc(void)
{
static uchar cButt;
static uchar cEnc;
//------------------
cButt=fnReadButt();
if(cButt)
{
lCnt=0;
fnCalc(lCnt);
}
//------------------
cEnc=Encoder_Exe();
if(cEnc != NULL_ENC)
{
switch(cEnc)
{
case PLUS_ENC:
lCnt+=5;
break;
case MINUS_ENC:
if(lCnt)lCnt-=5;
break;
}
fnCalc(lCnt);
}
}
//------------------------------------
void fnLtoA(unsigned long tmp)
{
const unsigned long step[DIGIT]={10000,1000,100,10,1};
uchar i,atemp;
unsigned long val,temp;
char flag=0;
val=tmp;
for (i=0; i<DIGIT; i++)
{
if(i==3){flag =1;}
temp=step[i];
atemp=0;
while(val >= temp)
{
atemp++;
val-=temp;
}
if((flag) || (atemp))
{
 cCalculate[i]=atemp;
 flag=1;
}
else{cCalculate[i]=10;}
}
}
//------------------------------------
void fnCalc(unsigned long l)
{
if(l >= 99999){l=0;}
fnLtoA(l);
strFlags.bReady=1;
}
//------------------------------------

kot_impuls_metr_05.rar

Изменено пользователем ura308

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    484

case MINUS_ENC:
if(lCnt)lCnt-=5;

А для чего тут проверка lCnt на нулевой значение ?

Оно Вам и вредит.

Поделиться сообщением


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

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас