Arrays, Variables or something else?

Good afternoon everyone.

I have a Temperature and Humidity temperature sensor project that I have developed, and wanted to include user defined parameters into the project. The project currently:
-Monitors Ambient temperature
-Displays it via a 16x2 LCD Display
-RGB LED ‘pre-set’ to set temperature thresholds

I have a 4x4 Matrix keypad attached that allows the user to differentiate between whether the display outputs “Celsius”, “Fahrenheit” or both. But I want to take that to the next level…

Problem

The RGB LED outputs a colour dependent on pre-set thresholds in the ambient temperature.

int COOL=liveTemp <= 16;
int NORMAL=liveTemp >= 17.0 && liveTemp<=23.99;
int HOT=liveTemp >= 24 && liveTemp<= 26.99;
int DANGER=liveTemp >=27;

The int’s are then called further down by an if loop where the RGB output is determined.

What I would like to do is allow the user to choose whether they use the pre-determined parameters, or choose there own. And this is where I am lost. I figure this step might be best facilitated in the void setup loop. I am presuming I need to make a “custom” variable for each of the “Cool”, “Normal”, “Hot” and “Danger” parameters, such as:

int coolMINcustom;
int coolMAXcustom;
int normalMINcustom;
int normalMAXcustom;
int hotMINcustom;
int hotMAXcustom;
int dangerMINcustom;
int dangerMAXcustom;

My idea would be to allow the user to use the keypad to navigate there way to each of these variables and enter using the keypad a value between 0-99. This value would then store for that variable.

Firstly - am I on the right path here? Or do I need to be using arrays? This is my first ever experience with Arduino and coding and its been a fun but steep learning curve :slight_smile:

Thankyou.

Welcome to the Forum.

The int's are then called further down by an if loop

means nothing to a programmer

Please post your entire sketch as explained here:


How to use this forum (short version)

What happens if temperature is 16.5 or 23.999? You only need to know 3 thresholds:

float thresholds[3] = {16.0, 24.0, 27.0};

if (t < thresholds[0]) cold();
else if (t < thresholds[1]) normal();
else if (t < thresholds[2]) hot();
else danger();

The int's are then called further down by an if loop

You cannot call in int and if commands don't loop so I have no idea what you mean

My apologies for not posting my programme. I have stripped out the rest of the programme that functions regardless of this section of code just to concentrate on what I need to happen. @UkHeliBob - my apologies - this syntax and programming in general is all a brand new adventure for me, so will try and put it in simple english!

#include <Keypad.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(22, 24, 38, 40, 42, 44);  

const byte ROWS = 4;                                                                      
const byte COLS = 4;                                                                      
char hexaKeys[ROWS][COLS]={                                                               
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'},
};
byte rowPins[ROWS] = {53, 51, 49, 47};                                                   
byte colPins[COLS] = {45, 43, 41, 39};                                                   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

int COOL;
int NORMAL;
int HOT;
int DANGER;
int customCOOL = 0; 
int customNORM = 0;
int customHOT = 0;
int customDANG = 0; 

char UserKey = customKeypad.getKey();
char WAIT = customKeypad.waitForKey();
char key = customKeypad.getKey();


void setup() {
  // put your setup code here, to run once:

lcd.begin(16, 2);                                                                       
lcd.setCursor(0,0);                                                                      
lcd.print("Initialising..");                                                          
delay(2500);

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Select Output");
lcd.setCursor(0,1);
lcd.print("A:C, B:F, C:C&F");
lcd.clear();
lcd.setCursor(0,0);
lcd.print("A:C, B:F, C:C&F");
lcd.setCursor(0,1);
lcd.print("* for Setup");
delay(2500);


if (key == 'A' || key == 'B' || key == 'C')
{
  }else{
  if (key == '*')
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("1: Threshold Adjustment");
  lcd.setCursor(0,1);
  lcd.print("2: ___________________ ");
  delay(1000);
   for (int positionCounter = 2; positionCounter < 11; positionCounter++) {
    lcd.scrollDisplayLeft();
    delay(250);
  }
  delay(2500);
   for (int positionCounter = 2; positionCounter < 11; positionCounter++) {
    lcd.scrollDisplayRight();
   delay(250);
  }
  delay(150);


if (key == '1')
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("1:COOL/2:NORM");
  lcd.setCursor(0,1);
  lcd.print("3:HOT/4:DANGER!");

customKeypad.waitForKey();
char swDisp;

if (key == '1' || key == '2' || key == '3' || key == '4')
{
  swDisp = key;
}
 switch (swDisp)
 {
  case '1':
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Enter Cool limit");
  lcd.setCursor(0,1);
  customKeypad.waitForKey();
  customCOOL=UserKey;
  lcd.print(UserKey);
  break;
  case '2':
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Enter Norm limit");
    lcd.setCursor(0,1);
    customKeypad.waitForKey();
    customNORM=UserKey;
    lcd.print(UserKey);
    break;
    case'3':
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Enter HOT limit");
    lcd.setCursor(0,1);
    customKeypad.waitForKey();
    customHOT=UserKey;
    lcd.print(UserKey);
    case '4':
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Enter DANG limit");
    lcd.setCursor(0,1);
    customKeypad.waitForKey();
    customDANG=UserKey;
    lcd.print(UserKey);
    break;
    }
  }
}
 
