Habitat Controller

Hi there, new to this Arduino stuff here, but certainly not to programming. I have experience with the basics of programming and logic design, C++, and a tad bit of Visual C++. I also have a general working knowledge of AC/DC electrical circuits.

Anyways, I'm here to upload my project idea of mine and I've already worked on some coding to implement the User Interface portion of it. It's a pet habitat controller and its going to be designed to measure temperature and humidity and adjust things according to the user's set parameters. The controller part of it, which i haven't coded yet will handle 2x things, switching on some sort of heating element and misting the pet habitat with water to raise the humidity levels. The habitat controller will implement a 16x2 LCD to display current readings and when the mode switch is flipped into the off position it will allow the user to adjust the desired readings so the controller will know when to make adjustments. I've basically have coded the 2x modes, auto cycle mode in which the controller will display current sensor values, and the programming mode in which the user can adjust temp and humidity. I've basically been only tweaking the user interface coding to remove any possible errors, like clearing the LCD of any hanging characters that were not overwritten by the last print command, and also prevented the user from adjusting any temp or humidity settings to go lower than 0. (I know temp can go below 0, but it's not like I have any pets that live in those conditions roflmao)

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 10, 7, 6, 5, 4);
const int digitalPin1 = 9;  //mode switch
const int digitalPin2 = 3;  //button 1
const int digitalPin3 = 2;  //button 2
const int digitalPin4 = 1;  //button 3

int value1 = 0;  //programming mode switch
int value2 = 0;  //Up button
int value3 = 0;  //Down button
int value4 = 0;  //Enter button
int select = 0;  //determines which value to adjust while programming
int temp = 85;   //dummy sensor values
int humidity = 60;  //dummy sensor value

void setup() {
  lcd.begin(16, 2);
}

void loop() {
  value1 = digitalRead(digitalPin1);
  value2 = digitalRead(digitalPin2);
  value3 = digitalRead(digitalPin3);
  value4 = digitalRead(digitalPin4);
  
  if(temp < 0) {   //prevents adjusting temp into negative values
    temp = 1;
  }
  
  if(humidity < 0) {  //prevents adjusting humidity into negative values
    humidity = 10;
  }
  
  if(value1 == 0) {         //starts the programming mode      
    lcd.setCursor(0, 0);
    lcd.print("Programming Mode");
    lcd.setCursor(0, 1);
    lcd.print(temp);         //prints values
    if(temp < 100) {        //cleans screen of hanging digits from adjusting triple to double digit values
      lcd.setCursor(3, 1);
      lcd.print(" ");
    }
    lcd.setCursor(3, 1);
    lcd.print((char)223);
    lcd.setCursor(4, 1);
    lcd.print("F");
    lcd.setCursor(12, 1);
    lcd.print(humidity);
    
    if(humidity < 100) {    //cleans screen of hanging digits from adjusting triple to double digit values
      lcd.setCursor(14, 1);
      lcd.print(" ");
    }
    lcd.setCursor(15, 1);
    lcd.print("%");
    
    if(value4 == 1) {
      select = 1;
    }
    
    if(select > 0) {
      lcd.setCursor(6, 1);
      lcd.print("   ->");    //prints an arrow to show which value your currently editing and covers up the old one
      if(value2 == 1) {     //adjusts humidity up
        humidity = (humidity + 10);
        delay(500);  
      }
      if(value3 == 1) {    //adjusts humidity down
        humidity = (humidity - 10);
        delay(500);
      }
    }
    
    if(select < 1) {
      lcd.setCursor(6, 1);
      lcd.print("<-");       //prints an arrow to show which value your currently editing
      if(value2 == 1) {     //adjusts temp up
        temp = (temp + 1);
        delay(500);  
      }
      if(value3 == 1) {    //adjusts temp down
        temp = (temp - 1);
        delay(500);
      }
    }
    
  }
  
  if(value1 == 1) {  //enters auto cycle mode 
    select = 0;
    lcd.setCursor(6, 1);
    lcd.print("     ");  //clears arrows from programming mode
    lcd.setCursor(0, 0);
    lcd.print("Auto-Cycle  Mode");
    lcd.setCursor(0, 1);
    lcd.print(temp);  //prints current readouts from sensors
    lcd.setCursor(3, 1);
    lcd.print((char)223);
    lcd.setCursor(4, 1);
    lcd.print("F");
    lcd.setCursor(12, 1);
    lcd.print(humidity);
    lcd.setCursor(15, 1);
    lcd.print("%");
  }
}

Right now my brain is having a mental block with some of this coding as I currently stuck trying to code it were I can go back and forth between adjusting temp and humidity without having to flip the mode switch back and forth. It's quick and easy so there really isn't a need for it too much, but if anyone knows a simple method to doing so i'm open to any suggestions. I'm also open to any suggestions on how to shorten any of the coding if at all possible.

How about displaying both the current reading and the desired setting on the LCD? Perhaps the setting could appear in brackets after the reading. Then you could adjust the settings on the fly without the use of the mode button. While you're at it though, consider renaming your valueN variables to make the code easier to understand.

