Similar device to Rolly.
My project, Rolly, is a low-cost, handheld digital ruler designed for visually impaired students pursuing STEM subjects. Rolly measures distance by rolling a tactile wheel across an object and announcing the measurement through audio feedback. It provides precise, real-time readings in centimeters, helping blind students perform laboratory and classroom measurements independently.
I used Autodesk Fusion 360 to create the model and to import the electronics components.
I began the design with the wheel—the core of the project and its most challenging element—because its accuracy directly determines the ruler’s resolution. From the outset, I calculated the optimal number of slits and ensured each one was cut cleanly without residue. For smooth operation, I selected a small 10 mm ball bearing instead of a plain shaft, which significantly reduced friction and provided steadier, more reliable rotation.
After successful trials with the wheel and motion mechanism, I turned my attention to designing the enclosure. Before the first sketch attempt, I began by estimating the space needed for each electronic component—Arduino board, speaker, wheel sensor, and wiring. Using those dimensions as a starting point, I created fully defined 2D sketches for each side of the enclosure to lock in exact measurements and relationships.
I determined the optimal speaker location by accounting for its physical dimensions, and incorporated a pattern of small front-panel openings to ensure clear sound output.
On the base, I planned the internal mounting layout with the wheel’s diameter, the sensor’s slit positions, and the arrangement of the Arduino and compact breadboard all in mind.
Sides
I created full-defined sketched with all features I need to include. Then, using the extrude command, I created bodies from those sketches. Further, I used the joint command to assemble the sides.
Importing the Electronics
After I imported the electronics into my design, I started to arrange the, aiming to save space as much as i can. To do so, I used the projection tool to locate the positions of the electronics such as the Speaker, Arduino UNO, the wheel sensor, and the OLED.
For any components whose 3D models were unavailable, I modeled equivalent objects with the same dimensions to ensure accurate fit and spacing.
I used the projection command to define the holes of the OLED.
I used the projection command to define the holes of the Arduino.
Side-view of the internal components
Doing the section analysis to view the available spaces for jumper wires.
Importing the logo
After I made the logo design, I used Inkscape to trace map the outlines of my design and saved it as a .dxf file format.
Software and materials:
Machines:
I began by designing a six-sided enclosure in Fusion 360 to house the Arduino Uno, speaker, wheel sensor, and wiring. Each panel was modeled with fully defined sketches, including precise cut-outs for the ports and controls.
For the wheel and sensor mounting, I created a separate 3D model in Fusion 360. This custom bracket was printed in PLA to ensure a secure fit and accurate alignment of the rotary wheel with the sensor.
Laser Cutting
The finalized enclosure panels were exported as DXF files and imported into the laser-cutting software. Cut lines were assigned with these parameters:
Laser Mode: Cut
Speed: 30 mm/s
Power: 50 %
Laser Mode: Speed cut
Speed: 303 mm/s
Power: 20 %
I placed the plywood sheet on the laser cutter bed and adjusted the focus height to match the material thickness.
A small test pulse was run to confirm clean cuts without burning. Once verified, I sent the file to the laser cutter.
After cutting, I removed the six panels, cleaned off any residue, and lightly sanded the edges for a smooth finish before assembling the box and installing the electronics along with the 3D-printed wheel-and-sensor mount.
3D printing
The slicing parameters as shown in the screen
Resolution 0.2 mm
Infill Density: 20%
Adhesion (Yes)
Support (No)
I used the Ultimaker Cura Software to prepare the *.STL file to be ready for the 3D printing.
I executed the slicing and then saved the file as a *.gcode format to be ready for the 3D printer.
The Rolly circuit is centered on an Arduino Uno microcontroller, which coordinates input from the wheel sensor and outputs real-time distance measurements through audio.
Input Components
Rotary (Optical) Wheel Sensor
Function: Detects wheel rotation and converts it into digital pulses.
Role in System: Measures the distance traveled as the wheel rolls along a surface.
Push Buttons (Speak / Reset/Info)
Function: Provide manual control such as resetting measurements and speaking meaurements.
Action (Output) Components
DFPlayer Mini MP3 Module + Speaker
Function: Plays pre-recorded audio files announcing the measured distance.
OLED Display (128×64) (if used in your build)
Function: Displays live distance readings for quick visual confirmation.
The Rolly device is powered by a 9 V adapter.
Arduino Uno Operating Range The Uno’s jack input accepts 7 – 12 V. Its on-board regulator steps this down to a stable 5 V required by the ATmega328P, the OLED display, and the DFPlayer Mini. Therefore, a 9 V source sits safely in the middle of that range.
Overview
The sketch measures the linear distance a wheel travels and reports the measurement two ways:
OLED display shows the current distance in centimeters with two decimal places.
DFPlayer Mini MP3 module speaks the measured distance aloud when a button is pressed.
Libraries
Wire / Adafruit_GFX / Adafruit_SSD1306 – I²C communication and graphics to drive the 128×64 px OLED screen.
SoftwareSerial – Provides an extra serial port (pins 10 & 11) to communicate with the DFPlayer Mini.
DFRobotDFPlayerMini – Simplifies sending play/volume commands to the MP3 module.
Part of the code
Overall Function
Measure: Wheel spins → sensor pulses → interrupt counts them.
Calculate: Distance = pulses × (wheel circumference ÷ pulses-per-rev).
Show: OLED updates every half second.
Speak: Button presses trigger MP3 playback for the number or a welcome.
Functions and Variables
The code has the following functions and variables:
Void setup:
I declared the pinmodes and the basic commands for the OLED and the MP3 module. For the sensor pin I used this resource (here) to learn about the ISR that handles the sensor data as I learned from the online tutorials.
Void loop:
I defined three buttons: reset, speak, and welcome. When one is pressed, I either reset the pulse counter, announce the distance, or play a welcome sound. I also refresh the OLED display every half second to show the latest measured length.
Void pulseCount
I wrote a short Interrupt Service Routine that runs whenever the sensor pin detects a falling edge. It uses micros() to avoid switch noise (debouncing) and then increments the pulseCount variable.
Void announceNumber
This function is the “talking” part of the project. When the speak button is pressed, it builds a spoken sentence that represents the measured distance.
It first turns off interrupts for a moment (noInterrupts()) so the wheel pulses can’t change pulseCount while it’s being read.
The length is calculated using the formula: Distance = pulses × (wheel circumference ÷ pulses-per-rev).
The result is sperated into a whole number and fraction:
If the whole number is zero, it simply plays the audio file “zero.” Otherwise it breaks the number into digits from left to right. It finds the largest divisor of 10 (div) to isolate each digit. For example, if whole is 123, it plays “1,” then “2,” then “3.” After each digit it waits about 800 ms to give the DFPlayer time to start the next file. It plays the “point” file, then the two decimal digits individually—again with short delays. Finally it plays the file for “centimeters,” waits a second, and ends. The audio files must be pre-loaded on the DFPlayer’s SD card in folder 1 with specific file numbers: 001.mp3 through 010.mp3 for digits 0–9, 011.mp3 for “point,” 012.mp3 for “centimeters,” and so on. So if the measured distance is 12.34 cm, the playback sequence is: One Two point Three Four centimeters.
Part of the code
The first trials
Testing the wheel sensor with OLED!
Testing the speaker!
Optimizing the wheel motion to make it steady and uniform!
Integration of Modules:
Internal Layout
The Arduino Uno is mounted inside the laser-cut plywood box, positioned for easy USB access.
The 3D-printed wheel and sensor bracket is fixed to the enclosure’s base so the optical sensor aligns precisely with the rotary wheel.
Electrical Connections
Sensor → Arduino: The optical wheel sensor’s output pin connects to Arduino digital interrupt pin 2, with VCC and GND linked to the 5 V and ground rails.
DFPlayer Mini → Arduino: RX/TX pins connect to Arduino digital pins 10/11 via a SoftwareSerial interface. A small 8 Ω speaker is wired to the DFPlayer’s output.
Power: A 9 V adapter powers the Arduino, which in turn supplies regulated 5 V to the sensor, DFPlayer, and OLED.
Assembly Steps
Route wires through the pre-cut openings in the plywood panels.
Secure the 3D-printed mount and wheel, then fasten the six panels together to complete the enclosure.
Load the Arduino sketch through the Arduino IDE, ensuring the DFPlayer SD card contains the pre-recorded distance audio files (I created the Audio files using AI TTS tool in the references section below).
I had many challenges, but I'll pick a major challenge that I enjoyed seeing it ended up resolved! The challenge was with the shaft-and-wheel combination, which made the wheel’s motion unstable. After several brainstorming sessions with friends at AUC and a range of creative ideas—none implemented yet—I chose the simplest solution: using ball bearings. Fortunately, I found 10 mm-diameter bearings that fit the wheel perfectly.
The project itself was challenging. I studied many resources online and tried so many things to make this project working alhamdullah!
I’ll highlight the most time-consuming task I tackled. Initially, I was inspired by online resources to embed the audio numbers directly in the code and use the Arduino PCM library. This approach plays back uncompressed 8-bit PCM (Pulse-Code Modulation) audio through a single digital output pin and a simple low-pass filter—just a resistor and capacitor or a small speaker. The plan would have allowed me to eliminate the bulky DFPlayer and further reduce the device’s size.
Plan A: Decoding the Audio files (No DFplayer)
Downloading libraries for the python code to decode the Audio files
The python code to decode the files and convert them to C++ headers so that they can be imported into the Arduino sketch as a library.
Plan B: Making the audio files (with the DFplayer)
In order to create Audiofiles with clear voice numbers, I used text-to-speech AI tool as shown below.
After downloading the files, I found out that there are a specs for the audio files I need to follow. So I had to make another tweaks on the generated file:
Bit rate: MP3: 8 kbps – 320 kbps
Sample rate: 8 kHz – 48 kHz (44.1 kHz is standard and works best).
Channels: Mono or Stereo (stereo was better)
working on improving the design and make it more smaller and user friendly. Also, I have more ideas to take the mechanism to the next level, and I will work on it very soon.
Code
Resources
Optical Encoders
https://www.youtube.com/watch?v=_45VomiyUk0
What is the Difference between Absolute and Incremental Encoders?
https://www.youtube.com/watch?v=-Qk--Sjgq78
Encoders types
https://www.youtube.com/watch?v=4FlDxaZpqtg
How do Scroll Wheels Work?
https://www.youtube.com/watch?v=-HVKm5fIUA8
Audio Trimmer
AI TTS tool
Audio converter
https://convert.routenote.com/mono-to-stereo