Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'akwarium'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - roboty
    • Projekty - DIY
    • Projekty - DIY (początkujący)
    • Projekty - w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie
    • Kosz

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Znaleziono 3 wyniki

  1. Od kiedy tylko ludzie zaczęli interesować się akwarystyką od tego momentu postanowili na każdym kroku ułatwiać sobie pracę. Powstawały coraz to nowsze urządzenia – napowietrzacze, filtry, oświetlenia i tym podobne. Także w tej dziedzinie pojawiły się urządzenia w pełni zautomatyzowane (sterowane za pomocą różnego rodzaju przełączników oraz czujników). Przykładem takiego rozwiązania był chociażby sterownik akwariowy “Skalar”. Jako że powstał on w czasach gdy o diodach mało kto słyszał a sterowanie PWM już chyba nikt postanowiłem stworzyć własny sterownik akwariowy Bella. Jest to kompletny sterownik oparty na Arduino Nano v3. Sterownik akwariowy Bella – lista materiałów do budowy Obudowa uniwersalna Z1W Panel przedni MN-Tech Panel tylny MN-Tech Płytka prototypowa Bella Compact 1.1 moduł pod driver PWM firmy Meanwell (5 kanał) – opcjonalny arduino nano wraz z programem sterownika akwariowego Bella zegar ds1307 wyświetlacz LCD 20×4 znaki na szynie I2C termometr DS18b20 wodoodporny na kablu – 1 szt drivery firmy Meanwell serii LDD (dowolny model) (max 5 szt) przekaźnik 1 kanałowy – 2 szt przekaźnik 4 kanałowy – 1 szt kable połączeniowe FF długości 20cm do podłączenia modułów (30 szt – liczone z zapasem) gniazdo na goldpin 3 pinowe – 8 szt gniazdo na goldpin 4 pinowe – 2 szt (do wyświetlacza) gniazdo na goldpin 5 pinowe – 1 szt (do klawiatury) gniazdo na goldpin 6 pinowe – 2 szt (przekaźnik 4 kanałowy) zworka 2 pinowa (używana w przypadku braku sondy pH) przycisk chwilowy – 4 szt (jako klawiatura) włącznik kołyskowy okrągły – 2 szt gniazdo montażowe płaskie (GS-035) – 6 szt gniazdo zasilające na kabel ósemka – 1 szt gniazdo + wtyk 3 pinowy mini CB (termometr) gniazdo + wtyk 2 pinowy mini CB do podłączenia zasilania driverów 2x gniazdo + 2x wtyk 4 pinowy CB na listwę led (każde na 2 kanały oświetlenia) lub 1 gniazdo CB 8 pinowe na 4 kanały gniazdo montażowe do zasilania arduino 5,5/2,1 gniazdo bezpiecznikowe – 1 szt śruby czarne M3 długość 12mm – około 30szt nakrętki M3 – około 60 sztuk Oświetlenie Najważniejszym założeniem sterownika akwariowego Bella było oczywiście sterowanie oświetleniem. Sterownik obsługuje 5 kanałów PWM. Na samej płytce jest miejsce na zamontowanie 5 driverów z firmy Meanwell (dowolnych od LDD-300L do LDD-1500H). 4 z nich znajdują się na płytce natomiast piąty można zamontować osobno na dodatkowej płytce. Napięcie zasilania driverów jest w zakresie od 12 do 48V. Na płytce zostały wyciągnięte piny pwm oraz masy do podłączenia dodatkowych driverów. Moc każdego kanału można ustawić dowolnie w granicy 0-100% (wartości 0-255 na wyświetlaczu). Wszystkie kanały włączają się jednocześnie i gaszą o tej samej godzinie (wyjątkiem są kanały 1 i 2, które w przypadku ustawienia oświetlenia nocnego gaszą się dopiero o północy. W przypadku kiedy moc któregoś z kanałów jest zmniejszona jego ściemnianie / rozjaśnianie działa tak samo długo lecz jest proporcjonalnie wolniejsze (skoki są mniejsze). Długości i zakresy które można ustawić w tym dziale zostaną opisane w ostatnim akapicie “Zakresy”. Termostat Kolejnym punktem jest zastosowanie wodoodpornego termometru DS18b20 i możliwość podłączenia do niego dwóch niezależnych urządzeń (np grzałki oraz chłodnicy czy też wentylatora). Jak w poprzednim punkcie zakresy zostały opisane na końcu. W przypadku awarii / odpięcia termometru temperatura na wyświetlaczu znika (zostaje zastąpiona przez znaki –. Dodatkowo w ramach zabezpieczenia w takim przypadku gniazda zarówno grzania jak i chłodzenia zostają odłączone od zasilania. W przypadku tej funkcjonalności mamy dostępne 2 zmienne. Pierwsza to temperatura (oznaczająca temperaturę dolną) poniżej której uruchomiona zostanie grzałka. Druga to histereza. Główną wartością jest temperatura – jest to deklarowana wartość dolna poniżej której uruchomiony zostanie przekaźnik odpowiadający za grzałkę. Na wyświetlaczu zmieni się opis z G-OFF na G- ON. Temperatura będzie rosła do momentu przekroczenia 1x histerezy w górę. W przypadku jeśli temperatura przekroczy wartość zadaną + 2x histerezę uruchomi się chłodzenie i będzie działać do momentu w którym włączyło się grzanie (T+H). Stycznik 1 oraz stycznik 2 Stycznik 1 może zostać ustawiony w 2 trybach – pierwszym z nich jest to tryb pracy do sterowania elektrozaworem do CO2 (sterowanie uruchamia się automatycznie po podłączeniu sondy pH). Drugim trybem jest uruchamianie się 1x dziennie na dowolny okres (od 1 minuty do 23 godzin i 59 minut). W przypadku gdy nie ma podpiętej sondy pH do sterownika należy zrobić mostek pomiędzy pinem A7 a pinem GND – program automatycznie zmienia działanie stycznika na tryb pracy 1x dziennie. Stycznik 2 działa tylko jako uruchamiany 1x dziennie (jak wyżej). Stycznik 3 oraz stycznik 4 Działają one automatycznie w zależności od pór dnia. Stycznik numer 3 uruchamia się w momencie rozpoczęcia świtu i wyłącza w momencie gdy kończy się zmrok. Stycznik numer 4 uruchamia się tylko w czasie trwania dnia. Sonda pH Program obsługuje sondy pH opisane w tym artykule. Podpinana jest ona do pinu A7. Za jej pomocą sterowany jest stycznik numer 1 do którego można podpiąć jak pisałem powyżej elektrozawór dozujący CO2. W momencie w którym nie mamy podpiętej sondy pH należy zewrzeć piny A7 oraz GND. Dzięki temu stycznik nr 1 przełącza się na działanie 1x dziennie. Wartości które możemy zmieniać to dolna granica pH oraz histereza. Po przekroczeniu górnej granicy uruchomiony zostaje stycznik (do którego można podłączyć elektrozawór dozujący CO2) i działa on do momentu obniżenia pH poniżej zadanej wartości. Oświetlenie awaryjne Pin analogowy A6 został przygotowany jako uruchamianie oświetlenia awaryjnego. W przypadku gdy pin zwarty jest do masy (za pomocą rezystora 10kOhm program działa w normalnym trybie. Gdy włącznik zostanie uruchomiony i zwarty do pinu 5V oświetlenie zacznie świecić na około 50% mocy (na tyle mocno żeby było widać lecz aby nie oślepiać). W tryb pracy awaryjnej zostaną uruchomione kanały 1 oraz 2. Do uruchomienia oświetlenia awaryjnego służy przycisk na boku obudowy (z przodu) po stronie wyświetlacza. Wyłącznik oświetlenia Istnieje także możliwość wyłączenia całkowicie napięcia podawanego na diody. Do tego celu służy przełącznik znajdujący się z boku obudowy (od strony wyświetlacza z tyłu). Dzięki temu możemy w sytuacji w której jest potrzeba odpięcia oświetlenia od sterownika odłączyć całkowicie zasilanie driverów. Wyświetlacz LCD Sterownik akwariowy Bella oferuje dwa tryby działania. Pierwszym z nich jest tryb wyświetlania informacji znajdujących się na sterowniku. Poniżej znajduje się właśnie taki układ. Na żółto zostały oznaczone pola odpowiednio od góry: Grzałka, Wentylator, Stycznik 1 (jeśli używamy sondy pH zmienia się jego nazwa z S na C – można podpiąć do niego elektrozawór CO2) oraz Stycznik S2. Styczniki S3 oraz S4 (ich godziny działania) wyświetlane są w menu rotacyjnym na dole ekranu. Kolejnym trybem w jakim pracuje ten sterownik akwariowy jest tryb menu. Aby go uruchomić należy jednocześnie przytrzymać przyciski + oraz – (góra i dół). W tym momencie układ wyświetlacza zmieni się całkowicie na prezentowany poniżej: Funkcje menu (nazwa, dostępne wartości oraz ich skoki) W trybie ustawień zmieniają się dwa dolne wiersze na wyświetlaczu. Na górnym jest informacja o aktualnie zmienianej funkcji oraz jej wartości. W dolnym rzędzie pokazany jest dostępny zakres w jakim może być on zmieniany. Dokładna struktura menu zakresy oraz skoki są dostępne w tabeli poniżej. Po uzyskaniu maksymalnej wartości (dla przykładu PWM1 – 255) jeśli nadal będzie włączony przycisk + wartości będą liczone dalej od najniższej. Podobnie dzieje się w przypadku uzyskania najniższej wartości i trzymania przycisku -. W tym przypadku wartość zmieni się na największą. Więcej informacji znajdziecie w filmie:
  2. Kolega Robert (SP9-10126-KR) poprosił mnie o wykonanie sterownika do akwarium. Założeniem była "symulacja dnia" (płynne rozjaśnianie i ściemnianie oświetlenia LED o świcie i zmierzchu) oraz monitorowanie temperatury wody z alarmem (w razie awarii fabrycznej grzałki z termostatem do akwariów). Pracę urządzenia można doglądać za pomocą strony WWW. Parametry odświeżają się na żywo dzięki zastosowaniu technologii AJAX. Jeżeli temperatura nie znajdzie się w ustawionym przedziale zostanie włączony alarm. Czas synchronizowany jest automatycznie korzystając z serwera NTP. Ciekowostką jest możliwość konfiguracji nazywy SSID sieci WiFi i hasła do niej przez samego użytkownika poprzez stronę sterująca. Standardowo urządzenie łączy się z siecią WiFi. W przypadku, gdy zapamiętana konfiguracja jest niezgodna z parametrami sieci domowej, wystarczy nacisnąć i przytrzymać przycisk przed podłączeniem do prądu. ESP8266 uruchomi się w trybie Access Pointa, z którym będziemy mogli się połączyć i na stronie http://192.168.1.1 dokonamy poprawek. Po podłączeniu do sieci domowej WiFi możemy też nacisnąć wspomniany przycisk w trakcie pracy urządzenia, co pozwoli na wyświetlenie uzyskanego z DHCP IP. Ułatwi to wejście na stronę konfiguracyjną. Przy uruchomieniu następuje odczyt ustawień sieci #include <EEPROM.h> String ssid = "", pass = ""; [...] setup(){ if (ssid == "") { int i; for (i = 100; i < 170; i++) { if (EEPROM.read(i) == NULL) { break; } ssid += char(EEPROM.read(i)); } for (int ii = i + 1; ii < 250; ii++) { if (EEPROM.read(ii) == NULL) { break; } pass += char(EEPROM.read(ii)); } } WiFi.mode(WIFI_STA); WiFi.begin(ssid.c_str(), pass.c_str()); [...] server.on("/", handleRoot); server.on("/sensors", handleSensors); server.begin(); } Za odbieranie danych z formularza WWW i zapisywanie ich w pamięci odpowiada void handleRoot() { [...] if (server.hasArg("SSID") && server.arg("SSID") != "" && server.hasArg("wifipass") && server.arg("wifipass") != "") { for (i = 0; i < server.arg("SSID").length(); i++) { EEPROM.write(i + 100, server.arg("SSID")[i]); } i += 100; EEPROM.write(i, NULL); for (i = 0; i < server.arg("wifipass").length(); i++) { EEPROM.write(i + 101 + server.arg("SSID").length(), server.arg("wifipass")[i]); } EEPROM.write(server.arg("SSID").length() + server.arg("wifipass").length() + 101, NULL); EEPROM.commit(); ESP.restart(); } } Cały kod wygląda następująco: #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <EEPROM.h> #include <WiFiUdp.h> #include <Time.h> // http://www.pjrc.com/teensy/td_libs_Time.html #include <ESP8266mDNS.h> #include <OneWire.h> //https://github.com/adafruit/ESP8266-Arduino/tree/esp8266/libraries/OneWire #include <DallasTemperature.h> //https://github.com/milesburton/Arduino-Temperature-Control-Library #include <Wire.h> #include <LiquidCrystal_I2C.h> //https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library #define PWMpin 15 //(D8) #define WiFimodeButton 12 //D6 #define PumpPin 13 //(D7) #define TempAlarmPin 14 //(D5) #define ONE_WIRE_BUS 4 //D2 /*char ssid[] = ""; // your network SSID (name) char pass[] = ""; // your network password */ String ssid = "", pass = ""; const char* WiFiHostname = "aquarium"; unsigned char screenCount = 0, tmBegin, tmEnd, dusk, pumpBegin, pumpEnd, tempMin, tempMax; bool lastTimeLCD, tempAlarm, lastButtonStatus = HIGH; unsigned int localPort = 2390; // local port to listen for UDP packets int PWM = 0; float temp = 0; /* Don't hardwire the IP address or we won't get the benefits of the pool. Lookup the IP address for the host name instead */ //IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server IPAddress timeServerIP; // time.nist.gov NTP server address const char* ntpServerName = "time.nist.gov"; const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets // A UDP instance to let us send and receive packets over UDP WiFiUDP udp; ESP8266WebServer server(80); OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); LiquidCrystal_I2C lcd(0x27, 16, 2); tmElements_t tm; time_t getNtpTime(); unsigned long last_time_sync = 0, last_NTP_check = 0; void setup() { pinMode(PWMpin, OUTPUT); pinMode(WiFimodeButton, INPUT_PULLUP); pinMode(TempAlarmPin, OUTPUT); Serial.begin(9600); EEPROM.begin(512); Wire.begin(0, 2); //D2, D4 Wire.setClock(100000); sensors.begin(); lcd.begin(); lcd.backlight(); tmBegin = EEPROM.read(0); tmEnd = EEPROM.read(1); dusk = EEPROM.read(2); pumpBegin = EEPROM.read(3); pumpEnd = EEPROM.read(4); tempAlarm = EEPROM.read(5); tempMin = EEPROM.read(6); tempMax = EEPROM.read(7); // We start by connecting to a WiFi network // WiFi.mode(WIFI_AP_STA); WiFi.softAPdisconnect(); WiFi.disconnect(); if (ssid == "") { int i; for (i = 100; i < 170; i++) { if (EEPROM.read(i) == NULL) { break; } ssid += char(EEPROM.read(i)); } for (int ii = i + 1; ii < 250; ii++) { if (EEPROM.read(ii) == NULL) { break; } pass += char(EEPROM.read(ii)); } } if (digitalRead(WiFimodeButton) == LOW) { //access point part Serial.println("Creating Accesspoint"); IPAddress apIP(192, 168, 1, 1); WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); WiFi.softAP("aquarium", "aquarium123"); Serial.print("IP address:\t"); Serial.println(WiFi.softAPIP()); } else { //station part Serial.print("connecting to..."); Serial.println(ssid); WiFi.hostname(WiFiHostname); WiFi.mode(WIFI_STA); WiFi.begin(ssid.c_str(), pass.c_str()); /* while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } */ Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } /* MDNS.begin("aquarium"); MDNS.addService("http", "tcp", 80);*/ Serial.println("Starting UDP"); udp.begin(localPort); Serial.print("Local port: "); Serial.println(udp.localPort()); server.on("/", handleRoot); server.on("/sensors", handleSensors); server.begin(); } void loop() { Serial.println(ssid); Serial.println(pass); Serial.println(WiFi.status()); if (millis() - last_time_sync > 10 * 24 * 60 * 60 * 1000 || last_time_sync == 0) { unsigned long unixt = unix_time(); if (unixt > 1512876158) { setTime(unixt); last_time_sync = millis(); } } Serial.print("Time library "); Serial.print(current_time(0)); breakTime(now(), tm); if (now() < 1512876158) { PWM = 0; } else if (tmBegin < tmEnd && tm.Hour >= tmBegin && tm.Hour < tmEnd || tmBegin > tmEnd && (tm.Hour >= tmBegin || tm.Hour < tmEnd)) { if (tm.Hour * 60 + tm.Minute < tmBegin * 60 + dusk || tm.Hour * 60 + tm.Minute < tmEnd * 60 - dusk) { PWM = 1023 - map(tmBegin * 60 * 60 + dusk * 60 - (tm.Hour * 60 * 60 + tm.Minute * 60 + tm.Second), 0, dusk * 60, 0, 1023); } if (tm.Hour * 60 + tm.Minute > tmEnd * 60 - dusk) { if (tmBegin < tmEnd) { PWM = 1023 - map(tm.Hour * 60 * 60 + tm.Minute * 60 + tm.Second - (tmEnd * 60 * 60 - dusk * 60), 0, dusk * 60, 0, 1023); } else { PWM = map(tmEnd * 60 * 60 - (tm.Hour * 60 * 60 + tm.Minute * 60 + tm.Second), 0, dusk * 60, 0, 1023); } } if (tm.Hour * 60 + tm.Minute >= tmBegin * 60 + dusk && tm.Hour * 60 + tm.Minute <= tmEnd * 60 - dusk || tmBegin > tmEnd && (tm.Hour * 60 + tm.Minute > tmBegin * 60 + dusk || tm.Hour * 60 + tm.Minute < tmEnd * 60 - dusk)) { PWM = 1023; } } /*else if (tmBegin < tmEnd && tm.Hour > tmBegin && tm.Hour < tmEnd || tmBegin > tmEnd && (tm.Hour > tmBegin || tm.Hour < tmEnd)) { PWM = 1023; } else if (tm.Hour == tmBegin) { PWM = map(tm.Minute, 0, 59, 0, 1023); } else if (tm.Hour == tmEnd) { PWM = map(59 - tm.Minute, 0, 59, 0, 1023); }*/ else { PWM = 0; } analogWrite(PWMpin, PWM); Serial.print(" "); Serial.println(PWM); server.handleClient(); if (now() % 2 != lastTimeLCD) { lastTimeLCD = now() % 2; sensors.requestTemperatures(); if (digitalRead(WiFimodeButton) == LOW && lastButtonStatus == HIGH && WiFi.status() == WL_CONNECTED) { screenCount++; } lastButtonStatus = digitalRead(WiFimodeButton); temp = sensors.getTempCByIndex(0); if (tempAlarm && (temp < (float)tempMin || temp > (float)tempMax)) { digitalWrite(TempAlarmPin, HIGH); } else { digitalWrite(TempAlarmPin, LOW); } if (tm.Hour >= pumpBegin && tm.Hour < pumpEnd) { digitalWrite(PumpPin, HIGH); } else { digitalWrite(PumpPin, LOW); } lcd.clear(); switch (screenCount % 2) { case 0: lcd.print(current_time(1)); lcd.setCursor(0, 1); lcd.print(temp, 1); lcd.print("C Day"); lcd.print(tmBegin); lcd.print("-"); lcd.print(tmEnd); break; case 1: lcd.print(WiFi.localIP().toString()); break; } } } void handleRoot() { int i; if (server.hasArg("begin") && server.arg("begin").toInt() >= 0 && server.arg("begin").toInt() <= 24 && server.hasArg("end") && server.arg("end").toInt() >= 0 && server.arg("end").toInt() <= 24 && server.hasArg("dusk") && server.arg("dusk").toInt() >= 0 && server.arg("dusk").toInt() <= 255) { tmBegin = server.arg("begin").toInt(); tmEnd = server.arg("end").toInt(); dusk = server.arg("dusk").toInt(); EEPROM.write(0, tmBegin); EEPROM.write(1, tmEnd); EEPROM.write(2, dusk); if (server.hasArg("pumpBegin") && server.arg("pumpBegin").toInt() >= 0 && server.arg("pumpBegin").toInt() <= 24 && server.hasArg("pumpEnd") && server.arg("pumpEnd").toInt() >= 0 && server.arg("pumpEnd").toInt() <= 24) { pumpBegin = server.arg("pumpBegin").toInt(); pumpEnd = server.arg("pumpEnd").toInt(); EEPROM.write(3, pumpBegin); EEPROM.write(4, pumpEnd); } // if (server.arg("tempMin").toInt() >= 0 && server.arg("tempMin").toInt() <= 100 && server.hasArg("tempMax") && server.arg("tempMax").toInt() >= 0 && server.arg("tempMax").toInt() <= 100 && server.arg("tempMax").toInt() > server.arg("tempMin").toInt()) if (server.arg("tempMin").toInt() >= 0 && server.arg("tempMin").toInt() <= 100 && server.arg("tempMax").toInt() >= 0 && server.arg("tempMax").toInt() <= 100 && server.arg("tempMax").toInt() > server.arg("tempMin").toInt()) { tempAlarm = server.arg("tempAlarm").toInt(); tempMin = server.arg("tempMin").toInt(); tempMax = server.arg("tempMax").toInt(); EEPROM.write(5, tempAlarm); EEPROM.write(6, tempMin); EEPROM.write(7, tempMax); } EEPROM.commit(); } if (server.hasArg("SSID") && server.arg("SSID") != "" && server.hasArg("wifipass") && server.arg("wifipass") != "") { for (i = 0; i < server.arg("SSID").length(); i++) { EEPROM.write(i + 100, server.arg("SSID")[i]); } i += 100; EEPROM.write(i, NULL); for (i = 0; i < server.arg("wifipass").length(); i++) { EEPROM.write(i + 101 + server.arg("SSID").length(), server.arg("wifipass")[i]); } //i += 3 + server.arg("wifipass").length(); EEPROM.write(server.arg("SSID").length() + server.arg("wifipass").length() + 101, NULL); EEPROM.commit(); ESP.restart(); } String content = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>Aquarium controller</title></head><body>"; /* for (i = 2; i < 100; i++) { if (EEPROM.read(i) == 5) { break; } content += char(EEPROM.read(i)); } content += ";"; for (int ii = i + 1; ii < 150; ii++) { if (EEPROM.read(ii) == 5) { break; } content += char(EEPROM.read(ii)); } */ content += "<DIV style=\"display:table; font-size: large; border-style: solid;\">Current time: <span id=\"time\"></span><BR>Temperature: <span id=\"temp\"></span>°C<BR>PWM: <span id=\"PWM\"></span>%<br>"; // content += "<div id=\"refresh\"> </div><script>var myVar = setInterval(myTimer, 1000); function myTimer() {var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById(\"refresh\").innerHTML = this.responseText;} }; xhttp.open(\"GET\", \"sensors\", true); xhttp.send();}</script>"; content += "\"Artificial day\" from " + String((int)tmBegin) + ":00 to " + String((int)tmEnd) + ":00. Dusk duration: " + String((int)dusk) + " minutes.</DIV>"; content += "<script>myTimer();var myVar = setInterval(myTimer, 1000);function myTimer() {var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var str = this.responseText; var values = str.split(\";\"); document.getElementById(\"time\").innerHTML = values[0]; document.getElementById(\"temp\").innerHTML = values[1]; document.getElementById(\"PWM\").innerHTML = values[2]; } }; xhttp.open(\"GET\", \"sensors\", true); xhttp.send();} var i = 0;</script>"; content += "<form action='/' method='POST'>Begin: <input type='number' pattern='[0-9]' maxlength='2' size='2' name='begin' value='" + String((int)tmBegin) + "'> UTC<br>"; content += "End: <input type='number' pattern='[0-9]' maxlength='2' size='2' name='end' value='" + String((int)tmEnd) + "'> UTC<br>"; content += "Dusk: <input type='number' pattern='[0-9]' maxlength='2' size='2' name='dusk' value='" + String((int)dusk) + "'> minutes<br>"; content += "Air pump operates between <input type='number' pattern='[0-9]' maxlength='2' size='2' name='pumpBegin' value='" + String((int)pumpBegin) + "'> and <input type='number' pattern='[0-9]' maxlength='2' size='2' name='pumpEnd' value='" + String((int)pumpEnd) + "'><br>"; content += "<input type=\"checkbox\" name=\"tempAlarm\" value=\"1\""; if (tempAlarm) { content += " checked"; } content += ">TempAlarm <input type='number' pattern='[0-9]' maxlength='2' size='2' name='tempMin' value='" + String((int)tempMin) + "'> - <input type='number' pattern='[0-9]' maxlength='2' size='2' name='tempMax' value='" + String((int)tempMax) + "'><br>"; content += "<a href=\"\" onclick=\"i = i+1; if(i % 2 == 0) {wifi.style.display = 'none';} else {wifi.style.display = 'block';} return false;\">Change WiFi settings</a>"; content += "<div id=\"wifi\" style=\"display:none;\">Home WiFi Network Name (SSID): <input type='text' name='SSID' value='" + String(ssid) + "'><br>"; content += "Password: <input type='password' name='wifipass'></div><br>"; content += "<input type='submit' value='Submit'></form> <br>"; content += "</body></html>"; server.send(200, "text/html", content); } void handleSensors() { String content = current_time(0) + ";" + String(temp) + ";" + String(100.0 * PWM / 1023.0); server.send(200, "text/html", content); } String current_time(bool shortstring) { breakTime(now(), tm); String timeStr; if (!shortstring) { if (tm.Year > 0) { tm.Year -= 30; } else { tm.Year = 0; } } timeStr = String(tm.Day) + "." + String(tm.Month); if (!shortstring) { timeStr += "." + String(tm.Year); } timeStr += " " + String(tm.Hour) + ":"; if (tm.Minute < 10) { timeStr += "0"; } timeStr += String(tm.Minute) + ":"; if (tm.Second < 10) { timeStr += "0"; } timeStr += String(tm.Second) + "UTC"; return timeStr; } // send an NTP request to the time server at the given address //https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino unsigned long sendNTPpacket(IPAddress& address) { //Serial.println("sending NTP packet..."); // set all bytes in the buffer to 0 memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: udp.beginPacket(address, 123); //NTP requests are to port 123 udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); } time_t unix_time() { if (WiFi.status() == WL_CONNECTED && ((unsigned long)(millis() - last_NTP_check) > 15000 || last_time_sync == 0)) { last_NTP_check = millis(); //get a random server from the pool WiFi.hostByName(ntpServerName, timeServerIP); sendNTPpacket(timeServerIP); // send an NTP packet to a time server // wait to see if a reply is available delay(1000); int cb = udp.parsePacket(); if (!cb) { //Serial.println("no packet yet"); } else { //Serial.print("packet received, length="); //Serial.println(cb); // We've received a packet, read the data from it udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer //the timestamp starts at byte 40 of the received packet and is four bytes, // or two words, long. First, esxtract the two words: unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); // combine the four bytes (two words) into a long integer // this is NTP time (seconds since Jan 1 1900): unsigned long secsSince1900 = highWord << 16 | lowWord; //Serial.print("Seconds since Jan 1 1900 = " ); //Serial.println(secsSince1900); // now convert NTP time into everyday time: Serial.println("Unix time sync "); // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: const unsigned long seventyYears = 2208988800UL; // subtract seventy years: unsigned long epoch = secsSince1900 - seventyYears; // print Unix time: if (epoch > 1512876158) { return epoch + 2; } else { return 0; } } } } Składniki: ESP8266 wodoodporny termometr oparty na układzie DS18B20 wyświetlacz LCD 2x16 z konwerterem I2C LCM1602 przetwornica step-down LM2596 zapewniająca zasilanie 3.3V dla elektroniki, konwertując z 12V na wejściu N-kanałowy tranzystor MOSFET do sterowania PWM oświetleniem LED buzzer
  3. Witajcie Chciałbym przedstawić tu swój projekt Sterownika do akwarium pracującego w systemie automatyki domowej opartej na Domoticzu. Pomysł i historia projektu Ponad rok temu wpadliśmy z żoną na pomysł założenia akwarium, pomysł jak pomysł, ale im więcej czytałem tym więcej kombinowałem, a jako że jestem elektronikiem to i pomysłów przybywało mi z każdym dniem Pierwsza próba budowy sterownika polegała na wykorzystaniu Arduino nano i stworzeniu samodzielnego układu pracującego lokalnie. Tyle że już w trakcie pisania kodu stwierdziłem że sterowanie sterowaniem, ale fajnie by było móc zrobić coś zdalnie, a przede wszystkim móc sprawdzić zdalnie co dzieje się w akwarium (temperatura, stan lamp itp). Tak zaczęła się moja przygoda z Domoticzem i szeroko pojętym IoT. Opis projektu Sam sterownik zbudowany jest na Arduino Pro mini, natomiast do komunikacji z serwerem wykorzystana jest platforma Mysensors zbudowana na modułach NRF24L01. Jak wcześniej pisałem sterownik pracuje w systemie mojej domowej automatyki opartej o serwer Domoticza, pracujący na RaspberryPi 3B. Na chwile obecną sterownik realizuje następujące funkcje: cztery kanały ON/OFF (przekaźniki 10A 250V), sterowanie: grzałka, filtr, falownik, chłodzenie (wentylatory w pokrywie). Z uwagi na bezpieczeństwo mieszkańców akwarium filtr podpięty jest pod styki NC przekaźnika, tzn, domyślnie jest on włączony, a możemy go wyłączyć. 16 kanałów PWM (z tranzystorami IRF520 jako elementy wykonawcze), sterowanie lampami LED, ściemnianie podświetlenia wyświetlacza, sterownie pracą falownika, rezerwa. funkcja "Karmienie" i "Serwis", załączane z lokalnej klawiatury, pierwsza umożliwia czasowe (5min) wyłączenie filtra, falownika i wentylatorów, druga umożliwia wyłączenie trybu automatyki i przejście w tryb serwisowy (przydatne przy pracach porządkowych w zbiorniku). pomiar temperatury w akwarium (czujniki DS18B20), układ zrobiony jest tak że może obsłużyć nieskończenie wiele termometrów, w praktyce w mniejszym zbiorniku mam 2 w większym 3 i to wystarcza. Dodatkowo można wybrać czy automatyka sterowania grzaniem/chłodzeniem korzysta z jednego z termometrów czy z wartości średniej wszystkich wskazań. zabezpieczenie przed przegrzaniem i wychłodzeniem wody (bezwarunkowe wyłączenie/włączenie grzania/chłodzenia w temperaturach skrajnych) pomiar temperatury zewnętrznej pomiar poziomu oświetlenia zewnętrznego Schemat blokowy sterownika przedstawiam na poniższym rysunku Jak widać większość układów pracuje na magistrali I2C, sprawia to że całość jest projektem rozwojowym, a wszelkie możliwe dodatkowe funkcje ograniczone są tylko wyobraźnią i.... pojemnością pamięci wykorzystanego Arduino Kanały PWM zrealizowane są na module PCA 9685, a jako elementy wykonawcze służą tranzystory IRF520 (oczywiście można zastosować inne MOSFETy), moduł z przekaźnikami podłączony jest do magistrali I2C poprzez expander PCF8574. Zarządzanie sterownikiem Podstawowe sterowanie pracą sterownika możliwe jest z lokalnej klawiatury, natomiast i informacje o pracy sterownika (temperatura, czas, poziom światła poszczególnych kanałów LED, stan urządzeń wykonawczych itp) wyświetlane są bezpośrednio na wyświetlaczu LCD 20x4. Pełne sterownie możliwe jest poprzez serwer Domoticza, za pośrednictwem strony www (poniżej przykładowy zrzut ekranu) i/lub aplikacji na androida. Teraz czas na kilka zdjęć elementów sterownika: Moduł arduino z przetwornica 3,3V, expanderem PCF 8574 i modułem NRF24L01 zmontowane są na płytce uniwersalnej, która osadzona jest na module przekaźników tworząc "kanapkę" Widok "kanapki" płytki uniwersalnej z arduino i modułu z przekaźnikami Moduł wykonawczy na tranzystorach IRF (sześć kanałów do sterowania lampami LED) Moduł przekaźników Wyświetlacz LCD Problemy napotkane przy realizacji projektu konieczne było wymuszenie niższej częstotliwości pracy platformy mysensors z powodu zegara jakim taktowane jest zastosowane arduino niestabilna praca modułów NRF, konieczne było dodanie elektrolitów (dałem 330u bo takie miałem :)) jak najbliżej pinów zasilających modułu (lutowałem bezpośrednio na tych pinach) okresowe zawieszanie i/lub przekłamanie odczytu temperatury z termometrów DS18B20, nie doszedłem przyczyny, wiec dodałem możliwość zdalnego resetu arduino (wiem że to tylko zaleczenie problemu a nie rozwiązanie, ale tymczasowo zdaje egzamin) zbyt małą pamięć programu zastosowanego modułu arduino, zastanawiam się czy nie przejść na ESP8266 z EasyESP konieczność zbudowania obudowy
×
×
  • Utwórz nowe...