Аквариумный контроллер
- Войдите на сайт для отправки комментариев
Всем доброго дня, появился у меня небольшой (40) литров аквариум, и так как ардуина и некотроые шилды валялись без дела в ящике стола, я решил собрать некое подобие аквариумного контроллера. Вдруг гому понадобится такая штука.
Пока что он умеет следующее:
Отображать температуру с датчика DS18B20 и времени c DS1307 на дисплее 1602 и на веб-страничке через шилд W5100. Так же умеет зажигать светодиод на 8 пине в 19.00 и тушить его в 0.00 , позже на его месте будет твердотелоное реле, оно будет включать и выключать аквариумное освещение.
Есть некоторые планы для развития этого гаджета, и по ходу дела буду обновлять темы и просить тут совета у бывалых, так как я только учусь :)
На сегодняшний день код выглядит так:
#include <DS1307new.h> // for clock #include <Wire.h> // for i2c protocol #include <OneWire.h> // for DS18B20 #include <LiquidCrystal_I2C.h> // for 1602 #include <SPI.h> #include <Ethernet.h> OneWire ds(6); // on pin 10 (a 4.7K resistor is necessary) int ledPin = 8; // pin for LED LiquidCrystal_I2C lcd(0x20,16,2); // 0x20 is adresss for LCC 16x2 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192,168,3,177); EthernetServer server(80); byte grad[8] = { // рисует значек градуса B01110, B10001, B10001, B01110, B00000, B00000, B00000, }; int ics =0; //count number of sensor void setup(){ pinMode(ledPin, OUTPUT); Serial.begin(9600); lcd.init(); lcd.backlight(); //backlight is now ON // set up the LCD's number of columns and rows: lcd.createChar(0, grad); lcd.begin(16, 2); /* Print a logo message to the LCD. lcd.print("AQUACONTROLLER"); lcd.setCursor(0, 1); lcd.print("by iWizard"); delay (2500); lcd.clear(); */ // Print a message to the LCD. // lcd.setCursor(1, 0); // lcd.print("temperatura in"); // lcd.setCursor(1, 1); // lcd.print("mai multe zone"); // delay (2500); // lcd.clear(); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } // start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); } void loop(){ byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius; if ( !ds.search(addr)) { // lcd.clear(); lcd.setCursor(0, 1); // lcd.print("doar "); // lcd.print(ics); // lcd.print(" senzor(i)"); ds.reset_search(); ics=0; if (RTC.hour >= 19 && RTC.hour <= 23) digitalWrite(ledPin, HIGH); //устанавливаем время и зажигаем светодиод else digitalWrite(ledPin, LOW); // тушим светодиод /// начало кода часов/// RTC.getTime(); if (RTC.hour < 10) { Serial.println(); Serial.print("0"); Serial.print(RTC.hour, DEC); } else { Serial.print(RTC.hour, DEC); } Serial.print(":"); if (RTC.minute < 10) Serial.print("0"); Serial.print(RTC.minute, DEC); Serial.print(":"); if (RTC.second < 10) Serial.print("0"); Serial.print(RTC.second, DEC); Serial.print(" "); if (RTC.day < 10) Serial.print("0"); Serial.print(RTC.day, DEC); Serial.print("-"); if (RTC.month < 10) Serial.print("0"); Serial.print(RTC.month, DEC); Serial.print("-"); Serial.print(RTC.year, DEC); Serial.print(" "); Serial.print("-"); //Serial.print(RTC.dow, DEC); switch (RTC.dow) { case 0: Serial.print("SUN"); break; case 1: Serial.print("MON"); break; case 2: Serial.print("TUE"); break; case 3: Serial.print("WED"); break; case 4: Serial.print("THU"); break; case 5: Serial.print("FRI"); break; case 6: Serial.print("SAT"); break; } ics++; ds.reset(); ds.select(addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end delay(1000); // maybe 750ms is enough, maybe not // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } // Convert the data to actual temperature // because the result is a 16 bit signed integer, it should // be stored to an "int16_t" type, which is always 16 bits // even when compiled on a 32 bit processor. int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { // "count remain" gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // at lower res, the low bits are undefined, so let's zero them if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms //// default is 12 bit resolution, 750 ms conversion time } //lcd.clear(); //lcd.setCursor(0, 1); // lcd.print("ROM="); // for( i = 0; i < 8; i++) { // lcd.print(' '); // lcd.print(addr[i], HEX); // } if (OneWire::crc8(addr, 7) != addr[7]) { lcd.print("CRC is not valid!"); return; } celsius = (float)raw / 16.0; lcd.setCursor(0,0); lcd.print("Temp"); // lcd.print(ics); //показывает номер датчика lcd.print(" = "); lcd.print(celsius); lcd.write(byte(0)); lcd.print("C "); //вывод часов на дисплей// lcd.setCursor(0, 1); if(RTC.hour<10)lcd.print(0); lcd.print(RTC.hour); lcd.print(":"); //lcd.print( (RTC.second %2 )?" ":":"); //мигать двоеточием if(RTC.minute<10)lcd.print(0); lcd.print(RTC.minute); //lcd.print(":"); //lcd.print( (RTC.second %2 )?" ":":"); //мигать двоеточием //if(RTC.second<10)lcd.print(0); //lcd.print(RTC.second); //lcd.print(" "); //lcd.print(RTC.dow); //lcd.print(RTC.month); //lcd.print("-"); //lcd.print(RTC.year); lcd.setCursor(10, 1); switch (RTC.dow) // Friendly printout the weekday { case 0: lcd.print("SUN"); break; case 1: lcd.print("MON"); break; case 2: lcd.print("TUE"); break; case 3: lcd.print("WED"); break; case 4: lcd.print("THU"); break; case 5: lcd.print("FRI"); break; case 6: lcd.print("SAT"); break; } lcd.print("-"); lcd.print(RTC.day); // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply //if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("<head> "); client.println("<meta http-equiv=Content-Type content=text/html; charset=utf-8/>"); client.println("<title> Arduino :: Акваконтролеер</title>"); client.println("</head> "); client.println("<body bgcolor=#B0C4DE>"); // цвет фона client.println("Connection: close"); // the connection will be closed after completion of the response client.println("Refresh: 5"); // refresh the page automatically every 5 sec client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<center>"); // output the value of each analog input pin for (int analogChannel = 0; analogChannel < 1; analogChannel++) { int sensorReading = analogRead(analogChannel); client.println("<H1>"); client.print(RTC.hour, DEC); client.print(":"); if (RTC.minute < 10) client.print("0"); client.print(RTC.minute, DEC); client.println("<br>"); client.println("</h1>"); client.println("<h2>"); if (RTC.day < 10) client.print("0"); client.print(RTC.day, DEC); client.print(" "); // if (RTC.month < 10) client.print("0"); // client.print(RTC.month, DEC); switch (RTC.month) { case 1: client.print("Января"); break; case 2: client.print("Февраля"); break; case 3: client.print("Марта"); break; case 4: client.print("Апреля"); break; case 5: client.print("Мая"); break; case 6: client.print("Июня"); break; case 7: client.print("Июля"); break; case 8: client.print("Августа"); break; case 9: client.print("Сентября"); break; case 10: client.print("Октября"); break; case 11: client.print("Ноября"); break; case 12: client.print("Декабря"); break; } client.print(" "); client.print(RTC.year, DEC); client.print(" "); client.print(","); switch (RTC.dow) { case 0: client.print("Воскресенье"); break; case 1: client.print("Понедельник"); break; case 2: client.print("Вторник"); break; case 3: client.print("Среда"); break; case 4: client.print("Четверг"); break; case 5: client.print("Пятница"); break; case 6: client.print("Суббота"); break; } client.println("</h2>"); client.println("<br>"); client.print("Температура"); // lcd.print(ics); //показывает номер датчика client.print(" = "); client.print(celsius); client.write(byte(0)); client.print("C"); /////////////////////////////////////////////////////////////////////// } client.println("</center>"); client.println("</html>"); break; // } // if (c == '\n') { // // you're starting a new line // currentLineIsBlank = true; // } // else if (c != '\r') { // // you've gotten a character on the current line // currentLineIsBlank = false; // } } } // give the web browser time to receive the data // delay(1); // close t1he connection: delay(500); client.stop(); Serial.println("client disonnected"); } } }
PS. схему сделаю в скором времени, и приложу все необходимые библиотеки которые я использовал.
И наверное сразу задам вопрос, как можно на веб страничке показать состояние светодиода (горит/не горит в данный момент)
И наверное сразу задам вопрос, как можно на веб страничке показать состояние светодиода (горит/не горит в данный момент)
META HTTP-EQUIV="Refresh" CONTENT="180" и подмена ссылок на картинку светодиода при изменении их состояния. Т.е., должна быть картинка горящего светодиода и выключенного.
И наверное сразу задам вопрос, как можно на веб страничке показать состояние светодиода (горит/не горит в данный момент)
META HTTP-EQUIV="Refresh" CONTENT="180" и подмена ссылок на картинку светодиода при изменении их состояния. Т.е., должна быть картинка горящего светодиода и выключенного.
Не, это я знаю про подмену картинок, тут вопрос в другом, как в коде реализовать переменную ? и как ее вставить в текст странички
Не, это я знаю про подмену картинок, тут вопрос в другом, как в коде реализовать переменную ? и как ее вставить в текст странички
А как Вы зажигаете светодиод? На каком-то пине меняете состояние на HIGH. Вот оттуда и берите значение, или рядом взводите еще одну переменную для web-интерфейса. А дальше - курите код формирования странички Вашим ethernet-шилдом - там примеры наверняка есть.
Не, это я знаю про подмену картинок, тут вопрос в другом, как в коде реализовать переменную ? и как ее вставить в текст странички
А как Вы зажигаете светодиод? На каком-то пине меняете состояние на HIGH. Вот оттуда и берите значение, или рядом взводите еще одну переменную для web-интерфейса. А дальше - курите код формирования странички Вашим ethernet-шилдом - там примеры наверняка есть.
Светодиод у меня зажигается воттаким образом
if
(RTC.hour >= 19 && RTC.hour <= 23) digitalWrite(ledPin, HIGH);
//устанавливаем время и зажигаем светодиод
else
digitalWrite(ledPin, LOW);
// тушим светодиод
Тоесть мне нужно написать что то нипа :
Тоесть мне нужно написать что то типа :
Я бы делал как-то так:
if ( digitalRead(ledPin) == HIGH ) {
client.print ("Led ON");
}
или прямо из первого условия:
if (RTC.hour >= 19 && RTC.hour <= 23) {
digitalWrite(ledPin, HIGH);
client.print ("Led ON");
}
Тоесть мне нужно написать что то типа :
Я бы делал как-то так:
if ( digitalRead(ledPin) == HIGH ) {
client.print ("Led ON");
}
или прямо из первого условия:
if (RTC.hour >= 19 && RTC.hour <= 23) {
digitalWrite(ledPin, HIGH);
client.print ("Led ON");
}
Спасибо, скоро попробую и отпишусь, мне лучше подойдет первый способ, так как я планирую не просто индикацию, а еще в будущем принудительное включение лампы, и чтобы было сразу видно включена она или нет :)
Все отлично получилось по первому примеру Andrey_Y_Ostanovsky :)
Еще вопрос, может кто подскажет какие материалы на тему как задействовать графику с SD карты на веб страничке?
Добавил к проекту индикацию максимальной и минимальной температуры на веб-страничке, так же добавил индикацию уровня освещенности , правда этот самый уровень - величина довольно таки относительная, теперь думаю нужен ли вообще этот показатель, если бы его сконвертировать в какую то определенную единицу то можно было бы оставить.
Всем привет, подскажите пожалуйста кто знает, так как я использую в проекте ethernet шилд на чипе wiznet5100 на этот же шилд может выступать картридером лоя карт micro-sd так вот в чем вопрос, если из скетча я вынесу вот этот код в отдельный html файл и положу его на карту памяти, будет он работать с нее ? цель: уменьшить скет, а то он уже занимает 20 кб из 32 возможных???
Код
Там, вроде бы, надо программно переключаться между устройствами, висящими на одной SPI шине: либо сетевуха, либо картридер... Сам - не проверял.
Вроде уже накопал примеры использования веб страничек и рисунков с сд карты, буду вечером пробовать, я просто думал может уже кто тут заморачивался уже
Пока внес небольшие косметические изменения и добавил функцию UPTIME
Скриншот:
Подскажите пожалуйста, вылез такой косяк, сначала все нормально как только запускаешь ардуину и заходишь на IP адрес ее, а при первом обновлении (через 5 секунд ) вылазит вот что
И не могу найти где косяк , кстати после того как выдает вот это уже не получается обраттится на эту страницу и обновить, пишет браузер что страница не найдена
похоже этот мусор на экране изза того что перегревается микруха w5100, как только запускашь ардуину все работает, но когда все зависает она горячая очень, если дать ей остыть то после этого все снова работает минуты 3, можеть быть какие то параметры нужно поправить в скетче чтобы меньше нагрузки на него было, или я не прав? неужели никто не сталкивался ? есть конечно вариант прилепить на него радиатор на термопасту но это не особо хороший выход
похоже этот мусор на экране изза того что перегревается микруха w5100,
Это фрагменты кода html странички, так что тут Ваша "микруха" скорее всего сажает контроллер так, что часть передаваемой информации теряется...
Почему то когда воткнута карта микро сд получается вот это, когда я ее вытащил стало все нормально, почему так может быть ?
Подскажите пожалйста как на страничке сделать две кнопки ON и OFF, соответственно включающие и выключающие светодиод принудительно, всю голову сломал....
Добавил возможность включения и выключения света кнопкой, пока только физической, также прикрутил сразу функцию DEBOUNCE которая утраняет эффект дребезга контактов
del
помогите разобраться пожалуйста, не работает включение кнопкой и включение по времени, тоесть либо одно либо другое, если закомментить код
Крайняя версия моего скетча
+Добавлена функция Uptime
*Планируется добавить изменение время включения и выключения света через веб интерфейс