I am familiar with timing using millis() function, but it seems that I have run into a problem with a for loop.
The thing is, I am comparing encoder readings with a value entered via 4x4 keypad. Since I have to enter more than one value, i placed all values from the keypad into an array. Then I created a for loop that will cycle through that array and compare each value with encoder readings, when encoder reached the entered keypad value an LED should light up for 2 seconds. This is where the problem occurs. When it reaches the set value the LED seems to light up for like a fraction of a second. My guess is that the loop is creating some trouble here. Maybe because the loop cycles so fast the LED doesn't have enough time to stay lit. What do you think?
When I tried this program without a for loop (with only one value entered from a keypad), it works fine.
The code below has two arrays with values already entered, so no need or keypad. I used it just for testing. When I solve this problem I will add a keypad.
Please ask if you need any clarification of the code , and thank you in advance
#include <Encoder.h>
#include<Wire.h>
#include<LiquidCrystal_I2C.h>
int led1=14;
int led2=15;
unsigned long encoder;
unsigned long prev_value;
int array1[]={100, 200, 300, 400, 500, 600};
int array2[]={150, 250, 420};
int i,j,k,l;
int brV=6;
int brM=3;
int tolerance=10;
unsigned long oldTime=0.0;
unsigned long newTime;
int dt=2000;
bool testRange=true;
bool testRange2=true;
Encoder myEnc(2,3);
LiquidCrystal_I2C lcd1(0x27, 16, 2);
void setup() {
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
lcd1.init();
lcd1.backlight();
}
void loop() {
newTime=millis();
lcd1.setCursor(0,0);
encoder=myEnc.read()*446/400;
if(encoder!=prev_value){
lcd1.clear();
delay(10);
prev_value=encoder;
}
lcd1.print(encoder);
digitalWrite(led1,LOW);
digitalWrite(led2,LOW);
k=brV+brM;
for(l=0;l<k;l++){
for(i=0;i<brV;i++){
if(encoder>=array1[i] && encoder<=(array1[i]+tolerance) && testRange){
oldTime=newTime;
digitalWrite(led1,HIGH);
testRange=false;
}
else if(oldTime-newTime >= dt){
oldTime=newTime;
digitalWrite(led1,LOW);
}
if(encoder>(array1[i]+tolerance){
testRange=true;
}
}
for(j=0;j<brM;j++){
if(encoder>=array2[j] && encoder<=(array2[j]+tolerance) && testRange2){
oldTime=newTime;
digitalWrite(led2,HIGH);
testRange2=false;
}
else if(newTime-oldTime >= dt){
oldTime=newTime;
digitalWrite(led2,LOW);
}
if(encoder>array2[j]+tolerance){
testRange2=true;
}
}
}
}
i usually figure out how to do something and then expand it to do more. I don't see how you could have done this with the error i described - 1 LED, 1 condition to test and basic timing
I don't understand why you have nested for loops to control each LED. while there may be multiple conditions for setting or clearing an LED, I would evaluate all those conditions completely and then decide how to set the LED.
why do you set both LEDs LOW near the top of loop()?
This is just a prototyping program, the nested for loops are necessary, and LEDs are set to LOW in the beginning so that they don't remain HIGH the whole time, before I added those two lines they wouldn't turn off at all.
In trying to understand your code I decomposed it. By that point I had rewritten it. This compiles however I can't test it right now but it should work, or be close to it, because it is simple. The idea is that is every iteration of loop() tests the encoder to see if it is within range for each element of the two arrays you provided. If so it turns on the appropriate LED, sets the old time, and exits the for loop. The way this code is written the LED that is turned on will stay on until the encoder goes out of range + 2 seconds. However, it could easily be modified to control the LED to go off after 2 seconds and ignore the subsequent readings.