PID Control (OLED Display - HDMI Output)
PID Control (OLED Display - HDMI Output)
1
Code 1: Arduino Uno
2
PID myPID(&input, &output, &setPoint, Kp, Ki, Kd, DIRECT);
void setup() {
// Define pin for relay pinMode(13, OUTPUT);
// Initialize LCD lcd.init(); lcd.backlight();
// Initialize OLED screen
if (!display.begin(SSD1306_I2C_ADDRESS, OLED_RESET)) {
lcd.print(“OLED init failed”);
for (;;);
}
display.display();
delay(2000);
display.clearDisplay();
// Start PID myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(0, 255);
// Set a range of 0-255 as an example }
void loop() {
// Read PID constants from pots
Kp = analogRead(A1) / 1023.0 * 10;
// Scale to get a value between 0-10
Ki = analogRead(A2) / 1023.0 * 10; // Scale to get a value between 0-10
Kd = analogRead(A3) / 1023.0 * 10; // Scale to get a value between 0-10
myPID.SetTunings(Kp, Ki, Kd);
// Sensor reading (in this case a potentiometer)
input = analogRead(A0);
// PID calculation
myPID.Compute();
// Relay control
if (output > 127) {
digitalWrite(13, HIGH);
} else {
digitalWrite(13, LOW);
}
// Print values to LCD screen lcd.setCursor(0, 0);
lcd.print("Input: ");
lcd.print(input); lcd.setCursor(0, 1);
3
lcd.print("Output: ");
lcd.print(output);
// Print PID values to OLED screen
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Kp: ");
display.println(Kp);
display.print("Ki: ");
display.println(Ki);
display.print("Kd: ");
display.println(Kd);
display.display();
delay(100); // Wait a bit and continue the loop.
}
• The system successfully displays the dynamic changes in the PID control as the
potentiometers are adjusted.
• The relay, acting as a simulated actuator, responds to the PID output, indicating the
controller’s decisions.
• Both the LCD and OLED screens provide a real-time visualization of the system’s
performance, with the LCD showing the input-output relationship and the OLED
presenting the PID parameters.
4
Explanation of the Code
1. Library Imports:
• <Wire.h>: This library is used for I2C communication, which is required for devices
like the LCD and OLED screens.
• <LiquidCrystal_I2C.h>: Library for controlling I2C-based Liquid Crystal Displays
(LCDs).
• <Adafruit_SSD1306.h> and <Adafruit_GFX.h>: Libraries for controlling the
SSD1306-based OLED display.
• <PID_v1.h>: This is the library used for implementing the PID control logic.
2. Constant and Variable Definitions:
• SCREEN_WIDTH and SCREEN_HEIGHT: Define the dimensions of the OLED
display.
• LiquidCrystal_I2C lcd(0x27, 16, 2);: Initialize the LCD with I2C address 0x27 and
specify that it has 16 columns and 2 rows.
• Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);:
Initialize the OLED display with the given width and height, and specify the I2C
communication method.
• PID related variables:
o input, output: Variables to store the input reading and the output of the PID.
o Kp, Ki, Kd: PID constants.
o PID myPID(&input, &output, &setPoint, Kp, Ki, Kd, DIRECT);: Initialize
the PID controller.
3. Setup Function (setup()):
• Pin Definitions:
o pinMode(13, OUTPUT);: Define pin 13 as an OUTPUT (intended for relay
control).
• LCD Initialization:
o lcd.init();: Initialize the LCD.
o lcd.backlight();: Turn on the backlight of the LCD.
• OLED Initialization:
o if (!display.begin(SSD1306_I2C_ADDRESS, OLED_RESET)) {...}:
Attempt to initialize the OLED, and if unsuccessful, display an error message
on the LCD and halt the program.
o display.display(); and display.clearDisplay();: Show the OLED’s initial state
and then clear it.
o
5
• PID Configuration:
6
Discussion Questions about the Experiment:
1. What is the effect on the system when you increase the Kp value?
2. Slowly increase the Ki value from zero. What changes do you observe in the system?
3. What are the effects of increasing or decreasing the Kd value?
4. Which PID value affects the system’s response time the most?
5. What are the advantages and disadvantages of PID control?
6. How would you explain the principles of PID control in your own words?
7. If you redo the experiment with Kp, Ki, and Kd values all set to zero, how does the
system respond? How would you explain this?
8. If you change the system’s setPoint value, how would you explain its impact on the
PID parameters and consequently on the system’s response?
9. If you use an LED instead of a relay, what differences might you observe in the
experiment results and what could be the reasons for these differences?
10. Which PID parameter most affects how quickly the system reaches the desired value?
How is this effect observed?
11. Which PID parameter most affects the oscillations (swings) in the system’s process of
reaching the desired value? How is this effect observed?
12. If a delay is introduced in the system, what would be the effect on the PID control and
the system’s response?
13. What differences do you think might exist between the PID control in this experiment
and PID control in real-world industrial applications?
14. If you set the Ki parameter to a very high value, what kind of behavior might you
observe, and why?
15. Despite the advantages of a PID controller, in what situations might other control
methods be more appropriate?
16. How would you explain the changes in the system’s response caused by increasing the
Kd parameter and the reasons for these changes?
17. What do you think is the importance of PID control for future technological
applications? Please explain with examples.
18. How might the sensitivity or quality of the potentiometers used in this experiment
affect the results?
19. If you increase the noise in the system, how would the performance of the PID control
be affected? How might you reduce this effect?
20. What methods or techniques do you think can be used to optimize PID control?
7
Conceptual Questions about the Experiment:
1. What is the processor architecture of Raspberry Pi? o A) x86 o B) ARM o C) MIPS o
D) SPARC
2. Which component do you need to directly read an analog signal on the Raspberry Pi?
o A) DAC o B) EEPROM o C) ADC o D) Comparator
3. Which Python library is used to control GPIO pins on Raspberry Pi? o A) RPi.GPIO o
B) PiGpio o C) GPIOZero o D) All of the above
4. What does the “P” letter in PID control stand for? o A) Proportional o B) Periodic o C)
Polar o D) Phase
5. In PID control, which component represents the sum of continuous errors? o A)
Proportional o B) Integral o C) Derivative o D) None of the above
6. What is the tkinter library used for? o A) Web development o B) Database
management o C) Creating a Graphic User Interface (GUI) o D) Game development
7. What change does the “D” letter in PID control monitor? o A) Error o B) Total error o
C) Change in error over time o D) Change in setpoint
8. Which option correctly states the voltage that the Raspberry Pi 4’s GPIO pins operate
on? o A) 5V o B) 3.3V o C) 12V o D) 9V
9. For which type of systems is PID control used? o A) Open-loop systems o B) Closed-
loop systems o C) Only mechanical systems o D) Only digital systems
10. Which command runs a script in Python 3 on the Raspberry Pi?
• A) python script.py
• B) py3 script.py
• C) run script.py
• D) python3 script.py
11. For which problem is the “I” letter in PID control added to cope?
• A) System’s late response
• B) System’s fast response
• C) Persistent errors
• D) Temporary errors
12. What is the name of the Linux distribution run on the Raspberry Pi?
• A) Ubuntu
• B) Fedora
• C) Raspbian
• D) CentOS
13. In PID control, which component reduces sudden changes in the system?
8
• A) Proportional
• B) Integral
• C) Derivative
• D) Setpoint
14. What type of USB does the Raspberry Pi have?
• A) USB Type-A
• B) USB Type-B
• C) USB Type-C
• D) USB Mini
15. Which file extension is used when running Python code on Raspberry Pi?
• A) .cpp
• B) .java
• C) .js
• D) .py Answer Key: 1-B, 2-C, 3-D, 4-A, 5-B, 6-C, 7-C, 8-B, 9-B, 10-D, 11-C, 12-C,
13-C, 14-C, 15-D.
9
Code 2: ESP32 C++
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <PID_v1.h>
#define SCREEN_HEIGHT 64
// PID Variables
void setup() {
pinMode(13, OUTPUT);
lcd.init();
lcd.backlight();
if (!display.begin(SSD1306_I2C_ADDRESS, OLED_RESET)) {
10
while (true);
display.display();
delay(2000);
display.clearDisplay();
myPID.SetMode(AUTOMATIC);
void loop() {
input = analogRead(35);
myPID.Compute();
digitalWrite(13, HIGH);
} else {
digitalWrite(13, LOW);
lcd.setCursor(0, 0);
11
lcd.print("Input: ");
lcd.print(input);
lcd.setCursor(0, 1);
lcd.print("Output: ");
lcd.print(output);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Kp: ");
display.println(Kp);
display.print("Ki: ");
display.println(Ki);
display.print("Kd: ");
display.println(Kd);
display.display();
delay(100);
12
Code 3: ESP32 MicroPython
import time
import ssd1306
# I2C setup
# OLED setup
sensor = ADC(Pin(35))
Kp_pot = ADC(Pin(32))
Ki_pot = ADC(Pin(33))
Kd_pot = ADC(Pin(34))
# Relay setup
class PID:
self.kp = kp
self.ki = ki
self.kd = kd
self.set_point = set_point
self.prev_error = 0
self.integral = 0
13
error = self.set_point - current_value
self.integral += error
self.prev_error = error
return output
set_point = 100
while True:
Kp = Kp_pot.read() / 4095.0 * 10
Ki = Ki_pot.read() / 4095.0 * 10
Kd = Kd_pot.read() / 4095.0 * 10
input_val = sensor.read()
pid.kp = Kp
pid.ki = Ki
pid.kd = Kd
output = pid.compute(input_val)
relay.on()
else:
relay.off()
oled.fill(0)
14
oled.text("Output: " + str(output), 0, 40)
oled.show()
time.sleep(0.1)
15
Code 4: Raspberry Pi 4 Python (OLED)
import time
import smbus
# LCD setup
# oled = YourOledLibraryHere
import spidev
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1350000
def readadc(adcnum):
return -1
return adcout
# Relay setup
relay_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(relay_pin, GPIO.OUT)
class PID:
self.kp = kp
16
self.ki = ki
self.kd = kd
self.set_point = set_point
self.prev_error = 0
self.integral = 0
self.integral += error
self.prev_error = error
return output
set_point = 100
while True:
Kp = readadc(0) / 1023.0 * 10
Ki = readadc(1) / 1023.0 * 10
Kd = readadc(2) / 1023.0 * 10
input_val = readadc(3)
pid.kp = Kp
pid.ki = Ki
pid.kd = Kd
output = pid.compute(input_val)
GPIO.output(relay_pin, GPIO.HIGH)
else:
GPIO.output(relay_pin, GPIO.LOW)
17
# Display values on LCD
lcd.clear()
time.sleep(0.1)
GPIO.cleanup()
18
Code 5: Raspberry Pi 4 Python (HDMI- Tkinter)
import time
import smbus
import RPi.GPIO as GPIO
from RPLCD.i2c import CharLCD
import tkinter as tk
# LCD setup
lcd = CharLCD('PCF8574', 0x27)
def readadc(adcnum):
if adcnum > 7 or adcnum < 0:
return -1
r = spi.xfer2([1, 8 + adcnum << 4, 0])
adcout = ((r[1] & 3) << 8) + r[2]
return adcout
# Relay setup
relay_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(relay_pin, GPIO.OUT)
set_point = 100
pid = PID(0, 0, 0, set_point)
frame = tk.Frame(root)
frame.pack(pady=20, padx=20)
19
lbl_kp.grid(row=0, column=0)
lbl_ki = tk.Label(frame, text="Ki: ")
lbl_ki.grid(row=1, column=0)
lbl_kd = tk.Label(frame, text="Kd: ")
lbl_kd.grid(row=2, column=0)
def update_gui():
# Read potentiometer values
Kp = readadc(0) / 1023.0 * 10
Ki = readadc(1) / 1023.0 * 10
Kd = readadc(2) / 1023.0 * 10
input_val = readadc(3)
pid.kp = Kp
pid.ki = Ki
pid.kd = Kd
output = pid.compute(input_val)
# Update GUI
lbl_kp.config(text=f"Kp: {Kp:.2f}")
lbl_ki.config(text=f"Ki: {Ki:.2f}")
lbl_kd.config(text=f"Kd: {Kd:.2f}")
lbl_input.config(text=f"Input: {input_val}")
lbl_output.config(text=f"Output: {output:.2f}")
# Update LCD
lcd.clear()
lcd.write_string(f"Input: {input_val}\nOutput: {output:.2f}")
20