Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

how to count speed for rotary encoder

Status
Not open for further replies.

joeylee

Newbie level 4
Joined
Jan 2, 2011
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,368
hi all,

can someone help me on how to write program for rotary encoder to count speed.
so far, i only manage to capture the high value of the rotary encoder using interrupt but the value stay there.

can someone please help me, how to set the value to zero after 1 second so i can keep loop to count the speed every 1 second.

im using pic18f452 with crystal 4 MHz.

here is my code,


#include <p18f452.h>
#include <delays.h>
#include <adc.h>
#include <capture.h>
#include <timers.h>
#include <stdlib.h>
#include <math.h>

#pragma config OSC = XT
#pragma config WDT = OFF
#pragma config LVP = OFF

#define LED_ON PORTCbits.RC4
#define LED2 PORTDbits.RD6
#define LED1 PORTDbits.RD5
#define LED3 PORTDbits.RD7


#define RW_PIN PORTDbits.RD1 /* PORT for RW */
#define RS_PIN PORTDbits.RD3 /* PORT for RS */
#define E_PIN PORTDbits.RD0 /* PORT for E */
#define DATA_PIN PORTB // data pins but only use PB0-PB3


#define CapRise 0b00000101;
#define CapFall 0b00000100;


//LCD FUNCTION
void lcd_print_char(unsigned int);
void lcd_print_string(char []);
void lcd_command(unsigned int);
void lcd_init(void);

/*===================================================================================================
||||| Declare IR SENSor Functions |||||
===================================================================================================*/

void Get_Distance(void);

/*===================================================================================================
||||| Declare Interupt Functions |||||
===================================================================================================*/
void isr_high(void);
void isr_low (void);
void init(void);


/*===================================================================================================
||||| String Messages |||||
===================================================================================================*/

char output[] = "Alarm Activated";
char output1[] = "Alert";
char output2[] = "Slow Down";
char output3[] = "Dangerous";
char output4[] = "Critical";

/*===================================================================================================
||||| Global Variables |||||
===================================================================================================*/

short sensor_flag=0;
int sensor=0;
char sensorASCII[5];
int counter = 0;

/*===================================================================================================
||||| Enable ISR Checking |||||
===================================================================================================*/

int i=0;
int value = 0;
char valueASCII[7];
char iASCII[7];



/*===================================================================================================
||||| Main Program |||||
===================================================================================================*/

void main(void)
{

TRISCbits.TRISC4=0; //set LED_ON as input
TRISDbits.TRISD5=0;
TRISDbits.TRISD6=0;
TRISDbits.TRISD7=0; //set BUTTON as output
TRISA=0Xff;


LED_ON=1; //to show power on


TRISB=0x00;
TRISDbits.TRISD0=0;
TRISDbits.TRISD1=0;
TRISDbits.TRISD3=0;

DATA_PIN=0x00;
RW_PIN=0;
RS_PIN=0;
E_PIN=0;


Delay10KTCYx(10);
lcd_init();
init();



while(1)
{
OpenADC(ADC_FOSC_4 & ADC_RIGHT_JUST & ADC_8ANA_0REF, ADC_CH0 & ADC_INT_OFF);
Delay10TCYx(5);
ConvertADC (); // Start conversion
while (BusyADC()); // Wait for completion
sensor = ReadADC();
CloseADC();

itoa(sensor , sensorASCII);
lcd_command(0b11000000);
lcd_print_string(sensorASCII);

Get_Distance(); //Check for deactivation code






}
}
/*===================================================================================================
||||| LCD Initialization |||||
===================================================================================================*/

void lcd_init(void)
{
E_PIN = 0;
RS_PIN = 0;
RW_PIN = 0;

lcd_command(0b00100000);

lcd_command(0b00101000);

lcd_command(0b00001100);

lcd_command(0b00000001);

lcd_command(0b00000010);
}

/*===================================================================================================
||||| LCD Print Character with 4-bits interface |||||
===================================================================================================*/
void lcd_print_char(unsigned int character)
{
DATA_PIN=character >> 4;

RS_PIN = 1;
E_PIN = 1;
E_PIN = 0;
RS_PIN = 0;

DATA_PIN=character & 0x0f;

RS_PIN = 1;
E_PIN = 1;
E_PIN = 0;
RS_PIN = 0;
}
/*===================================================================================================
||||| LCD Print String |||||
===================================================================================================*/

void lcd_print_string(char string[])
{
int count =0;
while(string[count] != '\0')
{
lcd_print_char(string[count]);
count++;
}
}

/*===================================================================================================
||||| LCD Instruction with 4-bits interface |||||
===================================================================================================*/


void lcd_command(unsigned int lcd_command)
{

DATA_PIN=lcd_command >> 4;
E_PIN = 1;
E_PIN = 0;
DATA_PIN=lcd_command &0x0f;
E_PIN = 1;
E_PIN = 0;

Delay1KTCYx(10);
}

/*===================================================================================================
||||| Keypad Get Inputs |||||
===================================================================================================*/

void Get_Distance(void)
{

LED2=~2;
ultoa(value, valueASCII);
lcd_command(0b10000000);
lcd_print_string(valueASCII);


}

// interrupt setup
#pragma code high_vector=0x08

void high_vector (void)
{
_asm GOTO isr_high _endasm
}

#pragma code low_vector=0x18


