Components and supplies
1
RTC Module
1
9V 1A Switching Wall Power Supply
1
Resistor 10k ohm
1
Metalic Case
1
Resistor 4.7k Ohm
1
DHT22 Temperature Sensor
1
Arduino UNO
1
Infrared Module (Generic)
1
Capacitor 10 µF
1
Single Turn Potentiometer- 10k ohms
1
Adafruit Waterproof DS18B20 Digital temperature sensor
1
Breadboard (generic)
1
RGB Backlight LCD - 16x2
2
2-Channel SPDT Relay Carrier with 5VDC Relays
Tools and machines
1
Mastech MS8217 Autorange Digital Multimeter
1
Hot glue gun (generic)
1
Soldering iron (generic)
Project description
Code
Aquarium server
Sketch File
arduino
1#include "RTClib.h" 2#include <Time.h> 3#include <TimeAlarms.h> 4#include <DHT.h> 5#include <OneWire.h> 6#include <DallasTemperature.h> 7#include <LiquidCrystal.h> 8#include <EEPROM.h> 9#include "IRremote.h" 10 11// RTC 12RTC_DS1307 rtc; 13 14// DHT humidity senzor 15#define DHTPIN 10 // what pin we're connected to 16#define DHTTYPE DHT22 // DHT 22 (AM2302) 17DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino 18 19// Water proof senzor DS18B20 20#define ONE_WIRE_BUS 13 21OneWire oneWire(ONE_WIRE_BUS); 22DallasTemperature sensors(&oneWire); 23 24// LCD screen 25LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 26byte degSymbol[8] = { 27 B11100, 28 B10100, 29 B11100, 30 B00000, 31 B00000, 32 B00000, 33 B00000, 34}; 35int lcdPage = 0; 36 37// IR 38int irPin = 6; 39IRrecv irrecv(irPin); 40decode_results irResults; 41long irKey = 0; 42 43// Serial read globals 44char rx_byte = 0; 45String key = ""; 46bool isKey = false; 47String value = ""; 48bool isValue = false; 49 50// Aquarium LED default values 51int led1OnH = 8; 52int led1OnM = 30; 53int led1OffH = 12; 54int led1OffM = 30; 55int led2OnH = 18; 56int led2OnM = 30; 57int led2OffH = 20; 58int led2OffM = 0; 59 60int led1OnHAddress = 0; 61int led1OnMAddress = 1; 62int led1OffHAddress = 2; 63int led1OffMAddress = 3; 64int led2OnHAddress = 4; 65int led2OnMAddress = 5; 66int led2OffHAddress = 6; 67int led2OffMAddress = 7; 68 69// Aquarium CO2 default values 70int co2OnH = 7; 71int co2OnM = 0; 72int co2OffH = 21; 73int co2OffM = 0; 74 75int co2OnHAddress = 8; 76int co2OnMAddress = 9; 77int co2OffHAddress = 10; 78int co2OffMAddress = 11; 79 80// Aquarium options 81bool ledAuto = true; 82bool co2Auto = true; 83bool co2On = false; 84bool ledOn = false; 85 86// Aquarium status 87float aquariumTemp; 88 89// Ambient status 90float ambientTemp, ambientHum; 91 92// Status send to DB every 15 mins 93int statusSendMinutes = 20; 94 95// Alarms 96AlarmID_t led1OnAlarm = 0; 97AlarmID_t led1OffAlarm = 0; 98AlarmID_t led2OnAlarm = 0; 99AlarmID_t led2OffAlarm = 0; 100AlarmID_t co2OnAlarm = 0; 101AlarmID_t co2OffAlarm = 0; 102 103// Relay pins 104int relayLed = 7; 105int relayCo2 = 8; 106 107void setup() { 108 pinMode(relayLed, OUTPUT); 109 pinMode(relayCo2, OUTPUT); 110 111 // Use only without RTC 112 // setTime(10,19,0,16,2,19); 113 114 Serial.begin(9600); 115 dht.begin(); 116 sensors.begin(); 117 118 lcd.createChar(0, degSymbol); 119 lcd.begin(16, 2); 120 121 // Start Ir reciever 122 irrecv.enableIRIn(); // Start the receiver 123 124 if (! rtc.begin()) { 125 Serial.println("Couldn't find RTC"); 126 while (1); 127 } 128 129 if (! rtc.isrunning()) { 130 Serial.println("RTC is NOT running!"); 131 } 132 133 // Sync time lib with RTC 134 setSyncProvider(getRTCTime); 135 setSyncInterval(60 * 60 * 4); 136 137 // should run only once at initial setup 138 // writeSettingsFromMemory(); 139 140 readSettingsFromMemory(); 141 updateLedState(); 142 updateCo2State(); 143 updateRelay(); 144 sendStatus(); 145 146 setAlarms(); 147 Alarm.timerRepeat(60 * statusSendMinutes, sendStatus); 148 Alarm.timerRepeat(60, updateLcd); 149} 150 151void loop() { 152 while(Serial.available()){ 153 // Read seril data and create key values pairs 154 rx_byte = Serial.read(); 155 156 if (rx_byte != '\n') { 157 if (rx_byte == '$') { 158 isValue = false; 159 isKey = true; 160 continue; 161 } 162 if (rx_byte == '=') { 163 isValue = true; 164 isKey = false; 165 continue; 166 } 167 if (rx_byte == '&') { 168 setData(); 169 170 value = ""; 171 key = ""; 172 isValue = false; 173 isKey = false; 174 continue; 175 } 176 177 if (!isKey) { 178 value += rx_byte; 179 } else { 180 key += rx_byte; 181 } 182 } else { 183 if (isValue) { 184 setData(); 185 186 if (key != "" && key != "ledOn" && key != "co2On") { 187 updateLedState(); 188 updateCo2State(); 189 updateAlarms(); 190 updateRelay(); 191 } 192 } 193 194 value = ""; 195 key = ""; 196 isKey = false; 197 isValue = false; 198 sendStatus(); 199 } 200 } 201 202 // IR remote loop 203 if (irrecv.decode(&irResults)) { 204 dumpIR(&irResults); 205 206 irrecv.resume(); // Receive the next value 207// Serial.println(irKey, HEX); 208// Serial.println(); 209 210 if (irKey == 16720605) { 211 toggleLed(); 212 } else if (irKey == 16712445) { 213 toggleCo2(); 214 } else if (irKey == 16724175) { 215 loopLcdPage(-1); 216 } else if (irKey == 16743045) { 217 loopLcdPage(1); 218 } 219 } 220 221 Alarm.delay(1000); 222} 223 224void dumpIR(decode_results *irResults) { 225 int count = irResults->rawlen; 226 irKey = irResults->value; 227} 228 229 230void setAlarms() { 231 led1OnAlarm = Alarm.alarmRepeat(led1OnH, led1OnM, 20, LedOn); 232 led1OffAlarm = Alarm.alarmRepeat(led1OffH, led1OffM, 20, LedOff); 233 234 if (led2OnH != 0) { 235 led2OnAlarm = Alarm.alarmRepeat(led2OnH, led2OnM, 20, LedOn); 236 led2OffAlarm = Alarm.alarmRepeat(led2OffH, led2OffM, 40, LedOff); 237 } 238 239 co2OnAlarm = Alarm.alarmRepeat(co2OnH, co2OnM, 40, Co2On); 240 co2OnAlarm = Alarm.alarmRepeat(co2OffH, co2OffM, 40, Co2Off); 241} 242 243void updateAlarms() { 244 Alarm.free(led1OnAlarm); 245 Alarm.free(led1OffAlarm); 246 247 if (led2OnH != 0) { 248 Alarm.free(led2OnAlarm); 249 Alarm.free(led2OffAlarm); 250 } 251 252 Alarm.free(co2OnAlarm); 253 Alarm.free(co2OffAlarm); 254 255 setAlarms(); 256} 257 258void sendStatus() { 259 readSensors(); 260 261 Serial.print("LOG"); 262 Serial.print("||"); 263 Serial.print(now()); 264 Serial.print("||"); 265 Serial.print(ledOn); 266 Serial.print("||"); 267 Serial.print(ledAuto); 268 Serial.print("||"); 269 Serial.print(led1OnH); 270 Serial.print(":"); 271 Serial.print(led1OnM); 272 Serial.print("||"); 273 Serial.print(led1OffH); 274 Serial.print(":"); 275 Serial.print(led1OffM); 276 Serial.print("||"); 277 Serial.print(led2OnH); 278 Serial.print(":"); 279 Serial.print(led2OnM); 280 Serial.print("||"); 281 Serial.print(led2OffH); 282 Serial.print(":"); 283 Serial.print(led2OffM); 284 Serial.print("||"); 285 Serial.print(co2On); 286 Serial.print("||"); 287 Serial.print(co2Auto); 288 Serial.print("||"); 289 Serial.print(co2OnH); 290 Serial.print(":"); 291 Serial.print(co2OnM); 292 Serial.print("||"); 293 Serial.print(co2OffH); 294 Serial.print(":"); 295 Serial.print(co2OffM); 296 Serial.print("||"); 297 Serial.print(ambientTemp); 298 Serial.print("||"); 299 Serial.print(ambientHum); 300 Serial.print("||"); 301 Serial.println(aquariumTemp); 302 303 Alarm.delay(500); 304 lcd.clear(); 305 updateLcd(); 306} 307 308// Function called once serial has recieved a key value pair 309void setData() { 310 if (key == "") { 311 return; 312 } 313 314 bool newStatus; 315 Serial.print(key); 316 Serial.println(value); 317 318 if ( key == "led1OnH" ) { 319 led1OnH = value.toInt(); 320 EEPROM.update(led1OnHAddress, led1OnH); 321 } 322 else if ( key == "led1OffH" ) { 323 led1OffH = value.toInt(); 324 EEPROM.update(led1OffHAddress, led1OffH); 325 } 326 else if ( key == "led1OnM" ) { 327 led1OnM = value.toInt(); 328 EEPROM.update(led1OnMAddress, led1OnM); 329 } 330 else if ( key == "led1OffM" ) { 331 led1OffM = value.toInt(); 332 EEPROM.update(led1OffMAddress, led1OffM); 333 } 334 else if ( key == "led2OnH" ) { 335 led2OnH = value.toInt(); 336 EEPROM.update(led2OnHAddress, led2OnH); 337 } 338 else if ( key == "led2OffH" ) { 339 led2OffH = value.toInt(); 340 EEPROM.update(led2OffHAddress, led2OffH); 341 } 342 else if ( key == "led2OnM" ) { 343 led2OnM = value.toInt(); 344 EEPROM.update(led2OnMAddress, led2OnM); 345 } 346 else if ( key == "led2OffM" ) { 347 led2OffM = value.toInt(); 348 EEPROM.update(led2OffMAddress, led2OffM); 349 } 350 else if ( key == "ledOn" ) { 351 bool newStatus = value == "true"; 352 if (ledOn != newStatus) { 353 ledAuto = !ledAuto; 354 } 355 356 ledOn = newStatus; 357 updateRelay(); 358 } 359 else if ( key == "co2On" ) { 360 bool newStatus = value == "true"; 361 if (co2On != newStatus) { 362 co2Auto = !co2Auto; 363 } 364 365 co2On = newStatus; 366 updateRelay(); 367 } 368 else if ( key == "co2OnH" ) { 369 co2OnH = value.toInt(); 370 EEPROM.update(co2OnHAddress, co2OnH); 371 } 372 else if ( key == "co2OffH" ) { 373 co2OffH = value.toInt(); 374 EEPROM.update(co2OffHAddress, co2OffH); 375 } 376 else if ( key == "co2OnM" ) { 377 co2OnM = value.toInt(); 378 EEPROM.update(co2OnMAddress, co2OnM); 379 } 380 else if ( key == "co2OffM" ) { 381 co2OffM = value.toInt(); 382 EEPROM.update(co2OffMAddress, co2OffM); 383 } 384} 385 386void readSettingsFromMemory() { 387 led1OnH = EEPROM.read(led1OnHAddress); 388 led1OffH = EEPROM.read(led1OffHAddress); 389 led1OnM = EEPROM.read(led1OnMAddress); 390 led1OffM = EEPROM.read(led1OffMAddress); 391 led2OnH = EEPROM.read(led2OnHAddress); 392 led2OffH = EEPROM.read(led2OffHAddress); 393 led2OnM = EEPROM.read(led2OnMAddress); 394 led2OffM = EEPROM.read(led2OffMAddress); 395 396 co2OnH = EEPROM.read(co2OnHAddress); 397 co2OffH = EEPROM.read(co2OffHAddress); 398 co2OnM = EEPROM.read(co2OnMAddress); 399 co2OffM = EEPROM.read(co2OffMAddress); 400} 401 402void writeSettingsFromMemory() { 403 EEPROM.write(led1OnHAddress, led1OnH); 404 EEPROM.write(led1OffHAddress, led1OffH); 405 EEPROM.write(led1OnMAddress, led1OnM); 406 EEPROM.write(led1OffMAddress, led1OffM); 407 EEPROM.write(led2OnHAddress, led2OnH); 408 EEPROM.write(led2OffHAddress, led2OffH); 409 EEPROM.write(led2OnMAddress, led2OnM); 410 EEPROM.write(led2OffMAddress, led2OffM); 411 412 EEPROM.write(co2OnHAddress, co2OnH); 413 EEPROM.write(co2OffHAddress, co2OffH); 414 EEPROM.write(co2OnMAddress, co2OnM); 415 EEPROM.write(co2OffMAddress, co2OffM); 416} 417 418 419void updateLedState() { 420 if (!ledAuto) { 421 return; 422 } 423 int h = hour(); 424 int m = minute(); 425 426 if (led1OnH > h || led2OffH < h) { 427 ledOn = false; 428 return; 429 } 430 431 if (led1OffH < h && led2OnH > h) { 432 ledOn = false; 433 return; 434 } 435 436 if (led1OnH == h && led1OnM > m ) { 437 ledOn = false; 438 return; 439 } 440 441 if (led1OffH == h && led1OffM <= m ) { 442 ledOn = false; 443 return; 444 } 445 446 if (led2OnH == h && led2OnM > m ) { 447 ledOn = false; 448 return; 449 } 450 451 if (led2OffH == h && led2OffM <= m ) { 452 ledOn = false; 453 return; 454 } 455 456 ledOn = true; 457} 458 459void updateCo2State() { 460 if (!co2Auto) { 461 return; 462 } 463 464 int h = hour(); 465 int m = minute(); 466 467 if (co2OnH > h || co2OffH < h) { 468 co2On = false; 469 return; 470 } 471 472 if (co2OnH == h && co2OnM > m ) { 473 co2On = false; 474 return; 475 } 476 477 if (co2OffH == h && co2OffM <= m ) { 478 co2On = false; 479 return; 480 } 481 482 co2On = true; 483} 484 485void toggleLed() { 486 ledOn = !ledOn; 487 ledAuto = !ledAuto; 488 489 updateRelay(); 490 sendStatus(); 491} 492 493void toggleCo2() { 494 co2On = !co2On; 495 co2Auto = !co2Auto; 496 497 updateRelay(); 498 sendStatus(); 499} 500 501void updateLcd() { 502 if (lcdPage == 1) { 503 updateLcdPage1(); 504 } else if (lcdPage == 2) { 505 updateLcdPage2(); 506 } else if (lcdPage == 3) { 507 updateLcdPage3(); 508 } else { 509 updateLcdPage0(); 510 } 511} 512 513void loopLcdPage(int val) { 514 int newPage = lcdPage + val; 515 516 if (newPage > 3) { 517 newPage = 0; 518 } 519 520 if (newPage < 0) { 521 newPage = 3; 522 } 523 524 lcdPage = newPage; 525 updateLcd(); 526} 527 528void updateLcdPage0() { 529 int h = hour(); 530 int m = minute(); 531 532 lcd.setCursor(0,0); 533 if (h < 10) { 534 lcd.print(F("0")); 535 } 536 lcd.print(h); 537 lcd.print(":"); 538 if (m < 10) { 539 lcd.print(F("0")); 540 } 541 lcd.print(m); 542 lcd.print(F(" | ")); 543 lcd.print((int) ambientTemp); 544 lcd.write(byte(0)); 545 lcd.print(F(" ")); 546 lcd.print((int) ambientHum); 547 lcd.print(F("% ")); 548 lcd.setCursor(0,1); 549 lcd.print(aquariumTemp); 550 lcd.write(byte(0)); 551 lcd.print(F(" ")); 552 lcd.print(ledOn); 553 lcd.print(F("-")); 554 if (ledAuto) { 555 lcd.print(F("A")); 556 } else { 557 lcd.print(F("M")); 558 } 559 lcd.print(F(" ")); 560 lcd.print(co2On); 561 lcd.print(F("-")); 562 if (co2Auto) { 563 lcd.print(F("A")); 564 } else { 565 lcd.print(F("M")); 566 } 567 lcd.print(F(" ")); 568} 569 570void updateLcdPage1() { 571 lcd.setCursor(0,0); 572 lcd.print(F("LED: ")); 573 if (ledOn) { 574 lcd.print(F("on ")); 575 } else { 576 lcd.print(F("off")); 577 } 578 579 lcd.print(F(" | ")); 580 581 if (ledAuto) { 582 lcd.print(F("auto ")); 583 } else { 584 lcd.print(F("user ")); 585 } 586 lcd.setCursor(0,1); 587 lcd.print(F("CO2: ")); 588 if (ledOn) { 589 lcd.print(F("on ")); 590 } else { 591 lcd.print(F("off")); 592 } 593 594 lcd.print(F(" | ")); 595 596 if (co2Auto) { 597 lcd.print(F("auto ")); 598 } else { 599 lcd.print(F("user ")); 600 } 601} 602 603void updateLcdPage2() { 604 605 lcd.setCursor(0,0); 606 lcd.print(F("LED: ")); 607 if (led1OnH < 10) { 608 lcd.print(F("0")); 609 } 610 lcd.print(led1OnH); 611 lcd.print(":"); 612 if (led1OnM < 10) { 613 lcd.print(F("0")); 614 } 615 lcd.print(led1OnM); 616 lcd.print(F("-")); 617 if (led1OffH < 10) { 618 lcd.print(F("0")); 619 } 620 lcd.print(led1OffH); 621 lcd.print(":"); 622 if (led1OffM < 10) { 623 lcd.print(F("0")); 624 } 625 lcd.print(led1OffM); 626 627 lcd.setCursor(0,1); 628 lcd.print(F(" ")); 629 if (led2OnH < 10) { 630 lcd.print(F("0")); 631 } 632 lcd.print(led2OnH); 633 lcd.print(":"); 634 if (led2OnM < 10) { 635 lcd.print(F("0")); 636 } 637 lcd.print(led2OnM); 638 lcd.print(F("-")); 639 if (led2OffH < 10) { 640 lcd.print(F("0")); 641 } 642 lcd.print(led2OffH); 643 lcd.print(":"); 644 if (led2OffM < 10) { 645 lcd.print(F("0")); 646 } 647 lcd.print(led2OffM); 648} 649 650void updateLcdPage3() { 651 lcd.setCursor(0,0); 652 lcd.print(F("CO2: ")); 653 if (co2OnH < 10) { 654 lcd.print(F("0")); 655 } 656 lcd.print(co2OnH); 657 lcd.print(":"); 658 if (co2OnM < 10) { 659 lcd.print(F("0")); 660 } 661 lcd.print(co2OnM); 662 lcd.print(F("-")); 663 if (co2OffH < 10) { 664 lcd.print(F("0")); 665 } 666 lcd.print(co2OffH); 667 lcd.print(":"); 668 if (co2OffM < 10) { 669 lcd.print(F("0")); 670 } 671 lcd.print(co2OffM); 672 lcd.setCursor(0,1); 673 lcd.print(F(" ")); 674} 675 676void readSensors() { 677 ambientTemp = dht.readTemperature(); 678 ambientHum = dht.readHumidity(); 679 sensors.requestTemperatures(); 680 aquariumTemp = sensors.getTempCByIndex(0); 681} 682 683void updateRelay() { 684 if (ledOn) { 685 setRelayState(0, 1); 686 } else { 687 setRelayState(0, 0); 688 } 689 690 if (co2On) { 691 setRelayState(1, 1); 692 } else { 693 setRelayState(1, 0); 694 } 695} 696 697void setRelayState(int relay, int state) { 698 if (relay == 1) digitalWrite(relayCo2, state); 699 if (relay == 0) digitalWrite(relayLed, state); 700} 701 702// functions to be called when an alarm triggers: 703void LedOn(){ 704 ledOn = true; 705 ledAuto = true; 706 updateRelay(); 707 sendStatus(); 708} 709 710void LedOff(){ 711 ledOn = false; 712 ledAuto = true; 713 updateRelay(); 714 sendStatus(); 715} 716 717void Co2On(){ 718 co2On = true; 719 co2Auto = true; 720 updateRelay(); 721 sendStatus(); 722} 723 724void Co2Off(){ 725 co2On = false; 726 co2Auto = true; 727 updateRelay(); 728 sendStatus(); 729} 730 731// Returns RTC date time 732// Used to sync alarm library 733time_t getRTCTime() { 734 DateTime now = rtc.now(); 735 Serial.println("Sync RTC time"); 736 return now.unixtime(); 737} 738
Aquarium server
Downloadable files
Fritzing
Fritzing

Fritzing
Fritzing

Comments
Only logged in users can leave comments