CTO

GUSH

Vertical Strawberry Farm Start-up

2024-Present

gush.farm
0

HARVESTS TRACKED

0

% LABOUR EFFICIENCY INCREASE

0

% YIELD INCREASE

Farming and Engineering

As CTO at GUSH, I've had the privilege of working with an incredible team of dedicated mission driven individuals to advance indoor vertical strawberry cultivation.

Joining just a few months after the farm's construction, I knew that optimizing operational efficiency and yield required reliable and highly automated data collection and analysis.

In the first month, I designed and built the 'Binscanner' which automated yield data collection. I also built a robust data model and database, and 'GUSH-OS' a custom web-app front-end to integrate, visualize and analyze all the farm's data. Finally, I built the 'GR-NFC' which tracks labour efficiency.

One key success was the design and implementation of a cost-effective solution to double our light uniformity across the entire farm, resulting in a 53% increase in yield.

Beyond these projects, my role at GUSH involves hands-on engineering across multiple disciplines - from designing industrial sized farms, integrating mechanical, fluid, electrical and biological systems, optimizing automation controls flows, and developing software solutions, to leading agronomic initiatives, experimental trials, strategic decision making and operations.

GUSH System 1 GUSH System 2 GUSH System 3 GUSH System 4 GUSH System 5 GUSH System 6

GR-NFC v.2.0

Data Collection System for Tracking Farm Labour Efficiency


import LCD_1in44
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime
import pytz
import sys
import time
from threading import Thread
import queue
from Gsheets import PostSheet, create_and_use_service_account
from sqlalchemy import create_engine

def main():
    try:
        # Initialize components
        disp = initialize_display()
        image, draw = initialize_graphics(disp)
        engine = initialize_database()
        input_thread = initialize_input_thread()
        
        # Initialize state
        current_state = 'IDLE'
        harvester = None
        bin_or_action = None
        
        # Main loop
        while True:
            # Handle RFID scans
            handle_rfid_scans(input_queue)
            
            # Handle button inputs
            handle_button_inputs(disp)
            
            # Update state machine
            current_state = update_state_machine(current_state)
            
            # Update display
            update_display(current_state, image, draw)
            
            # Show updated display
            disp.LCD_ShowImage(image, 0, 0)
            time.sleep(0.1)

    except KeyboardInterrupt:
        cleanup(disp)
    except Exception as e:
        print(f"Error in main loop: {e}")
        cleanup(disp)

if __name__ == "__main__":
    main()
                        

Binscanner

Harvest Data Collection for Strawberries


import datetime
from GSheets import PostSheet, GetLastEntry, upload_file_to_drive
from dymoM11 import get_bin_weight
from Cam2 import capture_image
from functions import check_wifi_connection
from gui import run_gui, nfc_page, confirm_data

def main():
    # 1. Initial Setup
    check_wifi_connection()
    values = run_gui()  # Get initial input values from GUI
    
    while True:
        # 2. NFC Card Reading
        if values['bin_id'] is None:
            nfc_data = nfc_page()
            # Process NFC data to get bin_id
            # Continue only when valid bin card is scanned
        
        # 3. Data Collection
        bin_weight = get_bin_weight()
        image = capture_image()
        
        # 4. Generate Scan ID
        scan_id = int(GetLastEntry()) + 1
        
        # 5. Process and Save Image
        image_path = f"{scan_id}-Berries.jpeg"
        cv2.imwrite(image_path, image)
        
        # 6. Upload to Google Drive
        image_id = upload_file_to_drive(image_path)
        
        # 7. Process and Submit Data
        try:
            confirm_data(
                scan_id=scan_id,
                date=datetime.datetime.now().date(),
                time=datetime.datetime.now().time(),
                bin_id=values['bin_id'],
                bin_weight=bin_weight,
                berry_weight=calculate_berry_weight(bin_weight, values['pack_type']),
                cultivar_id=values['cultivar_id'],
                grow_room=values['cycle_id'][:3],
                cycle_id=values['cycle_id'],
                grade=values['grade'],
                pack_type=values['pack_type'],
                week_num=calculate_week_number(),
                group_id=values['group_id']
            )
            values['bin_id'] = None  # Reset for next scan
        except Exception as e:
            print(f"Error submitting data: {e}")
            break

if __name__ == "__main__":
    main()
                        

Robotic Harvester

Prototype End-Effector for Robotic Harvester


#README
#PINOUT
# Positive to 3.3V
# Negative to GND
# Signal to GPIO0

# SETUP
# ls /dev/tty.*
# rshell -p /dev/tty.usbmodem*
# cp main.py /pyboard/main.py
# repl
# import main


from gpiozero import Servo
from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep

# Initialize pigpio factory
factory = PiGPIOFactory()

# Create servo on GPIO17 using pigpio with specific pulse widths
# MG90S servo uses 500-2400 microseconds
servo = Servo(14, 
                min_pulse_width=0.0005,  # 500us
                max_pulse_width=0.0024,  # 2400us
                pin_factory=factory)

try:
    while True:
        print("Moving to maximum position")
        servo.value = -0.18  # Full clockwise
        sleep(0.2)
        
        print("Moving to minimum position")
        servo.value = -0.8  # Full counter-clockwise
        sleep(0.2)


except KeyboardInterrupt:
    print("\nExiting program")
    servo.detach()