User Tools

Site Tools


amc:ss2024:irrigantion_cart_nozzle:start

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
amc:ss2024:irrigantion_cart_nozzle:start [2024/07/31 01:21] – [Structural adjustment by adding a lever] amr.abdelkhalekamc:ss2024:irrigantion_cart_nozzle:start [2024/10/20 23:40] (current) – [Enhancing the If-Condition for Better Plant Recognition] amr.abdelkhalek
Line 36: Line 36:
  
 The following diagram Figure 1 shows the overall layout of our project: The following diagram Figure 1 shows the overall layout of our project:
 +the system uses LIDAR sensors for distance measurements, processes the data with an ESP32-S3-WROOM-1 microcontroller, and communicates the results to a personal computer and other components. 
 +  * **VLX53L0X (LIDAR Sensors):**
 +Horizontal Distance Input: One VLX53L0X sensor measures horizontal distance.
 +Vertical Distance Input: Another VLX53L0X sensor measures vertical distance.
 +  * **ESP32-S3-WROOM-1 (Arduino):**
 +Receives distance readings from both VLX53L0X sensors (horizontal and vertical distance).
 +Processes these readings and performs various tasks based on the data.
 +  * **LED Light/Actuator:**
 +Connected to the Arduino.
 +Can be turned on or off based on commands from the Arduino.
 +  * **Battery/Charger:**
 +Powers the ESP32-S3-WROOM-1.
 +  * **MQTT Server:**
 +Receives processed readings (distance data and actuator state) from the Arduino.
 +Sends actuator control commands (like "On" or "Off") to the Arduino.
 +  * **Personal Computer with Jupyter Notebooks:**
 +Communicates with the MQTT server to receive the distance readings and actuator state.
 +control commands to the MQTT server, which then relays them to the Arduino.
  
  
-{{amc:ss2024:irrigantion_cart_nozzle:blank_diagram.png?1000|Figure 1: Project Layout}}\\ +<imgcaption image1| Project Layout>{{amc:ss2024:irrigantion_cart_nozzle:blank_diagram.png?1000|Figure 1: Project Layout}}</imgcaption>\\
-**Figure 1: Project Layout**+
  
  
 The following Figure 2 is the implementation of the previous layout in real-life application: The following Figure 2 is the implementation of the previous layout in real-life application:
  
 +<imgcaption image2| Real-life Implementation>{{amc:ss2024:irrigantion_cart_nozzle:untitled.png?426.6x775.3|Figure 2: Real-life Implementation}}</imgcaption>\\
  
- 
-{{amc:ss2024:irrigantion_cart_nozzle:untitled.png?426.6x775.3|Figure 2: Real-life Implementation}}\\ 
-**Figure 2: Real-life Implementation** 
  
   - **Vertical VL53L0X Sensor**    - **Vertical VL53L0X Sensor** 
Line 283: Line 298:
 </file> </file>
 ===== Python Code =====  ===== Python Code ===== 
 +
 +==== Required Libraries ====
 +
 +To install the required libraries for the project, open and download the following text file "requirements.txt"
 +
 +<file txt requirements.txt>
 +bqplot
 +traits
 +numpy
 +paho-mqtt
 +ipywidgets
 +pandas
 +</file>
 +
 +Then run the following terminal command in the environment where you will run the project:
 +
 +<code python>
 +pip install -r requirements.txt
 +</code>
  
  
Line 508: Line 542:
  
 ==== Defining and Initializing System States with Enum ====  ==== Defining and Initializing System States with Enum ==== 
-<code python>+
 class State(Enum): class State(Enum):
     IDLE = 1       # State when the system is idle     IDLE = 1       # State when the system is idle
Line 1083: Line 1117:
     10001.0   296.0              185.0     12427.5     10001.0   296.0              185.0     12427.5
     10002.0   253.0              200.0     7500.5     10002.0   253.0              200.0     7500.5
-==== Enhancing the If-Condition for Better Plant Recognition ==== 
-To enhance the condition for recognizing plants more accurately, we need to implement peak detection logic and replace the older one; to ensure only true plants are detected. This approach reduces the likelihood of false positives caused by objects with heights above 120 mm even as mentioned earlier and help creating an automated system that keeps track of the plants.  
- 
  
 ==== Enhancing the If-Condition for Better Plant Recognition ==== ==== Enhancing the If-Condition for Better Plant Recognition ====
Line 1231: Line 1262:
  
 <code python> <code python>
- peaks_total_xposition+peaks_total_xposition
 </code> </code>
  
Line 1251: Line 1282:
     global state     global state
     global peaks_total_xposition, peaks_last     global peaks_total_xposition, peaks_last
-    global counter , checker+    global counter, counter_2, checker
     global arm_sens_lead      global arm_sens_lead 
  
Line 1260: Line 1291:
     traw, xraw, zraw = map(float, payload.strip('()').split(','))     traw, xraw, zraw = map(float, payload.strip('()').split(','))
  
-   # Initialize the start time if it's the first reading 
     if (i==0):      if (i==0): 
         t0 = traw         t0 = traw
  
