0
\$\begingroup\$

I'm using this encoder https://www.cuidevices.com/product/resource/acz09.pdf to scroll through a menu and I'm having an issue where when you turn it clockwise, it thinks the button was pressed (this does not happen when I turn it counter-clockwise). They're both on two different interrupt pins (2,3 on Arduino Pro Mini) and my code is included below as well as the schematic.

#include <SoftwareSerial.h>
#define Button1 2
#define pinA 3
#define pinB 4



//encoder setup
String bits[] = {"00","01","10","11"};
int bump[] = {0,0,-1,1};
byte state = 0; 
int Level = 1;
byte M_pressed = 0;
byte T_pressed = 0;
unsigned long lastButtonPress = 0;
int page = 0;
int setting = 0;
String Motor;
int MotorState = 0;
String Heat;
int HeatState = 1;
byte change = 1;
byte Tempchange = 1;
unsigned long windowStartTime = millis();
float SetTemp;
int TempState =1; 

double Setpoint, Input1, Output1, Input2, Output2;

SoftwareSerial OpenLCD(1,7); //RX,TX
byte contrast = 2; 

void setup() {
  
 Serial.begin(115200);

 //encoder
 pinMode(pinA,INPUT_PULLUP);
 pinMode(pinB,INPUT_PULLUP);
 digitalWrite(pinA,HIGH);
 digitalWrite(pinB,HIGH);
 pinMode(Button1,INPUT_PULLUP);

  //interrupts
 attachInterrupt(0,knobTurned,RISING);
 attachInterrupt(1,buttonpressed,LOW); 
  
  OpenLCD.begin(9600);
}

//////Interrupts/////////////////////////////////////////////////////
void knobTurned(){

 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();
 // If interrupts come faster than 200ms, assume it's a bounce and ignore
 if (interrupt_time - last_interrupt_time > 250) 
 {
   state = 0;
   state = state + digitalRead(pinA);
   state <<= 1;
   state = state + digitalRead(pinB);
  //Serial.println(state);
   if (setting == 0){                       //if you are in general menu, scroll through temp/motor
    Level = Level + bump[state];
    if (Level > 2) Level = 2;                //Level 2 is motor menu
    else if (Level < 1) Level = 1;           //Level 1 is temp menu
    Serial.println(Level);
   }
   
  else if (setting == 2){                       // if you are in motor menu, scroll through motor settings
    MotorState = MotorState + bump[state];
    if(MotorState > 4) MotorState=4;
    else if (MotorState <0) MotorState=0;
    Serial.println(MotorState);
  }
   else if (setting == 1){                    // if you are in temp menu, scroll through temp (res 0.5)
      SetTemp = SetTemp + bump[state]*.5;
       if (SetTemp > 75) SetTemp = 75;
       else if (SetTemp < 25) SetTemp = 25;
       Setpoint = SetTemp;
       Serial.println(SetTemp);
    }
    change = 1;
    
   }
}

void buttonpressed(){

 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();
 // If interrupts come faster than 200ms, assume it's a bounce and ignore
 if (interrupt_time - last_interrupt_time > 250) 
 {
  
  //Serial.println("pressed");
  if (Level ==1){                       //if button is pressed at temperature setting 
   if (setting == 0){                   // enter into temperature menu if in general menu
      setting =1;                       //Allow to scroll through temperature
      Serial.println("enter Temp");
   }
   else if (setting ==1){               //if in temperature menu
    Setpoint = SetTemp;
    setting =0;                         //returns to main menu
    Serial.println("Back T");
    
   }
  }
  else if (Level ==2){                  //if button is pressed at motor setting
    if(setting ==2)  {                 //if in motor menu
      setting =0;                       //return to main menu
      Serial.println("Back M");
    }
    else if(setting ==0){                   //if in general menu enter into motor menu
      setting =2;                       //Allow to scroll through motors
      Serial.println("enter Motor");
    }
  }
  delay(50);
 }
    last_interrupt_time = millis();
      change = 1;  
      
}

 ////////////////////////////////////////////////////////////////////

