Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2023:adarmaz:sistem-cartografiere-sol [2023/05/29 19:47]
ioana.profeanu [Configurare timer]
pm:prj2023:adarmaz:sistem-cartografiere-sol [2023/05/30 09:13] (current)
ioana.profeanu [Download cod]
Line 1: Line 1:
 ====== Sistem Cartografiere Sol - Profeanu Ioana 333CA ====== ====== Sistem Cartografiere Sol - Profeanu Ioana 333CA ======
 ===== Introducere ===== ===== Introducere =====
-Proiectul constă într-un sistem inteligent de monitorizare și înregistrare a diferșilor parametri necesari dezvoltării plantelor, date care, utilizând o bază de date predefinită (stocată pe un card micro SD) cu plante și condițiile lor de mediu, pot fi comparate și interogate de utilizator, acesta putând să vadă o listă a plantelor viabile, să vadă toate plantele din baza de date, să afiseze sau reseteze media metricilor.+Proiectul constă într-un sistem inteligent de monitorizare și înregistrare a diferșilor parametri necesari dezvoltării plantelor, date care, utilizând o bază de date predefinită (stocată pe un card micro SD) cu plante și condițiile lor de mediu, pot fi interogate de utilizator, acesta putând să vadă o listă a plantelor viabile, să vadă toate plantele din baza de date, să afiseze sau reseteze media metricilor.
  
 Sistemul este extrem de util atât pentru cei din domeniul agriculturii,​ pentru a identifica plantele ce pot crește într-un anumit tip de sol și mediu, precum și pentru cei care își doresc să cultive diverse plante în grădină și vor să afle ce opțiuni au, sau să vadă daca o anumită plantă poate supraviețui condițiilor. Sistemul este extrem de util atât pentru cei din domeniul agriculturii,​ pentru a identifica plantele ce pot crește într-un anumit tip de sol și mediu, precum și pentru cei care își doresc să cultive diverse plante în grădină și vor să afle ce opțiuni au, sau să vadă daca o anumită plantă poate supraviețui condițiilor.
  
-Ideea a pornit de la nevoia de a cultiva plante într-un sol și mediu care să fie propice dezvoltării lor, sistemul ținând cont nu doar de climă, ci și de factorii impredictibili de mediu (seceta, inundații etc).+Ideea a pornit de la nevoia de a cultiva plante într-un sol și mediu care să fie propice dezvoltării lor, sistemul ținând cont nu doar de climă, ci și de factorii impredictibili de mediu (secetă, inundații etc).
 ===== Descriere generală ===== ===== Descriere generală =====
-Inițial, sistemul se află în starea de stand by, unde afișeaza date pe ecran despre condițiile de mediu și coordonatele GPS. Acestea sunt recalculate la interval de o oră și adăugate unei medii generale. Tot atunci, mediile generale ale factorilor de meniu sunt inregistrați într-un fișier de log pe cardul SD.+Inițial, sistemul se află în starea de stand by, unde afișează date pe ecran despre condițiile de mediu și coordonatele GPS. Acestea sunt recalculate la interval de o oră și adăugate unei medii generale. Tot atunci, mediile generale ale factorilor de meniu sunt inregistrați într-un fișier de log pe cardul SD.
  
 La apăsarea butonului joystick-ului,​ se afișează 5 opțiuni de meniuri, fiecare apărând pe ecran la interval de 6 secunde. Selectarea meniului dorit se face apăsând din nou pe buton, în timp ce meniul dorit este afișat pe ecran. La apăsarea butonului joystick-ului,​ se afișează 5 opțiuni de meniuri, fiecare apărând pe ecran la interval de 6 secunde. Selectarea meniului dorit se face apăsând din nou pe buton, în timp ce meniul dorit este afișat pe ecran.
