Help on Rotatry encoder to scroll pages and push button to restart arduino...

Hi, am having trouble setting up my rotatry encoder, am not sure am having the correct library, for now ive completed the project what i aimed for, but missing few extra fittings like displaying date and time using RTC module, scrolling/changing pages through encoder, and logging kwh used for the day in tf card slot, since am using 16x2 lcd i dnt have enough space to display all parameters in one page so am opting to use my rotatry encoder and its inbuilt push button but my main sketch is here

// Cost calculation for 2 Months

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C  lcd(0x3F,2,1,0,4,5,6,7); // 0x3F is my backpack Address

#define pulsein 7   //connect pulse pin in 7th pin.
float one_pulse=1,units=0,kwh=0,pulse;
int piezoPin = 8;


void showWelcome()
{
 lcd.clear();
 lcd.setCursor(0, 0);           
 lcd.print("Counter");
 lcd.setCursor(0, 1);          
 lcd.print("initialising...");      
}

void setup()
{
Serial.begin(9600);
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
lcd.begin(16, 2);
showWelcome();
delay(2000); 
pinMode(pulsein,INPUT);

 }

void loop()
{
 lcd.clear();
 tone( 8, 20000, 500);
 while(1)
 {
  if(digitalRead(pulsein))
  {
   pulse++;
  
   while(digitalRead(pulsein));
   Serial.println(pulsein);
   
  }
units=one_pulse*pulse*6/1000; //total units consumed multiplied by govt.cost
kwh=one_pulse*pulse/1000;    // Display kwh
lcd.setCursor(0,0);
lcd.print("Amount: ");  //display total Amount Till Reset
lcd.print(units); 
lcd.setCursor(0,1);
lcd.print("Kwh   : ");  //display pulse 
lcd.print(kwh);


 }
}

can someone help me in the sketch to scroll through pages using rotatry encoder and its wiring ? i have time and date sketch seperately but untill i know a way to use the encoder i cant use any of the sketch ty…

Please read this

When posting code , use the CODE TAGS toolbutton [</>] so the code will look like this:

  // Cost calculation for 2 Months

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C  lcd(0x3F,2,1,0,4,5,6,7); // 0x3F is my backpack Address

#define pulsein 7   //connect pulse pin in 7th pin.
float one_pulse=1,units=0,kwh=0,pulse;
int piezoPin = 8;


void showWelcome()
{
  lcd.clear();
  lcd.setCursor(0, 0);           
  lcd.print("Counter");
  lcd.setCursor(0, 1);          
  lcd.print("initialising...");      
}

void setup()
{
 Serial.begin(9600);
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
lcd.begin(16, 2);
showWelcome();
delay(2000); 
pinMode(pulsein,INPUT);

  }
 
 void loop()
{
  lcd.clear();
  tone( 8, 20000, 500);
  while(1)
  {
   if(digitalRead(pulsein))
   {
    pulse++;
   
    while(digitalRead(pulsein));
    Serial.println(pulsein);
    
   }
 units=one_pulse*pulse*6/1000; //total units consumed multiplied by govt.cost
 kwh=one_pulse*pulse/1000;    // Display kwh
 lcd.setCursor(0,0);
 lcd.print("Amount: ");  //display total Amount Till Reset
 lcd.print(units); 
 lcd.setCursor(0,1);
 lcd.print("Kwh   : ");  //display pulse 
 lcd.print(kwh);


  }
}

can someone help me in the sketch to scroll through pages using rotatry encoder and its wiring ? i have time and date sketch seperately but untill i know a way to use the encoder i cant use any of the sketch ty…

Maybe if you posted a link for the encoder so we can look at the datasheet we might be able to help.

or you could just Google “arduino rotary encoder” to find this

Maybe if you posted a link for the encoder so we can look at the datasheet we might be able to help.

or you could just Google "arduino rotary encoder" to find this
[/quote]

thank you updated my post,now my sketch looks neat and tidy and regarding encoder i googled it but the one i have is very different , still i managed to get one that looks similar like mine

http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/

before using encoder i wanna know how to change lcd page every 10 seconds, can you help me with the sketch?

