|
@@ -348,18 +348,190 @@ void Statemachine::input(int n) {
|
348
|
348
|
} else if (n == -2) {
|
349
|
349
|
switch_to((state == auto_fert_a) ? auto_fert_b : auto_fert_a);
|
350
|
350
|
}
|
|
351
|
+ } else if (state == fullauto_stirr_run) {
|
|
352
|
+ // allow user to stop stirring and continue with fertilizers
|
|
353
|
+ plants.abort();
|
|
354
|
+ stop_time = millis();
|
|
355
|
+ if (selected_ferts.countSet() > 0) {
|
|
356
|
+ selected_time = auto_pump_runtime[0];
|
|
357
|
+ for (int i = 0; i < plants.countFertilizers(); i++) {
|
|
358
|
+ if (auto_pump_runtime[i] > selected_time) {
|
|
359
|
+ selected_time = auto_pump_runtime[i];
|
|
360
|
+ }
|
|
361
|
+
|
|
362
|
+ if (selected_ferts.isSet(i)) {
|
|
363
|
+ plants.startFertilizer(i);
|
|
364
|
+ }
|
|
365
|
+ }
|
|
366
|
+
|
|
367
|
+ start_time = millis();
|
|
368
|
+ switch_to(fullauto_fert_run);
|
|
369
|
+ } else {
|
|
370
|
+ auto wl = plants.getWaterlevel();
|
|
371
|
+ if ((wl != Plants::full) && (wl != Plants::invalid)) {
|
|
372
|
+ // if the waterlevel is currently empty, we
|
|
373
|
+ // set a flag to record the time to fill
|
|
374
|
+ filling_started_empty = (wl == Plants::empty);
|
|
375
|
+
|
|
376
|
+ plants.openWaterInlet();
|
|
377
|
+ selected_id = plants.countPlants() + 1;
|
|
378
|
+ selected_time = MAX_TANK_FILL_TIME;
|
|
379
|
+ start_time = millis();
|
|
380
|
+ switch_to(fullauto_tank_run);
|
|
381
|
+ } else if (wl == Plants::full) {
|
|
382
|
+ // check if kickstart is required for this
|
|
383
|
+ bool need_kickstart = false;
|
|
384
|
+ for (int i = 0; i < plants.countPlants(); i++) {
|
|
385
|
+ if (selected_plants.isSet(i)) {
|
|
386
|
+ if (plants.getKickstart()->getPinNumber(i) >= 0) {
|
|
387
|
+ need_kickstart = true;
|
|
388
|
+ }
|
|
389
|
+ }
|
|
390
|
+ }
|
|
391
|
+
|
|
392
|
+ // start kickstart/valve as needed
|
|
393
|
+ for (int i = 0; i < plants.countPlants(); i++) {
|
|
394
|
+ if (selected_plants.isSet(i)) {
|
|
395
|
+ plants.startPlant(i, need_kickstart);
|
|
396
|
+ }
|
|
397
|
+ }
|
|
398
|
+
|
|
399
|
+ watering_started_full = (wl == Plants::full);
|
|
400
|
+
|
|
401
|
+ selected_time = MAX_AUTO_PLANT_RUNTIME;
|
|
402
|
+ start_time = millis();
|
|
403
|
+ if (need_kickstart) {
|
|
404
|
+ switch_to(fullauto_kickstart_run);
|
|
405
|
+ } else {
|
|
406
|
+ switch_to(fullauto_plant_run);
|
|
407
|
+ }
|
|
408
|
+ } else if (wl == Plants::invalid) {
|
|
409
|
+ plants.abort();
|
|
410
|
+ error_condition = F("Invalid sensor state");
|
|
411
|
+ state = fullauto_fert;
|
|
412
|
+ switch_to(error);
|
|
413
|
+ }
|
|
414
|
+ }
|
|
415
|
+ } else if (state == fullauto_fert_run) {
|
|
416
|
+ // allow user to stop fertizilers and continue with tank filling
|
|
417
|
+ auto wl = plants.getWaterlevel();
|
|
418
|
+ if ((wl != Plants::full) && (wl != Plants::invalid)) {
|
|
419
|
+ // if the waterlevel is currently empty, we
|
|
420
|
+ // set a flag to record the time to fill
|
|
421
|
+ filling_started_empty = (wl == Plants::empty);
|
|
422
|
+
|
|
423
|
+ plants.openWaterInlet();
|
|
424
|
+ selected_id = plants.countPlants() + 1;
|
|
425
|
+ selected_time = MAX_TANK_FILL_TIME;
|
|
426
|
+ start_time = millis();
|
|
427
|
+ switch_to(fullauto_tank_run);
|
|
428
|
+ } else if (wl == Plants::full) {
|
|
429
|
+ // check if kickstart is required for this
|
|
430
|
+ bool need_kickstart = false;
|
|
431
|
+ for (int i = 0; i < plants.countPlants(); i++) {
|
|
432
|
+ if (selected_plants.isSet(i)) {
|
|
433
|
+ if (plants.getKickstart()->getPinNumber(i) >= 0) {
|
|
434
|
+ need_kickstart = true;
|
|
435
|
+ }
|
|
436
|
+ }
|
|
437
|
+ }
|
|
438
|
+
|
|
439
|
+ // start kickstart/valve as needed
|
|
440
|
+ for (int i = 0; i < plants.countPlants(); i++) {
|
|
441
|
+ if (selected_plants.isSet(i)) {
|
|
442
|
+ plants.startPlant(i, need_kickstart);
|
|
443
|
+ }
|
|
444
|
+ }
|
|
445
|
+
|
|
446
|
+ watering_started_full = (wl == Plants::full);
|
|
447
|
+
|
|
448
|
+ selected_time = MAX_AUTO_PLANT_RUNTIME;
|
|
449
|
+ start_time = millis();
|
|
450
|
+ if (need_kickstart) {
|
|
451
|
+ switch_to(fullauto_kickstart_run);
|
|
452
|
+ } else {
|
|
453
|
+ switch_to(fullauto_plant_run);
|
|
454
|
+ }
|
|
455
|
+ } else if (wl == Plants::invalid) {
|
|
456
|
+ plants.abort();
|
|
457
|
+ error_condition = F("Invalid sensor state");
|
|
458
|
+ state = fullauto_fert;
|
|
459
|
+ switch_to(error);
|
|
460
|
+ }
|
|
461
|
+ } else if ((state == fullauto_tank_run)
|
|
462
|
+ || (state == fullauto_tank_purge_run)) {
|
|
463
|
+ // allow user to stop tank and continue with kickstart
|
|
464
|
+ plants.abort();
|
|
465
|
+ stop_time = millis();
|
|
466
|
+ auto wl = plants.getWaterlevel();
|
|
467
|
+ if ((wl != Plants::empty) && (wl != Plants::invalid)) {
|
|
468
|
+ // check if kickstart is required for this
|
|
469
|
+ bool need_kickstart = false;
|
|
470
|
+ for (int i = 0; i < plants.countPlants(); i++) {
|
|
471
|
+ if (selected_plants.isSet(i)) {
|
|
472
|
+ if (plants.getKickstart()->getPinNumber(i) >= 0) {
|
|
473
|
+ need_kickstart = true;
|
|
474
|
+ }
|
|
475
|
+ }
|
|
476
|
+ }
|
|
477
|
+
|
|
478
|
+ // start kickstart/valve as needed
|
|
479
|
+ for (int i = 0; i < plants.countPlants(); i++) {
|
|
480
|
+ if (selected_plants.isSet(i)) {
|
|
481
|
+ plants.startPlant(i, need_kickstart);
|
|
482
|
+ }
|
|
483
|
+ }
|
|
484
|
+
|
|
485
|
+ watering_started_full = (wl == Plants::full);
|
|
486
|
+
|
|
487
|
+ selected_time = MAX_AUTO_PLANT_RUNTIME;
|
|
488
|
+ start_time = millis();
|
|
489
|
+ if (need_kickstart) {
|
|
490
|
+ if (state == fullauto_tank_run) {
|
|
491
|
+ switch_to(fullauto_kickstart_run);
|
|
492
|
+ } else {
|
|
493
|
+ switch_to(fullauto_kickstart_purge_run);
|
|
494
|
+ }
|
|
495
|
+ } else {
|
|
496
|
+ if (state == fullauto_tank_run) {
|
|
497
|
+ switch_to(fullauto_plant_run);
|
|
498
|
+ } else {
|
|
499
|
+ switch_to(fullauto_plant_purge_run);
|
|
500
|
+ }
|
|
501
|
+ }
|
|
502
|
+ } else if (wl == Plants::empty) {
|
|
503
|
+ stop_time = millis();
|
|
504
|
+ switch_to(auto_done);
|
|
505
|
+ } else if (wl == Plants::invalid) {
|
|
506
|
+ error_condition = F("Invalid sensor state");
|
|
507
|
+ state = auto_mode_a;
|
|
508
|
+ switch_to(error);
|
|
509
|
+ }
|
|
510
|
+ } else if ((state == fullauto_kickstart_run)
|
|
511
|
+ || (state == fullauto_kickstart_purge_run)) {
|
|
512
|
+ // allow user to stop kickstarting and continue with plants
|
|
513
|
+ plants.abort();
|
|
514
|
+ selected_time = MAX_AUTO_PLANT_RUNTIME;
|
|
515
|
+ start_time = millis();
|
|
516
|
+
|
|
517
|
+ // start required valves
|
|
518
|
+ for (int i = 0; i < plants.countPlants(); i++) {
|
|
519
|
+ if (selected_plants.isSet(i)) {
|
|
520
|
+ plants.startPlant(i, false);
|
|
521
|
+ }
|
|
522
|
+ }
|
|
523
|
+
|
|
524
|
+ if (state == fullauto_kickstart_run) {
|
|
525
|
+ switch_to(fullauto_plant_run);
|
|
526
|
+ } else {
|
|
527
|
+ switch_to(fullauto_plant_purge_run);
|
|
528
|
+ }
|
351
|
529
|
} else if ((state == auto_fert_run) || (state == auto_tank_run)
|
352
|
530
|
|| (state == auto_stirr_run) || (state == auto_plant_run)
|
353
|
531
|
|| (state == auto_plant_kickstart_run)
|
354
|
532
|
|| (state == fillnwater_kickstart_run)
|
355
|
|
- || (state == fullauto_stirr_run)
|
356
|
|
- || (state == fullauto_fert_run)
|
357
|
|
- || (state == fullauto_tank_run)
|
358
|
|
- || (state == fullauto_kickstart_run)
|
359
|
533
|
|| (state == fullauto_plant_run)
|
360
|
534
|
|| (state == fullauto_plant_overrun)
|
361
|
|
- || (state == fullauto_tank_purge_run)
|
362
|
|
- || (state == fullauto_kickstart_purge_run)
|
363
|
535
|
|| (state == fullauto_plant_purge_run)
|
364
|
536
|
|| (state == fullauto_plant_purge_overrun)) {
|
365
|
537
|
plants.abort();
|
|
@@ -1119,6 +1291,7 @@ void Statemachine::act(void) {
|
1119
|
1291
|
if ((runtime / 1000UL) >= KICKSTART_RUNTIME) {
|
1120
|
1292
|
// kickstart is done, switch over to valves
|
1121
|
1293
|
plants.abort();
|
|
1294
|
+ selected_time = MAX_AUTO_PLANT_RUNTIME;
|
1122
|
1295
|
start_time = millis();
|
1123
|
1296
|
|
1124
|
1297
|
// start required valves
|
|
@@ -1155,6 +1328,12 @@ void Statemachine::act(void) {
|
1155
|
1328
|
}
|
1156
|
1329
|
}
|
1157
|
1330
|
|
|
1331
|
+ if ((millis() - last_animation_time) >= 500) {
|
|
1332
|
+ // update animation if needed
|
|
1333
|
+ last_animation_time = millis();
|
|
1334
|
+ switch_to(state);
|
|
1335
|
+ }
|
|
1336
|
+
|
1158
|
1337
|
if (selected_ferts.countSet() <= 0) {
|
1159
|
1338
|
plants.abort();
|
1160
|
1339
|
|
|
@@ -1438,37 +1617,53 @@ void Statemachine::act(void) {
|
1438
|
1617
|
// check water level state
|
1439
|
1618
|
auto wl = plants.getWaterlevel();
|
1440
|
1619
|
if (wl == Plants::empty) {
|
1441
|
|
- plants.abort();
|
1442
|
|
- stop_time = millis();
|
|
1620
|
+ if ((state == auto_plant_run) || (state == fillnwater_plant_run)) {
|
|
1621
|
+ plants.abort();
|
|
1622
|
+ stop_time = millis();
|
|
1623
|
+ }
|
1443
|
1624
|
|
1444
|
|
- // if we started watering with a full tank
|
1445
|
|
- // and then finished watering when it was empty
|
1446
|
|
- // and we were only watering a single plant
|
1447
|
|
- // look at this as a "calibration run" and record
|
1448
|
|
- // the time it took to empty the tank
|
1449
|
|
- if ((state == fillnwater_plant_run) && watering_started_full && (selected_plants.countSet() == 1)) {
|
1450
|
|
- unsigned long time_to_water = stop_time - start_time;
|
1451
|
|
- debug.print("Watering plant ");
|
1452
|
|
- debug.print(selected_plants.getFirstSet() + 1);
|
1453
|
|
- debug.print(" with the complete tank took ");
|
1454
|
|
- debug.print(String(time_to_water));
|
1455
|
|
- debug.println("ms");
|
|
1625
|
+ if ((state == auto_plant_run) || (state == fillnwater_plant_run)
|
|
1626
|
+ || (state == fullauto_plant_run)) {
|
|
1627
|
+ // if we started watering with a full tank
|
|
1628
|
+ // and then finished watering when it was empty
|
|
1629
|
+ // and we were only watering a single plant
|
|
1630
|
+ // look at this as a "calibration run" and record
|
|
1631
|
+ // the time it took to empty the tank
|
|
1632
|
+ if (watering_started_full && (selected_plants.countSet() == 1)) {
|
|
1633
|
+ unsigned long time_to_water = stop_time - start_time;
|
|
1634
|
+ debug.print("Watering plant ");
|
|
1635
|
+ debug.print(selected_plants.getFirstSet() + 1);
|
|
1636
|
+ debug.print(" with the complete tank took ");
|
|
1637
|
+ debug.print(String(time_to_water));
|
|
1638
|
+ debug.println("ms");
|
1456
|
1639
|
|
1457
|
|
-#if defined(PLATFORM_ESP)
|
1458
|
|
- bool success = wifi_write_database(time_to_water, "calibrated_watering", selected_plants.getFirstSet() + 1);
|
1459
|
|
- if (!success) {
|
1460
|
|
- debug.print("Error writing to InfluxDB ");
|
1461
|
|
- debug.print(INFLUXDB_HOST);
|
1462
|
|
- debug.print(":");
|
1463
|
|
- debug.print(INFLUXDB_PORT);
|
1464
|
|
- debug.print("/");
|
1465
|
|
- debug.print(INFLUXDB_DATABASE);
|
1466
|
|
- debug.println("/calibrated_watering");
|
|
1640
|
+ #if defined(PLATFORM_ESP)
|
|
1641
|
+ bool success = wifi_write_database(time_to_water, "calibrated_watering", selected_plants.getFirstSet() + 1);
|
|
1642
|
+ if (!success) {
|
|
1643
|
+ debug.print("Error writing to InfluxDB ");
|
|
1644
|
+ debug.print(INFLUXDB_HOST);
|
|
1645
|
+ debug.print(":");
|
|
1646
|
+ debug.print(INFLUXDB_PORT);
|
|
1647
|
+ debug.print("/");
|
|
1648
|
+ debug.print(INFLUXDB_DATABASE);
|
|
1649
|
+ debug.println("/calibrated_watering");
|
|
1650
|
+ }
|
|
1651
|
+ #endif // PLATFORM_ESP
|
1467
|
1652
|
}
|
1468
|
|
-#endif // PLATFORM_ESP
|
1469
|
1653
|
}
|
1470
|
1654
|
|
1471
|
|
- switch_to(auto_done);
|
|
1655
|
+ if ((state == auto_plant_run) || (state == fillnwater_plant_run)) {
|
|
1656
|
+ switch_to(auto_done);
|
|
1657
|
+ } else if (state == fullauto_plant_run) {
|
|
1658
|
+ start_time = millis();
|
|
1659
|
+ selected_time = OVERRUN_RUNTIME;
|
|
1660
|
+ switch_to(fullauto_plant_overrun);
|
|
1661
|
+ } else if (state == fullauto_plant_purge_run) {
|
|
1662
|
+ start_time = millis();
|
|
1663
|
+ selected_time = OVERRUN_RUNTIME;
|
|
1664
|
+ switch_to(fullauto_plant_purge_overrun);
|
|
1665
|
+
|
|
1666
|
+ }
|
1472
|
1667
|
} else if (wl == Plants::invalid) {
|
1473
|
1668
|
plants.abort();
|
1474
|
1669
|
error_condition = F("Invalid sensor state");
|