[SOLVED] Blynk - WIFI Humidity level control with set point and hysteresis, DHT22 and relay on/off

Hi, I’m trying to merge code for temperature and humidity based on DHT22 readings with Arduino PID control.

I’m unsure how to get get the correct output.

I would like to be able to set the setpoint humidity by the blynk slider ex. at 40% and also follow the flow and the measurements as the screen dump below.

I’m using the Wemos D1 mini board with the DHT22 and the relay brick.

This is my code so far…

#include <PID_v1.h>
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <DHT.h>


#define DHTPIN 2
#define DHTTYPE DHT22   
DHT dht(DHTPIN, DHTTYPE);


char auth[] = "XXX";
SimpleTimer timer;

#define RelayPin D1 //Relay is on D1 pin

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

int WindowSize = 5000;
unsigned long windowStartTime;

void sendUptime()
{
  
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  Blynk.virtualWrite(10, t); // virtual pin temperature app graph 
  Blynk.virtualWrite(11, h); // virtual pin humidity app graph 
  
  Blynk.virtualWrite(1, t); // virtual pin temperature app Value
  Blynk.virtualWrite(2, h); // virtual pin humidity app Value 
  Blynk.virtualWrite(15, RelayPin); // Virtual pin relay LED on/OFF

}

void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, "GRID", "1992");
  timer.setInterval(1000, sendUptime);

windowStartTime = millis();
  
  //initialize the variables we're linked to
  Setpoint = 100;

  //tell the PID to range between 0 and the full window size
  myPID.SetOutputLimits(0, WindowSize);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);

}

void loop()
{   
  Blynk.run();
  timer.run();

Input = digitalRead(0);
  myPID.Compute();

  /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  if(millis() - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  }
  if(Output < millis() - windowStartTime) digitalWrite(RelayPin,HIGH);
  else digitalWrite(RelayPin,LOW);

  
}

I get the readings but are unsure of the PID routine and setting the right pins for blynk.

Please advice…

1 Like

Ok first of all if you don’t know theory behind PID please read it as it helps a lot in understanding what you are doing, why and how you gonna achieve it. Based on what you chose your P, I, D? Have you done any tuning of your system whatsoever? Make sure you are casting your variable correctly from float to double when initializing myPID. Also you need to set sampleTime for myPID

Actually you can use Matlab to tune your PID controller if you take some readings without actuall PID controller and measure how environment reacts.

Just for interests sake, why are you controlling relative humidity?

Hi, yes I will dig into the PID routines and I have not done any tuning yet.
The plan is to set up the code and do some tuning 1:1. If you have any input to the set point temp or the timewindow, please provide.

I use a dehumidifier for controlling the environment - it can take 50% humidity to 30% in around 60 minutes.

Hi, I will use the setup for controlling the humidity in a part of the basement in my house - this part of the basement is not yet renovated and the bottom floor and walls are in bad condition.
If I do nothing the humidity will rise to a high level and it would be perfect to control it over wifi and with PID control.

I think you might actually be needing to control the “dew point” in your basement, not the RELATIVE humidity…

Luckily dew point can be calculated from temperature and relative humidity outputs :slight_smile:

Dave made good point. As for PID I would suggest to tune it to have overshoot but at the same time rapid response you will have more rapid system response overall. As for tuning itself you can use http://support.motioneng.com/downloads-notes/tuning/pid_overshoot.htm

Start tuning from having I and D as 0 and changing P only then adding other parameters. Plot your graphs using Plotly for example as with Blynk it’s gonna be quite hard. Write some code to be able to change PIDs on the fly through serial port or in Blynk. Lastly add some filtering to your humidity readings cause you don’t want some disturbance to alter your system (as I can see it fluctuates a lot on your graph)

for my moisture reduction ventilation system (not using a de-humidifier) i use a running median calculation to smooth the readings… i don’t use PID though - my target humidity is “the lowest possible”…

PID Controller has nothing to do with filtering. It’s basically a way to control Complex control industrial systems that usually have some kind of delay from let’s say using heater to heat up sth to actual change in temperature.

it must be possible to make a simple humidity Control - it is possible to buy these exhaust fans at homedepot.com, they all have a buildin humidity controller. (+ wifi and live feed in Blynk for turning on and off a dehumifier)

http://www.homedepot.com/p/Delta-Breez-Signature-130-CFM-Ceiling-Humidity-Sensing-Exhaust-Bath-Fan-VFB25AEH/203314719

Besides the PID routine (code) that has to be tunede, can anybody help with the code setup. I think it is somehow the timer lib., that is giving me problems. It is compiling without errors but the relay is not kicking in.

KSinning I haven’t got a clue what PID is and know very little about humidity.

All I can really make out in your sketch is that the relay should be on for 5 seconds based on “Output” or it should be off.

Can’t you just have a 5 second SimpleTimer rather than the millis stuff to check for your condition and then turn the relay on and off. Are you familiar with SimpleTimer?

