• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Sterownik Akwarystyczny DIY
#1
Witajcie po ponad półrocznej przerwie.
Od moich ostatnich walk z arduino Nano i różnymi LCD  powstał projekcik który z powodzeniem pracuje (arduino Nano +

LCD 20x4) który obsługuje:
  1. sterowanie PWM świt/zmierzch,
  2. pomiar temperatury plus chłodzenie,
  3. pomiar pH, plus obliczenie zawartości Co2 na podstawie wprowadzanego KH,
  4. obsługa dozownika nawozów na bazie pompy perstaltycznej,
  5. wyświetlanie danych na LCD 20x4.
Projekt były OK ale brakuje mu np. możliwości ustawień bez konieczności ładowania sketcha ze zmianami.
Dlatego też jak to w życiu bywa potrzeba człowiekowi zmian :-). i postanowiłem udoskonalić sterownik.
W wyniku prób różnych wyświetlaczy i obsługi menu (temat widmo w zwykłych LCD) wybór padł na wyświetlacze NEXTION a dokładnie 2,4''.

Obecnie nowy sterownik będzie obsługiwać:
  1. sterowanie dwoma kanałami PWM świt/zmierzch, (ustawienia z LCD godzin włączania i wyłączania)
  2. pomiar temperatury - 2 kanały plus obsługa dwóch wiatraków do chłodzenia, (ustawienia z LCD histerezy oraz temperatur),
  3. pomiar pH (z możliwością kalibracji sondy),
  4. ustawianie wartości KH z pozycji LCD (bez konieczności aktualizacji sketcha jak to było do tej pory)
  5. wyliczanie zawartości Co2 na bazie pH i KH,
  6. obsługa dozownika nawozów (z możliwością zadawania jednorazowych porcji, czasu dozowania oraz monitorowania ilości nawozu w zasobniku),
  7. no i obowiązkowo: Data i Czas.
Jak widać zmiany spore :-) ale już pierwsze efekty są co można zobaczyć na krótkim filmiku:

