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.

Programmin rotary encoder

Status
Not open for further replies.

venkates2218

Full Member level 6
Full Member level 6
Joined
Sep 30, 2016
Messages
354
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,298
Activity points
4,306
Friends,In my project i need rotary encoder to increase and decrease the value...
I dono how t program it...
I tired so many times but i can't correct output...
please help me to program encoder for increment and decrements operation. 41lYwFeNduL._SX425_.jpg
 

Hi,

a picture doesn´t say much about the signals.
It tells no levels, it tells not how you did connect it with the microcontroller.
It doesn´t say which microcontroller you use.
It doesn´t say which language you use.
And it doesn´t tell what you want to achieve.

***
The most important is the datasheet of the rotary encoder.
Then a schematic,
Then a flow chart of your software.

Klaus
 

Try this example (...) This code is for 3 pin rotary encoder.

There is absolutely no indication of similarity on both encoders signal patterns, even pinouts. Please don't provide hints based on clearly wrong assumptions, actually different scenarios.
 

Yes, you are right.

I had that Rotary encoder. Actually I have both those encoders that is the one OP posted and another from mikroE. I have used mikroE one and had not used the other one. The one OP asked has 5 pins.

GND = GND
+ = VCC
SW = same as INT of mikroE rotary encoder. It is to detect encoder switch press and can be connected to INT pin of MCU.

DT = DATA
CLK = Clock.

I don't know why clock is needed for a rotary encoder. I will test it today and will update this thread.

- - - Updated - - -

Edit:

Here is an example for OP's Rotary Encoder. I will also try it.

https://circuitdigest.com/microcontroller-projects/avr-rotary-encoder-interfacing
 

Here is an example for OP's Rotary Encoder. I will also try it.

https://circuitdigest.com/microcontroller-projects/avr-rotary-encoder-interfacing

This code seems like not suited to work with encoders - even for the ones having low resolution - unless being the program purposed to do nothing else than just dealing with it. In addition to the fact that the author did not use the core's interrupt feature to handle the asynchronous state change events of the pins, he added 10ms fixed delay, supposedly as a debounce, but did not reread the value of these inputs after that period. In shorts, it just seems like an experimental code, not eligible to be used as a template in a serious project.
 

The most likely explanation is that the pin names D (or DT) and CLK are inappropriate and it's actually a industry standard quadrature encoder with A/B outputs. In this case all code examples dedicated to quadrature encoders can be used.

It's however quite simple to verify if it's a quadrature encoder.

You could interprete the A/B outputs as clock and direction signals. Use e.g. A rising edge as count clock and B as up/down signal. But you get only 1 pulse where you can get four by using a standard quadrature decoder algorithm.

https://en.wikipedia.org/wiki/Rotary_encoder#Incremental_rotary_encoder
 

I experimented a little and this code works fine. I have tested it on hardware. It is actually mikroE rotary encoder code only. I just removed the 74HC695 code and used LATD to display LED state.
I will make video and post link here.

My connections

GND = GND
+ = Vcc (5V)
SW = INT0
DT = A
CLK = B

mikroC PRO PIC Code


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
sbit ENCA               at RC0_bit;
sbit ENCB               at RA2_bit;
sbit ENC_SW             at RB0_bit;
sbit ENCA_direction     at TRISC0_bit;
sbit ENCB_direction     at TRISA2_bit;
sbit ENC_SW_direction   at TRISB0_bit;
 
unsigned int Led_State = 0x01;
char ENCA_bit = 0,ENCB_bit = 0;
char ENC_Button_State = 0;
 
// ISR
void Interrupt(){
  ENC_Button_State++;                                   // set new ENC button state
  if (ENC_Button_State == 4)
    ENC_Button_State = 0;
  // check for interrupt
  if(INT0IF_bit){                                         // clear Interrupt flag
    // check ENC button state
    switch (ENC_Button_State){
      case 0 : LATD = Led_State = 0b00000001;                      // One LED are ON
               break;
      case 1 : LATD = Led_State = 0b00000101;                      // Two LEDs are ON
               break;
      case 2 : LATD = Led_State = 0b00010101;                    // Four LEDs are ON
               break;
      case 3 : LATD = Led_State = 0b01010101;                     // Eight LEDs are ON
               break;
      default :
               break;
    }
    
    INT0IF_bit = 0;
  }
}
 
