I want to make a circuit that control speed of DC fan Using Arduino PID Library to get thing at specific temperature. enter image description here
The circuit looks like this but can be changed, The dc fan motor connected to PWM 3 and thermistor connected with pin A0.
The thermistor check the temperature of a device that heated by nearby heater so fan cools the device to get the specific temperature.
Case 1
When Heater not running, the thermistor value in Serial monitor 0-1023, When fan not running it gives 1023 and when fan runs at full speed it gives about 0.
Case 2
But when heater is running the values of thermistor has been changed and when fan not running it gives 1023 and when fan runs at full speed it gives about 500.
I want to set a point 650 from thermistor value(INPUT Value), and fan speed have to adjust using pid so temperature adjusted and the thermistor gives 650 value.
Sample PID code
#include <PID_v1.h>
//Define Variables we'll be connecting to double Setpoint, Input, Output;
//Define the aggressive and conservative Tuning Parameters
double aggKp=4, aggKi=0.2, aggKd=1;
double consKp=1, consKi=0.05, consKd=0.25;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
void setup()
{
Serial.begin(115200);
//initialize the variables we're linked to
Input = map(analogRead(0), 0, 1023, 255, 0);
Setpoint = 650;
myPID.SetOutputLimits(0, 255);
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
void loop()
{
int sensorValue = analogRead(0);
Input = map(analogRead(0), 0, 1023, 255, 0);
double gap = abs(Setpoint-Input); //distance away from setpoint
if(gap<10)
{ //we're close to setpoint, use conservative tuning parameters
myPID.SetTunings(consKp, consKi, consKd);
}
else
{
//we're far from setpoint, use aggressive tuning parameters
myPID.SetTunings(aggKp, aggKi, aggKd);
}
myPID.Compute();
analogWrite(3,Output);
Serial.println(sensorValue);
}
What changes have to done in code so we can set point from input values? And Please help me so this code works for me.
-
4You can't connect a motor directly to an output pin (unless it's a really small motor). You also need to a flyback diode to the motor. My guess is that the motor is generating a lot of "noise" on the power rail, leading to weird analogRead values.Gerben– Gerben2015年03月31日 17:38:15 +00:00Commented Mar 31, 2015 at 17:38
5 Answers 5
Two thing that may be helpful. First make sure you have a common ground. For instance for you transistor you are using separate power from the arduino and 12 volt source. Connecting the two ground of the arduino and the power supply may resolve this for you. The other thing is it is often times helpful to put a capacitor across the DC motor to help with voltage fluctuations.
-
1But the grounds are connected in the diagram...CharlieHanson– CharlieHanson2015年10月01日 12:33:17 +00:00Commented Oct 1, 2015 at 12:33
First try using external power source to power the motor, as only very small motors can be connected to an Arduino's power source.(Basically, the Motor is using most of the power, leaving too little power for the Arduino to operate properly)
If that fails, change the code(I will give sample code by tomorrow, if you cannot find one yourself)-maybe use a PWM signal instead of trying PID, as it is much simpler and give very little room for error.
And also, don't forget the fly back diode mentioned by Gerben.
-
you do not read full question , i know the output of dc motor is always a PWM Signal for speed Controlling. i want to use PID Library to detect error between Set Point and current temperature value and change speed of motor according to that value.ANKIT JAIN– ANKIT JAIN2015年04月13日 12:12:31 +00:00Commented Apr 13, 2015 at 12:12
-
I knew that you obviously knew that output to a DC motor is always a PWM signal, I meant to tell you to leave the PID library and write your own code so that it acts like PID.Mathsman 100– Mathsman 1002015年04月13日 15:20:54 +00:00Commented Apr 13, 2015 at 15:20
-
I have tried that and it works easily enough.Mathsman 100– Mathsman 1002015年04月13日 15:22:26 +00:00Commented Apr 13, 2015 at 15:22
-
There are some issues with your map command.
For example, you are reading the thermistor value using analogRead(A0)
, which has a return range from 0 to 1023. After that you attempt to use map()
to change this value to 0 - 255 but use the wrong syntax. The correct syntax for this command is Input = map(analogRead(0), 0, 1023, 0, 255);
. However, I can't see the reason for that because you are reading values 0-1023, change it to 0-255, but set point is 650. So you never get setpoint because maximum is 255.
Try use as input just analogread(0)
. There is no reason to change input into PWM range and output is for PID library in PWM range as a default so you can send output direct to motor pin. Of course use some H-bridge or something like that.
//Now it will work
// https://arduino.stackexchange.com/questions/9731/control-speed-of-dc-fan-using-arduino-pid-library
#include <PID_v1.h>
double Setpoint, Input, Output; //not there in original sketch
//Define Variables we'll be connecting to double Setpoint, Input, Output;
//Define the aggressive and conservative Tuning Parameters
double aggKp = 4, aggKi = 0.2, aggKd = 1;
double consKp = 1, consKi = 0.05, consKd = 0.25;
//double consKp=2, consKi=5, consKd=1;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, REVERSE);
void setup()
{
Serial.begin(9600);
//initialize the variables we're linked to
// Input = map(analogRead(0), 0, 1023, 255, 0);
//int val = analogRead(0);
//val = map(val, 0, 1023, 0, 255);
// analogWrite(9, val);
Setpoint = 100;
myPID.SetOutputLimits(0, 255); //MIN,MAX
//turn the PID on
myPID.SetMode(AUTOMATIC); // MANUAL
myPID.SetControllerDirection(REVERSE); // DIRECT
}
void loop()
{
int sensorValue = analogRead(0);
Input = map(sensorValue, 0, 1023, 0, 255);
double gap = abs(Setpoint - Input); //distance away from setpoint
if (gap < 10)
{ //we're close to setpoint, use conservative tuning parameters
myPID.SetTunings(consKp, consKi, consKd);
}
else
{
//we're far from setpoint, use aggressive tuning parameters
myPID.SetTunings(aggKp, aggKi, aggKd);
}
myPID.Compute();
analogWrite(3, Output);
Serial.print(" PWM = ");
Serial.print(Output,0);
Serial.print(" sensor value = ");
Serial.print(sensorValue);
Serial.print(" Input =");
Serial.println(Input,0);
}
It may be better to not use map()
, as it will give trouble between float
and int
variable usage - do it manually in the code.
-
This is both a comment rather than an answer, and also erroneous. Arduino's map() in an integer function. It is perfectly legitimate to initialize a floating point variable with an integer value.Chris Stratton– Chris Stratton2018年01月22日 02:04:37 +00:00Commented Jan 22, 2018 at 2:04
Explore related questions
See similar questions with these tags.