void loop() {
  // put your main code here, to run repeatedly:
  Menu();
}

 void Menu(){
  if (change == 1){
    if (setting == 0){                // if in the general menu
      if (Level == 1){                // if on temp arrow
        OpenLCD.write('|'); 
        OpenLCD.write('-');
        OpenLCD.write(254); //Send command character
        OpenLCD.write(128 + 20 + 0); //Change the position (128) of the cursor to 2nd row (64), position 0 (0)
        OpenLCD.print("-> Set Temp: "); //For 16x2 LCD;
        OpenLCD.print(SetTemp); //For 16x2 LCD
        OpenLCD.print(" C");

        OpenLCD.write(254);
        OpenLCD.write(128 + 84 + 3);
        OpenLCD.print("Set Motor");
      }
      else if (Level == 2){         //if on the motor arrow
        OpenLCD.write('|'); 
        OpenLCD.write('-');
        OpenLCD.write(254);
        OpenLCD.write(128 + 20 + 3);
        OpenLCD.print("Set Temperature");
        OpenLCD.write(254); 
        OpenLCD.write(128 + 84 + 0); 
        OpenLCD.print("-> Set Motor: "); 
        if (MotorState <= 0) Motor = "off";
        else Motor = String(MotorState);
        OpenLCD.print(Motor); //For 16x2 LCD
      }
    }
    else if (setting == 1){        //Temperature menu
      OpenLCD.write('|');
      OpenLCD.write('-');
      OpenLCD.write(254);
      OpenLCD.write(128 + 20 + 6); 
      OpenLCD.print(SetTemp); 
      OpenLCD.print(" C");
      OpenLCD.write(254); 
      OpenLCD.write(128 + 84 + 0); 
      OpenLCD.print("<- Click to Return");
    }
   else if (setting == 2){
      OpenLCD.write('|');
      OpenLCD.write('-');
      OpenLCD.write(254);
      OpenLCD.write(128 + 20 + 9); 
      if (MotorState <= 0) Motor = "off";
      else Motor = String(MotorState);
      OpenLCD.print(Motor); 
      OpenLCD.write(254); 
      OpenLCD.write(128 + 84 + 0); 
      OpenLCD.print("<- Click to Return");
   }
   change = 0;
  }

  if(setting ==0){
    windowStartTime = millis();
    OpenLCD.write(254); //Send command character
    OpenLCD.write(128 + 0 + 3); //Change the position (128) of the cursor to 2nd row (64), position 0 (0)
    OpenLCD.print("Temp = "); //For 16x2 LCD
    OpenLCD.print(SetTemp);//12x
    OpenLCD.print(" C"); //For 16x2 LCD
  }
 }

Schematic

\$\endgroup\$
4
  • 1
    \$\begingroup\$ I don't have an answer but a few things to check. I see you pull up the inputs and your knobTurned interrupt is on RISING. I am not sure if this is correct. Maybe change it to FALLING edge. I don't understand this row "state <<= 1;" What is this line of code supposed to do? You don't have an if statement there. \$\endgroup\$
    – Komental
    Jul 16, 2021 at 18:48
  • \$\begingroup\$ Spend some time making your schematic readable. At the moment it is pretty random. Have gnd pointing downwards. The r and c are reversed on the encoder. You want the encoder signal togo through the r then to the c and the port pin. Using interrupts for an encoder is not the most robust method - using a timer tick to sample and filter the inputs is a better solution. \$\endgroup\$
    – Kartman
    Jul 16, 2021 at 22:03
  • 1
    \$\begingroup\$ Does this happen 100% of the time for every encoder tick or specific pattern of encoder ticks when turning left? If not then it is noise and you need to program filtering in for both button press and encoder. You just won't see a button press fake an encoder tick as often since there are much fewer of them. This happened to me once. \$\endgroup\$
    – DKNguyen
    Jul 17, 2021 at 1:48
  • \$\begingroup\$ It is not every tick, just some of them usually when you turn the wheel very quickly. Changing the interrupt to FALLING fixed it for the most part; I've only had it happen twice since then. I don't quite understand why you mean by "program filtering in". How would that work? \$\endgroup\$ Jul 20, 2021 at 14:22

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.