-    # Calculate the time relative to the start time 
     t = traw - t0     t = traw - t0
-    # Calculate the relative x position 
     x = x0 - xraw     x = x0 - xraw
- 
-    # Calculate the relative z position 
     z = z0 - zraw     z = z0 - zraw
          
-    # Format the data string for logging 
     s = f"{i:4d}  {t:12.2f}  {x:6.2f}  {z:6.2f}"     s = f"{i:4d}  {t:12.2f}  {x:6.2f}  {z:6.2f}"
- 
     # Check if the system is idle and the current x position is at a peak position     # Check if the system is idle and the current x position is at a peak position
     if (state == state.IDLE) & np.isin(x,peaks_total_xposition):# & (z > 120) if a threshold is needed     if (state == state.IDLE) & np.isin(x,peaks_total_xposition):# & (z > 120) if a threshold is needed
- 
-       # Turn on the water nozzle 
         client.publish("gw/duese002-licht", "on")         client.publish("gw/duese002-licht", "on")
- 
-       # Set the state to watering 
         state = state.WATERING         state = state.WATERING
- +    # Check if the system is watering and the current x position is not at a peak position
-   # Check if the system is watering and the current x position is not at a peak position+
     if (state == state.WATERING) & np.isin(x,peaks_total_xposition,invert=True):     if (state == state.WATERING) & np.isin(x,peaks_total_xposition,invert=True):
- 
-     # Turn off the water nozzle 
         client.publish("gw/duese002-licht", "off")         client.publish("gw/duese002-licht", "off")
- 
-     # Set the state to idle 
         state = state.IDLE         state = state.IDLE
 +        
 +     #checks if the water is off and the cart position is on a plant location .. turns it on
 +     #checks if the water is on and the cart position is not on a plant location (inverts the logic).. turns it off
  
-     #check if the water is off and the cart position is on a plant location .. turns it on +          
-     #check if the water is on and the cart position is not on a plant location (inverts the logic).. turns it off+
  
-           
-   # Update the time data array 
     t_data = np.roll(t_data, -1); t_data[-1] = t         t_data = np.roll(t_data, -1); t_data[-1] = t    
- 
-   # Update the x data array 
     x_data = np.roll(x_data, -1); x_data[-1] = x     x_data = np.roll(x_data, -1); x_data[-1] = x
- 
-    # Update the z data array 
     z_data = np.roll(z_data, -1); z_data[-1] = z     z_data = np.roll(z_data, -1); z_data[-1] = z
  
-    # Combine the data into a single array 
     data = np.array([t_data, x_data, z_data]).T     data = np.array([t_data, x_data, z_data]).T
-   # Increment the counter+
     counter += 1     counter += 1
- 
-   # Check if counter reaches the checker value 
     if counter == checker:     if counter == checker:
- 
-       # Find peaks in the z_data array with specified width and distance between peaks 
         peaks_wd, wid_dis = find_peaks(z_data, width=9,distance=50)         peaks_wd, wid_dis = find_peaks(z_data, width=9,distance=50)
- 
-       # Check if the number of detected peaks is greater than the last detected peaks 
         if   len(peaks_wd) > len(peaks_last):         if   len(peaks_wd) > len(peaks_last):
-        +            peak_positions = np.add(np.full(len(x_data[peaks_wd]), arm_sens_lead), x_data[peaks_wd]) 
-      # Calculate the new peak positions by adding the sensor lead distance to the current peak     positions +            peaks_total_xposition = np.sort(np.unique(np.append(peaks_total_xposition,peak_positions)))
-# np.full(len(array_x[peaks_wd]), arm_sens_lead): Creates an array of the same length as array_x[peaks_wd], # where every element is equal to arm_sens_lead (300 mm). This represents the lead distance for the sensor. +
- # array_x[peaks_wd]: Retrieves the x positions corresponding to the detected peaks.  +
-# np.add(...): Adds the sensor lead distance to each of the x positions of the detected peaks. +
-          peak_positions = np.add(np.full(len(array_x[peaks_wd]), arm_sens_lead), array_x[peaks_wd]) +
- +
-       # Update the total x positions of the peaks with the new peak position +
-            peaks_total_xposition = np.unique(np.append(peaks_total_xposition,peak_positions)) +
- +
-# Update the last detected peaks with the new peak position+
             peaks_last = peaks_wd             peaks_last = peaks_wd
- 
-# Reset the counter 
         counter = 0         counter = 0
- +        
-#Check if the secondary counter reaches N1+
     if counter_2 == N1:     if counter_2 == N1:
- +        x_data = np.linspace(xsc_min, xsc_max, N1)  # reinitialize with empty arrays
-# Reinitialize the x data array with linear spacing between xsc_min and xsc_max +
-        x_data = np.linspace(xsc_min, xsc_max, N1)   +
- +
-Reinitialize the z data array with zeros+
         z_data = np.array(np.zeros(N1))  # reinitialize with empty arrays         z_data = np.array(np.zeros(N1))  # reinitialize with empty arrays
