Hi,
I am new to arduino but learn fast I need to build a humidity control device. Its purpose to measure room humidity and if it below or above a certain value turn on or turn off the humidifier and show the values on oled screen. I have did main part of coding and it works, but I don't know how to enter a threshold value. So far it is set as a constant.
here is my code:
I use 2 DHT22 sensors. and made a read from sensor as a function (maybe it is not a good idea?)
There is no OLED output yet. I turn on and off humidifier via sending IR command.
I use if and do while loop because sometimes I get more that 1000 humidity values (maybe it is problem of sensor or my code) and want to bypass them.
I also use some time stamps to see how program is working.
So 1 question how to implement manually set a humidity threshold value?
Second question do I need to use a 2 sec delay with DHT sensors (it is recommended by manual?) without delay it works too
Also any advices on how to optimize my code are welcome
Firstly, do you really need to measure every 2 seconds? Must be a pretty small room!
You appear to have 2 humidity sensors? One needs to take priority over the other...otherwise you have the potential to be flipping the humdifier on and off repetedly each loop.
I.e. if H1 is low and H2 is high, H1 will be wanting to turn on the humidifier but H2 wants it of...who wins?
A Truth Table may be of use here...
What do you want to do if:
H1 = HIGH and H2 = HIGH
H1 = HIGH and H2 = LOW
H1 = LOW and H2 = HIGH
H1 = LOW and H2 = LOW
Yours will be more like...
H1 = HIGH H2 = OK
H1 = HIGH H2 = LOW
Where HIGH = Over the max, OK = between Max and Min and LOW = Below min.
Made that for you....you need to fill in the blanks...
Use the above idea and basic statements in the main() loop to get the desired outcomes of the truth table.
PSUEDO CODE!
humidity_max = 50
humidity_min = 40
humidity1 = get_humidity1();
humidity2 = get_humidity2();
if (humidity1 > MIN AND humidity2 BETWEEN max and min){turn off humidifier}
if (humidity1 < MIN AND humidity2 < MIN ) { turn on humidifier}
The gap between maximum and minimum means that the humidifier wont be turned on and off repeatedly in a short space of time (leading to the potential for failure).
As for "manually setting", a couple of potentiometers (rotary variable resistors) with a series current limiting resistor if required and a couple of the analogRead() pins can be used to set the values. map() is a useful function for you if you go down this route. map() takes a range (like 0-1023) and outputs a value as a different range (like 0-100). So the analog voltage of the pin can be mapped to 0-100% humidity.
Just remember, that if the user "accidentally" sets the minimum value HIGHER than the maximum, your code will give undesirable results. Put a software check in that basically will only allow the minimum to be 10 or more under the maximum...and if not, set it as 10 under the maximum.
Thank you for your help Johnny010, I forget to mention that I will use only 1 DHT sensor to control the humidifier, another on will measure humidity in other room.
And I only need one humidity threshold value. I inserted some analog read lines in a code, and it works, but there is a problem when it goes to "turn on" while loop, it doesn't react on potentiometer, should I also duplicate analog read line in that while loop too?
#include <dht.h>
#include <OLED_I2C.h>
#include <IRremote.h>
#define DHTTYPE DHT22
#define dataPin1 9
#define dataPin2 5
int potPin = 1;
int val = 0;
dht DHT1;
dht DHT2;
OLED myOLED(SDA, SCL, 8);
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];
unsigned long time;
IRsend irsend;
void setup() {
myOLED.begin();
myOLED.setFont(SmallFont);
Serial.begin(9600);
}
void loop() {
Serial.print("Time: ");
time = millis() / 1000;
//prints time since program started
Serial.print(time);
Serial.print(" \t");
val = analogRead(potPin);
val = map(val, 0, 1023, 0, 100);
int Hset = val; // humidity threshold value
Serial.print(time);
Serial.print(" \t");
Serial.print("SetH: ");
Serial.print(Hset);
Serial.print(" \t");
float h1, h2;
hum(&h1, &h2);
if ( h1 > 101 || h2 > 101)
{
do
{
hum(&h1, &h2);
Serial.print("ower1 \t");
} while ( h1 > 101 || h2 > 101);
}
Serial.print("H1: ");
Serial.print(h1);
Serial.print("\t");
Serial.print("H2: ");
Serial.print(h2);
Serial.print("\n");
if (h1 < Hset)
{
irsend.sendNEC(0x1FE7887, 32);
Serial.println("Turn On");
while(h1 < Hset)
{
hum(&h1, &h2);
if ( h1 > 101 || h2 > 101)
{
do
{
hum(&h1, &h2);
Serial.print("ower2 \t");
} while ( h1 > 101 || h2 > 101);
}
Serial.print("Time: ");
time = millis() / 1000;
//prints time since program started
Serial.print(time);
Serial.print(" \t");
Serial.print("H1: ");
Serial.print(h1);
Serial.print("\t");
Serial.print("H2: ");
Serial.print(h2);
Serial.print("\n");
}
irsend.sendNEC(0x1FE7887, 32);
Serial.println("Turn OFF");
}
}
float hum(float* h1, float* h2)
{
float readData1 = DHT1.read22(dataPin1);
float readData2 = DHT2.read22(dataPin2);
*h1 = DHT1.humidity;
*h2 = DHT2.humidity;
delay (2000);
return *h1, *h2;
}
And how to output all this information to the OLED display? Do I need to rearrange the code, introduce interruption if i move a potentiometer during loop operation?
Why does this function expect 2 pointers/floats? I don't really understand what pointers are (except a bit like a direct "address" to a place in SRAM that contains a float for example)...but I may be wrong.
float hum(byte sensor)
{
switch (sensor){
case 1:
return DHT1.read22(dataPin1);
break;
case 2:
return DHT2.read22(dataPin2);
break;
default:
Serial.println("Unknown Sensor or ERROR");
break;
}
Will mean hum(1) returns a float equal to the result of DHT1.read22(dataPin1);
These "while true" loops will mean the code is stuck in the loops.
if ( h1 > 101 || h2 > 101)
{
do
{
hum(&h1, &h2);
Serial.print("ower1 \t");
} while ( h1 > 101 || h2 > 101);
}
I don't really understand them either.
if H1 or H2 is greater than 101 (which they wont be...100% is the maximum)
Do while (the above is always true): Get some humidity values and prin some "ower1 \t"
These "while true" loops will mean the code is stuck in the loops.
if ( h1 > 101 || h2 > 101)
{
do
{
hum(&h1, &h2);
Serial.print("ower1 \t");
} while ( h1 > 101 || h2 > 101);
}
I don't really understand them either.
if H1 or H2 is greater than 101 (which they wont be...100% is the maximum)
Do while (the above is always true): Get some humidity values and prin some "ower1 \t"
It is weird but sometimes I get humidity values more than 3000%, so I put this if condition. And in normal operation my sensors does not show value more that 91- 93 % (when I breath on them).
Thank you for your suggestions, I will try to avoid blocking loops
I think there is one big problem in my setup, that turn on and turn off is the same IR command, and there is no feedback with humidifier (ther control box doesn't know the status of humidifier), so according to your code in any case it will trigger the humidifier back and force.
the wire diagram is simple DHT1 is connected to pin D9, DHT2 to pin D5, IR diode to pin D3 and analog potentiometer to pin A1. other contacts to vcc and gnd. I don't use nay resistors for potentiometer and ir led, dht sensors are mount on a board and have some resistors.
when doing any control, I always recommend that one does some process data logging.
turn on your unit, data log the change, turn off your unit and watch to see if the result is a gradual change or if it is more drastic.
this will give you some idea how large of a hysteresis window you need. if your humidifier ALWAYS shoots way past your control point, then the process has a built in hysteresis. if your process can move easily nears your control point, then you need to have the ON point and OFF point set differently to prevent the control from going on and off rapidly at the control point.
I can offer that you need some good devices to control humidity in a narrow range. you cannnot do it with crappy devices and 'fix' it in software.