Crate-Scan Pro: the AI Surface Inspector - CTAI HOWEST

by Joran Planckaert in Circuits > Raspberry Pi

37 Views, 1 Favorites, 0 Comments

Crate-Scan Pro: the AI Surface Inspector - CTAI HOWEST

Schermafbeelding 2026-06-17 145353.png

thousands of plastic crates run through industrial washing machines everyday, but a lot of companies don't check whether they actually came out clean. Stickers stay stuck. Mud hides in the corners. Broken crates slip back into the supply chain. That is where Crate-Scan Pro steps in.

This project is a fully automated AI inspection tunnel that scans crates for filth or structural defects inside the crates. A YOLO11 detection model, running on a Raspberry Pi 5, instantly classifies any defects: mud, stickers, organic material, or structural damage.

Built from laser-cut multiplex, a custom conveyor, and a bunch of electronics, this is a real industrial prototype made from scratch.

Supplies

For this Project you will need a handful of supplies:

Total estimated cost if buying everything new: +-€280

Electronics & Computing

  1. Raspberry Pi 5 Starter Kit - €99.99
  2. 5" TFT LCD Display - €46.90
  3. 120° Wide Angle USB Camera (OV2643) - €20.67
  4. L298N Dual H-Bridge Motor Controller - €5.99
  5. DC 12V 50RPM Gear Reduction Motor - €9.81
  6. AC Adapter 12V 2A 24W - €7.99
  7. HC-SR04 Ultrasonic Distance Sensor - €6.28
  8. RGB LED Module - €1.25
  9. Active Buzzer Module - €6.99
  10. Round Momentary Push Button (22mm) - €7.59
  11. 2x LED Strip White 6000K 12V 0.5m - €12.90
  12. Raspberry Jumper Wires - €4.99
  13. M2.5 Nylon Standoff / Spacer Assortment - €8.59
  14. Breadboard 400 point - €8.29

Housing & Mechanical

  1. 5x Multiplex 4mm / 600×450mm sheets - €19.50
  2. HC-SR04 3D Printed Adjustable Mount - €1.80
  3. Rubber Feet 25×15mm (optional) - €2.99

Custom Conveyor Parts (self-sourced)

  1. electricity wire 0,5 mm²
  2. 2x Aluminium L-profile 370-390mm
  3. 3x Steel axles
  4. 6x Roller bearings
  5. grip sleeves ( a couple little ones or 3 long ones)
  6. Toothed rubber conveyor belt
  7. Timing belt + pulley set
  8. Spring clip Or something to hold the Roller bearings
  9. Roller bearing glue

Tools

  1. Laser cutter
  2. Adobe Illustrator
  3. Autodesk Inventor, or any 3d drawing program
  4. Soldering iron + solder
  5. Wire stripper / crimper
  6. Spray paint, matte grey
  7. Screwdrivers, pliers, scissors, drill, basic tools

Taking Photos & Annotating the Dataset

WhatsApp Image 2026-06-18 at 22.03.15.jpeg
Schermafbeelding 2026-06-18 231341.png

Before any model can work, you need data. I photographed plastic crates with manually applied filths and annotated every image with bounding boxes.

The 5 defect Classes

  1. Clean
  2. Sticker
  3. Mud_Dirt
  4. Organic
  5. Structural


2 Extra classes

  1. Bad_crate
  2. Good_crate


How I collected the images

  1. I used one consistent crate in different lightning, positions and background.
  2. I manually applied defects: pressed stickers on, smeared mud, placed leaves inside, and used physically damaged crates for the structural class.
  3. I made sure to also capture images with multiple defects in one frame to prepare the model for real situations.


Annotating With Roboflow

I used Roboflow to draw bounding boxes around each defect and assigned it to a class. Each image has more then one bounding box and try to be as accurate as possible.


Target: 100 annotations per defect class

This is the bare minimum for a working model. You will need to take more photos of clean crates to get rid of a unbalanced dataset. It is also recommended to take photos with different classes inside one crate.



First Model Training

Schermafbeelding 2026-06-18 223326.png
Schermafbeelding 2026-06-18 223419.png
Schermafbeelding 2026-06-18 231122.png

With the first batch of images annotated, I trained an YOLO11 model to see where it struggled, then improved the dataset based on what I found. I used my own GPU to speed up the process.


The Confusion Matrix

After training, YOLO generates a confusion matrix. I looked for classes that were regularly confused with each other. The biggest problem, mud_dirt vs. background.


What I fixed

  1. Added more varied mud images.
  2. Added saturation and brightness augmentation in RoboFlow.
  3. Photographed more images with multiple classes in one frame.

3D Design

