Trying to Reset Rotary Encoders

Hi Guys

I’m struggling … … .

I’m doing some experiments related to measuring position on 2 axis … I’ve got two Rotary Encoders, one on X axis, one on Y axis … linked to a Mega 2560 and a 1602 LCD.

Moving either encoder increments or decrements the display values perfectly so I then thought I’d ice my cake and use the push button on the encoder to reset the value the same encoder.

I’ve looked at it and looked at it, but can’t get it to do it … … …

Any pearls of wisdom going spare ? It’s the code below the dotted line that won’t co-operate … …

#define inputA 8
#define inputB 9
#define inputC 33
#define inputD 35
#define inputE 2
#define inputF 31

#include "LiquidCrystal.h"

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);


int counter1 = 0;
int counter2 = 0;
int astate;
int bstate;



void setup() {
    pinMode (inputA, INPUT_PULLUP);
    pinMode (inputB, INPUT_PULLUP);
    pinMode (inputC, INPUT_PULLUP);
    pinMode (inputD, INPUT_PULLUP);
    pinMode (inputE, INPUT_PULLUP);
    pinMode (inputF, INPUT_PULLUP);

  lcd.begin(16, 2);

    Serial.begin (9600);
    // Reads the initial state of the outputA
      astate = digitalRead(inputA) << 3 + digitalRead(inputA) << 2 ;
  bstate = digitalRead(inputC) << 3 + digitalRead(inputC) << 2 ;
}
void loop() {
   
    astate +=  digitalRead(inputA) << 1;
    astate +=  digitalRead(inputB);
    if (astate == 1   || astate == 7 || astate == 14 || astate == 8)
        {
         counter1++;
         Serial.print(counter1);
         Serial.print(" \n\r");
       
  }
    if (astate == 2   || astate == 11 || astate == 13 || astate == 4)
        {
         counter1--;
         Serial.print(counter1);
         Serial.print(" \n\r");
       
  }
  {
    bstate +=  digitalRead(inputC) << 1;
      bstate +=  digitalRead(inputD);
      if (bstate == 1   || bstate == 7 || bstate == 14 || bstate == 8)
          {
           counter2++;
           Serial.print(counter2);
           Serial.print(" \n\r");
         
    }
      if (bstate == 2   || bstate == 11 || bstate == 13 || bstate == 4)
          {
           counter2--;
           Serial.print(counter2) ;
           Serial.print(" \n\r");
    }

       lcd.setCursor(0, 0);
       lcd.print("X Pos      Y Pos");
     
    lcd.setCursor(1, 1);
    lcd.print(counter1, DEC);
               lcd.print(" ");

    lcd.setCursor(12, 1);
    lcd.print(counter2, DEC);
               lcd.print(" ");
             
      astate = astate << 2 & 0xc;
    bstate = bstate << 2 & 0xc;
  }
// -------------------------------------------------------------

   
  if (inputE == HIGH)
  {
    counter1 = 0; 
    lcd.setCursor(1, 1);
    lcd.print(counter1, DEC);
    lcd.print(" ");

  }
  if (inputF == HIGH)
  {
    counter2 = 0;
    lcd.setCursor(12, 1);
    lcd.print(counter2, DEC);
    lcd.print(" ");
    
  }
}

Thanks

S

Musicmanager: Hi Guys

I'm struggling .. .. .

I'm doing some experiments related to measuring position on 2 axis .. I've got two Rotary Encoders, one on X axis, one on Y axis .. linked to a Mega 2560 and a 1602 LCD.

Here's an encoder handler plus read and write code that I use for my projects:

volatile int32_t position;
volatile uint8_t state;

// one of the encoder outputs
ISR (INT0_vect)
{
    updEncoder ();
}

// the other encoder output
ISR (INT1_vect)
{
    updEncoder ();
}

void updEncoder (void)
{
    state >>= 2;
    state |= (ENC_INP & ENC_A) ? 0b0100 : 0;
    state |= (ENC_INP & ENC_B) ? 0b1000 : 0;

    switch (state) {
        case 1: case 7: case 8: case 14: {
            position += 1;
            break;
        }
        case 2: case 4: case 11: case 13: {
            position -= 1;
            break;
        }
        default: {
            break;
        }
    }
}

int32_t readEncoder (void)
{
    int32_t newval;
    cli();
    newval = position;
    sei();
    return newval;
}

void writeEncoder (int32_t newval)
{
    cli();
    position = newval;
    sei();
}

Obviously, you setup your #defines for ENC_INP (which will be a PINx equate depending on what pin you use) and also setup ENC_A and ENC_B which will be _BV(x) equates depending on what bit of the port you use. And, you setup the interrupts as "either edge trigger".

Or, you can use digitalRead(x) if you want.

Notice that in addition to readEncoder() there is also a writeEncoder(). You can set (or reset) the encoder value to whatever you want by using writeEncoder().

Note that an encoder only outputs pulses which correlate to movement and direction. There is no such thing as a "value" in an encoder. That is, you cannot set an ENCODER to a particular value... you can only set the value that the encoder handler code uses to keep track of pulses and direction.

Hope this helps.

Hi Krupski

Thanks for the response.

I initially tried to set up my encoders using ISR's but I couldn't get it to run so there's a useful example there for me study.

However, my sketch works fine as it is in that movement of either RE generates a 'value' for X or Y displayed on the LCD.

What I cannot get it to do .. there is a button on the top of each RE which in effect is a simple momentary push button and the code in my sketch after the dotted line is my attempt to get the 'value' on the LCD to return to zero when the button is pressed, ie when either pin 2 or pin 31 is HIGH.

