Rotary encoder values combined instead of separated

I'm making a custom timer project, and I have been having this issue with using two encoders where they both have the same value when they should be separated, I'll paste the code here. Hope anyone can help!

#include <Bounce2.h> //add all mandatory librarys
#include "SevSeg.h"

const byte ENCODER_PINA= A5; //set all encoder pins
const byte ENCODER_PINB= A4;
const byte ENCODER2_PINA= A1;
const byte ENCODER2_PINB= A0;

int valueA; //debounced encoder switch reads
int valueB;
int valueA2; //debounced encoder switch reads for second encoder
int valueB2;

bool motionDetected = false;
bool motionDetected2 = false;
int grossCounter = 0; // total steps
int grossCounter2 = 0; // total steps for second encoder
int nettCounter = 0;  // cw-ccw
int nettCounter2 = 0;  // cw-ccw for second encoder
int fullRevolutions = 0;   // full revolution counting for first encoder
int fullRevolutions2 = 0;   // full revolution counting for second encoder
int surplusSteps = 0; //part revs
int surplusSteps2 = 0; //part revs for second encoder
bool CW;
bool CW2;

byte cyclesPerRev =20;  //check encoder datasheet

// Instantiate 4 Bounce object for all encoders and directions
Bounce debouncerA = Bounce(); 
Bounce debouncerB = Bounce();
Bounce debouncerA2 = Bounce(); 
Bounce debouncerB2 = Bounce();

SevSeg Display; // Set up display 1 (Minutes)
SevSeg Display2; // Set up display 2 (Hours)
long buzzerFrequency = 10;
const unsigned long period = 1000; //one second
const unsigned long led_period = 500; //LED blink millisecond
unsigned long startMillis;
unsigned long led_startMillis;
unsigned long currentMillis;
unsigned long led_currentMillis;
const int go_btn = A3;
const int ledPin = A2;
int Hrs = 0;
int Min = 0;
int Sec = 0;
int Time;
int ledState = LOW;
int go = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(go_btn, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  byte numDigits = 2; // Identifys the amount of digits on the two separated displays (DO NOT TOUCH)
  byte digitPins[] = {11, 10}; // Identifys the digit pins of the specific displays (NO TOUCHIE)
  byte digitPins1[] = {13, 12};
  byte segmentPins[] = {6, 5, 2, 3, 4, 7, 8, 9}; // Identifys the Pins for the segments of the MegaPlexed Displays (FINGERS AWAYUS)
  bool resistorsOnSegments = false;

  byte hardwareConfig = COMMON_CATHODE; // Sets the display as Common Cathode (YOU GET THE DRILL DON'T TOUCH)
  Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments); // Sets the Displays up (DNT)
  Display2.begin(hardwareConfig, numDigits, digitPins1, segmentPins, resistorsOnSegments);
  Display.setBrightness(100); // Sets Brightness of the Displays (DNT)

  // Setup the buttons
  Serial.println("Setup");
  pinMode(ENCODER_PINA,INPUT_PULLUP);
  pinMode(ENCODER_PINB,INPUT_PULLUP);
  pinMode(ENCODER2_PINA,INPUT_PULLUP);
  pinMode(ENCODER2_PINB,INPUT_PULLUP);


  // After setting up the button, setup debouncer
  debouncerA.attach(ENCODER_PINA);
  debouncerA.interval(5);
  debouncerB.attach(ENCODER_PINB);
  debouncerB.interval(5);
  
  debouncerA2.attach(ENCODER2_PINA);
  debouncerA2.interval(5);
  debouncerB2.attach(ENCODER2_PINB);
  debouncerB2.interval(5);

  Serial.println("Setup done");
  
}
void loop()
{
   
   // Update the debouncers
   doDebounce();

   // Read the encoder switches
   doEncoderRead();

   //determine direction and update counter

   updateCounter();

   updateCounter2();
   
 if (go != 1) 
 {  
   Hrs = nettCounter2;
   Min = nettCounter;

   if (Hrs < 0) 
   {
    Hrs = 0;
    if (nettCounter < 0)
    {
      nettCounter = 0;
    }
   }
   if (Min < 0) 
   {
    Min = 0;
    if (nettCounter2 < 0)
    {
      nettCounter2 = 0;
    }
   }
   if (digitalRead(go_btn) == LOW)
   {
    if (Hrs >= 0)
    {
      if (Min > 0)
      {
       go = 1;
       Min = Min - 1;
       Sec = 60;
      }
    } 
   }
 }
  if (go == 1)  {
   currentMillis = millis();
   if (currentMillis - startMillis >= period)
   {
     Sec = Sec - 1;
     startMillis = currentMillis;
   }
   led_currentMillis = millis();
   if (led_currentMillis - led_startMillis >= led_period)
   {
     led_startMillis = led_currentMillis;
     if (ledState == LOW)
     {
       ledState = HIGH;
     }
     else
     {
       ledState = LOW;
     }
     digitalWrite(ledPin, ledState);
   }
   if (Sec == 0)  {
     Sec = 60;
     Min = Min - 1;
   }
   if (Min == 0)  {
     if (Hrs > 0)  { 
     Min = (59);
     Hrs = Hrs - 1;
     }
   
   }
   //Time = Hrs * 100 + Min;
   //Display.setNumber(Min);
   //Display2.setNumber(Hrs);
   //Display.refreshDisplay();
   //Display2.refreshDisplay();
   //Serial.println(Sec);
   //Serial.println(nettCounter2);
 }
 Display.setNumber(Min);
 Display2.setNumber(Hrs);
 Display.refreshDisplay();
 Display2.refreshDisplay();
}

