-
Notifications
You must be signed in to change notification settings - Fork 0
/
chromatography.py
490 lines (389 loc) · 16 KB
/
chromatography.py
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
# This is a sample code that demonstrates wireless communication.
# You are expected to use this code and modify it to suit your project needs.
# ------------------------------------------------------------------------
# In this project, a red LED is connected to GP14.
# The red LED is controlled based on the value of a light sensor's output.
# The light sensor output is connected to GP26 (ADC pin).
# The red LED status and the value of the red LED pin (GP14) are communicated wirelessly to a server.
# The status and value are displayed on the webpage. In addition, the user interface has
# a circle indicating the LED turns color depending upon the status of the physical LED.
# ------------------------------------------------------------------------
# -----------------------------------------------------------------------
# The following list of libraries are required. Do not remove any.
import machine
import network
import usocket as socket
import utime as time
import _thread
import json
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# The below portion of the code is to be tweaked based on your needs.
light_intensity="" # this is the variable that holds the value of the colour of the light read. Its is the virtual LED
# Configure GP14 as output and define it as redLED_pin
data_collection_led = machine.Pin(12, machine.Pin.OUT) # This LED is used to illuminate the TLC plate for data collection.
actuator_leds = [machine.Pin(i, machine.Pin.OUT) for i in (13, 15, 14)] # These LEDs simulate various actuator states or stages in the experiment.
ir_emitter = machine.Pin(11, machine.Pin.OUT) # The IR emitter sends an IR beam that the IR sensor can detect.
thermistor = machine.ADC(26)# Thermistors measure temperature based on resistance changes.
light_sensor=machine.ADC(28)# Light sensors measure light intensity.
ir_sensor = machine.ADC(27) # The IR sensor detects the IR beam from the IR emitter, used to determine paper position.
# provides the status of the ouptut. Determines the colour of the buttons online
def get_output_status():
if actuator_leds[0].value()==1:
if actuator_leds[1].value()==1:
if data_collection_led.value()==1:
if actuator_leds[2].value()==1:
return light_intensity
return "Scanning"
return "Spraying"
return "Saturating"
# this code will be sent to the JSON function. Its used for signalling completion
def colour_error():
if actuator_leds[2].value()==1:
return "on"
# new thermistor detection code which will detect a fluctuation in temperature.
def interpret_thermistor():
temp_thermistor_value = thermistor.read_u16()
time.sleep(1)
if ((temp_thermistor_value - thermistor.read_u16()) > 500) or ((temp_thermistor_value - thermistor.read_u16()) < -500):
return True
else:
return False
def read_light_intensity():
"""Read the raw analog value from the light sensor, which is proportional to the light intensity, then decide which colour it matches up with."""
while light_sensor.read_u16() > 40000 or light_sensor.read_u16() < 10000:
time.sleep(0.2)
if (light_sensor.read_u16() >10000 and light_sensor.read_u16() <24600):
return "blue"
elif(light_sensor.read_u16() > 24600 and light_sensor.read_u16() <30800):
return "red-pink"
elif(light_sensor.read_u16() > 34350 and light_sensor.read_u16() <40000):
return "pink"
elif(light_sensor.read_u16() > 30800 and light_sensor.read_u16() <33100):
return "yellow"
elif(light_sensor.read_u16() > 33100 and light_sensor.read_u16() <34350):
return "white"
else:
return "void"
def toggle_data_collection_led(state):
"""Set the state of the data collection LED: 1 for on, 0 for off."""
data_collection_led.value(state)
def activate_actuator_led(led_number, state):
"""Activate or deactivate a specific actuator LED based on its number and the desired state. """
if 0 <= led_number < len(actuator_leds):
actuator_leds[led_number].value(state)
# turns off the leds
def reset_leds():
activate_actuator_led(0,0)
activate_actuator_led(1,0)
activate_actuator_led(2,0)
def check_paper_position():
# Ensure the IR emitter is on to send a beam to the IR sensor.
ir_emitter.value(1)
# Check if the IR sensor detects the beam. If not, the beam is interrupted (like by the paper), indicating the desired position.
return ir_sensor.read_u16()
def experiment_sequence():
reset_leds()
# Check for the correct paper position using the IR sensor and emitter.
print("Checking paper position...")
while check_paper_position()<5000:
time.sleep(0) # Wait for the paper to reach the correct position.
print("Paper in position.")
# Activate an actuator LED to simulate reaching a stage in the experiment.
activate_actuator_led(0, 1)
# Monitor the temperature with the thermistor until it indicates the saturation solution has reached the desired height.
print("Monitoring temperature...")
while interpret_thermistor() is False:
time.sleep(0)
print("Desired temperature reached.")
# Activate an actuator LED to simulate reaching a stage in the experiment.
activate_actuator_led(1, 1) # Example: Turn on the first actuator LED.
time.sleep(3)
# Illuminate the TLC plate with the data collection LED and read the light intensity from the light sensor.
toggle_data_collection_led(1) # Turn on the data collection LED. Which is the actuator for starting the scanning process.
print("Collecting data")
global light_intensity
light_intensity= read_light_intensity()
print("Light intensity/colour: ", light_intensity)
time.sleep(1)
# toggle_data_collection_led(0) # Turn off the data collection LED after reading the light intensity.
# Activate an actuator LED to indicate completion of experiment
activate_actuator_led(2, 1)
# Signal the completion of the experiment.
print("Experiment complete.")
time.sleep(10)
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
# Below given code should not be modified (except for the name of ssid and password).
# Create a network connection
ssid = 'Chemists' #Set access point name
password = '12345678' #Set your access point password
ap = network.WLAN(network.AP_IF)
ap.config(essid=ssid, password=password)
ap.active(True) #activating
while ap.active() == False:
pass
print('Connection is successful')
print(ap.ifconfig())
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Below given code defines the web page response. Your html code must be used in this section.
#
# Define HTTP response
def web_page():
# Modify the html portion appropriately.
# Style section below can be changed.
# In the Script section some changes would be needed (mostly updating variable names and adding lines for extra elements).
html = """
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Chemists</title>
<!--The following css code is to alter the look and colour of the website to make it more professional and colour code the outputs -->
<style>
:root {
--primary-color: #007bff;
--hover-color: #0056b3;
--error-color: #ff4136;
--error-hover-color: #c2302a;
--background-color: #f4f4f4;
--text-color: #333;
--button-font-weight: bold;
--button-text-transform: uppercase;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: var(--background-color);
color: var(--text-color);
}
.header {
display: flex;
justify-content: center;
text-align: center;
align-items: center;
padding: 20px;
background-color: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.group-members, .results {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
justify-items: center;
align-items: center;
width: 90%;
max-width: 600px;
margin: 20px auto;
padding: 10px;
background-color: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
border-radius: 8px;
}
.process-indicator {
display: grid;
grid-template-columns: repeat(4, auto);
gap: 15px;
justify-items: center;
padding: 20px;
}
.process-unit {
display: flex;
flex-direction: column;
align-items: center;
}
.process-circle {
width: 30px;
height: 30px;
border: 2px solid var(--primary-color);
border-radius: 50%;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
transition: transform 0.3s ease;
}
.process-circle:hover {
transform: scale(1.1);
}
.process-text {
margin-top: 8px;
color: var(--primary-color);
font-size: 0.8em;
text-align: center;
}
.button, .emergency-stop {
padding: 15px 30px;
border: none;
border-radius: 5px;
cursor: pointer;
font-weight: var(--button-font-weight);
text-transform: var(--button-text-transform);
transition: background-color 0.3s ease;
display: block;
margin: 10px auto;
}
.button {
background-color: var(--primary-color);
color: white;
}
.button:hover {
background-color: var(--hover-color);
}
.emergency-stop {
background-color: var(--error-color);
color: white;
}
.emergency-stop:hover {
background-color: var(--error-hover-color);
}
.results {
grid-template-columns: 1fr;
text-align: center;
}
</style>
</head>
<body>
<div class="header">
<h1 style="font-size: 1.2em; padding: 10px;"> Automated Visual Chrmatography
</h1>
</div>
<div class="group-members"> <!--This is a div class to add our names to the website-->
<div>Rohann</div>
<div>Rohan</div>
<div>Animish</div>
</div>
<div class="process-indicator"> <!--This HTML code is to display progress circles displaying our current stage of chromatography -->
<div class="process-unit">
<div class="process-circle" id="sat" style="background-color: yellow;"></div>
<span class="process-text" >Saturation</span>
</div>
<div class="process-unit">
<div class="process-circle" id="spray" ></div>
<span class="process-text">Spray</span>
</div>
<div class="process-unit">
<div class="process-circle" id="scan"></div>
<span class="process-text" >Scan</span>
</div>
<div class="process-unit">
<div class="process-circle" id="error" ></div>
<span class="process-text" >Completion</span>
</div>
</div>
<div class="button-container"> <!-- Here is the code for each of the buttons to start each step-->
<div class="start-button-container" style="display:flex; justify-content:center; ">
<button class="button" style="margin-left: 500px;" onclick="startSpray()">Start Spray</button>
<button class="button" style="margin-right: 500px;"onclick="startScan()">Start Scan</button></a>
</div>
<button class="emergency-stop" onclick="emergencyStop()"><a href="/?error">Emergency Stop</a></button>
</div>
<div class="results">
<p id="results-text">Results</p>
</div> <!--This is the code to display our results. It is linked to the micropython code to display the appropriate result-->
<script>
// continuously checks the code to update it. Takes in the json and is useful for communication.
function updateStatus() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var results = JSON.parse(xhr.responseText); // The values are parsed here
var results_element = document.getElementById("results-text");
results_element.innerHTML = results.output_status;
document.getElementById('error').style.backgroundColor=results.completion_status=="on"? "green":"yellow"; // Completion marked
}
};
xhr.open("GET", "/status", true); //used for starting functions later
xhr.send();
}
// This code will create dynamic changes to the website based on button clicks. This first function is the code for the button start spraying
function startSpray() {
var element = document.getElementById('sat');
element.style.backgroundColor = 'green';
var element = document.getElementById('spray');
element.style.backgroundColor = 'yellow';
var element = document.getElementById('scan');
element.style.backgroundColor = 'white';
}//Helper
function completion(){
var element = document.getElementById('scan');
element.style.backgroundColor = 'green';
} // Starts the second scan function. Contains timed elements.
function startScan() {
var element = document.getElementById('sat');
element.style.backgroundColor = 'green';
var element = document.getElementById('spray');
element.style.backgroundColor = 'green';
var element = document.getElementById('scan');
element.style.backgroundColor = 'yellow';
setTimeout(completion, 6000);
}
// This code will stop all processes and all the circles shall turn red. The code to end the process will be filled in later.
function emergencyStop() {
var element = document.getElementById('sat');
element.style.backgroundColor = 'red';
var element = document.getElementById('spray');
element.style.backgroundColor = 'red';
var element = document.getElementById('scan');
element.style.backgroundColor = 'red';
var element = document.getElementById('error');
element.style.backgroundColor = 'red';
}
setInterval(updateStatus, 1000); // Refresh every 1 second
</script>
</body>
</html>"""
return html
# --------------------------------------------------------------------
# This section could be tweaked to return status of multiple sensors or actuators.
# Define a function to get the status of the red LED.
# The function retuns status.
def get_status():
status = {
"output_status":get_output_status(),
"completion_status":colour_error()
# You will add lines of code if status of more sensors is needed.
}
return json.dumps(status)
# ------------------------------------------------------------------------
# -------------------------------------------------------------------------
# This portion of the code remains as it is.
# Start the ADC monitoring function in a separate thread
_thread.start_new_thread(experiment_sequence, ())
# Create a socket server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
# This section of the code will have minimum changes.
while True:
conn, addr = s.accept()
print('Got a connection from %s' % str(addr))
request = conn.recv(1024)
if request:
request = str(request)
print('Content = %s' % request)
LED_on = request.find('/?error') # this part of the code could be modified
# this part of the code could be modified
if LED_on == 6:
print('Emergency Stop')
reset_leds()
data_collection_led.value(0)
exit()
# this part of the code remains as it is.
if request.find("/status") == 6:
response = get_status()
conn.send("HTTP/1.1 200 OK\n")
conn.send("Content-Type: application/json\n")
conn.send("Connection: close\n\n")
conn.sendall(response)
else:
response = web_page()
conn.send("HTTP/1.1 200 OK\n")
conn.send("Content-Type: text/html\n")
conn.send("Connection: close\n\n")
conn.sendall(response)
conn.close()