-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLaserSafety.ino
405 lines (325 loc) · 11.6 KB
/
LaserSafety.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
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
// PIN LAYOUT
// +-----+
// +----[PWR]-------------------| USB |--+
// | +-----+ |
// | GND/RST2 [ ][ ] |
// | MOSI2/SCK2 [ ][ ] A5/SCL[ ] | C5
// | 5V/MISO2 [ ][ ] A4/SDA[ ] | C4
// | AREF[ ] |
// | GND[ ] |
// | [ ]N/C SCK/13[ ] | B5 OUT Laser Controller: p_safety
// | [ ]IOREF MISO/12[ ] | .
// | [ ]RST MOSI/11[ ]~| .
// | [ ]3V3 +---+ 10[ ]~| .
// | [ ]5v -| A |- 9[ ]~| .
// | [ ]GND -| R |- 8[ ] | B0
// | [ ]GND -| D |- |
// | [ ]Vin -| U |- 7[ ] | D7 I/O One Wire bus: p_onewire
// | -| I |- 6[ ]~| D6 IN Water leak sensor: p_waterleak3
// | [ ]A0 -| N |- 5[ ]~| D5 IN Water leak sensor: p_waterleak2
// | [ ]A1 -| O |- 4[ ] | D4 IN Water leak sensor: p_waterleak1
// | [ ]A2 +---+ INT1/3[ ]~| D3 IN Pressure Sensor: p_pressure
// | [ ]A3 INT0/2[ ] | D2 IN Flow sensor: p_flow_sensor
// | [ ]A4/SDA RST SCK MISO TX>1[ ] | D1
// | [ ]A5/SCL [ ] [ ] [ ] RX<0[ ] | D0
// | [ ] [ ] [ ] |
// | UNO_R3 GND MOSI 5V ____________/
// \_______________________/
// Source: http://busyducks.com/ascii-art-arduinos
// Set debug to 1 if you would like to receive msgs on the Serial bus.
#define DEBUG 0
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print (x)
#define DEBUG_PRINTLN(x) Serial.println (x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#endif
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <EEPROM.h>
#include <TimerOne.h>
#include <avr/wdt.h>
// Pins
#define p_flow_sensor 2
#define p_pressure 3
//#define p_waterleak1 4
//#define p_waterleak2 5
//#define p_waterleak3 6
#define p_onewire 7
#define p_safety 13 // The output pin to the laser controller
// Sensor states
bool s_waterflow_ok = false;
bool s_pressure_ok = false;
//bool s_waterleak1_ok = false;
//bool s_waterleak2_ok = false;
//bool s_waterleak3_ok = false;
bool s_temp1_ok = false;
bool s_temp2_ok = false;
bool safety_flag = false;
bool disable_laser = true;
// Temp stuff
float s_temp1;
float s_temp2;
float temp1_min = 8.0;
float temp1_max = 27;
float temp2_min = 8.0;
float temp2_max = 26;
bool temp1_fail_last_cycle = false;
bool temp2_fail_last_cycle = false;
// Dallas temp sensor adresses
DeviceAddress water_outlet = {0x28, 0x04, 0xDD, 0xAC, 0x04, 0x00, 0x00, 0x55};
DeviceAddress water_inlet = {0x28, 0xC3, 0x0D, 0xAE, 0x04, 0x00, 0x00, 0x16};
OneWire oneWire(p_onewire);
DallasTemperature temp_sensors(&oneWire);
unsigned int temp_requests_time = 1000;
unsigned long temp_last_update;
// Flow sensor
float volume;
float volume_min = 4;
float volume_max = 10;
volatile int NbTopsFan; //measuring the rising edges of the signal
// function prototypes to overwrite Arduino auto-prototyping
bool check_temperature(float &temp_reading, float threshold_min, float threshold_max, bool &temp_fail_last_cycle, DeviceAddress &SensorAddr);
// ################## setup functions #################
void dim_leds() {
for (int p=255 ; p >0; p--) // Dimmrichtung dunkler
{
Set_LED_ALL(p);
delay(1); // Warten
}
}
void Set_LED_ALL(int PWM)
{
Wire.begin(); // I2C-Start
Wire.beginTransmission(B1100000); // TLC59116 Slave Adresse ->C0 hex
Wire.write(0x82); // Startregister 02h
for (int i=1 ; i < 17; i++){ // 16Bytes (Register 02h bis 11h) schreiben
Wire.write(PWM);
}
Wire.endTransmission(); // I2C-Stop
}
void i2c_setup() {
Wire.begin(); //I2C-Start
Wire.beginTransmission(B1100000); // TLC59116 Slave Adresse ->C0 hex
Wire.write(0x80); // autoincrement ab Register 0h
Wire.write(0x00); // Register 00 / Mode1
Wire.write(0x00); // Register 01 / Mode2
// default all on (not fully)
Wire.write(0xF0); // Register 02 / PWM LED 1
Wire.write(0xF0); // Register 03 / PWM LED 2
Wire.write(0xF0); // Register 04 / PWM LED 3
Wire.write(0xF0); // Register 05 / PWM LED 4
Wire.write(0xF0); // Register 06 / PWM LED 5
Wire.write(0xF0); // Register 07 / PWM LED 6
Wire.write(0xF0); // Register 08 / PWM LED 7
Wire.write(0xF0); // Register 09 / PWM LED 8
Wire.write(0xF0); // Register 0A / PWM LED 9
Wire.write(0xF0); // Register 0B / PWM LED 10
Wire.write(0xF0); // Register 0C / PWM LED 11
Wire.write(0xF0); // Register 0D / PWM LED 12
Wire.write(0xF0); // Register 0E / PWM LED 13
Wire.write(0xF0); // Register 0F / PWM LED 14
Wire.write(0xF0); // Register 10 / PWM LED 15
Wire.write(0xF0); // Register 11 / PWM LED 16
Wire.write(0xFF); // Register 12 / Group duty cycle control
Wire.write(0x00); // Register 13 / Group frequency
Wire.write(0xAA); // Register 14 / LED output state 0 // Default alle LEDs auf PWM
Wire.write(0xAA); // Register 15 / LED output state 1 // Default alle LEDs auf PWM
Wire.write(0xAA); // Register 16 / LED output state 2 // Default alle LEDs auf PWM
Wire.write(0xAA); // Register 17 / LED output state 3 // Default alle LEDs auf PWM
Wire.write(0x00); // Register 18 / I2C bus subaddress 1
Wire.write(0x00); // Register 19 / I2C bus subaddress 2
Wire.write(0x00); // Register 1A / I2C bus subaddress 3
Wire.write(0x00); // Register 1B / All Call I2C bus address
Wire.write(0xFF); // Register 1C / IREF configuration
Wire.endTransmission(); // I2C-Stop
}
void temp_setup() {
temp_sensors.begin();
temp_sensors.setResolution(water_inlet, 10);
temp_sensors.setResolution(water_outlet, 10);
temp_sensors.requestTemperatures();
temp_last_update = millis();
}
void setup() {
// Deactivate Watchdog
wdt_disable();
pinMode(p_safety, OUTPUT);
digitalWrite(p_safety, LOW);
Serial.begin(9600);
DEBUG_PRINTLN("START;");
// init Display
i2c_setup();
delay(700);
dim_leds();
temp_setup();
//pinMode(p_lid, INPUT_PULLUP);
//pinMode(p_waterflow, INPUT_PULLUP);
pinMode(p_pressure, INPUT);
// pinMode(p_waterleak1, INPUT);
// pinMode(p_waterleak2, INPUT);
// pinMode(p_waterleak3, INPUT);
pinMode(p_flow_sensor, INPUT);
attachInterrupt(0, count_rpms_flow_sensor, RISING); //flow sensor
// activate Watchdog
wdt_enable(WDTO_2S);
// manually set waterleaks to green
Set_LED_PWM(11, 255);
Set_LED_PWM(13, 255);
Set_LED_PWM(15, 255);
}
// ################## loop functions #################
void Set_LED_PWM(int LED, int PWM)
{
Wire.begin(); //I2C-Start
Wire.beginTransmission(B1100000); // TLC59116 Slave Adresse ->C0 hex
Wire.write(0x01 + LED); // Register LED-Nr
Wire.write(PWM);
Wire.endTransmission(); // I2C-Stop
}
void count_rpms_flow_sensor() //This is the function that the interupt calls
{
NbTopsFan++; //This function measures the rising and falling edge of the flow sensor
}
bool check_generic_LOW(int pin) {
if (digitalRead(pin) == LOW) {
return true;
} else {
return false;
}
}
bool check_generic_HIGH(int pin) {
if (digitalRead(pin) == HIGH) {
return true;
} else {
return false;
}
}
bool check_flow() {
DEBUG_PRINTLN("check_flow()");
volume = messure_flow_over_time();
DEBUG_PRINT (volume); //Prints the number calculated above (x ,DEC)
DEBUG_PRINT (" L/hour\r\n"); //Prints "L/hour" and returns a new line
if (volume > volume_min && volume < volume_max ) {
DEBUG_PRINTLN("flow ok");
return true;
} else {
DEBUG_PRINTLN("flow not ok");
return false;
}
}
float messure_flow_over_time() {
DEBUG_PRINTLN("messure_flow_over_time()");
NbTopsFan = 0; //Set NbTops to 0 ready for calculations
delay(1000); //Wait 1 second
// ((Pulse frequency x 60) / 7.5Q,) / 60 = flow rate in liters per minute (normal ~5)
return ((NbTopsFan * 60 / 7.5) / 60);
}
bool check_temperature(float &temp_reading, float threshold_min, float threshold_max, bool &temp_fail_last_cycle, DeviceAddress &SensorAddr) {
bool res = false;
temp_reading = temp_sensors.getTempC(SensorAddr);
// is s_temp within our threshold range?
if ( threshold_min < temp_reading) {
if ( temp_reading < threshold_max ) {
res = true;
temp_fail_last_cycle = false;
}
} else {
//If the temp doesn't make sense (-127.00) but the last reading cycle did make sense, then...
if ( -127.00 == temp_reading) {
if (! temp_fail_last_cycle) {
res = true; // ...go on
temp_fail_last_cycle = true; // But remember that something was wrong.
}
} else { // It's just too low or high, but plausible
res = false;
}
}
return res;
}
void get_sensor_states() {
// s_pressure_ok
s_pressure_ok = check_generic_LOW(p_pressure);
// s_waterleak
// s_waterleak1_ok = check_generic_HIGH(p_waterleak1);
// s_waterleak2_ok = check_generic_HIGH(p_waterleak2);
// s_waterleak3_ok = check_generic_HIGH(p_waterleak3);
// temperatur sensors
s_temp1_ok = check_temperature(s_temp1,temp1_min, temp1_max, temp1_fail_last_cycle, water_inlet);
s_temp2_ok = check_temperature(s_temp2,temp2_min, temp2_max, temp2_fail_last_cycle, water_outlet);
s_waterflow_ok = check_flow();
DEBUG_PRINTLN("get_sensor_states() done");
}
void set_safety_flag() { // Checks, if all inputs indicate safe operation, then sets safety_flag
if (
s_pressure_ok &&
s_waterflow_ok &&
// s_waterleak1_ok &&
// s_waterleak2_ok &&
// s_waterleak3_ok &&
s_temp1_ok &&
s_temp2_ok
)
{
safety_flag = true;
// DEBUG_PRINTLN("True");
} else {
safety_flag = false;
}
}
void generic_display_state(int pin, bool state){
DEBUG_PRINT(state);
if (state) {
DEBUG_PRINTLN("true");
Set_LED_PWM(pin, 255);
Set_LED_PWM(pin+1, 0);
} else {
DEBUG_PRINTLN("false");
Set_LED_PWM(pin, 0);
Set_LED_PWM(pin+1, 255);
}
}
void update_display() {
// Write out sensor states to i2c
// (Counting from 1!)
DEBUG_PRINT("States: ");
generic_display_state(1, safety_flag);
generic_display_state(3, s_pressure_ok);
generic_display_state(5, s_waterflow_ok);
generic_display_state(7, s_temp1_ok);
generic_display_state(9, s_temp2_ok);
// generic_display_state(11, s_waterleak1_ok);
// generic_display_state(13, s_waterleak2_ok);
// generic_display_state(15, s_waterleak3_ok);
DEBUG_PRINT("\nTemps:");
DEBUG_PRINT("water inlet temperature: ");
DEBUG_PRINT(s_temp1);
DEBUG_PRINT(" / water outlet temperature: ");
DEBUG_PRINTLN(s_temp2);
}
void request_update_temp_sensors() {
//global temperature request to all devices on the bus
//cli();
temp_sensors.requestTemperatures();
temp_last_update = millis();
//sei();
}
void loop() {
// Reset Watchdog
wdt_reset();
if ( temp_last_update + temp_requests_time < millis() ) {
// DEBUG_PRINTLN("Updating temp sensors");
DEBUG_PRINTLN("-----");
request_update_temp_sensors();
}
DEBUG_PRINTLN("get_sensor_states()");
get_sensor_states();
DEBUG_PRINTLN("set_safety_flag()");
set_safety_flag();
disable_laser = safety_flag; // If save operation not ok, disable laser (HIGH Output will disable the laser!)
digitalWrite(p_safety, disable_laser); // Write out pin state
DEBUG_PRINTLN("update_display");
update_display();
}