Skocz do zawartości

Program mierzący temperaturę i wilgotność gleby


autozaglada

Pomocna odpowiedź

Po skończeniu obu części kursu postanowiłem napisać własny program aby sprawdzić swoją wiedzę.

Kod jest całkowicie mojego autorstwa, napisany na podstawie kursu i referencji ze strony Arduino. Kod ma z założenia mierzyć temperaturę i wilgotność gleby a po przekroczeniu progu alarmu, wyświetlić komunikat alarmu. Posiada także możliwość ustawiania progu alarmu oraz zapamiętanie go w razie zaniku zasilania.

I niestety tak do końca nie jest:

1. O ile na wyświetlaczu LCD wyświetla informacje co 2 sek do momentu odczytu temperatury z czujnika wtedy czas się wydłuża do około 3s.

2. Na serial porcie już niestety nie działa to prawidłowo.

3. Część dotycząca ustawień działa bez zarzutów.

Z góry dziękuję za wszystkie sugestie i oceny tego kodu

#include <EEPROM.h>     //biblioteka EEPROMu
#include <LiquidCrystal.h>      //biblioteka wyświetlacza
#include <OneWire.h>      //biblioteka onewire
#include <DallasTemperature.h>  //biblioteka czujnika cyfrowego temperatury
#define ONE_WIRE_BUS 6      //określenie pinu onewire
#define ustaw 9    //pin 9 jako ustaw
#define plus 7    //pin 7 jako plus
#define minus 8   //pin 8 jako minus
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);  //przekazanie informacji do bliblioteki
int ustawienia = 0; //ustawienia jako int po wlaczeniu zasilania wylaczone
int alarm ;   //alarm jako int
unsigned long aktualnyCzas = 0;
unsigned long czas1 = 0;
unsigned long czas2 = 0;
unsigned long czas3 = 0;

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);    //piny wyświetlacza

void setup() {
  Serial.begin(9600);   //otwieram UART
  lcd.begin(16, 2);    //definiuje rodzaj wyswietlacza
  sensors.begin();  //inicjacja czujnikow
  pinMode(A0, INPUT); //czujnik wilgotnosci gleby
  pinMode(ustaw, INPUT_PULLUP); //pin ustaw podciagniety do zasilania
  pinMode(plus, INPUT_PULLUP);    //pin plus podciagniety do zasilania
  pinMode(minus, INPUT_PULLUP);   //pin minus podciagniety do zasilania
  alarm = EEPROM.read(0);   //odczytaj wartosc alarmu z eepromu po wlaczeniu zasilania
}

