The V-Box: Smart Capacity-Tracking Box With Pi Pico

by learningninja496i in Circuits > Microcontrollers

64 Views, 0 Favorites, 0 Comments

The V-Box: Smart Capacity-Tracking Box With Pi Pico

IMG_1605.JPG

Let's face it-we all lose our things. From our phone to our car keys, to even an important letter, it all mysteriously goes away. I'm a student, and I misplace my school supplies very often. To solve this issue, I worked for a few days on a box that will securely store my items, and will also track capacity, so I don't overfill the box. This is a relatively simple project-it uses only a few components.

Downloads

Supplies

To build this mechanism, you will need:

1x Raspberry Pi Pico @2020

1x Servo Motor SG90

1x HCSR04 Ultrasonic sensor

1x 10 segment LED Bar Graph

1x Micro Slide Switch

1x Cardboard Box of any size

2x Half Breadboard

Male to Male Jumper Wires

Male to Female Jumper Wires

220-ohm Resistors

10K ohm Resistors

1x Red LED

1x Green LED

1x 104 ceramic capacitor

Tape

Minus the breadboards and the Cardboard Box, everything is included in Sunfounder's Euler Ultimate Kit for Raspberry Pi Pico.

MicroPython on Thonny IDE will be needed for this project.

Find a Box

This step takes the quickest amount of time, out of this entire Instructable. The best ones to use are Amazon boxes, or you can go to your local grocery store (such as Costco, Harris Teeter, Walmart, etc.) to get a box. The box can be any size; for my project, I used a 5in x 5in x 12in box, though the box should probably be bigger than 4 in x 1 in x 9 in.

The Circuit

Screenshot 2025-08-25 200941.png

This circuit has an ultrasonic, a servo, an LED bar graph, a slide switch, and an LED indicator. Turning on the switch will allow the servo to rotate, and the indicator will turn from green to red. One thing to note: in the diagram, the light blue wire is meant to be a 104-ceramic capacitor.

Box Modifications

To be able to accommodate the wires, the box will need to be modified. The following steps will explain those details.

The Lid

IMG_1611.JPG

The box will need to be cut off with a pair of scissors or a utility knife. Often the box will have two lids that close together and open together, and two reinforcing lids underneath it. Use tape to bind the two top lids together and the two reinforcing lids together, and the two taped lids together.

The Ultrasonic

IMG_1610.JPG
IMG_1614.JPG

The ultrasonic sensor will go under the lid. To have the wires easily flow through, a utility knife is needed to cut a 1cm x 1cm hole on the top of a side adjacent to where the breadboards will be taped, but not the lid or bottom of the box. Once the hole is cut, create a tape loop, stick one side of it to the ultrasonic, and stick the other end of it to the box lid. the wires will need to be disconnected, stuck through the hole, and reconnected.

The Servo

IMG_1612.JPG

Once the ultrasonic is secured, cut a trench on the side of the box to accommodate the servo. After that, bind the side of the box to the arm of the servo with tape. This will allow the box to open when the servo rotates.

The Breadboards

IMG_1613.JPG

On a side adjacent to the ultrasonic sensor wire hole, add tape loops that will stick to the breadboard and the box.

The Code

The following is the MicroPython code. Specify the height of the box in lines 54, 60, and 61(wherever it says '29.6', that was the height of my box)

import machine
from machine import Pin, PWM
import time

servo_pin = machine.Pin(0)#pin
servo = PWM(servo_pin)

close = 1802
opem = 3032
frequency = 50
servo.freq(frequency)

slide = machine.Pin(15, machine.Pin.IN)#pin
nsc = machine.Pin(13, machine.Pin.OUT)#pin
sc = machine.Pin(12, machine.Pin.OUT)#pin

trig = machine.Pin(5, machine.Pin.OUT)#pin
echo = machine.Pin(6, machine.Pin.IN)#pin
pin = [16, 17, 18, 19, 20, 21, 22, 26, 27, 28]#pin
led = []

for i in range(10):
led.append(None)
led[i] = machine.Pin(pin[i], machine.Pin.OUT)
led[i].value(0)

def distance():
trig.low()
time.sleep_us(2)
trig.high()
time.sleep_us(5)
trig.low()
while echo.value() == 0:
time1 = time.ticks_us()
while echo.value() == 1:
time2 = time.ticks_us()
time2 = time.ticks_us()
durin = time.ticks_diff(time2,time1)
return durin *343/2/10000