Schermafbeelding 2026-06-18 224106.png
Schermafbeelding 2026-06-18 231220.png

With the model working, I moved to designing the build in Inventor. The tunnel housing uses interlocking finger joints, so there won't be any need for screws.


Tunnel dimensions

  1. 290mm wide × 400mm long × 290mm tall (4mm multiplex)
  2. Two-level design: lower level = scan tunnel, upper level = electronics bay


Design

  1. Generate a box template with a generator online with thickness = 4.0mm. The other settings are own preference.
  2. Import the DXF into Autodesk Inventor.
  3. Cut out new joints for the false roof and make the exit/entrance to own preference based on which crate you are using.
  4. Cut out hardware equipment
  5. Export each panel as a separate DXF.
  6. Arrange all panels in Adobe Illustrator to fit across your used lasercutter.
  7. Add Engravings and use the right color coding
  8. Laser cut. For 4mm multiplex


Cut outs per panel

  1. Front face: arched crate opening, LCD slot, push button hole, LED slot
  2. False Roof: camera mount hole in centre, cable pass-throughs at the corners
  3. Back Plate: arched crate exit, ventilation slots
  4. Side Plate: Cable holes, 12V jack connector hole, hole for Raspberry Pi connections


Engravings

You can put an image on the sides of the tunnel to give it more life and let the lasercut engrave this.


Spray Painting

Paint all panels before assembling with a industrial looking color. make sure you only do a light spray so you dont cover your engravings on the side.

Testing the Hardware

942e9bb9-d72a-409c-8794-218d3a7cfff3.jpg
Schermafbeelding 2026-06-18 235718.png

Before writing the full application, I tested every hardware component individually with simple Python scripts which are stored in a file debugging.py. This saves a lot of debugging time later.


What I Tested

  1. RGB LED
  2. Buzzer
  3. Distance sensor
  4. Motor via L298N
  5. LCD
  6. Button
  7. Led strips
  8. Camera

Downloads

Writing the Main App & Gradio Interface

Schermafbeelding 2026-06-18 235245.png
Schermafbeelding 2026-06-18 234901.png
Schermafbeelding 2026-06-18 234937.png
Schermafbeelding 2026-06-18 235008.png

App.py

With all hardware tested, I built the main application (app.py) that handles the camera, YOLO inference, hardware output, and the Gradio web interface.


Gradio Interface pages

  1. Onboarding - Operator guide: how to place a crate, how to read the LED signals
  2. Operating - Manual camera stream with YOLO bounding boxes overlaid & thresholds
  3. Data - Live crate count, defect distribution chart per class and previous image
  4. Debugging - Manual toggle for hardware in manual mode


Open the interface at http://<raspberry-pi-ip>:7860 from any device on the same network.

Downloads

Assembling the Tunnel

bc0b9469-7535-462e-b45b-0d04d7521fd1.jpg
8d8c543d-b030-425c-b92b-c9d849fd6746.jpg
e54280a2-f48c-4e74-9c10-7ea26e147298.jpg

With the software working and all the panels cut, corrected and spray painted, it was time to assemble everything together.


Tunnel Assembly

  1. Slot all painted finger-jointed panels together. Use wood glue / superglue on permanent joints. Keep the electronics bay lid and one side panel removable
  2. Mount the HC-SR04 on its 3D-printed bracket, pointing down towards the entrance of the tunnel
  3. fit the LED strips along the inside top edge of the scan tunnel. Press them firmly against the wood
  4. Install the push button in its circular hole on the front panel
  5. Montage the M2.5 nylon standoffs for the camera, Pi and L298N Module
  6. Place the Raspberry Pi, Projectboard, L298N Module, Power extension block firmly close to each other
  7. Place the 12V Jack Connector in the hole
  8. Place the LCD
  9. Place the RGB led

Assemble the Conveyor

Schermafbeelding 2026-06-19 001344.png

This was the most custom part of the entire build and took the most time to get right. Rather than buying a pre-made conveyor, I built one from scratch to fit exactly inside the tunnel dimensions.


Conveyor Assembly

Frame

  1. Cut two aluminium L-profiles to the internal tunnel width.
  2. Drill axle holes at the middle and both ends, spaced to give the belt the correct tension. ( Or how I did it is make a long notch at the driver side so you can bring the belt under tension)
  3. Also drill holes to connect 2 middle plates for strenght and 6 small holes for the conduit spring clips.


Axles and bearings

  1. Cut three steel axles to length, long enough to span the rails with a small overhang on each side.
  2. Press the roller bearings onto each axle end. I used conduit spring clips mounted to the L-Pofiles to held the bearings in place.
  3. Use an old toothed belt and cut them into pieces the size of the circumference of your axles.
  4. Glue them around the axles so the teeths can mount into eachother and the belt doesnt slip.