i tu się kończy moje chwalenie :-( gdyż są tematy który nie mogę ogarnąć :-(

Mam gorącą prośbę  do Fachowców od arduino o pomoc!!!

Poniżej zamieszczam sketch sterownika. Całość pracuje na arduino MEGA 2560.

Na chwilę obecną co całości szczęścia brakuje:
  1. Jak zaprogramować zegar/datę aby można było z pozycji LCD ustawiać datę i godzinę (obecnie jest to aktualizowanie RTC DS1307 i start),
  2. Jak ustawić pętlę w części dozownika aby za każdym razem kiedy jest dozowana ustalona porcja wartość zasobnika zmniejszała się o ustaloną wartość (graficzne przedstawienie ilości w zasobniku jest skojarzone z pozycji LCD i działa na zmianę wartości zasobnika),
  3. Czy jest inny - prostszy sposób/metoda sterowania PWM gdyż w moim kodzie jest możliwość tylko zmiany godzin startu i końca natomiast ustalanie mocy świecenie wymaga ustawień ręcznych w kodzie (tabeli).
a teraz obiecany kod:

Kod:
#include "Arduino.h"
#include "Nextion.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <TimeLib.h>
#include <Time.h>  
#include <Wire.h>
#include <DS1307RTC.h>

#define ONE_WIRE_BUS 13                               // pin 13 termomoetr
#define TEMPERATURE_RECISION 9
#define ODSTEP 1000
#define SensorPin A7                                  // wejście analogowe dla sensora pH - pin analogowy 7
#define LED A7                                        // nowy wpis do pH
#define samplingInterval 20                           // nowy wpis do pH
#define printInterval 800                             // nowy wpis do pH
#define ArrayLenth 40                                // times of collection
#define Offset 0.50                                   // kalibracja pH

//-----------------------PINY WE/WY ---------------------------------
int W1 = 5;                                           // pin 5 - wyjście do stycznika nr 1 - wentylator
int dozownik_1 = 6;                                           // pin 6 - wyjście do stycznika nr 2 - dozownik
int LED1 = 11;                                        // pin 11 - wyjście PWM do sterowania LED1
int LED2 = 10;                                        // pin 11 - wyjście PWM do sterowania LED2

int STEP = 1;                                         // długość trwania jednego kroku
int CZAS;                                             //czas do lampy led
int czas1;
int czas2;
int GODZ;                                             // godziny
int MIN;                                              // minuty
int maxD1 = 60;                                       // maksymalna moc kanału LED1
int maxD2 = 60;                                       // maksymalna moc kanału LED2
int ZMIANA = 60;  


int godzina_OFF;                                      // godzina wyłączenia dozownika
int minuta_OFF;                                       // minuty wyłączenia dozownika
int sekunda_ON = 00;                                  // sekunty włączenia dozownika

//int porcja;                                           // ilość wdozowywanego nawozu w ml

//int dzienG = 7;                                     // początek dnia - godziny
//int dzienM = 00;                                    // początek dnia - minuty
//int nocG = 20;                                      // początek nocy - godziny
//int nocM = 00;                                      // początek nocy - minuty
unsigned long czas_poprzedni = 0;
int licznik = 0;


int pH;
float b;
//float pH;                                            // dla sensora pH
                                   
int pHArray[ArrayLenth];                               //Store the average value of the sensor feedback  
int pHArrayIndex=0;                                    // nowy wpis do pH

//-----------------------ZMIENNE DLA TERMOMETRÓW -------------------------------
NexText t1 = NexText(1, 23, "t2");               //zmienna tekstowa dla termometra 1 (strona0)
NexText t2 = NexText(1, 24, "t3");               //zmienna tekstowa dla termometra 2 (strona0)


//-----------------------ZMIENNE DLA RTC -------------------------------

NexNumber g = NexNumber(1, 16, "page0.n1");     //zmienna numeryczna do zegara dla godzin (strona0)
NexNumber m = NexNumber(1, 17, "page0.n2");     //zmienna numeryczna do zegara dla minut (strona0)
NexNumber s = NexNumber(1, 18, "page0.n3");     //zmienna numeryczna do zegara dla sekund (strona0)
NexNumber d = NexNumber(1, 19, "page0.n4");     //zmienna numeryczna do kalendarza dla dni
NexNumber mie = NexNumber(1, 20, "page0.n5");   //zmienna numeryczna do kalendarza dla mieięcy
NexNumber r = NexNumber(1, 21, "page0.n6");     //zmienna numeryczna do kalendarza dla lat


//-----------------------ZMIENNE DLA TEMPERATURY - WIATRAK  -------------------------------

NexNumber limes = NexNumber(3, 4, "te0");           //zmienna numeryczna dla ustawień temperatury pobierana ze strony 3

//-----------------------ZMIENNE DLA SONDY PH  -------------------------------

NexNumber PHval = NexNumber(1, 12, "page0.n7");    //zmienna numeryczna dla wartosci pH wyswietlanej na stronie 0

//-----------------------ZMIENNE DLA TWARTOŚCI/co2  -------------------------------

NexNumber num1 = NexNumber(1, 31, "page0.n0");           //zmienna numeryczna dla twardości wyświetlanej na stronie 0
NexNumber co2 = NexNumber(1, 29, "page0.n8");            // obliczenie wartosci Co2 wyswietlanej na stronie 0

//-----------------------ZMIENNE DO STEROWANIA LAMPAMI   -------------------------------

NexNumber dG1 = NexNumber(3, 5, "page2.dg1");                     //zmienna numeryczna dla twardości wyświetlanej na stronie 0
NexNumber dM1 = NexNumber(3, 7, "page2.dm1");                     //zmienna numeryczna dla ustawień twardości pobierana ze strony 5
NexNumber nG1 = NexNumber(3, 4, "page2.ng1");                     //zmienna numeryczna dla twardości wyświetlanej na stronie 0
NexNumber nM1 = NexNumber(3, 6, "page2.nm1");                     //zmienna numeryczna dla ustawień twardości pobierana ze strony 5
NexNumber dzienG2 = NexNumber(7, 5, "page8.dzienG2");             //zmienna numeryczna dla twardości wyświetlanej na stronie 0
NexNumber dzienM2 = NexNumber(7, 7, "page8.dzienM2");             //zmienna numeryczna dla ustawień twardości pobierana ze strony 5
NexNumber nocG2 = NexNumber(7, 4, "page8.nocG2");                 //zmienna numeryczna dla twardości wyświetlanej na stronie 0
NexNumber nocM2 = NexNumber(7, 6, "page8.nocM2");                 //zmienna numeryczna dla ustawień twardości pobierana ze strony 5

NexText pora = NexText(0, 6, "po");                           // zmienna tekstowa dla pory dnia oświetlenia
NexNumber lamp1 = NexNumber(1, 23, "page0.l1");               // zmienna numeryczna dla statusu % lampy 1
NexNumber lamp2 = NexNumber(1, 24, "page0.l2");               // zmienna numeryczna dla statusu % lampy 2

//-----------------------ZMIENNE DO STEROWANIA DOZOWNIKIEM   -------------------------------

NexNumber zapas = NexNumber(8, 10, "zapas1");               // zmienna numeryczna dla ilości pełnego namiaru nawozu
NexNumber stan = NexNumber(1, 37, "zasobnik");                 // zmienna numeryczna dla wyswietlenia pozostalej ilosci nawozu
NexNumber porcja = NexNumber(8, 7, "doza1");                // zmienna numeryczna dla jednorazowej porcji nawozu
NexNumber porcja2 = NexNumber(1, 41, "n10");                 // zmienna numeryczna dla wyswietlenia ustalonej porcji nawozu
NexNumber nawozG = NexNumber(8, 17, "nawozG");              // zmienna numeryczna dla godziny podania nawozu
NexNumber nawozM = NexNumber(8, 16, "nawozM");              // zmienna numeryczna dla minuty  podania nawozu
NexProgressBar poziom = NexProgressBar(1, 35, "j1");          // wskaznik poziomu zasobnika z nawozem

NexTouch *nex_Listen_List[]=
{
  NULL
};


char buffer[10] = {0};


OneWire oneWire(ONE_WIRE_BUS);                        // termometr one wire
DallasTemperature sensors(&oneWire);                  // termometr
int numberOfDevices;
DeviceAddress tempDeviceAddress;

//--------------------------------------------------------------------------------------------------------
//-------------------SETUP-------------------------------
//--------------------------------------------------------------------------------------------------------
void setup() {

nexInit();
    sensors.begin();                                   // aktywacja termometr
    Serial.begin(9600);                                // aktywacja portu szeregowego
    Serial2.begin(9600);                               // aktwacja drugiego portu szeregowego
     while (!Serial) ;                                 // wait until Arduino Serial Monitor opens
 
   
   numberOfDevices = sensors.getDeviceCount();       // pobranie danych z sensora

//    pinMode(LED1, OUTPUT);                            // LED 1
//    pinMode(LED2, OUTPUT);                            // LED 2
//    pinMode(W1, OUTPUT);                              // wyjście wentylator
//    pinMode(W2, OUTPUT);                              // wyjście dozownik


   }                 // koniec void setup

   

//--------------------------------------------------------------------------------------------------------
//------------------- loop -------------------------------
//--------------------------------------------------------------------------------------------------------
void loop()
{


//------------------- ZEGAR -------------------------------  
tmElements_t tm;
 if (RTC.read(tm)) {                           // pobierz czas na wyświetlacz
   d.setValue(tm.Day);
 mie.setValue(tm.Month);
   r.setValue(tmYearToCalendar(tm.Year));
   g.setValue(tm.Hour);
   m.setValue(tm.Minute);
   s.setValue(tm.Second);
 }




unsigned long czas_aktualny = millis();
 if(czas_poprzedni - czas_aktualny> ODSTEP)

 czas_poprzedni = czas_aktualny;
 licznik = licznik + 1;


 Serial.println("swiatła start");
 LAMPY();                                                        // dane z bloku lampy
 Serial.println("temperatura start");
// printTemperature(DeviceAddress deviceAddress, int index);      // dane z bloku temperatury
 Serial.print("");
dozownik();                                                      // dane z bloku dozownika
 Serial.println("dozownik start");

PH_SONDA();                                                      // dane z bloku sondy pH
 Serial.println("sonda pH start");
   
}                                                                 // konice void loop


//-----------------------------------------------------------------------------------------

bool setSys0(uint32_t number)

{
 char buf[10] = {0};
 String cmd;

 utoa(number, buf, 10);
 cmd += "sys0=";
 cmd += buf;
 sendCommand(cmd.c_str());
 return recvRetCommandFinished();
}      // koniec funkcji bool

uint32_t numLimes;
//--------------------------------------------------------------------------------------------------------
//-------------------void ZEGAR-------------------------------
//--------------------------------------------------------------------------------------------------------
void zegar()
{



}





//--------------------------------------------------------------------------------------------------------
//-------------------void TEMPERATURY-------------------------------
//--------------------------------------------------------------------------------------------------------

void printTemperature(DeviceAddress deviceAddress, int index)
{
 float tempC = sensors.getTempC(deviceAddress);
 memset(buffer, 0, sizeof(buffer));
 String tempTXT = String(tempC, 2);
 tempTXT.toCharArray(buffer, 10);
 
 
   if(index == 0){
   t1.setText(buffer);
   Serial.print("temperatura 1=");
   Serial.print(buffer);

   limes.getValue(&numLimes);
   if(tempC > numLimes){
     setSys0(1);
   digitalWrite(W1,HIGH);
   Serial.println("wiatrak 1 - ON");
   }
   else{
     setSys0(0);
    digitalWrite(W1,LOW);  
    Serial.println("wiatrak 1 - OFF");
   }
 }
 if(index ==1){
   
    t2.setText(buffer);
    Serial.print("temperatura 2=");
    Serial.print(buffer);
   }
}




//--------------------------------------------------------------------------------------------------------
//-------------------VOID DOZOWNIK-------------------------------
//--------------------------------------------------------------------------------------------------------
void dozownik()
{
uint32_t d1;
uint32_t nG1;
uint32_t nM1;
uint32_t zasobnik;
tmElements_t tm;

//----------------------------pobieranie danych ---------------------------
porcja.getValue(&d1);           // pobranie wartosci ustawionej na wyswietlaczu ze strony page 10 - ilosc dozowana jednorazowo
nawozG.getValue(&nG1);          // pobranie wartosci ustawionej na wyswietlaczu ze strony page 10 - godzina dozowania
nawozM.getValue(&nM1);          // pobranie wartosci ustawionej na wyswietlaczu ze strony page 10 - minuta dozowania
zapas.getValue(&zasobnik);           // pobranie wartosci ustawionej na wyswietlaczu ze strony page 10 - stan zasobnika

//------------------------ wysłyłanie danych------------------------------
porcja2.setValue(d1);           // wyswietlenie na wyswietlaczu na stronie głównej wartosci - ilosc dozowana jednorazowo
stan.setValue(zasobnik);            // wysłanie wartosci do wyswietlenia na stronie 1
poziom.setValue(zasobnik);           // wysłanie wartosci na wskaznik poziomu na stronie 1

int sekunda_OFF = d1*60/100;                                                   // przeliczenie porcji w ml na czas dosowania w sekundach


if((nG1==tm.Hour)&&(nM1==tm.Minute)&&(sekunda_ON==tm.Second))    // warunek włączenia dozownika
{
 digitalWrite(dozownik_1,HIGH);                                                      //właczenie dozownika
 Serial.println("dozownik start");
 //a = a - d1;
 
}

if((nG1==tm.Hour)&&(nM1==tm.Minute)&&(sekunda_OFF==tm.Second)) // warunek wyłączenia dozownika
{
 digitalWrite(dozownik_1,LOW);                                                       //wyłaczenie dozownika
 Serial.println("dozownik stop");
}

}   //koniec void dozownik


//--------------------------------------------------------------------------------------------------------
//-------------------VOID  LAMPY-------------------------------
//--------------------------------------------------------------------------------------------------------
void LAMPY()
{
uint32_t num;
uint32_t dg1;
uint32_t dm1;
uint32_t ng1;
uint32_t nm1;

//uint32_t dG2;
//uint32_t dM2;
//uint32_t nG2;
//uint32_t nM2;
//------------------- ZEGAR -------------------------------  
tmElements_t tm;

 if (RTC.read(tm)) {                           // pobierz czas na wyświetlacz



//------------------- OŚWIETLENIE -------------------------------
 
   
  dG1.getValue(&dg1);
  dM1.getValue(&dm1);
  nG1.getValue(&ng1);
  nM1.getValue(&nm1);
   
//    dzienG2.getValue(&dG2);
//    dzienM2.getValue(&dM2);
//    nocG2.getValue(&nG2);
//    nocM2.getValue(&nM2);

    GODZ =  (tm.Hour);                                   // pobranie godziny z zegara
    MIN = (tm.Minute);                                      // pobranie minut z zegara
   
     int CZAS = (GODZ*60+MIN);                        // przejście na minuty - czas ogólny
     int czas1 = (dg1*60+dm1);                        // przeliczenie na minuty dla czasu gdy dzień
     int czas2 = (ng1*60+nm1);                        // przeliczenie na minuty dla czsu gdy noc

   // int czas1L2 = (dG2*60+dm2);                     // przeliczenie na minuty dla czasu gdy dzień
 //   int czas2L2 = (nG2*60+nm2);                   // przeliczenie na minuty dla czsu gdy noc

      static int D1;                                  //stopień rozjaśniania LED1, LED2
  //    static int D2;                                  //stopień rozjaśniania LED1, LED2

// -------------- LAMPA 1 --------------------------------------------

       int mocD1[61] =                                      //stopień rozjaśniania LED1
         {
            0,1,2,3,4,5,6,7,8,9,10,
            11,12,13,14,15,16,17,18,19,20,
            25,30,35,40,45,50,55,60,65,70,
            75,80,85,90,95,100,105,110,115,120,
            125,130,135,140,145,150,155,160,165,170,
            175,175,179,190,205,205,205,205,205,205                   // zasilanie na 100%
       };
         int mocD2[61] =                                      //stopień rozjaśniania LED1
         {
            0,1,2,3,4,5,6,7,8,9,10,
            11,12,13,14,15,16,17,18,19,20,
            25,30,35,40,45,50,55,60,65,70,
            75,80,85,90,95,100,105,110,115,120,
            125,130,135,140,145,150,155,160,165,170,
            175,175,179,195,210,215,225,235,245,255                   // zasilanie na 100%
         };

   if (CZAS < czas1)                                            // warunek gdy NOC
      {
       D1=0;                        //
 //    sendCommand("po.val=NOC");
       Serial.println("LED - NOC");
     pora.setText("NOC");
        }
    if ((czas1 <= CZAS)&&(CZAS <(czas1+ZMIANA)))                 // warunek gdy PORANEK
       {
        D1=((CZAS-czas1)/STEP);
      //  sendCommand("po.val=SWIT");
        Serial.println("LED - SWIT");
        pora.setText("SWIT");        

        }
    if (((czas1+ZMIANA) <= CZAS)&&(CZAS < (czas2-ZMIANA)))       // warunek gdy  DZIEŃ
        {
        D1=maxD1;
      //  sendCommand("po.val=DZIEN");
         Serial.println("LED - DZIEN");
     pora.setText("DZIEN");
         }
    if (((czas2-ZMIANA)<=CZAS)&&(CZAS<czas2))                     // warunek gdy ZMROK
         {
        D1=((czas2-CZAS)/STEP);
    //  sendCommand("po.val=ZMROK");
         Serial.println("LED - ZMROK");
  pora.setText("ZMROK");
         }
     if (czas2<=CZAS)                                            //NOC
         {
        D1=0; //
     
    pora.setText("NOC");
         Serial.println("LED - NOC");
        }
//      analogWrite(LED1, mocD1[D1]);
//      analogWrite(LED2, mocD2[D1]);
      lamp1.setValue((mocD1[D1]*100)/255);
      lamp2.setValue((mocD2[D1]*100)/255);
       Serial.println("stan lampy 1=");
       Serial.print(lamp1.setValue((mocD1[D1]*100)/255));
       Serial.println("stan lampy 2=");
       Serial.print(lamp2.setValue((mocD2[D1]*100)/255));
}
}


//--------------------------------------------------------------------------------------------------------
//-------------------void PH SONDA -------------------------------
//--------------------------------------------------------------------------------------------------------
void PH_SONDA()
{


 uint32_t num;                                  // pobrana wartosc
static unsigned long samplingTime = millis();
 static unsigned long printTime = millis();
 static float pHValue,voltage;
 if(millis()-samplingTime > samplingInterval)
 {
     pHArray[pHArrayIndex++]=analogRead(SensorPin);
     if(pHArrayIndex==ArrayLenth)pHArrayIndex=0;
     voltage = avergearray(pHArray, ArrayLenth)*5.0/1024;
     pHValue = 3.5*voltage+Offset;
     samplingTime=millis();
 }
 if(millis() - printTime > printInterval)   //Every 800 milliseconds, print a numerical, convert the state of the LED indicator
 {
       Serial.print("Voltage:");
       Serial.print(voltage,2);
       Serial.print("    pH value: ");
     
       Serial.print(pHValue,2);                     // wyswietlenie wartości pH na LCD wynik do dwóch miejsc po przecinku
                             
 PHval.setValue(pHValue);                         // wyswietlenie wartości pH na LCD
     
float CO2 = (3*num*pow(10,7-pHValue));


num1.getValue(&num);                                  //pobieranie wartości twardosci z wyswietlacza
 

 co2.setValue(3*num*pow(10,7-7));                    //wysłanie wartosci Co2 na wyswietlacz

 
}
}

double avergearray(int* arr, int number){
 int i;
 int max,min;
 double avg;
 long amount=0;
 if(number<=0){
   Serial.println("Error number for the array to avraging!/n");
   return 0;
 }
 if(number<5){   //less than 5, calculated directly statistics
   for(i=0;i<number;i++){
     amount+=arr[i];
   }
   avg = amount/number;
   return avg;
 }else{
   if(arr[0]<arr[1]){
     min = arr[0];max=arr[1];
   }
   else{
     min=arr[1];max=arr[0];
   }
   for(i=2;i<number;i++){
     if(arr[i]<min){
       amount+=min;        //arr<min
       min=arr[i];
     }else {
       if(arr[i]>max){
         amount+=max;    //arr>max
         max=arr[i];
       }else{
         amount+=arr[i]; //min<=arr<=max
       }
     }//if
   }//for
   avg = (double)amount/(number-2);
 }//if
 return avg;

}
 
Odpowiedź
  


Wiadomości w tym wątku
Sterownik Akwarystyczny DIY - przez nebari - 18-09-2018, 22:35
RE: Sterownik Akwarystyczny DIY - przez kaczakat - 19-09-2018, 02:51
RE: Sterownik Akwarystyczny DIY - przez nebari - 19-09-2018, 20:20
RE: Sterownik Akwarystyczny DIY - przez es2 - 19-09-2018, 09:22
RE: Sterownik Akwarystyczny DIY - przez nebari - 19-09-2018, 20:41
RE: Sterownik Akwarystyczny DIY - przez es2 - 19-09-2018, 21:39
RE: Sterownik Akwarystyczny DIY - przez kaczakat - 20-09-2018, 07:29
RE: Sterownik Akwarystyczny DIY - przez es2 - 20-09-2018, 09:22
RE: Sterownik Akwarystyczny DIY - przez kaczakat - 20-09-2018, 15:44
RE: Sterownik Akwarystyczny DIY - przez es2 - 20-09-2018, 15:56
RE: Sterownik Akwarystyczny DIY - przez nebari - 20-09-2018, 18:43

Skocz do:


Przeglądający: 1 gości