- 
-# Reinitialize the t data array with zeros 
         t_data = np.array(np.zeros(N1))  # reinitialize with empty arrays         t_data = np.array(np.zeros(N1))  # reinitialize with empty arrays
  
-# Update the plotter with the new data 
     plotter.update_data1(data)     plotter.update_data1(data)
  
-Calculate the index of x_acc array with the x closest to x_acc[idx]+# index of x_acc array with the x closest to x_acc[idx]
     idx = int(np.round(x/dx))      idx = int(np.round(x/dx)) 
- +    if (idx >= 0) & (idx < N2):
-# Check if the calculated index is within the valid range of the x_acc array +
-    if (idx >= 0) & (idx < N2): # N2 is the length of the x_acc array +
- +
-      # If the accumulator count at this index is zero+
         if n_acc[idx] == 0:         if n_acc[idx] == 0:
- 
-      # Initialize the z_acc value at this index with the current z position 
             z_acc[idx] = z             z_acc[idx] = z
         else:         else:
 #            z_acc[idx] = (n_acc[idx] * z_acc[idx] + z) / (n_acc[idx] + 1) #            z_acc[idx] = (n_acc[idx] * z_acc[idx] + z) / (n_acc[idx] + 1)
-# Update the z_acc value at this index with a weighted average of the previous z_acc value and the current z position 
             z_acc[idx] = (4 * z_acc[idx] + z) / 5             z_acc[idx] = (4 * z_acc[idx] + z) / 5
-        +            
-# Increment the accumulator count at this index     +
         n_acc[idx] += 1         n_acc[idx] += 1
  
-# Combine the accumulated data into a single array 
     data2 = np.array([n_acc, x_acc, z_acc]).T     data2 = np.array([n_acc, x_acc, z_acc]).T
  
-# Update the plotter with the accumulated data 
     plotter.update_data2(data2)     plotter.update_data2(data2)
          
-#    out.append_stdout(s + "\n")+#    out.append_stdout(s + "\n")def on_message(client, userdata, message): 
 +    
 </code> </code>
 ====== VI. Conclusion ====== ====== VI. Conclusion ======
  
-Further development and testing will continue to refine the detection algorithms and explore alternative communication protocols to enhance system performance and reliability as well as creating proper backups using PostgreSQL Dashboards.+This project addresses water scarcity by developing an automated irrigation cart that conserves water through precise plant detection and targeted watering.  
 + 
 +Utilizing VL53L0X sensors and an Arduino, the system accurately monitors plant presence and cart movement, ensuring efficient water use.  
 + 
 +The integration of MQTT for communication and Python for data processing lays the groundwork for future enhancements, including improved sensors and expanded scalability. 
 + 
 +Future enhancements will focus on refining detection algorithms and exploring alternative communication protocols, including PostgreSQL Dashboards for reliable backups 
  
 Sensors may be replaced in the future with faster detecting ones so that their algorithms may be easier or more straight forward to accommodate a much larger number of sensors.  Sensors may be replaced in the future with faster detecting ones so that their algorithms may be easier or more straight forward to accommodate a much larger number of sensors. 
Line 1385: Line 1368:
 Multiplexers most probably will be used for connecting with the multiple number of nozzles for our system e.g. irrigating 30 rows at the same time. Each of which will have at least a single sensor, and a water nozzle. 30 controlling MOSFETS hence may be connected to our microcontroller plus the 30 sensors.  Multiplexers most probably will be used for connecting with the multiple number of nozzles for our system e.g. irrigating 30 rows at the same time. Each of which will have at least a single sensor, and a water nozzle. 30 controlling MOSFETS hence may be connected to our microcontroller plus the 30 sensors. 
  
-Further studies are going to be done on the rush in current in case large nozzles will be used .. and 30 of those will mean multiple of that rush in current, in case a smooth start is needed to be done to ease that rush in current PWM may be required.+Further studies are going to be done on the rush in current in case large nozzles will be used .. and 30 of those will mean multiple of that rush in current. Additionallythis further research will be conducted on managing current surges when using large nozzles might introduce the possibility of implementing PWM to ensure a smooth startup to mitigate the current spikes.
  
 https://wiki.eolab.de/doku.php?id=eolab:projects:giesswagen:start https://wiki.eolab.de/doku.php?id=eolab:projects:giesswagen:start
Line 1391: Line 1374:
 ====== VII. References ====== ====== VII. References ======
  
 +  * Pololu, “VL53L0X-arduino/examples/single/single.ino at master · Pololu/VL53L0X-arduino,” GitHub, https://github.com/pololu/vl53l0x-arduino/blob/master/examples/Single/Single.ino (accessed Jun. 17, 2024). 
 +  *  “Find_peaks#,” find_peaks - SciPy v1.14.0 Manual, https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html#scipy.signal.find_peaks (accessed Jul. 09, 2024).
  
  
  
amc/ss2024/irrigantion_cart_nozzle/start.1722381695.txt.gz · Last modified: 2024/07/31 01:21 by amr.abdelkhalek