Line 61: Line 61:
 În lipsa vreunui input de la utilizator, se verifică dacă au trecut 60 de minute de la ultima citire a datelor, iar daca da, se face recitirea. În lipsa vreunui input de la utilizator, se verifică dacă au trecut 60 de minute de la ultima citire a datelor, iar daca da, se face recitirea.
  
 +Programul face diverse verificări și afișări de mesaje pe ecran în cazurile speciale/de eroare, precum căutarea unei plante după resetarea metricilor, imposibilitatea de a citi cardul SD (de exemplu, dacă acesta nu este introdus) și dacă nu există nicio plantă care să poată fi plantată în mediul curent.
 ==== Configurare timer ==== ==== Configurare timer ====
  
-Deoarece în program am nevoie să contorizez diferite acțiuni (recalcularea metricilor o data la o oră, afișarea unui nou meniu la 6 secunde distanță, revenirea la meniul de stand-by in cazul neinteracțiunii user-ului timp de 3 minute). Am ales să configurez un timer utilizând Timer1, ce numără aproximativ 2 secunde, utilizând apoi mai multe variabile globale care contorizează de câte ori au trecut cele 2 secunde.+Deoarece în program am nevoie să contorizez diferite acțiuni (recalcularea metricilor o data la o oră, afișarea unui nou meniu la 6 secunde distanță, revenirea la meniul de stand-by in cazul neinteracțiunii user-ului timp de 3 minute), am ales să configurez un timer utilizând Timer1, ce numără aproximativ 2 secunde, folosind un prescaler de 1024 și CTC, utilizând apoi mai multe variabile globale care contorizează de câte ori au trecut cele 2 secunde.
  
 <spoiler Cod timer> <spoiler Cod timer>
 <code cpp> <code cpp>
 // timer contorizare durata de afisaj a statisticilor în stand-by // timer contorizare durata de afisaj a statisticilor în stand-by
-unsigned long int timerDisplayInfo = 0;+volatile ​unsigned long int timerDisplayInfo = 0;
 // timer contorizare timp de la ultimul input al user-ului // timer contorizare timp de la ultimul input al user-ului
-int timerUser = 0;+volatile ​int timerUser = 0;
 // contorizare timpul unui frame // contorizare timpul unui frame
