Hi all!
I have been working for some time on the development of a control system, to control the temperature inside a box.
I would do this with a blower fan by means of a control system of the PID type (PID_V1 of Brett Beauregard) in which sucking air from the outside, if the internal temperature of the box exceeds 35 °C, I would maintain the desired temperature (about 35 °C).
This would be a basic scheme of the system:
Why should the interior of the box ever heat up above the temperature of the outside air? If anything, the slight partial vacuum inside would lower the interior temperature.
Since it is likely that there is something wrong with the wiring, please edit your post to remove the confusing, misleading, incomplete Fritzing diagram and instead, post a clear hand-drawn wiring diagram, with properly labeled components.
This is wrong: double Kp_T=(-1), Ki_T=(-0.05), Kd_T=(-0.25); .
The K values must be non-negative. Please study the user guide to the PID library and use DIRECT or REVERSE for the controller direction parameter.
Mosfet IRF540 channel N
This is a very poor choice and probably won't work. Choose a logic level MOSFET instead, such as the IRL540.
We strongly advise beginners to get each part of the project working before throwing everything together.
First learn to turn a fan ON and OFF using a logic level MOSFET.
Then learn to read the sensors.
Implement a simple controller that turns the fan ON when the temperature is too high, and OFF when too low.
jremington:
Why should the interior of the box ever heat up above the temperature of the outside air? If anything, the slight partial vacuum inside would lower the interior temperature.
Hi Jremington!
Thanks for you reply!
In the interior box, I have a tiny heat source and I need to controlate it (similar to a server).
Since it is likely that there is something wrong with the wiring, please edit your post to remove the confusing, misleading, incomplete Fritzing diagram and instead, post a clear hand-drawn wiring diagram, with properly labeled components.
Sorry, I thought the diagram was enough to understand the problem.
This is wrong:
double Kp_T=(-1), Ki_T=(-0.05), Kd_T=(-0.25);
The K values must be non-negative. Please study the user guide to the PID library and use DIRECT or REVERSE for the controller direction parameter.
Ok, I will to try it!
This is a very poor choice and probably won't work. Choose a logic level MOSFET instead, such as the IRL540.
Ok!
We strongly advise beginners to get each part of the project working before throwing everything together.
First learn to turn a fan ON and OFF using a logic level MOSFET.
Then learn to read the sensors.
Implement a simple controller that turns the fan ON when the temperature is too high, and OFF when too low.
Finally, add PID and properly tune the K values.
I will apply your recommendations. I am very grateful with your help!
Greetings
[/quote]
Hi everybody!
I worked on this project this month and I added some new features.
I added a bluetooth module (HM-10) for send data to my smartphone and a sdcard shield for data sensor storage.
Sound good because I left the display for a new blt module!
But I have a problem... When I send the "V" character I don't receive any data from arduino! everything else works fine!
The character doesn't enter to arduino and I don't know why??
If I use this code without sd card it's work fine! for another hand, if I use this code without blt module works fine too! But together doesn't works
This is the code:
//*****************Serial port******************
#include <SPI.h> //Serial Peripheral Interface
#include <SoftwareSerial.h>
//***************** BME280***********************
#include "cactus_io_BME280_I2C.h"
//***************** RTC-SDCARD***********************
#include <SD.h> //Interface SD
#include "RTClib.h" //Interface RTC
File myFile;
const int chipSelect = 10; // SDCARD
DS1307 rtc;
//***************** PID***********************
#include "PID_v1.h"
//**************Instances************
//**************Def Bluetooth HM10**********************
SoftwareSerial HM10(10, 11); // 10--Rx y 11--Tx
char appData;
char rxData; // Var for get data from HM10
String inData = "";
//**************Def BME280**********************
BME280_I2C bme_Int(0x76); // i2C address: 0x77 BME and 0x76 for original BME
BME280_I2C bme_Ext(0x77);
float Ti; // Internal temp (C)
float Hi; // Internal Rel. hum
float Te; // Ext temp (C)
float He; // Ext Rel. hum
int K=273;
//*********Def PID********
#define PIN_OUTPUT 3 // pwm
double Setpoint_T, Input_T, Output_T;
double Setpoint_H, Input_H, Output_H;
double Kp_T=10, Ki_T=1, Kd_T=1;
double Kp_H=2, Ki_H=5, Kd_H=1;
PID myPID_T(&Input_T, &Output_T, &Setpoint_T, Kp_T, Ki_T, Kd_T, REVERSE);
PID myPID_H(&Input_H, &Output_H, &Setpoint_H, Kp_H, Ki_H, Kd_H, REVERSE);
//*********Def millis********
long previousMillis_SD = 0;
long intervaloSD = 60000;
void setup() {
//********Set frec PIN 3********
TCCR2B = TCCR2B & B11111000 | B00000001; //change frec on PIN3 to 31372.55 Hz
//**********Init Serial port*************
Serial.begin(9600);
//**********Init BLT*************
HM10.begin(9600); // set HM10 serial at 9600 baud rate
//**********Init BME280**********
bme_Int.begin();
if (!bme_Int.begin()) {
Serial.println("TI?");
}
bme_Ext.begin();
if (!bme_Ext.begin()) {
Serial.println("TE?");
}
//*************Init SDCARD**********************
if (! rtc.begin()) {
Serial.println("RTCX"); //RTCX
}
if (! rtc.isrunning()) {
Serial.println("RTC?"); //RTC?
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));// sets the RTC to the date & time this sketch was compiled
}
if (!SD.begin(chipSelect)) { // Is sdcard present?
Serial.println("SDX"); //SDX
}
//**********Init var**********
Input_T = Ti;
Setpoint_T = 30; //Set point Temp
Input_H = Hi;
Setpoint_H = 60; //Set point hum
myPID_T.SetMode(AUTOMATIC); //Temp PID
myPID_H.SetMode(AUTOMATIC); //Hum PID
}
void loop() {
//*******RTC update time**********
DateTime now = rtc.now();
//**************read data BME*************
bme_Int.readSensor();
Ti = bme_Int.getTemperature_C()+K;
Hi = bme_Int.getHumidity();
bme_Ext.readSensor();
Te = bme_Ext.getTemperature_C()+K;
He = bme_Ext.getHumidity();
//****************HM10********************
HM10.listen(); // listen the HM10 port
if (HM10.available() > 0){
appData = HM10.read();
inData = String(appData);
Serial.write(appData);
}
if (inData == "V" ){
HM10.println("T" + String(Te-K) + " " + String(He)+ " T" + String(Ti-K) + " " + String(Hi));
}
//******************PID code*****************************
if (Te >= 283 && Te < 310 ){
myPID_H.Compute(); //PID Hum
analogWrite(PIN_OUTPUT, Output_H);
}
if (Te >= 310 ){ // 37°C
myPID_T.Compute(); //PID Temp
analogWrite(PIN_OUTPUT, Output_T);
}
else analogWrite(PIN_OUTPUT, 0);
//**************Send data to SDCARD**************
if (millis() - previousMillis_SD >= intervaloSD){
previousMillis_SD = millis();
myFile = SD.open("Log.txt", FILE_WRITE);
if (myFile) {
myFile.print(now.year(), DEC);
myFile.print('/');
myFile.print(now.month(), DEC);
myFile.print('/');
myFile.print(now.day(), DEC);
myFile.print(' ');
myFile.print(now.hour(), DEC);
myFile.print(':');
myFile.print(now.minute(), DEC);
myFile.print(':');
myFile.print(now.second(), DEC);
myFile.print(';');
myFile.print(" Ti ");
myFile.print(Ti-K);
myFile.print(" H ");
myFile.print(Hi);
myFile.print(" Te ");
myFile.print(Te-K);
myFile.print(" H ");
myFile.println(He);
myFile.flush();
myFile.close();
Serial.print("D");
}
else {
Serial.println("Log?");
}
}
}
Hi everybody!
Yesterday I changed and reorganized the code to make it more readable...
I need to know how long the pwm cooler is ON and then send this elapsed time to in a SD Card. The code than I write for this purpose is the line 184 to 197, and 252 to 255. But it doesn't work...doesn't write any time data in Sd Card or BLT.
I am not sure how to use the PIN_OUTPUT states... maybe this is the problem.
//*****************Serial port******************
#include <SPI.h> //Serial Peripheral Interface
#include <SoftwareSerial.h>
//***************** BME280***********************
#include "cactus_io_BME280_I2C.h"
//***************** RTC-SDCARD***********************
#include <SD.h> //Interface SD
#include "RTClib.h" //Interface RTC
File myFile;
const int chipSelect = 10; // SDCARD
DS1307 rtc;
//***************** PID***********************
#include "PID_v1.h"
//**************Instances************
//**************Def Bluetooth HM10**********************
SoftwareSerial HM10(10, 11); // 10--Rx y 11--Tx
char appData;
char rxData; // Var for get data from HM10
String inData = "";
//**************Def BME280**********************
BME280_I2C bme_Int(0x76); // i2C address: 0x77 BME and 0x76 for original BME
BME280_I2C bme_Ext(0x77);
float Ti; // Internal temp (C)
float Hi; // Internal Rel. hum
float Te; // Ext temp (C)
float He; // Ext Rel. hum
int K=273;
//*********Def PID********
#define PIN_OUTPUT 3 // pwm
double Setpoint_T, Input_T, Output_T;
double Setpoint_H, Input_H, Output_H;
double Kp_T=10, Ki_T=1, Kd_T=1;
double Kp_H=2, Ki_H=5, Kd_H=1;
PID myPID_T(&Input_T, &Output_T, &Setpoint_T, Kp_T, Ki_T, Kd_T, REVERSE);
PID myPID_H(&Input_H, &Output_H, &Setpoint_H, Kp_H, Ki_H, Kd_H, REVERSE);
//*********Def millis********
long previousMillis_SD = 0;
long intervaloSD = 60000;
unsigned long event_start_time=0; //
unsigned long event_actual_time=0;
unsigned long event_elapsed_time=0;
volatile boolean flag_state = false; //flag for pwm state.
void setup() {
//********Set frec PIN 3********
TCCR2B = TCCR2B & B11111000 | B00000001; //change frec on PIN3 to 31372.55 Hz
//**********Init Serial port*************
Serial.begin(9600);
//**********Init BLT*************
HM10.begin(9600); // set HM10 serial at 9600 baud rate
//**********Init BME280**********
bme_Int.begin();
if (!bme_Int.begin()) {
Serial.println("TI?");
}
bme_Ext.begin();
if (!bme_Ext.begin()) {
Serial.println("TE?");
}
//*************Init SDCARD**********************
if (! rtc.begin()) {
Serial.println("RTCX"); //RTCX
}
if (! rtc.isrunning()) {
Serial.println("RTC?"); //RTC?
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));// sets the RTC to the date & time this sketch was compiled
}
if (!SD.begin(chipSelect)) { // Is sdcard present?
Serial.println("SDX"); //SDX
}
//**********Init var**********
Input_T = Ti;
Setpoint_T = 30; //Set point Temp
Input_H = Hi;
Setpoint_H = 60; //Set point hum
myPID_T.SetMode(AUTOMATIC); //Temp PID
myPID_H.SetMode(AUTOMATIC); //Hum PID
}
void W_SdCard(); //Function for write in SD_Card
void Codes(String inData); //Function for manager codes
void loop() {
//*******RTC update time**********
DateTime now = rtc.now();
//**************read data BME*************
bme_Int.readSensor();
Ti = bme_Int.getTemperature_C()+K;
Hi = bme_Int.getHumidity();
bme_Ext.readSensor();
Te = bme_Ext.getTemperature_C()+K;
He = bme_Ext.getHumidity();
//****************HM10********************
HM10.listen(); // listen the HM10 port
if (HM10.available() > 0){
appData = HM10.read();
inData = String(appData);
Codes(inData);
}
//******************PID code*****************************
if (Te >= 288 && Te < 310 ){
if (Hi < Setpoint_H && Setpoint_H < He){
myPID_H.SetControllerDirection(DIRECT);
myPID_H.Compute();
}
else {
myPID_H.SetControllerDirection(REVERSE);
myPID_H.Compute();
}
analogWrite(PIN_OUTPUT, Output_H);
}
if (Te >= 310 ){
myPID_T.Compute(); //PID Temp
analogWrite(PIN_OUTPUT, Output_T);
}
//**************Send data to SDCARD**************
//Two criteria apply. First: time criteria... Second: cooler state criteria
//First:
if (millis() - previousMillis_SD >= intervaloSD){
previousMillis_SD = millis();
W_SdCard();
}
//Second: I need to know how long the cooler is ON:
if (( PIN_OUTPUT==HIGH) && (flag_state==false)){
event_start_time=millis(); //start time count
HM10.println(String(event_start_time));
flag_state==true;
}
if ((PIN_OUTPUT==LOW) && (flag_state==true)){
flag_state==false; //turn flag
event_actual_time=millis();
event_elapsed_time = event_actual_time - event_start_time;
HM10.println(String(event_elapsed_time));
W_SdCard(); //send to sdcard
}
}
void Codes(String inData){
if (inData == "A" ){
HM10.println(String(Te-K) +" "+ String(He)+" "+ String(Ti-K) +" "+ String(Hi));
}
if (inData == "C" ){ //Read ctes values PID Temp Hum
HM10.println(String(Kp_T) +" "+ String(Ki_T) +" "+ String(Kd_T));
HM10.println(String(Kp_H) +" "+ String(Ki_H) +" "+ String(Kd_H));
}
if (inData == "X"){ //cooler pwm OFF
analogWrite(PIN_OUTPUT, LOW);
HM10.println("OFF");;
}
if (inData == "Y"){ //cooler pwm ON
analogWrite(PIN_OUTPUT, HIGH);
HM10.println("ON");;
}
}
void W_SdCard(){
//*******RTC update**********
DateTime now = rtc.now();
myFile = SD.open("Log.txt", FILE_WRITE);
if (myFile) {
myFile.print(now.year(), DEC);
myFile.print('/');
myFile.print(now.month(), DEC);
myFile.print('/');
myFile.print(now.day(), DEC);
myFile.print(' ');
myFile.print(now.hour(), DEC);
myFile.print(':');
myFile.print(now.minute(), DEC);
myFile.print(':');
myFile.print(now.second(), DEC);
myFile.print(';');
myFile.print(" ");
myFile.print(Te-K);
myFile.print(" ");
myFile.print(He);
myFile.print(" ");
myFile.print(Ti-K);
myFile.print(" ");
myFile.print(Hi);
myFile.print(" ");
if ((flag_state==true) && (event_elapsed_time > 0)){ //I use event_elapsed_time to.
myFile.print(event_elapsed_time/1000); //Print sec.
event_elapsed_time=0;
}
myFile.println("");
myFile.flush();
myFile.close();
HM10.println("SD");
}
else {
Serial.println("4");
}
}