Right now that was just sample coding to make an interactive menu on an LCD as I'm still fairly new to this arduino bit. Anyways, I did make overall improvements to the code, but i won't be using that specific code for the actual pet habitat controller. I'm coming up with more ideas on how to get this thing up and running and how to expand its capabilities which may require more than one arduino board, or upgrade it with a mega. Right now I've acquired 2x DHT11 temperature and humidity sensors and have already tested having it actively update live reports on the small LCD screen I had. I'm not entirely sure I'll be using the 16x2 LCD for running this project of mine, unless I purchase a shield version instead that requires less pins to operate. On top of that I may seek having a ethernet shield reporting data and status on the habitat controller on the web so I could actively check it with my phone whenever I'm not home.

So essentially if I get the coding and design down right the habitat controller will be able to...

  • Keep a constant check on the temp and humidity in more than one tank
  • Mist one or another tank at specific times or in which the humidity is in need of tweaking
  • Heat one or more tanks simultaneously
  • Report Temp/Humidity of each tank to my phone
  • Report Low Water level in the reservoir

Right now I'm working on getting a reliable misting system in which I can modify to be controlled by my arduino and to have a number of solenoids controlling valves so not all tanks are misted at the same time. The annoying part is choosing a high quality system in which I have to provide my own water reservoir, or get the dinky system with a 2.5 gallon tank attached to it that I would have to seal its electronics better because of their cheap design. Something about their hose lines leaking into the electronics portion of the the system and it typically breaks the so called timer circuit it has.

The high quality system being the MistKing Starter package, and the dinky system being Exo Terra's Monsoon RS400.

So on top of coding I would need to be constructing a relay board that can also handle 120VAC on top of the voltage needed for controlling any valve solenoids so as not to harm the Arduino's circuits. Ayaaahhh so much to do and so little time to do it.

Ok I've designed a new program to load readouts from a DHT11 on a Adafruit (ST7735) 1.8" TFT LCD Shield w/ joystick and micro SD slot. And I've already hit a mild bump in programming this, a LCD handles a bit different than a true TFT LCD, as the pixels hang as long as the screen is not refilled so it makes the readouts unreadable when they update. So for right now I've added to the screen fill into the loop to help redraw the whole screen, plus whatever doesn't actively update with the DHT11. Does anyone know a simple line of code to remove the pixels in the area in which my readouts are to be printed so as not to make a mass of them and make it unreadable?

Here is the sample code in which I wrote for right now. I just wanted to sample scaling and everything with the TFT LCD. I just plugged in other bits of code from an older sample sketch to handle the DHT11.

#define cs   10
#define dc   8
#define rst  -1
#define DHT11PIN 2

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <dht11.h>

dht11 DHT11;

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);

void setup() {
  tft.initR(INITR_REDTAB);
}

void loop() {
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(35, 0);
  tft.setTextColor(ST7735_RED);
  tft.print("* Farhenheit");
  tft.setTextColor(ST7735_BLUE);
  tft.setCursor(15, 50);
  tft.print("% Humidity");
  int chk = DHT11.read(DHT11PIN);
  tft.setTextColor(ST7735_RED);
  tft.setCursor(0, 0);
  tft.print(Fahrenheit(DHT11.temperature));
  tft.setTextColor(ST7735_BLUE);
  tft.setCursor(0, 50);
  tft.print(DHT11.humidity);
  delay(5000);
}

double Fahrenheit(double celsius)
{
        return 1.8 * celsius + 32;
}

Ok with some tweaking and assistance from the programming section here on the forums I was able to perfect refreshing the certain areas of the screen. After a readout was printed it's value would be saved to a parameter for the next cycle of the loop and before the next readout was printed it would use the parameter to write over the existing readout on screen in black. This doesn't even require a lot of extra coding so it certainly saves space for the bigger portion of my project.

#define cs   10
#define dc   8
#define rst  -1
#define DHT11PIN 2

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <dht11.h>

dht11 DHT11;
double temp;
int humidity;

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);

void setup() {
  tft.initR(INITR_REDTAB);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(35, 0);
  tft.setTextColor(ST7735_RED);
  tft.print("o");
  tft.setCursor(45, 2);
  tft.print("Fahrenheit");
  tft.setTextColor(ST7735_BLUE);
  tft.setCursor(15, 50);
  tft.print("% Humidity");
}

void loop() {
  
  int chk = DHT11.read(DHT11PIN);
  tft.setTextColor(ST7735_BLACK);
  tft.setCursor(0, 2);
  tft.print(temp);
  tft.setTextColor(ST7735_RED);
  tft.setCursor(0, 2);
  tft.print(Fahrenheit(DHT11.temperature));
  temp = (Fahrenheit(DHT11.temperature));
  tft.setTextColor(ST7735_BLACK);
  tft.setCursor(0, 50);
  tft.print(humidity);
  tft.setTextColor(ST7735_BLUE);
  tft.setCursor(0, 50);
  tft.print(DHT11.humidity);
  humidity = (DHT11.humidity);
  delay(5000);
}

double Fahrenheit(double celsius)
{
        return 1.8 * celsius + 32;
}