void loop() {
  // put your main code here, to run repeatedly:

int COOL=liveTemp <= 16;
int NORMAL=liveTemp >= 17.0 && liveTemp<=23.99;
int HOT=liveTemp >= 24 && liveTemp<= 26.99;
int DANGER=liveTemp >=27; 

         if(COOL){
         strip.setPixelColor(0,0,0,255);       
         strip.show();  
         }else{
         strip.setPixelColor(0,0,0,0); 
         }
         if(NORMAL){
         strip.setPixelColor(0,0,255,0);       
         strip.show(); 
         }else{
         strip.setPixelColor(0,0,0,0);
         }
         if(HOT){
         strip.setPixelColor(0,255,0,0);
         strip.show();  
         }else{
         strip.setPixelColor(0,0,0,0);
         }
         if(DANGER){ 
         strip.setPixelColor(0,255,0,0);       
         strip.show(); 
         tone(ALARM, 100);
         delay(500); 
         strip.setPixelColor(0,0,0,0);       
         strip.show(); 
         noTone(ALARM);
         delay(500); }
}

So you will probably spot a thousand mistakes - but I am here to learn!

The menu in the Void Setup works up until the selection between ‘1’, ‘2’, ‘3’ and ‘4’ - where regardless of keypad input it just defaults to "Case ‘1’ ". The user input is displayed on the LCD as a weird looking character as well.

Thankyou for your help.

railedbee:
I have stripped out the rest of the programme that functions regardless of this section of code just to concentrate on what I need to happen.

Yeah, and by doing that you provide a defunct piece of code. Many ppl in here are actually testing posted code in order to debug it, but that's not possible with snippets.

In order to test for a user defined temperature range, you must test for that specific range before testing all other ranges. Some temperatures will not be in any of your own "baked in" ranges and your range testing is unnescessarily complex, as per post #2. You are using "int" data type as bool which is not a good idea.

#include <Keypad.h>
#include <Adafruit_NeoPixel.h>
#include <Servo.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(22, 24, 38, 40, 42, 44);  

const byte ROWS = 4;                                                                      
const byte COLS = 4;                                                                      
char hexaKeys[ROWS][COLS]={                                                               
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'},
};
byte rowPins[ROWS] = {53, 51, 49, 47};                                                   
byte colPins[COLS] = {45, 43, 41, 39};                                                   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

float DegDiv=0.009697;                                                                   
float BitDiv=0.001564;                                                                                                                                        
float ServoInput;


int COOL;
int NORMAL;
int HOT;
int DANGER;
int customCOOL = 0; 
int customNORM = 0;
int customHOT = 0;
int customDANG = 0; 

char UserKey = customKeypad.getKey();
char WAIT = customKeypad.waitForKey();
char key = customKeypad.getKey();

int ALARM=9;                                                                       
int TempSens=A0;                                                                   
int servoPin=8;

Servo TempServo;

#define NeoPixel 32
#define NUM_LEDS 1
Adafruit_NeoPixel strip = Adafruit_NeoPixel (NUM_LEDS, NeoPixel, NEO_GRBW + NEO_KHZ800);






