-
Notifications
You must be signed in to change notification settings - Fork 0
/
08-IoT_PID_Monitor.ino
300 lines (248 loc) · 7.34 KB
/
08-IoT_PID_Monitor.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/***********************************************
* Program : Pemantauan Suhu dengan PID via IoT
* Menggunakan Kit iTCLab
* Oleh : Tim io-t.net
* Surabaya, 20 April 2022
***********************************************/
#include <WiFi.h>
#include <PubSubClient.h>
#include <Arduino.h>
const char* ssid = "wifi"; // Enter your WiFi name
const char* password = "Password_wifi"; // Enter WiFi password
#define mqttServer "broker.hivemq.com"
#define mqttPort 1883
WiFiServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);
String Topic;
String Payload;
// constants
const int baud = 115200; // serial baud rate
// pin numbers corresponding to signals on the iTCLab Shield
const int pinT1 = 34; // T1
const int pinT2 = 35; // T2
const int pinQ1 = 32; // Q1
const int pinQ2 = 33; // Q2
const int pinLED = 26; // LED
// setting PWM properties
const int freq = 5000; //5000
const int ledChannel = 0;
const int Q1Channel = 1;
const int Q2Channel = 2;
const int resolutionLedChannel = 8; //Resolution 8, 10, 12, 15
const int resolutionQ1Channel = 8; //Resolution 8, 10, 12, 15
const int resolutionQ2Channel = 8; //Resolution 8, 10, 12, 15
float cel, cel1, degC, degC1;
float P, I, D, Kc, tauI, tauD;
float KP, KI, KD, op0, ophi, oplo, error, dpv;
float sp = 35, //set point
pv = 0, //current temperature
pv_last = 0, //prior temperature
ierr = 0, //integral error
dt = 0, //time between measurements
op = 0; //PID controller output
unsigned long ts = 0, new_ts = 0; //timestamp
const float batas_suhu_atas = 58;
// global variables
float Q1 = 0; // value written to Q1 pin
float Q2 = 0; // value written to Q2 pin
int iwrite_value = 25; // integer value for writing
int iwrite_led = 255; // integer value for writing
int iwrite_min = 0; // integer value for writing
void setup() {
// put your setup code here, to run once:
ts = millis();
Serial.begin(baud);
while (!Serial) {
; // wait for serial port to connect.
}
// configure pinQ1 PWM functionalitites
ledcSetup(Q1Channel, freq, resolutionQ1Channel);
// attach the channel to the pinQ1 to be controlled
ledcAttachPin(pinQ1, Q1Channel);
// configure pinQ2 PWM functionalitites
ledcSetup(Q2Channel, freq, resolutionQ2Channel);
// attach the channel to the pinQ2 to be controlled
ledcAttachPin(pinQ2, Q2Channel);
// configure pinLED PWM functionalitites
ledcSetup(ledChannel, freq, resolutionLedChannel);
// attach the channel to the pinLED to be controlled
ledcAttachPin(pinLED, ledChannel);
ledcWrite(Q1Channel,0);
ledcWrite(Q2Channel,0);
ledcWrite(ledChannel,0);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Connect to Server IoT (CloudMQTT)
client.setServer(mqttServer, mqttPort);
client.setCallback(receivedCallback);
while (!client.connected()) {
Serial.println("Connecting to MQTT Broker ...");
// if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
if (client.connect("iTCLab Suhu dengan Kendali PID...")) {
Serial.println("connected");
Serial.print("Message received: ");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
//client.subscribe("heater1");
//client.subscribe("heater2");
}
}
void Q1on(){
ledcWrite(Q1Channel,iwrite_value);
//Serial.println(Q1);
}
void Q1off(){
ledcWrite(Q1Channel,iwrite_min);
//Serial.println(Q1);
}
void Q2on(){
ledcWrite(Q2Channel,iwrite_value);
//Serial.println(Q2);
}
void Q2off(){
ledcWrite(Q2Channel,iwrite_min);
//Serial.println(Q2);
}
void ledon(){
ledcWrite(ledChannel,iwrite_led);
}
void ledoff(){
ledcWrite(ledChannel,iwrite_min);
}
void cektemp(){
degC = analogRead(pinT1) * 0.322265625 ; // use for 3.3v AREF
cel = degC/10;
degC1 = analogRead(pinT2) * 0.322265625 ; // use for 3.3v AREF
cel1 = degC1/10;
Serial.print("Temperature T1: ");
Serial.print(cel); // print the temperature T1 in Celsius
Serial.print("°C");
Serial.print(" ~ "); // separator between Celsius and Fahrenheit
Serial.print("Temperature T2: ");
Serial.print(cel1); // print the temperature T2 in Celsius
Serial.println("°C");
}
// PID Controller
// inputs -----------------------------------
// sp = setpoint
// pv = current temperature
// pv_last = prior temperature
// ierr = integral error
// dt = time increment between measurements
// outputs ----------------------------------
// op = output of the PID controller
// P = proportional contribution
// I = integral contribution
// D = derivative contribution
float pid(float sp, float pv, float pv_last, float& ierr, float dt) {
float Kc = 10.0; // K / %Heater
float tauI = 50.0; // sec
float tauD = 1.0; // sec
// PID coefficients
float KP = Kc;
float KI = Kc / tauI;
float KD = Kc*tauD;
// upper and lower bounds on heater level
float ophi = 100;
float oplo = 0;
// calculate the error
float error = sp - pv;
// calculate the integral error
ierr = ierr + KI * error * dt;
// calculate the measurement derivative
float dpv = (pv - pv_last) / dt;
// calculate the PID output
float P = KP * error; //proportional contribution
float I = ierr; //integral contribution
float D = -KD * dpv; //derivative contribution
float op = P + I + D;
// implement anti-reset windup
if ((op < oplo) || (op > ophi)) {
I = I - KI * error * dt;
// clip output
op = max(oplo, min(ophi, op));
}
ierr = I;
Serial.println("sp="+String(sp) + " pv=" + String(pv) + " dt=" + String(dt) + " op=" + String(op) + " P=" + String(P) + " I=" + String(I) + " D=" + String(D));
return op;
}
void receivedCallback(char* topic, byte* payload, unsigned int length) {
/* we got '1' -> Q1_on */
if ((char)payload[0] == '1') {
Q1on();
Serial.println("Q1 On");
}
/* we got '2' -> Q1_off */
if ((char)payload[0] == '2') {
Q1off();
Serial.println("Q1 Off");
}
/* we got '3' -> Q2_on */
if ((char)payload[0] == '3') {
Q2on();
Serial.println("Q2 On");
}
/* we got '4' -> Q2_off */
if ((char)payload[0] == '4') {
Q2off();
Serial.println("Q2 Off");
}
}
void loop() {
// put your main code here, to run repeatedly:
new_ts = millis();
if (new_ts - ts > 1000) {
char suhu1[4];
char suhu2[4];
char SetPoint[4];
char Nilai_op[4];
client.loop();
cektemp();
if (cel > batas_suhu_atas){
Q1off();
ledon();
}
else {
Q1on();
ledoff();
}
if (cel1 > batas_suhu_atas){
Q2off();
ledon();
}
else {
Q2on();
ledoff();
}
pv = cel; // Temperature T1
dt = (new_ts - ts) / 1000.0;
ts = new_ts;
op = pid(sp,pv,pv_last,ierr,dt);
ledcWrite(Q1Channel,op);
pv_last = pv;
dtostrf(cel, 1, 0, suhu1);
client.publish("Suhu1",suhu1);
dtostrf(sp, 1, 0, SetPoint);
client.publish("SetPoint",SetPoint);
dtostrf(op, 1, 0, Nilai_op);
client.publish("Nilai_op",Nilai_op);
delay (200);
dtostrf(cel1, 1, 0, suhu2);
client.publish("Suhu2",suhu2);
delay (200);
}
}