Everything you need to know is on the page you linked.

I also found this example. which claims to have reliable code.

and this one

I did not find any clear statement regarding the number of encoder counts per revolution (the resolution) so I don’t know if it is 360 (1 count /per degree of revolution) or what.

Perhaps this is obvious to someone who has worked with rotary encoders but I have not personally used one. If you find that out it would be useful to know. I found a comment on the Backshed page that states:

because of Bourns encoder has 128pulses/revolution

and

yes, the encoder label says:

ENA1P-B28
LDO128
1050M MEX

but nothing such can be found in catalog. Looks like an obsolete part and that’s why the price was so low. The encoder has resolution 128 pulses/turn. Closest type in catalog is ENA1P-B50. Works perfectly.

The module is designed so that a low is output when the switches are closed and a high when the switches are open.

The low is generated by placing a ground at Pin C and passing it to the CLK and DT pins when switches are closed.

The high is generated with a 5V supply input and pullup resistors, such that CLK and DT are both high when switches are open.

Not previously mentioned is the existence of of push button switch that is integral to the encoder. If you push on the shaft, a normally open switch will close. The feature is useful if you want to change switch function. For example, you may wish to have the ability to between coarse and fine adjustments.

Does yours have the switch that closes when you push on the shaft ?

before using encoder i wanna know how to change lcd page every 10 seconds, can you help me with the sketch?

Use the millis() function.

Look at the Blinkwithoutdelay IDE example (File\Examples\Digital\BlinkWithoutDelay)

Look at the ENTIRE sketch, from start to finish.
Note value of constant/variable interval

const long interval = 1000;           // interval at which to blink (milliseconds)

In this sketch, interval is a constant because the purpose of the sketch is to blink the led every second. Obviously, if you wanted an interval that could be changed under program control you would make a variable instead of a constant, to allow changing the interval “on the fly” . If you are fine with a 10 second interval then just change it to 10000. That’s fairly straight forward.

All the code you need to use the encoder is on the page you linked.

As far as scrolling through LCD pages, I would advise rewriting ALL the LCD code into something more structured and organized. It should not take you very long to figure out how to write a function called
“page_1()” that sets up the LCD with some specific information. It should be just as easy to write nine more functions named page_2() , page_3(), etc . etc.
Each function displays the information reserved for that page
ie:

void page_1()
{
 lcd.setCursor(0,0);
 lcd.print("[something for page 1, line 1");  //display page 1, line 1
 lcd.print(units); // print units for page 1, line 1
 lcd.setCursor(0,1);
 lcd.print("something for page 1, line 2");  //display page 1, line 2
 lcd.print([units for page 1 , line 2]); //print units for page 1, line 2

}
void page_2()
{
 lcd.setCursor(0,0);
 lcd.print("[something for page 2, line 1");  //display page 1, line 1
 lcd.print(units); // print units for page 1, line 1
 lcd.setCursor(0,1);
 lcd.print("something for page 2, line 2");  //display page 1, line 2
 lcd.print([units for page 1 , line 2]); //print units for page 1, line 2

}
// etc. etc. etc.

if you use an IF statement for

 int encoderPosCount = 0;

128/10=12.8

such that IF encoderPosCount >= 0 && < 12
var = 1
such that IF encoderPosCount >= 13 && < 24
var = 2
such that IF encoderPosCount >= 24 && < 36
var = 3
etc , etc etc.

This divides the 128 steps of a revolution into 10 steps that can be used assign the value of “var”
for the CASE statement.

Having done that, you should be able to use the CASE() function where “var” = the encoder value such that the value returned by the encoder service routine is used to select the CASE
and each case corresponds to a different LCD page.
ue:
CASE 1 = PAGE 1
CASE 2 = PAGE 2
etc., etc. etc.

Software is really not my area of expertise but that’s what I would do.
I could probably write the code if I had to but I think that’s your job.

