Quadrature encoder and OLED with Arduino

For general Flowcode discussion that does not belong in the other sections.
Post Reply
geomanfred
Posts: 18
http://meble-kuchenne.info.pl
Joined: Mon Jun 27, 2022 2:56 pm
Has thanked: 5 times
Been thanked: 1 time

Quadrature encoder and OLED with Arduino

Post by geomanfred »

Hello,
I would like to test how an quadrature encoder component works and to show its counter on my OLED.
From hardware point of view everything is fine, because it works nice with Arduino IDE.
I used the code from examples of Rotary Encoder component page:
https://www.matrixtsl.com/wiki/index.ph ... :_General)
I use also a pushbutton from encoder.
When I push it, then it just changeing the value from 0 to 1 and then back to 0 at the next push.
I tried the attached Flowcode file.
In the simulation it works, but in reality, the OLED and Pushbutton works, but the encoder shows no values.
What can be wrong?
Attachments
Arduino Uno SH1106 I2C and Encoder FC9.fcfx
(17.11 KiB) Downloaded 50 times

chipfryer27
Valued Contributor
Posts: 1148
Joined: Thu Dec 03, 2020 10:57 am
Has thanked: 285 times
Been thanked: 412 times

Re: Quadrature encoder and OLED with Arduino

Post by chipfryer27 »

Hi

My first guess would be with the connections. How have you connected the encoder?

Which of the examples have you tried? Do none of them work or just one in particular (they each use different techniques)?

Regards

BenR
Matrix Staff
Posts: 1739
Joined: Mon Dec 07, 2020 10:06 am
Has thanked: 440 times
Been thanked: 603 times

Re: Quadrature encoder and OLED with Arduino

Post by BenR »

My Guess is the encoder is changing to fast to catch all the edges and therefore EncChanged is often equal to 255 and resetting the counter.

One option might be to try and remove the 10ms delay and see if that helps.

Another option is to use the interrupt based approach and see if this helps. Ether an IOC type interrupt or a timer based interrupt should be fine. This is probably more suitable because the GLCD will be relatively slow to update and may cause you to miss encoder pulses using a polling method.

geomanfred
Posts: 18
Joined: Mon Jun 27, 2022 2:56 pm
Has thanked: 5 times
Been thanked: 1 time

Re: Quadrature encoder and OLED with Arduino

Post by geomanfred »

Hi,
The next code works for me with interrupt on change on Arduino Port D, including Pushbutton state.
I noticed there is a debouncing in ms for the pushbutton.
I expect is the same, probably hidden, for the encoder inputs A and B too.
In Arduino IDE there are many ways how a debouncing can be implemented.
Then I have the next question:
- If I do not want to use the default debouncing, mostly done with timing in milliseconds, I guess, for pushbutton or for rotary encoder, then how can implement my own debouncing subroutine/code?
- With pushbutton seems simpler, because I just set the Debounce to 0ms, but how can I do it with the rotary encoder?
For example, a faster and better debounce code for rotary quadrature encoder, already tested with good results, would be next:

Code: Select all

void read_encoder() {
  // Encoder interrupt routine for both pins. Updates counter
  // if they are valid and have rotated a full indent
 
  static uint8_t old_AB = 3;  // Lookup table index
  static int8_t encval = 0;   // Encoder value  
  static const int8_t enc_states[]  = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // Lookup table

  old_AB <<=2;  // Remember previous state

  if (digitalRead(ENC_A)) old_AB |= 0x02; // Add current state of pin A
  if (digitalRead(ENC_B)) old_AB |= 0x01; // Add current state of pin B
  
  encval += enc_states[( old_AB & 0x0f )];

  // Update counter if encoder has rotated a full indent, that is at least 4 steps
  if( encval > 3 ) {        // Four steps forward
    counter++;              // Increase counter
    encval = 0;
  }
  else if( encval < -3 ) {  // Four steps backwards
   counter--;               // Decrease counter
   encval = 0;
  }
}
And for a pushbutton:

Code: Select all

bool debounce_switch() {
static uint16_t state = 0; //holds present state
state = (state << 1) | (digitalRead(SW)) | 0xE000;
if (state == 0xF000) return 1;
return 0;
}

Now, how can I implement this in Flowcode?
Should I just write C code and consider the pins A and B of the encoder as normal Inputs and just ignore the Flowcode component Rotary Encoder? Or may I change somehow that component? Or do I have to make a new component from scratch?
Or can be the existing component modified, maybe with a free/open code for debouncing, where the user can implement his own code or to have several debouncing subroutines to choose from?
What is the faster, easier or the better way?
Can you help in that direction?
Attachments
Arduino Uno SH1106 I2C and Encoder FC9_IOC.fcfx
(15.87 KiB) Downloaded 53 times

Post Reply