A proportional–integral–derivative controller (PID controller or
three-term controller) is a control loop mechanism employing feedback
that is widely used in industrial control systems and a variety of
other applications requiring continuously modulated control. A PID
controller continuously calculates an error value e(t) as the
difference between a desired setpoint (SP) and a measured process
variable (PV) and applies a correction based on proportional, integral,
and derivative terms (denoted P, I, and D respectively), hence the name.
simplest PID control setup - the photocell and the LED.
Connect the Arduino board, the photocell, the LED, and the resistors as
shown in the following schematic:
The photocell shows very
large resistance in dark. The stronger the liglht it receives, the
lower the internal resistance it has. By sensing the voltage at the
bottom pin of the photocell in the schematic above, the voltage at A0
increases as the light gets more intense and vice versa.
Test the ambient light
intensity. Keep in mind that the circuit setup doesn't have an 'Ambient
Liglht Dimmer'. You cannot make your ambient light intensity weaker
than what you have (it is from the sun!). At a different time point (it
receives different amount of light during different time of the day)
are testing your circuit, you must test the ambient light first before
you move forward.
If the ambient ligh intensity is very strong and easily saturates your
photocell, you may use a box to cover your photocell to block some of the light.
In the following example, I did this experiment at noon, it was very
bright in the room, the ambient light intensity received by the
photocell is 677 (0-1023).
In my PID controller, the
setpoint must be larger than this value because I can not make it
dimmer, the only thing the external LED can do is add more light.
Now, I will turn on the LED to the brightest level and see what is the
maximum value being receied by the photocell:
Is this correct?
Remember the Arduino board is
running at 16M Hz, from 'digitalWrite(3,255)' to 'int
ambientLight=analogRead(A0)' may only take several microseconds. Before
the LED is being turned on to the full brightness, the 'ananlogRead'
function has been executed and the light intensity being read to the
CPU is smaller than the real value.
So, we need a time delay
after the 'digitalWrite()' function:
After the delay function is
added, the intensity is a lot higher than the previous one, and it
refelects the real light being received by the photocell.
Now I know my current ambient
light intensity is 677 and the brightest light my LED can provide plus
the ambient light is 924. I'll set the SP (set point) to the middle of
these two values: 800.
Now let's look at the the
following code to implement the PID controller.
(Note that I did not use the
Ki*I so I've to integrate the PID_value to make it work, which is
PID_value=PID_value+Kp*p+Ki*I+Kd*D. If you have a non-zero Ki value,
you can directlly use PID_value=Kp*P+Ki*I+Kd*D)
The set point is 400 but the
ambient light is already way above the setpoint. The system will never
be able to reach the set point!
Task 1: Fix
the code above to make the sensed light oscillate around the setpoint (use an appropriate setpoint).
Complete the blocked line for the 'PID_value'.
3. Add an
extra LED to change the
We can add an extra LED light
beside the photocell to see the respose
of the PID controller:
Connect the following
circuit. Use a pushbutton to turn on/off the LED.
Now, change Kp to 0.001. Run
the program, turn on/off the LED and
observe what the real-time plot looks like:
At 0:03, I turned on the
extra LED (hold the push buton) so the signal
being received the photocell is more than the SP. The PID controller
generates a negative error to reduce the light from the original LED to
bring the intensity back to the set point. At 0:20, I release the push
button to turn off the extra LED. The PID controller must send more
power to the original LED to bring the light intensity back to the set
Aparently the 'P' gain is too
low. I changed it to 'Kp=0.1', it looks
like this: At 0:03, I pressed the
pushbutton to turn on the LED and held it. At 0:06, I released the
pushbutton to turn off the LED.
Task 2: Repeat the work in this section.
Save the data in a local drive and plot your data use Python and
present your data in your report. Show clear X/Y axis, labels, and
titles. Record and plot data using
Python can be found in this link: http://yilectronics.com/Courses/CE232/Spring2019/lectures.html Refer to the lectures on
Aprial 12th for how to save your data to your local drive. Refer to the
lectures on March 1st and March 11th for plotting/presenting your data
4. Setpoint tracking
The set point can be a
variable and your system must be adjusted to follow the set point in
Add an extra pushbutton to
your system, every time you push the button to trigger activate a new setpoint, the board will detect a
signal and the PID system will adjust the setpoint to a new value.
A function 'setPointChange()'
was added to the script. I was trying to add 10 to the LED intensity
every time I push the button. However, this code won't make it.
** Correction: I=+error should be I+=error
Keep in mind that the CPU
runs at 16M Hz, the mechanical pushbutton won't give you a clear step
function but a lot of bounces. Also, how can you make your code only
detect one 'push' when you push it? You finger definitely cannot push
it at the similar rate (16M Hz), which means when you push it even
though you think you did it fast, the loop() function has been executed
for thousands of times.
3: Fix the setPointChange()
function to enable the desired PID function as follows. Plot both the
SP and the sensor data in a same figure using Python. Present your
result in your report.
Complete Task 1 - Task 3, upload your report to the website.