void loop() {
  aktualnyCzas = millis();

  int odczyt = analogRead(A0);      //Odczytanie wartości z czujnika gleby
  odczyt = map(odczyt, 200, 1023, 100, 0);   //kalibracja czujnika gleby w procentach
  if (odczyt > 100) //jezeli wilgotnosc jest wieksza od 100 procent to:
  {
    odczyt = 100; //wilgotnosc = 100 procent
  }
  sensors.requestTemperatures();   //odczytaj wartosc temperatury

  if (aktualnyCzas - czas1 >= 2000UL) {   //jezeli roznica czasu jest wieksza badz rowna 2s to:

    czas2 = aktualnyCzas;  // zapamietaj aktualny czas dla nastepnego IFa i:

    lcd.setCursor(0, 0);   //ustaw kursor
    lcd.print("                "); //wyczysc linie
    lcd.setCursor(0, 1); //ustaw kursor
    lcd.print("                ");  //wyczysc linie
    lcd.setCursor(2, 0); //Ustawienie kursora
    lcd.print("Temperatura"); //wpisz  tekst
    lcd.setCursor(3, 1);  //ustaw kursor
    Serial.println(sensors.getTempCByIndex(0));
    lcd.print(sensors.getTempCByIndex(0));//wpisz wartosc z czujnika temperatury o indeksie 0
    lcd.setCursor(9, 1);  //ustaw kursor
    lcd.print("st.C");    //wpisz tekst
  }
  if (aktualnyCzas - czas2  >= 2000UL) {    //jezeli roznica czasu jest wieksza badz rowna 2s to:

    czas3  = aktualnyCzas ;      // zapamietaj aktualny czas dla nastepnego IFa i:
    Serial.println(odczyt);
    lcd.setCursor(0, 0);    //ustaw kursor
    lcd.print("     ziemia    ");   //wstaw tekst
    lcd.setCursor(0, 1);    //ustaw kursor
    lcd.print("              ");//wyczysc linie
    lcd.setCursor(6, 1);    //ustaw kursor
    lcd.print(odczyt);      //wstaw wartosc z czujnika wilgotnosci
    lcd.setCursor(10, 1);   //ustaw kuror
    lcd.print("%");       //wstaw tekst
    lcd.setCursor(12, 1);   //ustaw kursor
    lcd.print("(");   //wstaw tekst
    lcd.setCursor(13, 1);   //ustaw kursor
    lcd.print(alarm);   //wstaw wartosc limitu wilgotnosci gleby
    lcd.setCursor(15, 1);   //ustaw kursor
    lcd.print(")");   //wstaw tekst
  }

  if (odczyt <= alarm && aktualnyCzas - czas3  >= 2000UL)    /*jezeli wilgotnosc jest mniejsza badz
  rowna ustwionemu alarmowi i roznica czasu jest wieksza badz rowna 2s to: */
  {
    czas1 = aktualnyCzas; 
    Serial.println("podlej ziemie");//zapisz aktualny czas i wyswietl alarm:
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("podlej");
    lcd.setCursor(0, 1);
    lcd.print("   ziemie  ");
  }
  else if (odczyt > alarm && aktualnyCzas - czas3 >= 2000UL) /*lub jezeli odczyt wilgonosci jest wiekszy
  od progu alarmu i roznica czasu jet wieksza badz rowna 2s to: */
  {
    czas1 = aktualnyCzas; //zapisz aktualny czas i wyjdz z IFa
  }


  //sekcja ustawien:
  if (digitalRead(ustaw) == LOW) //jezeli wcisniety guzik ustawienia to:
  {
    delay(20);    //poczekaj (zmiana stanu low high wibracja)i:
    ustawienia = 1;   //wejdz do trybu ustawien i wyswietl na lcd:
    lcd.setCursor(0, 0);
    lcd.print("   ustawienia   ");
    lcd.setCursor(0, 1);
    lcd.print("      ");
    lcd.print(alarm);
    lcd.print(" %      ");
    while (digitalRead(ustaw) == LOW)
      delay(20);
  }
  while (ustawienia == 1)  //tryb zmiany ustawien
  {
    if (digitalRead(plus) == LOW) //jezeli wcisniety przycisk plus to:
    {
      delay(20);
      alarm++; // zwieksz prog alarmu o jeden i:
      if (alarm >= 99) //jezeli prog jast wiekszy badz rowny 99% to:
      {
        alarm = 99; //ustaw maksymalna wartosc progu
      }
      lcd.setCursor(0, 1);  // wyswietl wartosc progu na lcd
      lcd.print("      ");
      lcd.print(alarm);
      lcd.print(" %      ");
      while (digitalRead(plus) == LOW)
        delay(20);
    }
    if (digitalRead(minus) == LOW)    //jezeli wcisniety przycisk minus to:
    {
      delay(20);
      alarm--;    //zmniejsz prog alarmu o jeden i:
      if (alarm <= 0)   //jezeli prog jest mniejszy badz rowny 0 to:
      {
        alarm = 0;  //ustaw minimalna wartosc progu
      }             // wyswietl wartosc progu na lcd
      lcd.setCursor(0, 1);
      lcd.print("      ");
      lcd.print(alarm);
      lcd.print(" %      ");

      while (digitalRead(minus) == LOW)
        delay(20);

    }
    if (digitalRead(ustaw) == LOW) //opuszczenie trybu ustawien przyciskiem ustaw
    {
      delay(20);
      EEPROM.update(0, alarm);    /*jezeli wartosc progu jest inna od
      zapisanej w eepromie to zamien na aktualna */
      ustawienia = 0;
      while (digitalRead(ustaw) == LOW)
        delay(20);
    }
  }
}

 

Link do komentarza
Share on other sites

(edytowany)

Z problem mills i opóźnieniami po odczycie temperatury z czujnika już sobie poradziłem. 

Mam teraz inne pytanie:

czy jest możliwość napisać tak program żeby zmieniać tekst na wyświetlaczu za pomocą np guzików??

 

Edytowano przez autozaglada
Link do komentarza
Share on other sites

(edytowany)

Właśnie chodzi o układanie z liter tzn w moim programie jest komunikat "podlej ziemie" i chciałbym mieć możliwość zmiany np ziemia na coś innego nie zdefiniowanego .

Jakieś sugestie jak to zrobić?

 

Edytowano przez autozaglada
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)

podobnie jak wypisujesz pomiar temperatury, 

lcd. printl("podlej ") 

lcd. print(zmienna w której masz zapisane: krzaczki maryśki) 

przyciskami wybierasz którą zmienną ma wstawić... 