My problem is that in spite of several hours of trying, nothing I can do will make that happen.

Thanks for looking

S

Musicmanager: What I cannot get it to do .. there is a button on the top of each RE which in effect is a simple momentary push button and the code in my sketch after the dotted line is my attempt to get the 'value' on the LCD to return to zero when the button is pressed, ie when either pin 2 or pin 31 is HIGH.

Well, from what you say it seems like you have the encoder button setting it's input high (assuming you connect VCC to the input when the button is pressed?).

If so, that's your problem. When the button is not pushed. the input is pulled high via the "INPUT_PULLUP" setting for the pin. When you press the button, you set the pin high (i.e. NOTHING CHANGES!).

You should use "INPUT_PULLUP" then use the encoder button to pull the pin to ground (i.e pull it LOW) then look for a "INPUT_E" or "INPUT_F" to be LOW.

Hope I'm on the right track now.......

Also, your if statements using inputE and inputF are not testing the condition of the pin. You're testing the value of the constant, inputE will always be 2 and inputF will always be 31. Try using digitalRead(inputE) and digitalRead(intputF).

I also agree with krupski. If you're wiring your pins with the switch to ground and using INPUT_PULLUP, when the switch is active, the digitalRead() should return LOW. If you want to test for HIGH, you'll need to wire it with an external pull-down resistor, and connect the other end of the switch to VCC. And don't use INPUT_PULLUP in that case.

Hi Guys

Here is my code, modified in the light of your advice …

#define inputA 8
#define inputB 9
#define inputC 33
#define inputD 35
#define inputE 18
#define inputF 19

#include "LiquidCrystal.h"

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);


int counter1 = 0;
int counter2 = 0;
int astate;
int bstate;
int reset1;
int reset2;



void setup() {
    pinMode (inputA, INPUT_PULLUP);
    pinMode (inputB, INPUT_PULLUP);
    pinMode (inputC, INPUT_PULLUP);
    pinMode (inputD, INPUT_PULLUP);
    pinMode (inputE, INPUT_PULLUP);
    pinMode (inputF, INPUT_PULLUP);

  lcd.begin(16, 2);

    Serial.begin (9600);
    // Reads the initial state of the outputA
      astate = digitalRead(inputA) << 3 + digitalRead(inputA) << 2 ;
  bstate = digitalRead(inputC) << 3 + digitalRead(inputC) << 2 ;
}
void loop() {
   
    astate +=  digitalRead(inputA) << 1;
    astate +=  digitalRead(inputB);

    if (astate == 1   || astate == 7 || astate == 14 || astate == 8)
        {
         counter1++;
         Serial.print(counter1);
         Serial.print(" \n \r");
       
  }
    if (astate == 2   || astate == 11 || astate == 13 || astate == 4)
        {
         counter1--;
         Serial.print(counter1);
         Serial.print(" \n \r");
       
  }
  {
    bstate +=  digitalRead(inputC) << 1;
      bstate +=  digitalRead(inputD);

      if (bstate == 1   || bstate == 7 || bstate == 14 || bstate == 8)
          {
           counter2++;
           Serial.print(counter2);
           Serial.print(" \n \r");
         
    }
      if (bstate == 2   || bstate == 11 || bstate == 13 || bstate == 4)
          {
           counter2--;
           Serial.print(counter2) ;
           Serial.print(" \n \r");
    }
   
       lcd.setCursor(0, 0);
       lcd.print("X Pos      Y Pos");
     
       lcd.setCursor(1, 1);
       lcd.print(counter1);
       lcd.print(" ");

       lcd.setCursor(12, 1);
       lcd.print(counter2);
       lcd.print(" ");
         
      astate = astate << 2 & 0xc;
      bstate = bstate << 2 & 0xc;
  }
 
//--------------------------------------
 /*
  digitalRead(inputE);
  if (inputE == LOW);
  {
      counter1 = 0;
      
      lcd.setCursor(1, 1);
      lcd.print(counter1);
      lcd.print("  ");
  }
  
  digitalRead(inputF);
  if (inputF == LOW)
  {
     counter2 = 0;

     lcd.setCursor(12, 1);
     lcd.print(counter2);
     lcd.print("  ");
  
  }
  */
}

The sketch down as far as the dotted line is my original script which reads the encoders and renders a value accordingly on the LCD.

The section below the dotted line, which is commented out at the moment IMO should allow a pushbutton on the RE to return the LCD value to zero, however, it actually does nothing … except …

It cause some kind of conflict with counter1. It is moving very quickly, so I can’t be sure, but it looks to me that the counter1 is read and displayed correctly and then immediately returned to zero ( as though the RE button was shorted - but I checked, it’s not )

I still can’t see what I’ve done wrong … … but then, I never have ! :slight_smile:

Thanks

S

Hi

As you were guys ... I've just found it !!!

Nothing more than a ; where there shouldn't be !!! Grrrr !

S

This is not correct:

  digitalRead(inputE);
  if (inputE == LOW);
  {
      counter1 = 0;
      
      lcd.setCursor(1, 1);
      lcd.print(counter1);
      lcd.print("  ");
  }

Try This:

  if (digitalRead(inputE) == LOW)
  {
      counter1 = 0;
      
      lcd.setCursor(1, 1);
      lcd.print(counter1);
      lcd.print("  ");
  }

Hi Jimmus

Yes, thanks for that ..

All is swell now, thanks

S