void low_vector (void)
{
_asm GOTO isr_low _endasm
}

#pragma code
#pragma interrupt isr_high
void isr_high (void)
{
if(!PIR1bits.TMR1IF)
{
//TMR0 Overflow ISR

counter++;//Increment Over Flow Counter
value +=1;
PIR1bits.CCP1IF = 0; // clear capture flag bit





}
else
{
value=0;
}
}
#pragma interruptlow isr_low
void isr_low(void)
{
// unused
}

void init(void)
{
TRISC = 0x04; // RC2 CCP1 pin = input
CCP1CON = CapRise; // capture on rising edge

// interrupt setup
PIR1bits.CCP1IF = 0; // clear capture flag bit

IPR1bits.CCP1IP = 1; // CCP1 int is high priority

PIE1bits.CCP1IE = 1; // enable CCP1 interrupt

RCONbits.IPEN = 1; // enable priority levels on interrupts

INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
PIE1bits.TMR1IE = 1;
PIR1bits.TMR1IF = 0;

INTCON = 0b11100000; // global & peripheral ints enabled
}
 

you need a mask
that counts seconds
when a second goes buy on int
then it takes a sample of the encoder position and

take the mean value as the new zero...

using 127 0 127 +- 0-255 0 is shared null so is null + null = 1

dont use unsigned bytes convert to signed ...

treat 0 as a state much like 1

and not null

then its not a 'dent' 128 - 128 is and this is a state
0 becomes 1

the encoder turns from tri state to bistate in code

if you want 1 second read and reset

you must add atleast an interrupt and its timer {quite hard to get exactly 1 second on a pic without 32khz crystal ref }
 
Last edited:

sorry i do not understand.

what it means by taking 127 0 127 +- 0 -255 ?

and what is mask? im new to programming.

thanks for replying..
 

i see ok if you have 0-255 this is 256 states

like most encoders give out

some are 1024 states {for a full rotation i mean}

so you must not measure as 0-255 or 0-1027
you need to use converted to signed number

127+127 = 254 but this is 255 states + 0
if 0 in not a null dented state

and a encoder only has either 256 or 1028 states non dented

.,, or 255 or 1027 etc etc dented states

if you want to sample and set to 0 an encoder
it doesnt matter where it is its on a dent or not

what type of encoder do you use

this matters most... in code

it can be done for both
but you need to know

is dented or not>>???

---------- Post added at 15:42 ---------- Previous post was at 15:39 ----------

is hard to grasp i agree

---------- Post added at 15:42 ---------- Previous post was at 15:42 ----------

what is the encoder number and datasheet url if you have it ??

---------- Post added at 15:43 ---------- Previous post was at 15:42 ----------

a mask is what you put on to disguise the face from an audience...

a dented encoder has parity
a non dented has no parity

---------- Post added at 15:53 ---------- Previous post was at 15:43 ----------

please post encoder details

ill give to you a proteus model

comvdd.dll does this already
you just need to set it up
if proteus is something you like using

then ill help more

par for the hole in golf = 0 added to score and no dent in score ...!
rule i find handy...:grin:

simple golf :|
 
Last edited:

oh man


this is not a rotory encoder
its a disk based 7 bit much like a mouse
is interupter and not step based by step taken {becouse micro races on}
so is 7 bit data and no null and mcu step independant

to zero it you just zero the variable every 1 second then sample yes no
add 1 or take away 1 or zero the count...
open closed and start from there for next count

eek

man i thought you ment like many states encoder

still

happy new year

you still need to add interrupt routine for ~1second
{best youll get on a pic with no actual 1 second clock is +- a nop {4/clock }
+ - 0.0000002 seconds @20mhz

Rotary encoder - Wikipedia, the free encyclopedia

a rotary encoder has preset binary states

advice is

to read the book i got on pic's when i was 12 some 30 years ago from microchip

how to build a mouse
it has route code
all you need as for time nop = as i sayed 4/clock you use
i will send you code
but man use port B
has int pins
similar written in c
uses intterupts
for referance only
man avoid port A
how to count speed is a mater of time elapsed counter since last stop
and a stack to do it if it takes more than 65534 seconds till next its moved in 16 bit mode
as you may know or use super set system time stacking ...

but man you need to use c compiler or code will be harder.. much more tough:-(
 

Attachments

  • TIMED DRIER ONOFF.zip
    9.1 KB · Views: 103
  • 4bit_toggle_latch_with_functions_v3final.zip
    46.3 KB · Views: 108
Last edited:
Hi,

ya this is what i wan, the interrupt routine for 1 second .

i really do not know how to write this in code, as i tried but it did not work.

can you please help me?:oops::oops:

thankssssss
 

One more elegant solution is to use RTOS like SALVO (see Pumpkin: Salvo, the RTOS that runs in tiny places) - you can run several programs simultaneosly inside a single uP. In this case you simply create a task that wakes up every 1s and then it's calculating the speed. I used to make a head position measurement of pad printing machine (linear encoder) with SALVO and it worked perfectly well. Depend on the frequency of the speed events (rotary encoder pulses) you can use interrupts or simply another task.

The beauty of the RTOS is that the program becomes extremely simple and easy for maintanence.
 

yes what he wants is the code written for him

no go
 

Hi luben and VSMVDD,

thanks for the info.

im still working on it.
will update after i finish it.

thanks alot.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top