void setup() {
  // put your setup code here, to run once:

pinMode (TempSens, INPUT);                                                                 
pinMode (ALARM, OUTPUT);    

strip.begin();                                                                           
strip.show(); 

TempServo.attach(servoPin);

lcd.begin(16, 2);                                                                       
lcd.setCursor(0,0);                                                                      
lcd.print("Initialising..");                                                          
delay(2500);

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Select Output");
lcd.setCursor(0,1);
lcd.print("A:C, B:F, C:C&F");
lcd.clear();
lcd.setCursor(0,0);
lcd.print("A:C, B:F, C:C&F");
lcd.setCursor(0,1);
lcd.print("* for Setup");
delay(2500);


if (key == 'A' || key == 'B' || key == 'C')
{
  }else{
  if (key == '*')
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("1: Threshold Adjustment");
  lcd.setCursor(0,1);
  lcd.print("2: ___________________ ");
  delay(1000);
   for (int positionCounter = 2; positionCounter < 11; positionCounter++) {
    lcd.scrollDisplayLeft();
    delay(250);
  }
  delay(2500);
   for (int positionCounter = 2; positionCounter < 11; positionCounter++) {
    lcd.scrollDisplayRight();
   delay(250);
  }
  delay(150);


if (key == '1')
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("1:COOL/2:NORM");
  lcd.setCursor(0,1);
  lcd.print("3:HOT/4:DANGER!");

customKeypad.waitForKey();
char swDisp;

if (key == '1' || key == '2' || key == '3' || key == '4')
{
  swDisp = key;
}
 switch (swDisp)
 {
  case '1':
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Enter Cool limit");
  lcd.setCursor(0,1);
  customKeypad.waitForKey();
  customCOOL=UserKey;
  lcd.print(UserKey);
  break;
  case '2':
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Enter Norm limit");
    lcd.setCursor(0,1);
    customKeypad.waitForKey();
    customNORM=UserKey;
    lcd.print(UserKey);
    break;
    case'3':
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Enter HOT limit");
    lcd.setCursor(0,1);
    customKeypad.waitForKey();
    customHOT=UserKey;
    lcd.print(UserKey);
    case '4':
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Enter DANG limit");
    lcd.setCursor(0,1);
    customKeypad.waitForKey();
    customDANG=UserKey;
    lcd.print(UserKey);
    break;
    }
  }
}
 
void loop() {
  // put your main code here, to run repeatedly:

int Temperature=analogRead(TempSens);                                                   
float liveTemp=(Temperature*BitDiv/DegDiv);                                             
float Fahrenheit=(liveTemp*1.8+32);  
int COOL=liveTemp <= 16;
int NORMAL=liveTemp >= 17.0 && liveTemp<=23.99;
int HOT=liveTemp >= 24 && liveTemp<= 26.99;
int DANGER=liveTemp >=27;                                                            
analogRead(TempSens);                                                                  
        
         
         if(COOL){
         strip.setPixelColor(0,0,0,255);       
         strip.show();  
         }else{
         strip.setPixelColor(0,0,0,0); 
         }
         if(NORMAL){
         strip.setPixelColor(0,0,255,0);       
         strip.show(); 
         }else{
         strip.setPixelColor(0,0,0,0);
         }
         if(HOT){
         strip.setPixelColor(0,255,0,0);
         strip.show();  
         }else{
         strip.setPixelColor(0,0,0,0);
         }
         if(DANGER){ 
         strip.setPixelColor(0,255,0,0);       
         strip.show(); 
         tone(ALARM, 100);
         delay(500); 
         strip.setPixelColor(0,0,0,0);       
         strip.show(); 
         noTone(ALARM);
         delay(500); }
           
ServoInput=map(liveTemp, -40, 125, 160, 0);
TempServo.write(ServoInput*0.969697/0.888+5);

lcd.clear();
lcd.setCursor(0,0);
lcd.print(liveTemp);
lcd.setCursor(0,1);
lcd.print(Fahrenheit);
}

Okay - there is my full code.

I read an AnalogIn pin which is connected to a temperature sensor and then determine the ambient temperature via a calculation. That temperature is the float “liveTemp”. That liveTemp is what is then used to determine whether it falls within the Cool, Normal, Hot and Danger ranges.

;
char WAIT = customKeypad.waitForKey();
char key = customKeypad.getKey();

What do you expect this to do?

TheMemberFormerlyKnownAsAWOL:

;

char WAIT = customKeypad.waitForKey();
char key = customKeypad.getKey();



What do you expect this to do?

Its unremoved/uncommented from my experimentation with trying to get the user defined custom parameters in the Void Setup. I was trying to use 'WAIT' instead of typing out customKeypad.waitForKey().
My apologies for keeping that in there and misleading.

There are multiple problems with the code. As AWOL already pointed out, you are only reading the keypad once and that is done before the hardware has been initialized, so that's no good. Then you process the faulty key-reading in setup() which is probably not what you want either. You should read the keypad in loop(), something like this could work:

void loop()
{
  if (keypad.waitForKey())
  {
    char key = keypad.getKey();
    //Process the key
  }
  //Do other loopings here
}