Belt and motor drive

  1. Fit the toothed rubber belt around axles. and bring it under tension.
  2. Mount the 12V DC gear motor to the frame using its mounting bracket on the drive-axle side.
  3. Connect the motor output shaft to the drive axle using a timing belt and pulley set. This gives a clean mechanical transmission without direct coupling and makes it easy to adjust tension later.


Installing in the tunnel

  1. Solder 2 electricity cables on to the motor pins and bring them to the upper bay.
  2. Slide the finished conveyor unit into the lower bay of the tunnel.


Wiring the Electronics

ea146e71-39aa-420c-a4d0-d26759ec7cd5.jpg
65975bdb-30b7-4c27-ba22-ce02691a0202.jpg
0fbac05a-3009-4029-8648-7d6c9000a7bb.jpg

All electronics are housed in the upper bay, separated from the scan zone below by the divider shelf. This keeps heat, cables, and components away from the crates passing through underneath. We already placed all our components.


First steps

  1. Provide the projectboard with the 3.3V / 5V and GND.
  2. Connect the Distance sensor to 5V, GND and your chosen GPIOs.
  3. Glue the led cables nicely to the panel leading to the Out3 and out4 of the L298N module.
  4. Connect the 12V Jack connector to the power extension block.

!! Dont connect the Echo pin directly to the pi !!

Go from the echo pin to a 1kOhm Resistor and from this with a 2kOhm resistor to the GND. Between the two resistors you can go to your assigned GPIO.


Soldering

I soldered the RGB led and button cables to jumper cables for easy GPIO connection. When done soldering tape the connection off so there can't be a bad connection.


Connections

  1. Provide the L298N with power
  2. Connect the RGB to your assigned GPIO's and Power.
  3. Connect the Buzzer to your assigned GPIO's, Power and GND.
  4. Connect one Button cable to a GPIO and one to a GND
  5. Connect the Motor cables to the OUT1 and OUT2 of the L298N

At last you connect the LCD and Camera to the connectors of the raspberry pi.

Automation Logic, Backend & Headless Operation

dbd293d8-f025-496c-88b3-6f4e08e38adf.jpg

With hardware assembled, I wrote the automation layer, the logic that runs the full system without any user input (automation.py).


automation.py

  1. Continuously reads the HC-SR04 distance sensor. When a crate is detected within 10–30cm, it triggers the conveyor and camera.
  2. Passes each captured frame to the YOLO model.
  3. Based on the detected class, activates the correct LED and optionally the buzzer.
  4. Logs every scan result to PostgreSQL via the FastAPI backend.
  5. Manages the push button for an Idle/Go mode.


PostgreSQL + Docker backend

The Docker Compose file deploys a PostgreSQL container. Every scan is logged with a timestamp, detected classes, confidence scores and bounding boxes. This feeds the Data page in Gradio and LCD with live statistics.


Auto-start on boot

The program works with two services who launch on startup.

  1. Conveyor.service ( automation.py)
  2. Cratescan.service ( app.py )


Downloads

Final Assembly & How to Use It

4f0ed244-b579-4616-a002-071582204c01.jpg
d57b8867-376c-4250-b695-16070735420a.jpg
dbd293d8-f025-496c-88b3-6f4e08e38adf (1).jpg

Final assembly checklist

  1. Confirm all panels (excluding the top / side) are glued.
  2. Confirm the conveyor belt runs smoothly with no belt slip or bearing noise.
  3. Confirm all GPIO connections are secure and cables are routed through trunking.
  4. Confirm the camera is centred and angled correctly over the belt.
  5. Confirm the LCD is secured and the HDMI cable is connected.
  6. Confirm the push button clicks and registers in the test script.
  7. Close the electronics bay lid.
  8. Attach rubber feet to the underside (Optional).


How to use it

  1. Connect the 12V adapter and USB-C power to the Raspberry Pi.
  2. Wait approximately 45-60 seconds, the system boots and the LCD shows the dashboard automatically.
  3. Press the push button to start automatic scanning mode. Or open http://<ip>:7860 on any device on the same network.
  4. Place a crate on the entry side of the conveyor. The distance sensor detects it and starts the belt.
  5. The crate passes through the tunnel. YOLO analyses the camera feed in real time.
  6. The LED signals the result:
  7. 🟢 Green → Clean crate — ready to use
  8. 🟡 Yellow → Dirty crate (mud, sticker, or organic) — needs rewashing
  9. 🔴 Red + Buzzer → Structural damage — remove from circulation
  10. All results are logged. Open the Data page in Gradio to see live defect statistics.
  11. Press the button again to pause the system.