void doDebounce()
{
  debouncerA.update();
  debouncerB.update();
  debouncerA2.update();
  debouncerB2.update();
} //doDebounce

void doEncoderRead()
{
  valueA = debouncerA.read();
  valueB = debouncerB.read();
  valueA2 = debouncerA.read();
  valueB2 = debouncerB.read();
} //doEncoderRead

void updateCounter()
{

  /*
  the possibilites are:
   
   AB: in a detent
   if just arrived, update counter, clear motiondetected
   otherwise do nothing
   Ab: start of CW or end of CCW
   if start, set CW bool and set motionDetected
   if at end (know becasue motionDetected already set), do nothing
   aB: start of CCW or end of CW
   if start, clear CW bool and set motionDetected
   if at end (know becasue motionDetected already set), do nothing
   ab: in middle of either CW or CCW, do nothing
   */

  if (valueA && valueB && motionDetected ) //in a detent and just arrived
  {
    if (CW)
    {
      grossCounter= grossCounter + 1;
      nettCounter= nettCounter + 1;
    }
    else //CCW
    {
      grossCounter= grossCounter + 1;
      nettCounter= nettCounter - 1;
    }
    motionDetected = false;
    //Serial.print("grossCounter: ");
    //Serial.println(grossCounter);
    //Serial.print("nettCounter: ");
    //Serial.println(nettCounter);
    
    fullRevolutions = nettCounter / cyclesPerRev; 
    surplusSteps = nettCounter % cyclesPerRev;
    
    //Serial.print("Nett position: ");
    //Serial.print(fullRevolutions);
    //Serial.print(" + ");
    //Serial.println(surplusSteps);
    //Serial.println(" ");
    
    


  }

  if (valueA && !valueB && !motionDetected ) // just started CW
  {
    CW= true;
    motionDetected=true;
    //Serial.println("CW");

  }

  if (!valueA && valueB && !motionDetected )  //just started CCW
  {
    CW= false;
    motionDetected=true;
    //Serial.println("CCW");

  }

}
void updateCounter2()
{

  /*
  the possibilites are:
   
   AB: in a detent
   if just arrived, update counter, clear motiondetected
   otherwise do nothing
   Ab: start of CW or end of CCW
   if start, set CW bool and set motionDetected
   if at end (know becasue motionDetected already set), do nothing
   aB: start of CCW or end of CW
   if start, clear CW bool and set motionDetected
   if at end (know becasue motionDetected already set), do nothing
   ab: in middle of either CW or CCW, do nothing
   */

  if (valueA2 && valueB2 && motionDetected2 ) //in a detent and just arrived
  {
    if (CW2)
    {
      grossCounter2= grossCounter2 + 1;
      nettCounter2= nettCounter2 + 1;
    }
    else //CCW
    {
      grossCounter2= grossCounter2 + 1;
      nettCounter2= nettCounter2 - 1;
    }
    motionDetected2 = false;
    //Serial.print("grossCounter2: ");
    //Serial.println(grossCounter2);
    //Serial.print("nettCounter2: ");
    //Serial.println(nettCounter2);
    
    fullRevolutions2 = nettCounter2 / cyclesPerRev; 
    surplusSteps2 = nettCounter2 % cyclesPerRev;
    
    //Serial.print("Nett position2: ");
    //Serial.print(fullRevolutions2);
    //Serial.print(" + ");
    //Serial.println(surplusSteps2);
    //Serial.println(" ");
    
    


  }

  if (valueA2 && !valueB2 && !motionDetected2 ) // just started CW
  {
    CW2= true;
    motionDetected2=true;
    //Serial.println("CW2");

  }

  if (!valueA2 && valueB2 && !motionDetected2 )  //just started CCW
  {
    CW2= false;
    motionDetected2=true;
    //Serial.println("CCW2");

  }

}

Please explain that you mean by this, describe the conditions under which the problem appears, and give some examples.

Should cyclesPerRev have a cyclesPerRev2 (because it doesn't) , or is cyclesPerRev used for both?

The cyclesPerRev is the variable for how many detents are in a revolution on the rotary encoder from what I gather. the thing is that the encoder code I'm using is from this link which is only for 1. I tried to alter the code so I could have two by just simply just duplicating the code where necessary and adding a duplicate separated variable for the second one. and that brings me to where I am now. a point there the nettCounter and nettCounter2 variables are the same value. but I can't seem to figure out why. The rest of the code is just the timer.

Can you force an error that will show if all the output is coming from only one encoder?

I'm not really too experienced with Arduino coding, so I have no idea how I would do such a thing. Hence the copy-pasted code.

I FOUND THE ISSUE. The thing I learnt... I'm blind
Figure A

void doEncoderRead()
{
  valueA = debouncerA.read();
  valueB = debouncerB.read();
  valueA2 = debouncerA.read();
  valueB2 = debouncerB.read();
} //doEncoderRead

Figure B (What it's supposed to be)

void doEncoderRead()
{
  valueA = debouncerA.read();
  valueB = debouncerB.read();
  valueA2 = debouncerA2.read();
  valueB2 = debouncerB2.read();
} //doEncoderRead

God I'm stupid...

It's not an error if you fixed it. You recognized "xxx" vs. "xxx2" and followed it. On with the show!

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.