hi,am testing the rotary encoder and determining its no of turns, am using this code

 int pinA = 3;  // Connected to CLK on KY-040
 int pinB = 4;  // Connected to DT on KY-040
 int encoderPosCount = 0; 
 int pinALast;  
 int aVal;
 boolean bCW;

 void setup() { 
   pinMode (pinA,INPUT);
   pinMode (pinB,INPUT);
   /* Read Pin A
   Whatever state it's in will reflect the last position   
   */
   pinALast = digitalRead(pinA);   
   Serial.begin (9600);
 } 

 void loop() { 
   aVal = digitalRead(pinA);
   if (aVal != pinALast){ // Means the knob is rotating
     // if the knob is rotating, we need to determine direction
     // We do that by reading pin B.
     if (digitalRead(pinB) != aVal) {  // Means pin A Changed first - We're Rotating Clockwise
       encoderPosCount ++;
       bCW = true;
     } else {// Otherwise B changed first and we're moving CCW
       bCW = false;
       encoderPosCount--;
     }
     Serial.print ("Rotated: ");
     if (bCW){
       Serial.println ("clockwise");
     }else{
       Serial.println("counterclockwise");
     }
     Serial.print("Encoder Position: ");
     Serial.println(encoderPosCount);
     
   } 
   pinALast = aVal;
 }

but the issue is for every slight turn, two increment adds up instead of one on both CW and CCW, is it because of debounce? ive also tested using a 100nf caps in parallel to digital input where clk & dt is inserted but still same issue, the push button works fine which is "NO" on pressing it closes circuit and resets the arduino, now am testing blink without delay on lcd...

If you want to actually understand how a Rotary Encoder actually works (and how it knows which direction you are turning the knob) then watch my YouTube video #19 How to use a Rotary Encoder, once you have watched this you will be in no doubt how it all hangs together (and it is so simple too, as most great ideas are).

URL in the footer of this post, enjoy! :slight_smile:

Do you have decoupling caps on the data pins of the encoder ?
It was mentioned in several comments that this would happen without them.

The KY040 module contains a rotary encoder together with a push-switch on a small
' PCB with 5 Connections. The KY040 was developed for Arduino, but of course us uMite
' folk can use it as well, and the KY040 is incredibly cheap, US$2.0 inc P&P, just
' search eBay for KY040.
'
' Wiring it up
'
' KY040 Micromite
' ----- ---------
' CLK 2 ---> 0.1uF ---> Ov
' DT 3 ---> 0.1uF ---> Ov
' SW 4 ---> 0.1uF ---> Ov
' + 3V3
' Gnd 0V
'
' NB
' 1) It is VERY important to decouple the DT,CLK & SW pins to 0V
**' using 0.1uF at the uMite end of the link wire. **
' If you don't decouple these signals, severe contact bounce will be evident,
' eg one click will generate a dozen or more increment/decrements.
'
' 2) The KY040 module has on-board pullup resistors. You must supply 3V3 or less
' to the + pin of the KY040 module
'
' 3) This s/w works fine with just a standalone rotary encoder, but you will need
' to supply your own 10K pullups to 3V3. For a standalone encoder RA=CLK, RB=DT, & SW=SW
'
' When this software runs, each CLOCKwise step of the rotary encoder will result
' in an increase of the variable DisplayValue which will be printed to the Console.
' Each ANTI-clockwise step of the rotary encoder will result in a decrease of the
' variable DisplayValue which will be printed to the Console.
' Pushing the push-switch will clear the variable DisplayValue to 0.

john2016:
hi,am testing the rotary encoder and determining its no of turns, am using this code

 int pinA = 3;  // Connected to CLK on KY-040

int pinB = 4;  // Connected to DT on KY-040
int encoderPosCount = 0;
int pinALast;  
int aVal;
boolean bCW;

void setup() {
  pinMode (pinA,INPUT);
  pinMode (pinB,INPUT);
  /* Read Pin A
  Whatever state it's in will reflect the last position  
  */
  pinALast = digitalRead(pinA);  
  Serial.begin (9600);
}

