amc:ss2024:irrigantion_cart_nozzle:start
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
amc:ss2024:irrigantion_cart_nozzle:start [2024/07/31 01:21] – [Structural adjustment by adding a lever] amr.abdelkhalek | amc: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, | ||
+ | * **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/ | ||
+ | Connected to the Arduino. | ||
+ | Can be turned on or off based on commands from the Arduino. | ||
+ | * **Battery/ | ||
+ | Powers the ESP32-S3-WROOM-1. | ||
+ | * **MQTT Server:** | ||
+ | Receives processed readings (distance data and actuator state) from the Arduino. | ||
+ | Sends actuator control commands (like " | ||
+ | * **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: | + | < |
- | **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: | ||
+ | < | ||
- | |||
- | {{amc: | ||
- | **Figure 2: Real-life Implementation** | ||
- **Vertical VL53L0X Sensor** | - **Vertical VL53L0X Sensor** | ||
Line 283: | Line 298: | ||
</ | </ | ||
===== Python Code ===== | ===== Python Code ===== | ||
+ | |||
+ | ==== Required Libraries ==== | ||
+ | |||
+ | To install the required libraries for the project, open and download the following text file " | ||
+ | |||
+ | <file txt requirements.txt> | ||
+ | bqplot | ||
+ | traits | ||
+ | numpy | ||
+ | paho-mqtt | ||
+ | ipywidgets | ||
+ | pandas | ||
+ | </ | ||
+ | |||
+ | Then run the following terminal command in the environment where you will run the project: | ||
+ | |||
+ | <code python> | ||
+ | pip install -r requirements.txt | ||
+ | </ | ||
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 | 10001.0 | ||
10002.0 | 10002.0 | ||
- | ==== 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 |
</ | </ | ||
Line 1251: | Line 1282: | ||
global state | global state | ||
global peaks_total_xposition, | global peaks_total_xposition, | ||
- | 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(' | traw, xraw, zraw = map(float, payload.strip(' | ||
- | # 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" | s = f" | ||
- | |||
# 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, | if (state == state.IDLE) & np.isin(x, | ||
- | |||
- | # Turn on the water nozzle | ||
client.publish(" | client.publish(" | ||
- | |||
- | # 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 | + | |
if (state == state.WATERING) & np.isin(x, | if (state == state.WATERING) & np.isin(x, | ||
- | |||
- | # Turn off the water nozzle | ||
client.publish(" | client.publish(" | ||
- | |||
- | # Set the state to idle | ||
state = state.IDLE | state = state.IDLE | ||
+ | | ||
+ | # | ||
+ | # | ||
- | # | + | |
- | # | + | |
- | | ||
- | # Update the time data array | ||
t_data = np.roll(t_data, | t_data = np.roll(t_data, | ||
- | |||
- | # Update the x data array | ||
x_data = np.roll(x_data, | x_data = np.roll(x_data, | ||
- | |||
- | # Update the z data array | ||
z_data = np.roll(z_data, | z_data = np.roll(z_data, | ||
- | # Combine the data into a single array | ||
data = np.array([t_data, | data = np.array([t_data, | ||
- | # 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, | peaks_wd, wid_dis = find_peaks(z_data, | ||
- | |||
- | # Check if the number of detected peaks is greater than the last detected peaks | ||
if | if | ||
- | + | | |
- | # Calculate the new peak positions by adding the sensor lead distance to the current peak | + | peaks_total_xposition = np.sort(np.unique(np.append(peaks_total_xposition, |
- | # np.full(len(array_x[peaks_wd]), | + | |
- | # array_x[peaks_wd]: | + | |
- | # np.add(...): | + | |
- | | + | |
- | + | ||
- | # Update the total x positions of the peaks with the new peak position | + | |
- | peaks_total_xposition = np.unique(np.append(peaks_total_xposition, | + | |
- | + | ||
- | # 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: | ||
- | + | | |
- | # Reinitialize the x data array with linear spacing between xsc_min and xsc_max | + | |
- | | + | |
- | + | ||
- | # Reinitialize the z data array with zeros | + | |
z_data = np.array(np.zeros(N1)) | z_data = np.array(np.zeros(N1)) | ||
- | |||
- | # Reinitialize the t data array with zeros | ||
t_data = np.array(np.zeros(N1)) | t_data = np.array(np.zeros(N1)) | ||
- | # 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/ | idx = int(np.round(x/ | ||
- | + | | |
- | # Check if the calculated index is within the valid range 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, | data2 = np.array([n_acc, | ||
- | # Update the plotter with the accumulated data | ||
plotter.update_data2(data2) | plotter.update_data2(data2) | ||
| | ||
- | # out.append_stdout(s + " | + | # out.append_stdout(s + " |
+ | | ||
</ | </ | ||
====== VI. Conclusion ====== | ====== VI. Conclusion ====== | ||
- | Further development | + | This project addresses water scarcity by developing an automated irrigation cart that conserves water through precise plant detection |
+ | |||
+ | Utilizing VL53L0X sensors and an Arduino, | ||
+ | |||
+ | The integration of MQTT for communication and Python for data processing lays the groundwork for future enhancements, | ||
+ | |||
+ | Future enhancements will focus on refining | ||
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, | + | 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. Additionally, this further research will be conducted on managing current surges when using large nozzles might introduce the possibility of implementing PWM to ensure |
https:// | https:// | ||
Line 1391: | Line 1374: | ||
====== VII. References ====== | ====== VII. References ====== | ||
+ | * Pololu, “VL53L0X-arduino/ | ||
+ | * “Find_peaks#, | ||
amc/ss2024/irrigantion_cart_nozzle/start.1722381695.txt.gz · Last modified: 2024/07/31 01:21 by amr.abdelkhalek