When you have retreived a successful custom user range from the keypad, then I would suggest you to store that range to EEPROM. When the device is reset, you can recover the user range from EEPROM and thereby ensuring that the user range will survive resets.

Btw., you have a stray "analogRead(TempSens);" below the temperature range testing, that's doing nothing.

Danois90:
There are multiple problems with the code. As AWOL already pointed out, you are only reading the keypad once and that is done before the hardware has been initialized, so that’s no good. Then you process the faulty key-reading in setup() which is probably not what you want either. You should read the keypad in loop(), something like this could work:

void loop()

{
 if (keypad.waitForKey())
 {
   char key = keypad.getKey();
   //Process the key
 }
 //Do other loopings here
}




When you have retreived a successful custom user range from the keypad, then I would suggest you to store that range to EEPROM. When the device is reset, you can recover the user range from EEPROM and thereby ensuring that the user range will survive resets.

Btw., you have a stray "analogRead(TempSens);" below the temperature range testing, that's doing nothing.

Okay - I will have another crack at it!
Between - when you mention that I only read the keypad once - correct me if my understand is wrong, but when I use “key”, as I have set “key” as “char key = customKeypad.getKey()” - does it not read the keypad at each if loop? The code will allow me to choose ‘*’ and then ‘1’ to navigate a couple of menus?

railedbee:
when I use "key", as I have set "key" as "char key = customKeypad.getKey()" - does it not read the keypad at each if loop?

No, the value of "key" will be assigned once.

And there is no such thing as an "if loop"

Okay. So I have finally managed to form a section of code that allows the user to use the keypad to enter a value. I have done this by use of Arrays, it seems the most logical way of doing this (too a beginner like myself anyway?)

So for example, I have:

int customCOOL[1];
    int customCval[2];

So - 'customCOOL' will be the user specified value. But I am aware that the value may be one or two digits - '2˚C' or '11˚C' for example. I am not dealing with negative values or values with more than two digits. So I have the following code:

                    if (userKey == 'A')    
                    {
                      lcd.clear();
                      lcd.setCursor(0, 0);
                      lcd.print("Enter COOL limit");
                      lcd.setCursor(0,1);
                      customCval[0] = customKeypad.waitForKey();
                          lcd.print(customCval[0]);
                      customCval[1] = customKeypad.waitForKey();
                          lcd.setCursor(1,1);
                          lcd.print(customCval[1]);

// Determine customCOOL[0] from customCval[0] && customCval[1]
// customCOOL[0] =
                      //lcd.print(customCOOL[0]);
                      //Serial.println(customCOOL[0]);
}

So - two issues.

  1. The keyboard returns an ASCII code, whereas I want the decimal value - '0' - '9'. How do I convert the value to decimal?
  2. How do I process the two inputs to represent a number? For example:
    customCval[0] = 5
    customCval[1] = 8

The number is 58, not 5+8. How would I go about achieving this?

Thankyou for your continued patience.

The number is 58, not 5+8. How would I go about achieving this?

Primary school arithmetic

TheMemberFormerlyKnownAsAWOL:
Primary school arithmetic

Thankyou for categorizing the level of arithmetic..
As no operators are involved in establishing '58' as a whole number, I am aware that 5 and 8 would refer to units. I'm asking how I would programme that.

No, one digit would refer to units, the other to tens (hint)

TheMemberFormerlyKnownAsAWOL:
No, one digit would refer to units, the other to tens (hint)

Okay.
So my 'customCval[0]' would be tens.
My 'customCval[1]' would be ones/units.
If I declared:

byte tens = 0;
byte ones = 0;

and then said:

customCval[0] = customKeypad.waitForKey();
customCval[0] = tens;
customCval[1] = customKeypad.waitForKey();
customCval[1] = ones;

customCOOL[0] = (tens && ones);

Is that the right way?

So, read the keypad value into an array element, and then overwrite that array element with zero?

Do that twice, for different array elements, and see what the logical AND of zero and zero is?

Does that sound right?

(Primary school kids don’t do much logic, but they do do arithmetic)

railedbee:
So - two issues.

  1. The keyboard returns an ASCII code, whereas I want the decimal value - '0' - '9'. How do I convert the value to decimal?
  2. How do I process the two inputs to represent a number? For example:
    customCval[0] = 5
    customCval[1] = 8

The number is 58, not 5+8. How would I go about achieving this?

Thankyou for your continued patience.

store the input as char array variable not int
then convert using atoi function

char inkey[2];
int value;
 
inkey[0] = '1';
inkey[1] = '2';

value = atoi(inkey);

result value = 12