A jeśli coś nie zdefiniowanego, to robisz tablicę z alfabetem i przyciskami, albo łatwiej enkoderem, wstawiasz literki... 

Edytowano przez SOYER
Link do komentarza
Share on other sites

(edytowany)

Na stronie arduino w referencjach znalazłem coś takiego jak "array" czy o to Tobie chodziło? Jeśli tak to proszę powiedz czy dobrze rozumiem:

1. char ustaw[3] ={ 'a', 'b', 'c'} ;

Gdzie liczba 0 to  a, 1 to b, 2 to c, 3 to obowiązkowe tzw. 0 czy:

2. char ustaw[4] ={ 'a', 'b', 'c'} ;

Gdzie liczba 1 to a, 2 to b, 3 to c, 4 to obowiązkowe tzw. 0

3. Jeszcze inaczej

Jest to tam napisane nie jasno dla mnie. Do tego piszą także, że źle utworzona tablica może powodować problemy z programem. 

 

Edytowano przez autozaglada
Link do komentarza
Share on other sites

Anonim

Może powodować problemy jak przekroczysz zakres. Np. próba przypisania do tablicy zadeklarowanej  char tablica[4]  na pozycji tablica[4] = 'a'; może powodować błąd nierozpoznawany przez kompilator.

napisy możesz deklarować tak:

const char *napis = "jakis napis";

jest to równoznaczne z zapisem:

const char napis[] = "jakis napis";

bo nazwa tablicy jest wskaźnikiem na pierwszy jej element. Przypisanie zawartości w ten sposób powoduje również wstawienie 0 na końcu takiego napisu więc rozmiar tablicy wynosi w rezultacie 12 a na ostatniej 11 pozycji jest znak końca stringa '\0' czyli 0  dzięki czemu odczytywanie zawartości tablicy można przeprowadzić za pomocą pętli for w taki sposób:

uint8_t cnt;
char bufor[16];

for(cnt = 0; napis[cnt]; cnt++){
  bufor[cnt] = napis[cnt];  // przepisuje zawartość tablicy napis do tablicy bufor
}

Pętla for sprawdza czy element tablicy pod indeksem cnt jest różny od 0 i jeśli tak to przepisuje element do tablicy bufor po czym zwiększa index o 1. 

Link do komentarza
Share on other sites

Nie mieszajmy innym w głowie, czasem lepiej nic nie pisać niż pisać nieprawdziwe rzeczy. Wskaźnik i tablica to co innego w języku C, więc zapis

const char *napis = "jakis napis";

oraz:

const char napis[] = "jakis napis";

nie są równoważne, chociaż podobne. Zachęcam do poczytania podstaw języka C oraz sprawdzenia czym się różnią.

Link do komentarza
Share on other sites

Anonim

Praktycznie o tym czy są równoważne decyduje kontekst i kompilator ale faktycznie względem standardu masz rację, mój błąd. W niektórych przypadkach przypisanie łańcucha do wskaźnika na char powoduje błąd lub warn, lepiej więc jest deklarować łańcuch notacją tablicową ale już dostęp do elementów tablicy z powodzeniem można realizować za pomocą notacji wskaźnikowej.  np. :

const char tablica[] = {"jakis tekst"};

char litera1 = *tablica; // litera1 == 'j'
char litera2 = *(tablica+2); // litera2 == 'k'

Warto mieć też świadomość, że po alokacji pamięci łańcucha znaków jego deklaracja jest zamieniana na właśnie adres pierwszego elementu i przypisywana zmiennej tablicowej czyli właśnie wskaźnikowi na pierwszy element a o tym czy można go przypisać do zmiennej wskaźnikowej decyduje właśnie kompilator który czasem jest bardziej liberalny od standardu języka.

Nie jestem też pewny czy standard określa stosowanie nawiasów klamrowych dla łańcuchów znaków czy też zależy to głównie od kompilatora bo w praktyce stosuję je jedynie dla zmiennych innych typów lub tablic wskaźników na łańcuchy znaków.

Aby zweryfikować te wywody można wywołać dowolną funkcję przyjmującą jako argument wskaźnik na char zarówno z łańcuchem znaków w cudzysłowach jak ze zmienną wskaźnikową lub też nazwą zmiennej tablicowej i nie powinno być sprzeciwu ze strony kompilatora, być może w skrajnych przypadkach pojawi się warning ale nie error.

Dzięki za konstruktywną uwagę.

Link do komentarza
Share on other sites

(edytowany)