def detect():
if slide.value() == 0:
servo.duty_u16(1802)
sc.value(0)
nsc.value(1)
if slide.value() == 1:
servo.duty_u16(4833)
sc.value(1)
nsc.value(0)

try:
while True:
dis = distance()
if dis > 29.6:
for i in range(10):
led[i].value(0)
detect()
time.sleep_ms(300)
continue
fill = 29.6 - dis
capac = fill/29.6
ld = round(capac, 1)
lednum = int(ld * 10)
if lednum == 0:
for i in range(10):
led[i].value(0)
detect()
time.sleep_ms(300)
continue
for i in range(lednum):
led[i].value(1)
detect()
time.sleep_ms(300)

except KeyboardInterrupt:
print("All right, I'm done here.")

Make sure, if you changed your pins such that they are different from my pins, make sure you specify them in the code. The pin definitions are tagged with #pin

How the Code Works

All code has to begin with an importation of the required modules:

import machine
from machine import Pin, PWM
import time

Next, we define the servo pin, the opening and closing positions, and the servo frequency.

servo_pin = machine.Pin(0)#pin
servo = PWM(servo_pin)

close = 1802
opem = 3032
frequency = 50
servo.freq(frequency)

After, we define the slide switch, the LEDs, and the ultrasonic pins.

slide = machine.Pin(15, machine.Pin.IN)#pin
nsc = machine.Pin(13, machine.Pin.OUT)#pin
sc = machine.Pin(12, machine.Pin.OUT)#pin

trig = machine.Pin(5, machine.Pin.OUT)#pin
echo = machine.Pin(6, machine.Pin.IN)#pin
pin = [16, 17, 18, 19, 20, 21, 22, 26, 27, 28]#pin
led = []

Then, we iterate through the pin numbers of the LED bar graph and assign them a pin on the Pico.

for i in range(10):
led.append(None)
led[i] = machine.Pin(pin[i], machine.Pin.OUT)
led[i].value(0)

Furthermore, we define a function distance() to track the capacity of the box.

def distance():
trig.low()
time.sleep_us(2)
trig.high()
time.sleep_us(5)
trig.low()
while echo.value() == 0:
time1 = time.ticks_us()
while echo.value() == 1:
time2 = time.ticks_us()
time2 = time.ticks_us()
durin = time.ticks_diff(time2,time1)
return durin *343/2/10000

Moreover, we define another function detect() to detect of the slide switch has changed positions, and if so, it will toggle the LEDs and open the box.

def detect():
if slide.value() == 0:
servo.duty_u16(1802)
sc.value(0)
nsc.value(1)
if slide.value() == 1:
servo.duty_u16(4833)
sc.value(1)
nsc.value(0)

Finally, we add the main loop, which we put in a try() so that if we Keyboard Interrupt, MicroPython won't flag an error.

try:
while True:

In this first part, we do several things. We:

  1. get the distance calculated by the ultrasonic.
dis = distance()
  1. check if the distance is greater than the box height. If this is the case, we have no LEDs light up. This might happen when the box is open.
if dis > 29.6:
for i in range(10):
led[i].value(0)
detect()
time.sleep_ms(300)
continue
  1. set a value as the remaining capacity(height - distance) divided by the total height.
fill = 29.6 - dis
capac = fill/29.6
  1. round it to the nearest tenth and multiply it by 10.
ld = round(capac, 1)
lednum = int(ld * 10)
  1. Check if the value lednum (the number of LEDs that should light up) is equal to 0. If it is, we have all values be 0.
if lednum == 0:
for i in range(10):
led[i].value(0)
detect()
time.sleep_ms(300)
continue
  1. Have the program turn on that many LEDs on the bar graph.
for i in range(lednum):
led[i].value(1)
detect()
time.sleep_ms(300)

Note that before the loop ended, or before each continue, we added detect() and asked the program to rest for 300 milliseconds. This is because we don't want the ultrasonic to receive an influx of values at the same time, and we also want to detect if the slide switch has been slid from one position to the other, and open/close the box accordingly. In my next version, I will extend this with a 3d printed box, an electronic lock with a keypad, and an item tracker. Now I will be able to store my items in a safe, secure way!