-int frameTime = 0;+volatile ​int frameTime = 0;
  
 ISR(TIMER1_COMPA_vect) { ISR(TIMER1_COMPA_vect) {
Line 100: Line 101:
  
 \\ \\
-Apoi, în loop, variabilele globale de contorizare a timpului sunt verificateși în funcție de acestea sunt afișate datele pe ecranul OLED / se execută diverse acțiuni.+Apoi, în loop, variabilele globale de contorizare a timpului sunt verificate și în funcție de acestea sunt afișate datele pe ecranul OLED / se execută diverse acțiuni.
  
 ==== Configurare întrerupere buton joystick ==== ==== Configurare întrerupere buton joystick ====
Line 149: Line 150:
  
 Pentru lucrul cu cardul SD, am utilizat biblioteca SD.h, ce pune la dispoziție funcții de bază pentru scrierea și citirea datelor de pe cardul SD. Pentru lucrul cu cardul SD, am utilizat biblioteca SD.h, ce pune la dispoziție funcții de bază pentru scrierea și citirea datelor de pe cardul SD.
 +
 +=== Scrierea metricilor medii ===
 +
 +La fiecare recalculare a metricilor, mediile datelor citite sunt stocate și pe cardul SD într-un fișier de log numit metrics.txt,​ inserându-se media temperaturii,​ a umitității aerului și solului, a luminozității și numărul de citiri.
  
 <spoiler Cod scriere metrici pe cardul SD> <spoiler Cod scriere metrici pe cardul SD>
 <code cpp> <code cpp>
-void writeMetricsToSD(){+// function which writes the average metrics to sd card 
 +void writeMetricsToSD() 
 +{
   if (SD.begin(7)) {   if (SD.begin(7)) {
     File myFile;     File myFile;
Line 186: Line 193:
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
- 
-=== Scrierea metricilor medii === 
- 
-La fiecare recalculare a metricilor, mediile datelor citite sunt stocate și pe cardul SD într-un fișier de log numit metrics.txt,​ inserându-se media temperaturii,​ a umitității aerului și solului, a luminozității și numărul de citiri. 
  
 === Citirea plantelor === === Citirea plantelor ===
Line 200: Line 203:
  
 //​**Lavender,​ 3, 10, 30, 30, 60, 1, 3, 1, 3**// //​**Lavender,​ 3, 10, 30, 30, 60, 1, 3, 1, 3**//
 +
 +Temperatura este măsurată în ºC, iar umiditatea aerului în procente.
  
 Datele cu valori între 1-4 au următoarele semnificații:​ Datele cu valori între 1-4 au următoarele semnificații:​
Line 209: Line 214:
 | 4    | Polar | | 4    | Polar |
  
-Pentru modul de afișare a plantelor ce pot trăi în mediul curent, se compară valorile medii pentru fiecare dintre categoriile de metrici, afișându-se doar plantele care se încadrează în datele stocate pe cardul SD.+Pentru modul de afișare a plantelor ce pot trăi în mediul curent, se compară valorile medii pentru fiecare dintre categoriile de metrici, primul criteriu de comparare fiind clima, afișându-se doar plantele care se încadrează în parametrii dați.
  
 Pentru modul de afișare a tututor plantelor, se afișează pe ecran toate plantele, fără a face vreo filtrare. Pentru modul de afișare a tututor plantelor, se afișează pe ecran toate plantele, fără a face vreo filtrare.
Line 217: Line 222:
 <code cpp> <code cpp>
  
-void displayPlantsList(bool showAll) { +// functions which displays the valid plants 
-  display.clear(); ​// Clear the display +// on the display 
-  display.setCursor(0,​ 0); // Set the cursor position +void displayPlantsList(bool showAll) 
-  if (SD.begin(7)){+
 +  display.clear();​ 
 +  display.setCursor(0,​ 0); 
 +  ​// try to read from SD card 
 +  if (SD.begin(7)) {
     File myFile;     File myFile;
-    if(SD.exists("​plants.txt"​)) {+    if (SD.exists("​plants.txt"​)) {
       myFile = SD.open("​plants.txt"​);​       myFile = SD.open("​plants.txt"​);​
- +      // if the file exists, read from it 
-      if(myFile) {+      if (myFile) {
         int noPlantsOk = 0;         int noPlantsOk = 0;
- +        // parse the data of the plant by extracting it; 
-        while(myFile.available()) {+        // each data is delimited by a comma 
 +        while (myFile.available()) {
           bool okPlant = false;           bool okPlant = false;
           String line = myFile.readStringUntil('​\n'​);​           String line = myFile.readStringUntil('​\n'​);​
Line 234: Line 244:
           int values[9];           int values[9];
           int index = 0;           int index = 0;
 +          // read line
           while (line.length() > 0) {           while (line.length() > 0) {
             int commaIndex = line.indexOf(','​);​             int commaIndex = line.indexOf(','​);​
-            ​ 
             if (commaIndex != -1) {             if (commaIndex != -1) {
               String element = line.substring(0,​ commaIndex);​               String element = line.substring(0,​ commaIndex);​
-              line = line.substring(commaIndex + 2); // Skip comma and space after each value+              line = line.substring(commaIndex + 2);
               ​               ​
               if (index == 0) {               if (index == 0) {
Line 246: Line 255:
               } else {               } else {
                 values[index - 1] = element.toInt();​                 values[index - 1] = element.toInt();​
 +                // check if the plant is between parameters
                 if (showAll == false) {                 if (showAll == false) {
                   if (index == 1) {                   if (index == 1) {
Line 258: Line 267:
                   if (index == 3) {                   if (index == 3) {
                     int mediumTemp = sumTemps / timesRead;                     int mediumTemp = sumTemps / timesRead;
-                    if ((mediumTemp >= values[1] && mediumTemp <= values[2]) == false) {+                    if ((mediumTemp >= values[1] && mediumTemp <= values[2]) ​ 
 +                        ​== false) {
                       break;                       break;
                     }                     }
Line 265: Line 275:
                   if (index == 5) {                   if (index == 5) {
                     int mediumAirMoist = sumAirMoist / timesRead;                     int mediumAirMoist = sumAirMoist / timesRead;
-                    if ((mediumAirMoist >= values[3] && mediumAirMoist <= values[4]) == false) {+                    if ((mediumAirMoist >= values[3] && mediumAirMoist 
 +                        ​<= values[4]) == false) {
                       break;                       break;
                     }                     }
Line 272: Line 283:
                   if (index == 7) {                   if (index == 7) {
                     int mediumSoilMoist = sumSoilMoist / timesRead;                     int mediumSoilMoist = sumSoilMoist / timesRead;
-                    if ((mediumSoilMoist >= values[5] && mediumSoilMoist <= values[6]) == false) {+                    if ((mediumSoilMoist >= values[5] && mediumSoilMoist 
 +                        ​<= values[6]) == false) {
                       break;                       break;
                     }                     }
Line 281: Line 293:
               index++;               index++;
             } else {             } else {
-              // Last value in the line (no comma at the end)+              // read last value from line
               String element = line;               String element = line;
               values[index - 1] = element.toInt();​               values[index - 1] = element.toInt();​
               int mediumLight = sumLight / timesRead;               int mediumLight = sumLight / timesRead;
-              if (showAll == false && (mediumLight >= values[7] && mediumLight <= values[8]) == false) {+              if (showAll == false && (mediumLight >= values[7] 
 +                  ​&& mediumLight <= values[8]) == false) {
                 break;                 break;
               }               }
 +
               okPlant = true;               okPlant = true;
               noPlantsOk++;​               noPlantsOk++;​
Line 293: Line 307:
             }             }
           }           }
 +          // if a plant was found, display it
           if (okPlant) {           if (okPlant) {
-            ​checkAndDisplayPlant(name, values);+            ​displayPlantDetails(name, values);
           }           }
         }         }
 +        // if no plants were found
         if (noPlantsOk == 0) {         if (noPlantsOk == 0) {
           display.println("​No plants matched!"​);​           display.println("​No plants matched!"​);​
-          display.displayRows(); ​// Update the display+          display.displayRows();​
           delay(8000);​           delay(8000);​
         }         }
Line 305: Line 321:
           ​           ​
       } else {       } else {
 +        // if the file is not found
         display.println("​Add plants.txt file first!"​);​         display.println("​Add plants.txt file first!"​);​
-        display.displayRows(); ​// Update the display+        display.displayRows();​
         delay(8000);​         delay(8000);​
       }       }
     }      } 
   } else {   } else {
 +    // if unable to read file
     display.println("​Failed to display plants!"​);​     display.println("​Failed to display plants!"​);​
-    display.displayRows(); ​// Update the display+    display.displayRows();​
     delay(8000);​     delay(8000);​
   }   }
 } }
-    ​ 
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
Line 322: Line 339:
 ==== Parsare date GPS ==== ==== Parsare date GPS ====
  
-Pentru a utiliza modulul GPS NEO-6M, am folosit biblioteca SoftwareSerial.h. Deși în mod normal modulul utilizează USART, nu am folosit ​cei doi pini dedicațai Arduino-ului,​ deoarece acest lucru m-ar fi împiedicat din a face debugging utilizând afișarea ​la serială.+Pentru a utiliza modulul GPS NEO-6M, am folosit biblioteca SoftwareSerial.h. Deși în mod normal modulul utilizează USART, nu am folosit ​pinii RX șTX Arduino-ului,​ deoarece acest lucru m-ar fi împiedicat din a face debugging utilizând afișarea serială.
 Am decis, de asemenea, să îmi implementez propria funcție de parsare a input-ului primit de la GPS, din considerente de memorie (introducerea unei biblioteci adiționale ar fi costat memorie), dar și pentru că doream să extrag doar latitudinea din input-ul primit (doar de aceasta este nevoie pentru a determina clima). Am decis, de asemenea, să îmi implementez propria funcție de parsare a input-ului primit de la GPS, din considerente de memorie (introducerea unei biblioteci adiționale ar fi costat memorie), dar și pentru că doream să extrag doar latitudinea din input-ul primit (doar de aceasta este nevoie pentru a determina clima).
  
Line 330: Line 347:
 <code cpp> <code cpp>
  
-// function ​for extracting ​the latitude +// function ​which, from an input NMEA sentence, 
-String ​extractLatitude(const String& sentence) {+// extracts a string with the latitude 
 +String ​extractCoordinates(const String& sentence) 
 +{
   int commas;   int commas;
   if (sentence.indexOf("​GPRMC"​) != -1) {   if (sentence.indexOf("​GPRMC"​) != -1) {
Line 345: Line 364:
   int endIndex = -1;   int endIndex = -1;
  
 +  // count commas and extract the value of the latitude
   for (size_t i = 0; i < sentence.length();​ i++) {   for (size_t i = 0; i < sentence.length();​ i++) {
     if (sentence[i] == ','​) {     if (sentence[i] == ','​) {
Line 364: Line 384:
 } }
  
-// function ​for receiving ​NMEA sentences+// function ​which reads NMEA sentences ​from 
 +// software serial for 20 seconds and returns the 
 +// latitude in case the sentence is valid
 String getGPGGAsentence() String getGPGGAsentence()
 { {
Line 373: Line 395:
   gpsSerial.begin(9600);​   gpsSerial.begin(9600);​
  
-  // repeat the reading for 20 seconds 
   while (timerDisplayInfo - currentTime < MINUTE / 4) {   while (timerDisplayInfo - currentTime < MINUTE / 4) {
     if (gpsSerial.available()) {     if (gpsSerial.available()) {
Line 397: Line 418:
   return sentence;   return sentence;
 } }
- 
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
Line 447: Line 467:
 ===== Download cod ===== ===== Download cod =====
  
-Codul poate fi vizualizat [[https://​github.com/​ioanaprofeanu/​Sistem-cartografiere-sol.git|aici]].+Codul poate fi vizualizat [[https://​github.com/​ioanaprofeanu/​Sistem-cartografiere-sol.git|aici]] ​sau descărcat {{:​pm:​prj2023:​adarmaz:​sistem_cartografiere_sol.zip|aici}}.
 ===== Jurnal ===== ===== Jurnal =====
  
Line 455: Line 475:
   * 5-8 mai - realizare parte hardware   * 5-8 mai - realizare parte hardware
   * 10-20 mai - realizare parte software   * 10-20 mai - realizare parte software
 +  * 28-29 mai - finalizare documentație
  
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
Line 463: Line 484:
   * http://​educ8s.tv/​arduino-sd-card-tutorial/​   * http://​educ8s.tv/​arduino-sd-card-tutorial/​
   * https://​www.youtube.com/​watch?​v=qKku-mmwNIA&​list=LL&​index=8&​ab_channel=BINARYUPDATES   * https://​www.youtube.com/​watch?​v=qKku-mmwNIA&​list=LL&​index=8&​ab_channel=BINARYUPDATES
 +  * https://​docs.arduino.cc/​learn/​built-in-libraries/​software-serial
 +  * https://​content.meteoblue.com/​en/​research-education/​educational-resources/​meteoscool/​general-climate-zones
 +  * ChatGPT pentru găsirea plantelor care să se încadreze în anumitele tipuri de climă
  
 <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​ <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
pm/prj2023/adarmaz/sistem-cartografiere-sol.1685378838.txt.gz · Last modified: 2023/05/29 19:47 by ioana.profeanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0