Uczę się pisać programy w arduino od miesiąca, teraz moje pytanie czy c++ w arduino i c++ w innym programie różni się sposobem pisania a zasada działania jest taka sama? Nie chciałbym uczyć się pseudo c++. 

Chodzi o to że jak opanuje AVRy i będę chciał programować inne mikrokontrolery to żeby nie okazało się że muszę języka uczyć się od nowa bo w arduino jest inna pisownia. 

Edytowano przez autozaglada
Link do komentarza
Share on other sites

Anonim

Myślę, że do programowania mikrokontrolerów najlepszym rozwiązaniem jest tradycyjnie język C nie C++ ale to się zmienia ze względu na coraz to nowsze szybsze i posiadające więcej pamięci mikrokontrolery więc nie będę zdziwiony kiedy za 10 lat podstawowym językiem programowania mikrokontrolerów nie będzie już ani C ani C++ a micropython.

Framework arduino i C++ w stosunku do AVR nie jest wcale dobrym rozwiązaniem pod względem wydajności i wykorzystania pamięci ale jest łatwy w użyciu a duża liczba gotowych bibliotek upraszcza sprawę do tego stopnia że nawet mało doświadczony użytkownik jest w stanie tworzyć zaawansowane projekty.

Każdy framework ma własną specyfikę, własne funkcje, własne możliwości bez względu na język programowania. Framework to zbiór gotowych narzędzi a nie język sam w sobie. Porównaj sobie arduino z Qt widgets, w jednym i drugim przypadku stosowany jest język C++ ale chcąc pisać aplikacje z ich wykorzystaniem nie wystarczy znajomość samego języka, trzeba też znać możliwości stosowanego frameworka i sprzętu na którym się go stosuje przynajmniej w takim zakresie aby nie mieć wątpliwości "z czym to się je". Doskonała znajomość arduino nie spowoduje jednocześnie, że nie będzie konieczne uczenia się od nowa Qt chcą pisać w nim aplikacje i na odwrót, jednak proces uczenia nowego frameworka będzie wtedy łatwiejszy.

Jeśli mogę coś doradzić to proponował bym uczyć się jednocześnie języka C i C++ gdzie C++ jest niejako rozszerzeniem języka C. Najlepiej nabrać doświadczenia pisząc na początku proste aplikacje konsolowe na PC, sprawdzić działanie pętli, tablic, wskaźników, pobawić się funkcjami z bibliotek std. dopiero z taką podstawą programistyczną siadać do mikrokontrolerów które mają własną specyfikę do której trzeba się dostosować. 

Sama znajomość danego języka nie jest równoznaczna z umiejętnością programowania bo to wymusza umiejętność myślenia w specyficzny sposób, której się nie da skopiować z githuba a która trzeba samemu nabyć jeśli się che ją posiadać. To jak z grą w szachy gdzie sama znajomość ruchów figur nie świadczy jeszcze o umiejętności gry.

Link do komentarza
Share on other sites

(edytowany)

Soyer dzięki za link. Napiszę dokładniej co chce zrobić. Arduino na wyświetlaczu wyswietla wyraz "dom" i chciałbym żeby od teraz wyświetlał "okno". Zakładając zadeklarowane przyciski lewo, prawo, góra, dół, ustaw, naciskam przycisk ustaw zaczyna migać kursor na literce "d" naciskam góra/dół aż pojawi się "o" potem przycisk prawo na literę obok itd. aż powstanie "okno" teraz potwierdzam ustaw i od teraz na wyświetlaczu jest wyraz okno. 

Dla alfabetu :

Char alfabet[] = "abcdefghijklmnoprstuwyz" ;

Do przewijania tekstu pętla for:

For(i = 0, i < x, i = z) 

z++ dla wciśnięcia przycisku góra

z-- dla wciśnięcia przycisku dół 

Lcd.print(alfabet 

 

Dobrze kombinuje? To jest oczywiście zarys programu. 

 

 

Edytowano przez autozaglada
Link do komentarza
Share on other sites

Anonim
15 minut temu, autozaglada napisał:

Lcd.print(alfabet

w ten sposób wypiszesz wszystkie litery bez względu na wybór. Musisz skanować 'alfabet' litera po literze albo skorzystać z funkcji biblioteki avrlibc do obsługi łańcuchów znaków. Zdaje się, że arduino operuje w tym zakresie jedynie na stringach.

Można korzystać z funkcji avrlibc korzystając jednocześnie z arduino. Wystarczy dodać do projektu odpowiednie pliki nagłówkowe za pomocą #include. do zadań matematycznych nieźle się również nadają funkcje biblioteki gsl .

linki:

avr-libc manual

GSL 2.6

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.