void loop() {
  aVal = digitalRead(pinA);
  if (aVal != pinALast){ // Means the knob is rotating
    // if the knob is rotating, we need to determine direction
    // We do that by reading pin B.
    if (digitalRead(pinB) != aVal) {  // Means pin A Changed first - We're Rotating Clockwise
      encoderPosCount ++;
      bCW = true;
    } else {// Otherwise B changed first and we're moving CCW
      bCW = false;
      encoderPosCount--;
    }
    Serial.print ("Rotated: ");
    if (bCW){
      Serial.println ("clockwise");
    }else{
      Serial.println("counterclockwise");
    }
    Serial.print("Encoder Position: ");
    Serial.println(encoderPosCount);
   
  }
  pinALast = aVal;
}




but the issue is for every slight turn, two increment adds up instead of one on both CW and CCW, is it because of debounce? ive also tested using a 100nf caps in parallel to digital input where clk & dt is inserted but still same issue, the push button works fine which is "NO" on pressing it closes circuit and resets the arduino, now am testing blink without delay on lcd...

Your test code just simply won't work. Yayaya, this is also saying that the demo code in your link doesn't work in the first place.

The bugs is here...

...
     Serial.print ("Rotated: ");
     if (bCW){
       Serial.println ("clockwise");
     }else{
       Serial.println("counterclockwise");
     }
     Serial.print("Encoder Position: ");
     Serial.println(encoderPosCount);
...

For the encoder to work, you need to test the pin state at a rate way faster than that of the encoder pins turning on/off. Serial communication is a very slow operation. Having it in sync with the test code, you are missing a whole lot of the encoder state change information while busy doing serial communication.

Use the code Code Archives - Arduino Learning that Raschemmel suggested. It should work like a charm. Be reminded that there are just a handful of hardware interrupt pins on an Arduino boards, please make sure you are using the interrupt pins for the job. For details, see attachInterrupt() - Arduino Reference .

the push button works fine which is "NO" on pressing it closes circuit and resets the arduino

What are you talking about ? Who says it's suppose to reset the arduino ? How did you connect the switch ? Post a schematic or something explaining the switch connection. Show me in the code where it is supposed to reset the arduino when you press the switch. If the arduino is reseting you are probably shorting the 5V because you connected the switch wrong.

this is the only reference I can find about the switch and even it does not say anything about how to connect it.

  1. This s/w works fine with just a standalone rotary encoder, but you will need
    ' to supply your own 10K pullups to 3V3. For a standalone encoder RA=CLK, RB=DT, & SW=SW
    '

So did YOU connect it to your RESET pin ?

yeah i just connected directly to reset havent implemented any code for that, am not sure its short circuiting it function as if the reset button aboard the Uno is pressed, i haven't measured the voltage but tomorrow ill do it first... pls check my connection design for the denounce is it correctly placed?

Check it how ? Where is the schematic ?

i have linked it but its not showing, am attaching here pls have a look…
Fritzing design

The RESET pin should have a 1 uF cap form the pin to GND.

hi, i have added the 100nf cap to reset , and is the debounce connection is correct?
updated circuit

That Fritzing file is much too small to read. Post a 1 Mbyte resolution version of that.

here it show full screen from that site! :o

Looks fine. so what's the problem ?

raschemmel:
Looks fine. so what's the problem ?

hi, sorry for delayed reply,got stuck with other job, am using if statement to trigger the buzzer if kwh exceeds 1000 units but am unable to stop it after it triggers ive set delay but what happens is because i put the trigger under void loop() after the delay the buzzer short beeps for every increment it doesn't stops there , ill post the code tomorrow as idnt have ide in my home pc...

raschemmel:
Looks fine. so what’s the problem ?

hi, today i also found another problem after field testing, the problem is when there is a power cut the unit and kwh meter gets turned off and once the power comes the counted value gets reset… i cannot use a 12 battery to keep it awake always instead am using a 12v 5amps power supply for the arduino, is there a way to tackle this issue like using a inbuilt memory function ? so even if power cuts and come back the counter must start running from where it left ?

Sure, store your results in a FRAM chip. SRAM speed for Read/writes, EEPROM non-volatility.
http://www.digikey.com/product-detail/en/cypress-semiconductor-corp/FM25040B-G/428-3200-ND/3788662
Thru hole parts no longer available.