Go Down

Topic: Help on Rotatry encoder to scroll pages and push button to restart arduino... (Read 12837 times) previous topic - next topic

john2016

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
Code: [Select]
// 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...  

raschemmel

Please read this

When posting code , use the CODE TAGS toolbutton [</>] so the code will look like this:
Code: [Select]
 // 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);


  }
}
  



Quote
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

john2016

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?

raschemmel

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:
Quote
because of Bourns encoder has 128pulses/revolution
and

Quote
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.
  
Quote
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 ?

Quote
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

Code: [Select]
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:
Code: [Select]

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
Code: [Select]
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.

john2016

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

Code: [Select]
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...

Ralph_S_Bacon

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!  :)
My YouTube Arduino Videos: https://www.youtube.com/RalphBacon
Arduino and electronics videos designed to get your project off the ground.

raschemmel

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


Quote
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.
 

ma_hty

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

Code: [Select]
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...
Code: [Select]
...
     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 http://arduinolearning.com/category/code 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 https://www.arduino.cc/en/Reference/AttachInterrupt .

raschemmel

Quote
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.
Quote
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
'   
So did YOU connect it to your RESET pin ?

john2016

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?


john2016

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

raschemmel


john2016

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

raschemmel

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

Go Up