Hi
I am working a very simple home management system, that uses a 16x2 lcd display to show inside tempurate, outside tempurate, the current time and date, and some other static messages.
In order to do this I am try to use a rotary encoder to "toggle" through each of these separate tabs. the encoder I am using is the KY-040.
currently my code looks like this
#include <dht.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#include "RTClib.h"
dht DHT;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
RTC_DS1307 RTC;
int greenPin = 7;
int screenselect = 1;
int screenselectprev = 1;
int pinA = 10; // Connected to CLK on KY-040
int pinB = 6; // Connected to DT on KY-040
int encoderPosCount = 0;
int pinALast;
int aVal;
boolean bCW;
void setup() {
Serial.begin(9600);
Wire.begin();
RTC.begin();
lcd.begin(16, 2);
pinMode (pinA, INPUT);
pinMode (pinB, INPUT);
pinALast = digitalRead(pinA);
Serial.begin (9600);
}
void loop() {
Screen();
aVal = digitalRead(pinA);
if (aVal != pinALast) { // Means the knob is rotating
if (digitalRead(pinB) != aVal) { // Means pin A Changed first - Rotating Clockwise
encoderPosCount ++;
screenselect ++;
bCW = true;
} else {// Otherwise B changed first and we're moving CCW
bCW = false;
encoderPosCount--;
screenselect--;
}
serialcheck(); //serialoutput of rotary encoders position (to check that it's reading)
}
}
void Screen()
{
if (screenselect > 3)
{
screenselect = 0;
}
if (screenselect < 0)
{
screenselect = 0;
}
switch (screenselect)
{
case 1:
{
temphum(); //tempurature/humidity function
}
case 2:
{
staticmessage(); //static message function
}
case 3:
{
showTime(); //time function, using rtc
}
}
}
I have tested each of the functions individually, and they all work on the screen.
The way the code is supposed to run is; when you turn the encoder, the screenselect variable increases(or decreases) and then it is tested to ensure it is a number between 1 and 3, then the corresponding function is brought up against the number. However, when I run this code the staticmessage() function comes onto the screen, the serialcheck() function doesnt output anything and turning the encoder doesnt achieve anything. when i remove the first line in the loop() function (Screen() the serialcheck function works normally.
I'm fairly sure this code won't run the dynamic parts properly, however I am trying to get the basic part to work first.
I'm sure the problem is to do with my loop() function, however I have been trying for about a week now and cant get the code to work. can anybody see the fault in my code?
using an arduino uno my layout is like this:
RTC
DS-9
SCL-A5
SDA-A4
tempurature/humidity sensor
S-7
gnd-gnd
5V
encoder
clk-10
DT-6
5V
gnd-gnd
display from 1-16
gnd
5V
pot
12
gnd
11
5
4
3
2
gnd
my first forum post, apologies if i missed any info or gave too much.
thanks in advance for the help.
I've used the Screen() to make the code easier to follow, rather having it all within the loop() function
That's fine. The problem is this:
void loop()
{
// Display some data.
// Determine what to display.
}
Doing things in that order does not make sense.
encoderPosCount is to determine the position of the rotary encoder, for the serialcheck()
Why does the value in encoderPosCount matter? It is NOT what is used to determine what to display.
aVal becomes the value of pinAlast every loop, does this not count as a reset?
Yes. What I meant to ask was where do you reset the value in pinAlast? It makes no sense to call a variable pinAlast when it does not contain the last value of pinA.
Personally, I think your two variables should be called pinAcurr and pinAprev, so that it is obvious that they are related, and it is obvious that they contain the current state of pin A and the previous state of pin A. And, of course, at the end of loop(), you need to copy the current value of pin A to the previous value of pin A.
oh, right. I had it the other way around, I just tried it first before I posted this forum. but in saying that, screenselect is given an initial value of 1, so it shouldn't matter what order it is the body?
I understand that it makes far more sense to have it as
//determine what to display
//display some data
however the same problem arises whether it's that way around, or the other way.
Why does the value in encoderPosCount matter? It is NOT what is used to determine what to display.
encoderPosCount was used to determine that the encoder was being read, i suppose this can be done just as easily with screenselect.
Yes. What I meant to ask was where do you reset the value in pinAlast? It makes no sense to call a variable pinAlast when it does not contain the last value of pinA.
ah, right, I forgot to reassign the value of pinAlast. I changed this, however the same problem still arrises.
updated code (loop() and serialcheck())
#include <dht.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#include "RTClib.h"
dht DHT;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
RTC_DS1307 RTC;
int greenPin = 7;
int screenselect = 1;
int screenselectprev = 1;
int pinA = 10; // Connected to CLK on KY-040
int pinB = 6; // Connected to DT on KY-040
int encoderPosCount = 0;
int pinALast;
int pinAcurr;
boolean bCW;
void setup() {
Serial.begin(9600);
Wire.begin();
RTC.begin();
lcd.begin(16, 2);
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() {
pinAcurr = digitalRead(pinA);
if (pinAcurr != 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) != pinAcurr) { // Means pin A Changed first - We're Rotating Clockwise
screenselect ++;
bCW = true;
} else {// Otherwise B changed first and we're moving CCW
bCW = false;
screenselect--;
}
serialcheck();
}
pinALast = pinAcurr;
Screen();
}
void serialcheck() {
Serial.print ("Rotated: ");
if (bCW) {
Serial.println ("clockwise");
} else {
Serial.println("counterclockwise");
}
Serial.print("Encoder Position: ");
Serial.println(screenselect);
}
I've updated the variable aval to pinAcurr, swapped the order of Screen() and the digital read on the encoder. This has not changed the initial problem.