Components and supplies
RTC Module
9V 1A Switching Wall Power Supply
Resistor 10k ohm
Metalic Case
Resistor 4.7k Ohm
DHT22 Temperature Sensor
Arduino UNO
Infrared Module (Generic)
Capacitor 10 µF
Single Turn Potentiometer- 10k ohms
Adafruit Waterproof DS18B20 Digital temperature sensor
Breadboard (generic)
RGB Backlight LCD - 16x2
2-Channel SPDT Relay Carrier with 5VDC Relays
Tools and machines
Mastech MS8217 Autorange Digital Multimeter
Hot glue gun (generic)
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