void main() {
  CM1CON0 = 0x00;
  CM2CON0 = 0x00;
  
  SLRCON = 0x00;
  
  ANSELA = 0;                                          // Configure PORTA pins as digital
  ANSELB = 0;                                          // Configure PORTB pins as digital
  ANSELC = 0;
  ANSELD = 0;                                          // Configure PORTC pins as digital
  
  TRISD = 0x00;
  LATD = 0x00;
  
  ENCA_direction     = 1;                               // Configure RC0 as input
  ENCB_direction     = 1;                               // Configure RA2 as input
  ENC_SW_direction   = 1;                               // Configure RB0 as input
 
  INT0IE_bit = 1 ;                                      // Enable INTE interrupt on RB0
  GIE_bit = 1 ;                                         // Enable Global Interrupt
  
  while(1) {
    if((ENCA_bit != RC0_bit)||(ENCB_bit != RA2_bit)){   // If logic state on pin A or pin B change
                                                        // Compare last logic state of pin B and new logick state on pin A
      if(ENCB_bit|RC0_bit==1){                          // If ENCB_old OR ENCA_new is 1
        Led_State = (Led_State << 1) | (Led_State >> 7);
      }
 
      if(ENCA_bit|RA2_bit==1){                          // If ENCA_old OR ENCB_new is 1
        Led_State = (Led_State >> 1) | (Led_State << 7);
      }
 
      LATD = Led_State;
      
      ENCA_bit = RC0_bit ;                              // Set new value of ENCA_bit
      ENCB_bit = RA2_bit ;                              // Set new value of ENCB_bit
    }
  }
}

 

Hi,

A rising edge as count clock and B as up/down signal.
For a simlified design this will work, but not for a reliable industrial design.
I assume my coffe machine uses this simple method.

The problem with the simple method is:
If "A" is used as clock ... and the encoder is close to the edge of "A" then "A" may toggle a couple of times, where "B" is stable. This makes the counter to erroneously run in one direction.

Therefore I recommend to use the true "quadrature encoder" code.

****
But as long as the OP doesn´t give useful informations, it´s just guessing.
It seems the OP is´n interested in this discussion, anyway.

****
Btw: I´ve seen encoders
* that don´t have "A" and "B"
* but "COUNT" and "DIR"
= no quadrature output

Klaus
 

I experimented a little and this code works fine

Your code performs only sequentially port read, it is not interrupt driven. You cannot state that it works fine, unless the only task expected to this program is just to play with that encoder.

mikroC PRO PIC Code

As said bofore stops suggesting this compiler in specific, unless mentioned along the discussion.
 

What is sequential port reading ? Polling ?

If yes, then I can use three INTx pin and modify the code to use external interrupts to read the encoder states.
 

What is sequential port reading ? Polling ?

It is not usual to read encoders by polling, but by interrupt driven pin change routine. Let's suppose OP uses this as panel knob and quickly turns it to reach the desired value at the menu screen. It is not guaranteed that any other routine (included the 10ms delay itself) will not blind the pin change any time with the reading being done in a sequence (I'm assuming that there will be more stuffs on this program). Anyway, let's wait for OP give more details on what exactly he wants.
 
  • Like
Reactions: Okada

    Okada

    Points: 2
    Helpful Answer Positive Rating
Curiously the libstock (mikroE library) code, which has been slightly modified in post #8, doesn't implement a correct quadrature decoder algorithm.

Code:
if(ENCB_bit|RC0_bit==1){   // If ENCB_old OR ENCA_new is 1
   // count up
}
if(ENCA_bit|RA2_bit==1){   // If ENCA_old OR ENCB_new is 1
   // count down
}
It counts both up and down in two cycles and up or down in the other two cycles. So it is "working" somehow, but not as expected. The fact that the code is authored by the "MikroElektronika Team" might be alarming for microC users...

A small modification sets up a regular quadrature encoder.
Code:
if(ENCB_bit^RC0_bit){   // If ENCB_old != ENCA_new
   // count up
}
if(ENCA_bit^RA2_bit){   // If ENCA_old != ENCB_new
   // count down
}
Of course I agree with the previous comments about better putting the decoder into a pin change interrupt.

- - - Updated - - -

To add a sidenote,
Code:
if(ENCB_bit|RC0_bit==1){   // If ENCB_old OR ENCA_new is 1
involves also a misunderstanding of C operator precedence, it should be
Code:
if((ENCB_bit|RC0_bit)==1){   // If ENCB_old OR ENCA_new is 1
 
  • Like
Reactions: Okada

    Okada

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top