-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfixed_flush_dwq_code.ino
775 lines (611 loc) · 30.3 KB
/
fixed_flush_dwq_code.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
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
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
//when flashing free chlorine systems, comment take_ph and comment take_ORPdup() functions in the void loop.
#include <stdlib.h>
#include <time.h> /* time_t, struct tm, difftime, time, mktime */
#include <stdlib.h>
#include <string.h>
#include <SdCardLogHandlerRK.h>
using namespace std;
#define PRES_READ_PERIOD 5 //defined in minutes. Take a pressure reading every 5 minutes
//#define SENS_READ_PERIOD 5 //defined in minutes. Take a sensor reading every 60 minutes
#define FLUSH_PERIOD 60 // defined in minutes. Flushed water every 60 minutes
#define fixedflushTime 15 //defined in minutes.
#define READ_DELAY 1 //defined in minutes. How long after new water is flushed through until atlas sensors take readings
#define bfc D7
#define pres_pin A5
#define signal_pin D6
#define pH_address 99
#define ORP_address 98
#define ORPDup_address 97
#define EC_address 100
#define RTD_address 102
// Connect to InfluxDB
#define HOSTNAME "REDACTED"
#define HOSTNUM REDACTED
TCPClient client; //Starts client to connect to the internet (library to make connection to influxdb)
SYSTEM_THREAD(ENABLED); //Allows the firmware to run without being connected to the cloud.
SerialLogHandler logHandler; //Particle speciic library to use the serial communication
//Initialize the String object
//declaring and initializing the SD card access
const int SD_CHIP_SELECT = D5; //
SdFat sd(&SPI1); // for an alternative SPI interface
//const int SD_CHIP_SELECT = D5; //for D5 pin, the SPI interface bellow needs to be adjusted to 1.
//SdFat sd(&SPI1); // for an alternative SPI interface
//declaring and initializing the pressure interrupt function
SdCardPrintHandler printToCard(sd, SD_CHIP_SELECT, SPI_FULL_SPEED);
Timer timer(7500, take_pressure_sd);
//int getID(String command); //Not sure we need this
double SENS_READ_PERIOD = 5; //defined in minutes.
bool fixedflushflag = FALSE;
int flushTime = 5; //defined in seconds
int am_flush_hour = 10; //6amEST //in UTC (to convert from EST to UTC add 5 hours during regular winter time OR 4 during daylight savings i.e 5am EST = 10am UTC)
int pm_flush_hour = 21; //17EST //in UTC
bool am_flush=FALSE; //indicator to keep track of the fixed flushing each day
bool pm_flush=FALSE; //indicator to keep track of the fixed flushing each day
double pvolt;
double pressure;
int pres_counter = 0;
int flush_counter = 0;
int wq_counter = 0;
String tempData;
String pHData;
String ECData;
String ORPData;
String ORPDupData;
String moistState;
String tie;
char computerdata[40]; //we make an 40 byte character array to hold incoming data from a pc/mac/other0.
byte code = 0; //used to hold the I2C response code.
char _data[200]; //we make a 200-byte character array to hold incoming data from any circuit.
byte in_char = 0;
String econd[4] = {"EC", "TDS", "SAL", "SG"};
char *ec; //char pointer used in string parsing. As the EC sensor sends all 4 of these readings as 1 string
char *tds; //char pointer used in string parsing.
char *sal; //char pointer used in string parsing.
char *sg; //char pointer used in string parsing.
unsigned long previousMillis_pres = 0; //used for pressure measurments frequency in intervals
unsigned long previousMillis_wq = 0; //used for wq measurments frequency in intervals
unsigned long previousMillis_flush = 0; //used for wq measurments frequency in intervals
unsigned long previousMillis_fixedflush = 0; //used for fixed flush events
int tinkerDigitalRead(String pin);
int tinkerDigitalWrite(String command);
int tinkerAnalogRead(String pin);
int tinkerAnalogWrite(String command);
void setup() {
pinMode(pres_pin, INPUT); //set pin as an input for the pressure transducer
pinMode(bfc, OUTPUT); //commented out because not using beef cake -- well we back here again fool! //Sets digital pin as output to the relay switch
pinMode(signal_pin, INPUT);
Wire.begin();
timer.start(); //starts timer funciton for pressure interrupter function
//Particle.function("Get Device ID",getID); //do not need
//Particle.variable("Device",DEV_ID); //do not need
Particle.function("Flush Time",getFlushTime);
Particle.variable("Flush Time",flushTime);
Particle.function("Take Pressure", take_pressure);
Particle.variable("Pressure Voltage",pvolt); //not sure we need this
Particle.variable("Pressure",pressure);
Particle.function("Take Moisture", take_moisture);
Particle.variable("Moisture", moistState);
Particle.function("Take Temperature", take_temp);
Particle.variable("Temperature", tempData);
Particle.function("Take pH", take_pH);
Particle.variable("pH", pHData);
Particle.function("Take EC", take_EC);
Particle.variable("EC", ECData);
Particle.function("Take ORP", take_ORP);
Particle.variable("ORP", ORPData);
Particle.function("Take ORPdup", take_ORPdup);
Particle.variable("ORPdup", ORPDupData);
//Register all the Tinker functions
Particle.function("digitalread", tinkerDigitalRead);
Particle.function("digitalwrite", tinkerDigitalWrite);
Particle.function("analogread", tinkerAnalogRead);
Particle.function("analogwrite", tinkerAnalogWrite);
}
void loop() {
fixed_flush(); //Function used to flush water out of the system by opening and closing the valve at a fixed time for a fixed amount of time
unsigned long currentMillis = millis();
if (currentMillis - previousMillis_pres >= PRES_READ_PERIOD*60*1000 || pres_counter == 0) {
previousMillis_pres = currentMillis; // save the last time pressure taken
::tie = String(Time.now())+"000000000";
take_pressure("");
take_moisture(""); // Take moisture reading
pres_counter = 1;
}
if (currentMillis - previousMillis_flush >= FLUSH_PERIOD*60*1000 || flush_counter == 0) {
previousMillis_flush = currentMillis; // save the last time pressure taken
::tie = String(Time.now())+"000000000";
//check wether or not there is an ongoing flush. If there is, don't interrupt.
if (am_flush == FALSE && pm_flush == FALSE ){
water_exchange(); // flushTime is defined through the particlefunciton and variable
}
flush_counter = 1;
}
if (currentMillis - previousMillis_wq >= SENS_READ_PERIOD*60*1000 || wq_counter == 0) {
previousMillis_wq = currentMillis; // save the last time pressure taken
::tie = String(Time.now())+"000000000";
take_temp("");
take_ORP("");
//take_ORPdup("");
take_pH("");
take_EC("");
wq_counter = 1;
}
if (fixedflushflag) {
::tie = String(Time.now())+"000000000";
take_temp("");
take_ORP("");
//take_ORPdup("");
}
}
//function to flush morning and afternoon for 5 minutes. The valve wil open and the node will continue its regular operations.
void fixed_flush(){
unsigned long currentflushMillis = millis();
//below is the code for the morning flush
if (Time.hour()==am_flush_hour && am_flush == FALSE){
digitalWrite(bfc,HIGH); //turn on beefcake (and therefore valve)
previousMillis_fixedflush = currentflushMillis; // save the last time valve was opened taken
am_flush = TRUE;
fixedflushflag=TRUE;
//delay(duration*1000); //valve left open for n seconds
//digitalWrite(bfc,LOW); //turn off beefcake
}
if (currentflushMillis - previousMillis_fixedflush >= fixedflushTime*60*1000) {
digitalWrite(bfc,LOW); //turn on beefcake (and therefore valve)
}
if (Time.hour()>am_flush_hour){
am_flush = FALSE;
}
//Below is the start to the afternoon flush
if (Time.hour()==pm_flush_hour && pm_flush == FALSE){
digitalWrite(bfc,HIGH); //turn on beefcake (and therefore valve)
previousMillis_fixedflush = currentflushMillis; // save the last time pressure taken
pm_flush = TRUE;
fixedflushflag=TRUE;
//delay(duration*1000); //valve left open for n seconds
//digitalWrite(bfc,LOW); //turn off beefcake
}
if (currentflushMillis - previousMillis_fixedflush >= fixedflushTime*60*1000) {
digitalWrite(bfc,LOW); //turn on beefcake (and therefore valve)
fixedflushflag=FALSE;
}
if (Time.hour()>pm_flush_hour){
pm_flush = FALSE;
}
}
int take_ORP(String command){
computerdata[0] = 'r';
Wire.beginTransmission(ORP_address);
Wire.write(computerdata);
Wire.endTransmission();
delay(815);
Wire.requestFrom(ORP_address, 48, 1); //call the circuit and request 48 bytes (this may be more than we need -- from https://www.arduino.cc/en/Reference/WireRead it might only send 1 byte)
code = Wire.read(); //the first byte is the response code, we read this separately.
// char P_code = (char)code; // Erros with type with these lines byte --> const char & char --> const char
// Particle.publish(P_code);
switch (code) { //switch case based on what the response code is.
case 1: //decimal 1 means the command was successful.
//Particle.publish("Success"); //commented out to avoid using too much data.
Serial.println("Success");
break; //exits the switch case.
case 2: //decimal 2. means the command has failed.
//Particle.publish("Failed");
Serial.println("Failed");
break; //exits the switch case.
case 254: //decimal 254 means the command has not yet been finished calculating.
//Particle.publish("Pending");
Serial.println("Pending");
break; //exits the switch case.
case 255: //decimal 255 means there is no further data to send.
//Particle.publish("No Data");
Serial.println("No Data");
break; //exits the switch case.
}
for (int j=0; Wire.available(); j++) { //are there bytes to receive.
in_char = Wire.read(); //receive a byte. (ASCII number)
_data[j] = in_char; //load this byte into our array.
if (in_char == 0) { //if we see that we have been sent a null command.
Wire.endTransmission(); //end the I2C data transmission.
break; //exit the while loop.
}
}
createDataStream("ORP", String(_data));
ORPData = String(_data);
memset(_data,0, sizeof(_data));
return 1;
}
int take_ORPdup(String command){
computerdata[0] = 'r';
Wire.beginTransmission(ORPDup_address);
Wire.write(computerdata);
Wire.endTransmission();
delay(815);
Wire.requestFrom(ORPDup_address, 48, 1); //call the circuit and request 48 bytes (this may be more than we need -- from https://www.arduino.cc/en/Reference/WireRead it might only send 1 byte)
code = Wire.read(); //the first byte is the response code, we read this separately.
// char P_code = (char)code; // Erros with type with these lines byte --> const char & char --> const char
// Particle.publish(P_code);
switch (code) { //switch case based on what the response code is.
case 1: //decimal 1 means the command was successful.
//Particle.publish("Success"); //commented out to avoid using too much data.
Serial.println("Success");
break; //exits the switch case.
case 2: //decimal 2. means the command has failed.
//Particle.publish("Failed");
Serial.println("Failed");
break; //exits the switch case.
case 254: //decimal 254 means the command has not yet been finished calculating.
//Particle.publish("Pending");
Serial.println("Pending");
break; //exits the switch case.
case 255: //decimal 255 means there is no further data to send.
//Particle.publish("No Data");
Serial.println("No Data");
break; //exits the switch case.
}
for (int j=0; Wire.available(); j++) { //are there bytes to receive.
in_char = Wire.read(); //receive a byte. (ASCII number)
_data[j] = in_char; //load this byte into our array.
if (in_char == 0) { //if we see that we have been sent a null command.
Wire.endTransmission(); //end the I2C data transmission.
break; //exit the while loop.
}
}
createDataStream("ORPdup", String(_data));
ORPDupData = String(_data);
memset(_data,0, sizeof(_data));
return 1;
}
int take_EC(String command){
computerdata[0] = 't'; //t takes first spot in array
computerdata[1] = ','; //, takes second spot
//sets remaining characters in computer data (computerdata+2) to be temperature reading for temperature compensation
//Since temp is a String, we must convert to c_str for function to work correctly
strcpy(computerdata+2, tempData.c_str());
Wire.beginTransmission(EC_address);
Wire.write(computerdata);
Wire.endTransmission();
delay(300);
memset(computerdata,0, sizeof(computerdata)); //now that the cirquit has been temperature compensated, take a reading "r" as usual
computerdata[0] = 'r';
Wire.beginTransmission(EC_address);
Wire.write(computerdata);
Wire.endTransmission();
delay(570);
Wire.requestFrom(EC_address, 48, 1); //call the circuit and request 48 bytes (this may be more than we need -- from https://www.arduino.cc/en/Reference/WireRead it might only send 1 byte)
code = Wire.read(); //the first byte is the response code, we read this separately.
// char P_code = (char)code; // Erros with type with these lines byte --> const char & char --> const char
// Particle.publish(P_code);
switch (code) { //switch case based on what the response code is.
case 1: //decimal 1 means the command was successful.
//Particle.publish("Success"); //commented out to avoid using too much data.
Serial.println("Success");
break; //exits the switch case.
case 2: //decimal 2. means the command has failed.
//Particle.publish("Failed");
Serial.println("Failed");
break; //exits the switch case.
case 254: //decimal 254 means the command has not yet been finished calculating.
//Particle.publish("Pending");
Serial.println("Pending");
break; //exits the switch case.
case 255: //decimal 255 means there is no further data to send.
//Particle.publish("No Data");
Serial.println("No Data");
break; //exits the switch case.
}
for (int j=0; Wire.available(); j++) { //are there bytes to receive.
in_char = Wire.read(); //receive a byte. (ASCII number)
_data[j] = in_char; //load this byte into our array.
if (in_char == 0) { //if we see that we have been sent a null command.
Wire.endTransmission(); //end the I2C data transmission.
break; //exit the while loop.
}
}
//break up the EC ASCII by comma to get the four different measurements it acutally takes
//Serial.println(_data);
ec = strtok(_data, ","); //let's pars the string at each comma.
tds = strtok(NULL, ","); //let's pars the string at each comma.
sal = strtok(NULL, ","); //let's pars the string at each comma.
sg = strtok(NULL, ","); //let's pars the string at each comma.
String edata[4] = {ec, tds, sal, sg}; //creates a string of the ASCII values from the EC sensor
for(int j = 0; j < 4; j++){
createDataStream(econd[j],edata[j]);
Serial.println(econd[j]+" "+edata[j]);
}
ECData = String(_data);
memset(_data,0, sizeof(_data));
return 1;
}
int take_pH(String command){
computerdata[0] = 't'; //t takes first spot in array
computerdata[1] = ','; //, takes second spot
//sets remaining characters in computer data (computerdata+2) to be temperature reading for temperature compensation
//Since temp is a String, we must convert to c_str for function to work correctly
strcpy(computerdata+2, tempData.c_str());
Wire.beginTransmission(pH_address);
Wire.write(computerdata);
Wire.endTransmission();
delay(300);
memset(computerdata,0, sizeof(computerdata)); //Since circuit has been compensated for temperature, now take a measurement as usual with "r"
computerdata[0] = 'r';
Wire.beginTransmission(pH_address);
Wire.write(computerdata);
Wire.endTransmission();
delay(815);
Wire.requestFrom(pH_address, 48, 1); //call the circuit and request 48 bytes (this may be more than we need -- from https://www.arduino.cc/en/Reference/WireRead it might only send 1 byte)
code = Wire.read(); //the first byte is the response code, we read this separately.
// char P_code = (char)code; // Erros with type with these lines byte --> const char & char --> const char
// Particle.publish(P_code);
switch (code) { //switch case based on what the response code is.
case 1: //decimal 1 means the command was successful.
//Particle.publish("Success"); //commented out to avoid using too much data.
Serial.println("Success");
break; //exits the switch case.
case 2: //decimal 2. means the command has failed.
//Particle.publish("Failed");
Serial.println("Failed");
break; //exits the switch case.
case 254: //decimal 254 means the command has not yet been finished calculating.
//Particle.publish("Pending");
Serial.println("Pending");
break; //exits the switch case.
case 255: //decimal 255 means there is no further data to send.
//Particle.publish("No Data");
Serial.println("No Data");
break; //exits the switch case.
}
for (int j=0; Wire.available(); j++) { //are there bytes to receive.
in_char = Wire.read(); //receive a byte. (ASCII number)
_data[j] = in_char; //load this byte into our array.
if (in_char == 0) { //if we see that we have been sent a null command.
Wire.endTransmission(); //end the I2C data transmission.
break; //exit the while loop.
}
}
createDataStream("pH", String(_data));
pHData = String(_data);
memset(_data,0, sizeof(_data));
return 1;
}
int take_temp(String command){
computerdata[0] = 'r'; //set the command to read
Wire.beginTransmission(RTD_address);
Wire.write(computerdata);
Wire.endTransmission();
delay(600);
Wire.requestFrom(RTD_address, 48, 1); //call the circuit and request 48 bytes (this may be more than we need -- from https://www.arduino.cc/en/Reference/WireRead it might only send 1 byte)
code = Wire.read(); //the first byte is the response code, we read this separately.
// char P_code = (char)code; // Erros with type with these lines byte --> const char & char --> const char
// Particle.publish(P_code);
switch (code) { //switch case based on what the response code is.
case 1: //decimal 1 means the command was successful.
//Particle.publish("Success"); //commented out to avoid using too much data.
Serial.println("Success");
break; //exits the switch case.
case 2: //decimal 2. means the command has failed.
//Particle.publish("Failed");
Serial.println("Failed");
break; //exits the switch case.
case 254: //decimal 254 means the command has not yet been finished calculating.
//Particle.publish("Pending");
Serial.println("Pending");
break; //exits the switch case.
case 255: //decimal 255 means there is no further data to send.
//Particle.publish("No Data");
Serial.println("No Data");
break; //exits the switch case.
}
for (int j=0; Wire.available(); j++) { //are there bytes to receive.
in_char = Wire.read(); //receive a byte. (ASCII number)
_data[j] = in_char; //load this byte into our array.
if (in_char == 0) { //if we see that we have been sent a null command.
Wire.endTransmission(); //end the I2C data transmission.
tempData = _data;
break; //exit the while loop.
}
}
createDataStream("Temp", String(_data));
tempData = _data;
memset(_data,0, sizeof(_data));
return 1;
}
int getFlushTime(String tim3){
flushTime = tim3.toInt();
return flushTime;
}
void water_exchange(){
digitalWrite(bfc,HIGH); //turn on beefcake (and therefore valve)
delay(flushTime*1000); //valve left open for n seconds
digitalWrite(bfc,LOW); //turn off beefcake
}
int take_pressure(String command){
// pvolt = map(analogRead(pres_pin),0,4095,0,3);
pressure = map(analogRead(pres_pin),0,4095,0,100); //ADC reading to pressure (PSI)
// pressure = map(pvolt,0,3,0,100);
if(pressure <0){ pressure=0;}
createDataStream("pressure",String(pressure));
return 1;
}
void take_pressure_sd(){
float pressure_sd = map(analogRead(pres_pin),0,4095,0,100); //ADC reading to pressure (PSI)
String tie = String(Time.now())+"000000000";
String sdata;
sdata = String("pressure,")+" value="+String(pressure_sd)+" "+tie; //removed siteID and NodeID
printToCard.println(sdata);
}
int take_moisture(String command){
// int moisture = digitalRead(signal_pin);
// Particle.publish(moisture);
if (digitalRead(signal_pin) == HIGH){
moistState = "Dry";
}
else if (digitalRead(signal_pin) == LOW){
moistState = "Wet";
}
createDataStream("Moisture",moistState);
return 1;
}
int writeinflux(String data){
//function that writes a measurement given as a string to influx and returns 1 if successful and 0 if failed
// Send data over to influx
String DEV_ID = System.deviceID(); //obtain the deviceid and store as a String object
String POSTNAME = "/api/v1/write?d="; //Initialize the String object
POSTNAME.concat(DEV_ID); //DEV_ID is appended to POSTNAME and stored as POSTNAME
POSTNAME.concat("&h=REDACTED HTTP/1.1"); //POSTNAMEtail is appended to POSTNAME and stored as POSTNAME
if(client.connect(HOSTNAME, HOSTNUM)){
Serial.println("Connected");
// Actual function
client.printlnf("POST %s", POSTNAME.c_str());
client.printlnf("HOST: %s:%d", HOSTNAME, HOSTNUM);
client.println("User-Agent: Photon/1.0");
client.printlnf("Content-Length: %d", data.length());
client.println("Content-Type: application/x-www-form-urlencoded");
client.println();
client.print(data);
//client.println();
delay(1*1000); //delay 10 seconds. function takes in milliseconds
//client.flush();
client.stop();
return 1;
}
else
{
Serial.println("Connection Failed!");
}
return 0;
}
void createDataStream(String name, String meas){
//function to create the data string to send to influx
// Get current time in UNIX time
//String tie = String(Time.now())+"000000000";
//get device ID to use as tag
//String myID = System.deviceID();
// Create data string for the parameter to pass into write influx
String data;
data = name+","+" value="+meas+" "+::tie; //removed siteID and NodeID
//write to influx and will try for 5 times before just taking a new reading
for(int j=0; j<5; j++){
if (writeinflux(data) == 1){
Serial.println("A success!");
break;
}
else{
Serial.println("Trying again");
}
}
}
/* Tinker
* This is a simple application to read and toggle pins on a Particle device.
* For the extended version of the Tinker app supporting more pins, see
* https://github.com/particle-iot/device-os/blob/develop/user/applications/tinker/application.cpp
*/
/* Function prototypes -------------------------------------------------------*/
/* This function is called once at start up ----------------------------------*/
/*******************************************************************************
* Function Name : tinkerDigitalRead
* Description : Reads the digital value of a given pin
* Input : Pin
* Output : None.
* Return : Value of the pin (0 or 1) in INT type
Returns a negative number on failure
*******************************************************************************/
int tinkerDigitalRead(String pin)
{
//convert ascii to integer
int pinNumber = pin.charAt(1) - '0';
//Sanity check to see if the pin numbers are within limits
if (pinNumber< 0 || pinNumber >7) return -1;
if(pin.startsWith("D"))
{
pinMode(pinNumber, INPUT_PULLDOWN);
return digitalRead(pinNumber);
}
else if (pin.startsWith("A"))
{
pinMode(pinNumber+10, INPUT_PULLDOWN);
return digitalRead(pinNumber+10);
}
return -2;
}
/*******************************************************************************
* Function Name : tinkerDigitalWrite
* Description : Sets the specified pin HIGH or LOW
* Input : Pin and value
* Output : None.
* Return : 1 on success and a negative number on failure
*******************************************************************************/
int tinkerDigitalWrite(String command)
{
bool value = 0;
//convert ascii to integer
int pinNumber = command.charAt(1) - '0';
//Sanity check to see if the pin numbers are within limits
if (pinNumber< 0 || pinNumber >7) return -1;
if(command.substring(3,7) == "HIGH") value = 1;
else if(command.substring(3,6) == "LOW") value = 0;
else return -2;
if(command.startsWith("D"))
{
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber, value);
return 1;
}
else if(command.startsWith("A"))
{
pinMode(pinNumber+10, OUTPUT);
digitalWrite(pinNumber+10, value);
return 1;
}
else return -3;
}
/*******************************************************************************
* Function Name : tinkerAnalogRead
* Description : Reads the analog value of a pin
* Input : Pin
* Output : None.
* Return : Returns the analog value in INT type (0 to 4095)
Returns a negative number on failure
*******************************************************************************/
int tinkerAnalogRead(String pin)
{
//convert ascii to integer
int pinNumber = pin.charAt(1) - '0';
//Sanity check to see if the pin numbers are within limits
if (pinNumber< 0 || pinNumber >7) return -1;
if(pin.startsWith("D"))
{
return -3;
}
else if (pin.startsWith("A"))
{
return analogRead(pinNumber+10);
}
return -2;
}
/*******************************************************************************
* Function Name : tinkerAnalogWrite
* Description : Writes an analog value (PWM) to the specified pin
* Input : Pin and Value (0 to 255)
* Output : None.
* Return : 1 on success and a negative number on failure
*******************************************************************************/
int tinkerAnalogWrite(String command)
{
//convert ascii to integer
int pinNumber = command.charAt(1) - '0';
//Sanity check to see if the pin numbers are within limits
if (pinNumber< 0 || pinNumber >7) return -1;
String value = command.substring(3);
if(command.startsWith("D"))
{
pinMode(pinNumber, OUTPUT);
analogWrite(pinNumber, value.toInt());
return 1;
}
else if(command.startsWith("A"))
{
pinMode(pinNumber+10, OUTPUT);
analogWrite(pinNumber+10, value.toInt());
return 1;
}
else return -2;
}