hi, Costas. As i understand the code - the millis() set the windows size for the PID calculation and it is changing based on the calculation over time.
I still want the temperature and humidity readings send to Blynk every second (sendUptime)…but i’m also new to coding so i might be doing everything the wrong way…maybe SimpleTimer can do the job, i’m not sure?

The optimum void loop for Blynk is shown below and everything else should normally be done outside the loop i.e. timers. That is why Blynk provide the SimpleTimer library. Your millis() looks fine and shouldn’t be a problem but timers are easier to read in the sketch.

void loop()
{
  Blynk.run();
  timer.run();
}

TImers in normal MCUs are only used to have either precise events or efficient power management. It’s massive overkill to have timers in some situations also in some other situations it’s actually not suitable to use timers. First of all use brackets makes code clearer.

Instead of :

if(millis() - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if(Output < millis() - windowStartTime) digitalWrite(RelayPin,HIGH);
else digitalWrite(RelayPin,LOW);
}

Use:

if((millis() - windowStartTime) >WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if(Output < (millis() - windowStartTime)) digitalWrite(RelayPin,HIGH);
else digitalWrite(RelayPin,LOW);
}

The reason for your code not to work is fact that your PID is broken as Input you should use humidity readings. Your set point should be some constant or variable you want to have and the output is pretty much relay state. In your code nothing changes.

There is however one big “but”. Why you are using PID if you only control 0/1 state of your humidifier. In my opinion using PID in your case doesn’t make sense because the whole point of PID would be to control intensity or the power output of your humidifier. Read about PID and think about it

Hi Conkerkh, I see you point - the PID setup would better fit a dehumidifier capable of a change in power.

I have tried to make the following simple setup for the relay trigger, but i would also be able to change the set point with a blynk slider.

#include <DHT.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <WidgetLED.h>

#define BLYNK_PRINT Serial

char auth[] = "XXX`indent preformatted text by 4 spaces`"; 

SimpleTimer timer;

#define DHTPIN 2
#define DHTTYPE DHT22

const int relay1 =  5;
int humLowTrigger = 40;

DHT dht(DHTPIN, DHTTYPE);

void Readdata()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  Blynk.virtualWrite(10, h);
  Blynk.virtualWrite(11, h);
  Blynk.virtualWrite(20, t);
  Blynk.virtualWrite(21, t);
  Blynk.virtualWrite(15, relay1);
  Blynk.virtualWrite(25, humLowTrigger);
  
  if(h < humLowTrigger) {
      digitalWrite(relay1, LOW); 
      Blynk.virtualWrite(V26, 0);
  } else {
      digitalWrite(relay1, HIGH);
      Blynk.virtualWrite(V26, 255);
  }
}

BLYNK_WRITE(V7)
{
  Blynk.virtualWrite(V7, humLowTrigger);
}


void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, "X", "Y");
  timer.setInterval(1000, Readdata);
  
  dht.begin();

  pinMode(relay1, OUTPUT);
  digitalWrite(relay1, LOW);

}

void loop()
{   
  Blynk.run();
  timer.run();

}

The slider is not working… any hints for optimising the code would be great.

how is your humidity so low?

isn’t your set point fixed at 40 with

int humLowTrigger = 40;

Hi Dave, please advice. If I delete it it doesn’t seem to work either?!

Do you know a simple example of how to use the slide widget for setting the set point value.

Create callback on slider change.

if you connected slider to V7 then you can do like so

BLYNK_WRITE(V7) {
updateSetPoint(param.asInt());
}

void updateSetPoint(int setPoint) {
humLowTrigger = setPoint;
}

it didn’t work…updateSetpoint not a function. I tried this adjustment in the code, but still no luck…

#include <DHT.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <WidgetLED.h>

#define BLYNK_PRINT Serial

char auth[] = "XX"; 

SimpleTimer timer;

#define DHTPIN 2
#define DHTTYPE DHT22

const int relay1 =  5;
int humLowTrigger;

DHT dht(DHTPIN, DHTTYPE);

BLYNK_WRITE(V7) {
  int humLowTrigger = param.asInt();
}

void Readdata()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  Blynk.virtualWrite(V10, h);
  Blynk.virtualWrite(V11, h);
  Blynk.virtualWrite(V20, t);
  Blynk.virtualWrite(V21, t);
  Blynk.virtualWrite(V15, relay1);
  Blynk.virtualWrite(V25, humLowTrigger);
  
  if(h < humLowTrigger) {
      digitalWrite(relay1, LOW); 
      Blynk.virtualWrite(V26, 0);
  } else {
      digitalWrite(relay1, HIGH);
      Blynk.virtualWrite(V26, 255);
  }
}

void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, "X", "X");
  timer.setInterval(1000, Readdata);
  
  dht.begin();

  pinMode(relay1, OUTPUT);
  digitalWrite(relay1, LOW);

  int humLowTrigger = 40;
}

void loop()
{   
  Blynk.run();
  timer.run();
}
  • At first run the set point for LowHumTrigger is set to the value 40.
  • Slider widget sets LowHumTrigger (App virtual pin is V7)

… still no luck